package service import ( "context" "errors" "github.com/google/uuid" "apskel-pos-be/internal/appcontext" "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" "apskel-pos-be/internal/models" "apskel-pos-be/internal/processor" "apskel-pos-be/internal/repository" ) // WalletAdminService is the dashboard's access to a customer's wallet // (docs/prd-point-coin.md F7). Every call is scoped to the caller's organization. type WalletAdminService interface { GetCustomerWallet(ctx context.Context, apctx *appcontext.ContextInfo, customerID uuid.UUID, query models.ListCustomerWalletTransactionsQuery) *contract.Response AdjustCustomerWallet(ctx context.Context, apctx *appcontext.ContextInfo, customerID uuid.UUID, req *contract.AdjustCustomerWalletRequest) *contract.Response } type WalletAdminServiceImpl struct { walletAdminProcessor *processor.WalletAdminProcessor } func NewWalletAdminService(walletAdminProcessor *processor.WalletAdminProcessor) *WalletAdminServiceImpl { return &WalletAdminServiceImpl{walletAdminProcessor: walletAdminProcessor} } func (s *WalletAdminServiceImpl) GetCustomerWallet(ctx context.Context, apctx *appcontext.ContextInfo, customerID uuid.UUID, query models.ListCustomerWalletTransactionsQuery) *contract.Response { wallet, err := s.walletAdminProcessor.GetCustomerWallet(ctx, apctx.OrganizationID, customerID, query) if err != nil { return walletErrorResponse(err) } return contract.BuildSuccessResponse(wallet) } func (s *WalletAdminServiceImpl) AdjustCustomerWallet(ctx context.Context, apctx *appcontext.ContextInfo, customerID uuid.UUID, req *contract.AdjustCustomerWalletRequest) *contract.Response { result, err := s.walletAdminProcessor.Adjust(ctx, apctx.OrganizationID, apctx.UserID, customerID, models.WalletAdjustment{ Currency: req.Currency, Amount: req.Amount, Reason: req.Reason, IdempotencyKey: req.IdempotencyKey, }) if err != nil { return walletErrorResponse(err) } return contract.BuildSuccessResponse(result) } // walletErrorResponse tells the dashboard's mistakes apart from server failures. func walletErrorResponse(err error) *contract.Response { code, message := constants.InternalServerErrorCode, err.Error() switch { case errors.Is(err, repository.ErrWalletNotFound): code, message = constants.NotFoundErrorCode, "customer not found" case errors.Is(err, repository.ErrWalletInsufficientBalance): code, message = constants.ValidationErrorCode, "the adjustment would take more than the customer can spend" case errors.Is(err, processor.ErrInvalidWalletQuery), errors.Is(err, processor.ErrWalletInvalidEntry), errors.Is(err, processor.ErrWalletIdempotencyConflict): code = constants.ValidationErrorCode } return contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(code, constants.WalletServiceEntity, message), }) }