package service import ( "context" "log/slog" "time" "git.kocoder.xyz/vt/financial-tracking-service/internal/config" "git.kocoder.xyz/vt/financial-tracking-service/internal/database" transactionv1 "git.kocoder.xyz/vt/financial-tracking-service/internal/proto/transaction/v1" "git.kocoder.xyz/vt/financial-tracking-service/internal/proto/transaction/v1/transactionv1connect" "google.golang.org/protobuf/types/known/timestamppb" ) type TransactionService struct { conf *config.Config db *database.Queries } func NewTransactionService(conf *config.Config, db *database.Queries) transactionv1connect.TransactionServiceHandler { return &TransactionService{ conf: conf, db: db, } } func (s *TransactionService) CreateTransaction(ctx context.Context, req *transactionv1.CreateTransactionRequest) (*transactionv1.CreateTransactionResponse, error) { txDate := time.Now() if req.TransactionDate != nil { txDate = req.TransactionDate.AsTime() } tx, err := s.db.CreateTransaction(ctx, database.CreateTransactionParams{ Description: req.Description, Amount: req.Amount, Category: req.Category, TransactionDate: txDate, }) if err != nil { slog.ErrorContext(ctx, "failed to create transaction", slog.String("err", err.Error())) return nil, err } return &transactionv1.CreateTransactionResponse{ Transaction: &transactionv1.Transaction{ TransactionId: tx.TransactionID, Description: tx.Description, Amount: tx.Amount, Category: tx.Category, TransactionDate: timestamppb.New(tx.TransactionDate), CreatedAt: timestamppb.New(tx.CreatedAt), }, }, nil } func (s *TransactionService) ListTransactions(ctx context.Context, req *transactionv1.ListTransactionsRequest) (*transactionv1.ListTransactionsResponse, error) { txs, err := s.db.ListTransactions(ctx) if err != nil { slog.ErrorContext(ctx, "failed to list transactions", slog.String("err", err.Error())) return nil, err } var protoTxs []*transactionv1.Transaction for _, tx := range txs { protoTxs = append(protoTxs, &transactionv1.Transaction{ TransactionId: tx.TransactionID, Description: tx.Description, Amount: tx.Amount, Category: tx.Category, TransactionDate: timestamppb.New(tx.TransactionDate), CreatedAt: timestamppb.New(tx.CreatedAt), }) } return &transactionv1.ListTransactionsResponse{ Transactions: protoTxs, }, nil } func (s *TransactionService) GetTransaction(ctx context.Context, req *transactionv1.GetTransactionRequest) (*transactionv1.GetTransactionResponse, error) { tx, err := s.db.GetTransaction(ctx, req.TransactionId) if err != nil { slog.ErrorContext(ctx, "failed to get transaction", slog.Int("id", int(req.TransactionId)), slog.String("err", err.Error())) return nil, err } return &transactionv1.GetTransactionResponse{ Transaction: &transactionv1.Transaction{ TransactionId: tx.TransactionID, Description: tx.Description, Amount: tx.Amount, Category: tx.Category, TransactionDate: timestamppb.New(tx.TransactionDate), CreatedAt: timestamppb.New(tx.CreatedAt), }, }, nil } func (s *TransactionService) DeleteTransaction(ctx context.Context, req *transactionv1.DeleteTransactionRequest) (*transactionv1.DeleteTransactionResponse, error) { err := s.db.DeleteTransaction(ctx, req.TransactionId) if err != nil { slog.ErrorContext(ctx, "failed to delete transaction", slog.Int("id", int(req.TransactionId)), slog.String("err", err.Error())) return &transactionv1.DeleteTransactionResponse{Ok: false}, err } return &transactionv1.DeleteTransactionResponse{ Ok: true, }, nil }