package cashier_session import ( "enaklo-pos-be/internal/common/logger" "enaklo-pos-be/internal/common/mycontext" "enaklo-pos-be/internal/entity" "github.com/pkg/errors" "go.uber.org/zap" ) type Service interface { OpenSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error) CloseSession(ctx mycontext.Context, sessionID int64, closingAmount float64) (*entity.CashierSessionReport, error) GetOpenSession(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error) GetSessionReport(ctx mycontext.Context, sessionID int64) (*entity.CashierSessionReport, error) GetSessionHistory(ctx mycontext.Context, partnerID int64, limit, offset int) ([]*entity.CashierSession, int64, error) } type Repository interface { CreateSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error) CloseSession(ctx mycontext.Context, sessionID int64, closingAmount, expectedAmount float64) error GetOpenSessionByCashierID(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error) GetSessionByID(ctx mycontext.Context, sessionID int64) (*entity.CashierSession, error) GetPaymentSummaryBySessionID(ctx mycontext.Context, sessionID int64) ([]entity.PaymentSummary, error) GetSessionHistoryByPartnerID(ctx mycontext.Context, partnerID int64, limit, offset int) ([]*entity.CashierSession, int64, error) } type cashierSessionSvc struct { repo Repository } func New(repo Repository) Service { return &cashierSessionSvc{repo: repo} } func (s *cashierSessionSvc) OpenSession(ctx mycontext.Context, session *entity.CashierSession) (*entity.CashierSession, error) { openSession, err := s.repo.GetOpenSessionByCashierID(ctx, session.CashierID) if err != nil { return nil, errors.Wrap(err, "failed to check existing open session") } if openSession != nil { return nil, errors.New("cashier already has an open session") } newSession, err := s.repo.CreateSession(ctx, session) if err != nil { logger.ContextLogger(ctx).Error("failed to create cashier session", zap.Error(err)) return nil, errors.Wrap(err, "failed to create cashier session") } return newSession, nil } func (s *cashierSessionSvc) CloseSession(ctx mycontext.Context, sessionID int64, closingAmount float64) (*entity.CashierSessionReport, error) { report, err := s.repo.GetPaymentSummaryBySessionID(ctx, sessionID) if err != nil { return nil, errors.Wrap(err, "failed to get payment summary") } var expectedAmount float64 for _, r := range report { expectedAmount += r.TotalAmount } if err := s.repo.CloseSession(ctx, sessionID, closingAmount, expectedAmount); err != nil { return nil, errors.Wrap(err, "failed to close session") } return &entity.CashierSessionReport{ SessionID: sessionID, ClosingAmount: closingAmount, ExpectedAmount: expectedAmount, Payments: report, }, nil } func (s *cashierSessionSvc) GetOpenSession(ctx mycontext.Context, cashierID int64) (*entity.CashierSession, error) { session, err := s.repo.GetOpenSessionByCashierID(ctx, cashierID) if err != nil { return nil, errors.Wrap(err, "failed to get open session") } return session, nil } func (s *cashierSessionSvc) GetSessionReport(ctx mycontext.Context, sessionID int64) (*entity.CashierSessionReport, error) { report, err := s.repo.GetPaymentSummaryBySessionID(ctx, sessionID) if err != nil { return nil, errors.Wrap(err, "failed to get payment summary") } var expectedAmount float64 for _, r := range report { expectedAmount += r.TotalAmount } return &entity.CashierSessionReport{ SessionID: sessionID, ExpectedAmount: expectedAmount, Payments: report, }, nil } func (s *cashierSessionSvc) GetSessionHistory(ctx mycontext.Context, partnerID int64, limit, offset int) ([]*entity.CashierSession, int64, error) { sessions, total, err := s.repo.GetSessionHistoryByPartnerID(ctx, partnerID, limit, offset) if err != nil { return nil, 0, errors.Wrap(err, "failed to get session history") } return sessions, total, nil }