Files
apskel-pos-backend/internal/service/wallet_admin_service.go
T

70 lines
2.8 KiB
Go
Raw Normal View History

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),
})
}