package processor import ( "apskel-pos-be/internal/entities" "apskel-pos-be/internal/mappers" "apskel-pos-be/internal/models" "apskel-pos-be/internal/repository" "context" "errors" "fmt" "github.com/google/uuid" ) type CustomerTokensProcessor struct { customerTokensRepo *repository.CustomerTokensRepository } func NewCustomerTokensProcessor(customerTokensRepo *repository.CustomerTokensRepository) *CustomerTokensProcessor { return &CustomerTokensProcessor{ customerTokensRepo: customerTokensRepo, } } // CreateCustomerTokens creates a new customer tokens record func (p *CustomerTokensProcessor) CreateCustomerTokens(ctx context.Context, req *models.CreateCustomerTokensRequest) (*models.CustomerTokensResponse, error) { // Convert request to entity customerTokens := mappers.ToCustomerTokensEntity(req) // Create customer tokens err := p.customerTokensRepo.Create(ctx, customerTokens) if err != nil { return nil, fmt.Errorf("failed to create customer tokens: %w", err) } return mappers.ToCustomerTokensResponse(customerTokens), nil } // GetCustomerTokens retrieves customer tokens by ID func (p *CustomerTokensProcessor) GetCustomerTokens(ctx context.Context, id uuid.UUID) (*models.CustomerTokensResponse, error) { customerTokens, err := p.customerTokensRepo.GetByID(ctx, id) if err != nil { return nil, fmt.Errorf("customer tokens not found: %w", err) } return mappers.ToCustomerTokensResponse(customerTokens), nil } // GetCustomerTokensByCustomerIDAndType retrieves customer tokens by customer ID and token type func (p *CustomerTokensProcessor) GetCustomerTokensByCustomerIDAndType(ctx context.Context, customerID uuid.UUID, tokenType string) (*models.CustomerTokensResponse, error) { customerTokens, err := p.customerTokensRepo.EnsureCustomerTokens(ctx, customerID, entities.TokenType(tokenType)) if err != nil { return nil, fmt.Errorf("failed to get customer tokens: %w", err) } return mappers.ToCustomerTokensResponse(customerTokens), nil } // ListCustomerTokens retrieves customer tokens with pagination and filtering func (p *CustomerTokensProcessor) ListCustomerTokens(ctx context.Context, query *models.ListCustomerTokensQuery) (*models.PaginatedResponse[models.CustomerTokensResponse], error) { // Set default values if query.Page <= 0 { query.Page = 1 } if query.Limit <= 0 { query.Limit = 10 } if query.Limit > 100 { query.Limit = 100 } offset := (query.Page - 1) * query.Limit // Get customer tokens from repository customerTokens, total, err := p.customerTokensRepo.List( ctx, offset, query.Limit, query.Search, query.TokenType, query.SortBy, query.SortOrder, ) if err != nil { return nil, fmt.Errorf("failed to list customer tokens: %w", err) } // Convert to responses responses := mappers.ToCustomerTokensResponses(customerTokens) // Calculate pagination info totalPages := int((total + int64(query.Limit) - 1) / int64(query.Limit)) return &models.PaginatedResponse[models.CustomerTokensResponse]{ Data: responses, Pagination: models.Pagination{ Page: query.Page, Limit: query.Limit, Total: total, TotalPages: totalPages, }, }, nil } // UpdateCustomerTokens updates an existing customer tokens record func (p *CustomerTokensProcessor) UpdateCustomerTokens(ctx context.Context, id uuid.UUID, req *models.UpdateCustomerTokensRequest) (*models.CustomerTokensResponse, error) { // Get existing customer tokens customerTokens, err := p.customerTokensRepo.GetByID(ctx, id) if err != nil { return nil, fmt.Errorf("customer tokens not found: %w", err) } // Update customer tokens fields mappers.UpdateCustomerTokensEntity(customerTokens, req) // Save updated customer tokens err = p.customerTokensRepo.Update(ctx, customerTokens) if err != nil { return nil, fmt.Errorf("failed to update customer tokens: %w", err) } return mappers.ToCustomerTokensResponse(customerTokens), nil } // DeleteCustomerTokens deletes a customer tokens record func (p *CustomerTokensProcessor) DeleteCustomerTokens(ctx context.Context, id uuid.UUID) error { // Get existing customer tokens _, err := p.customerTokensRepo.GetByID(ctx, id) if err != nil { return fmt.Errorf("customer tokens not found: %w", err) } // Delete customer tokens err = p.customerTokensRepo.Delete(ctx, id) if err != nil { return fmt.Errorf("failed to delete customer tokens: %w", err) } return nil } // AddTokens adds tokens to a customer's balance func (p *CustomerTokensProcessor) AddTokens(ctx context.Context, customerID uuid.UUID, tokenType string, tokens int64) (*models.CustomerTokensResponse, error) { if tokens <= 0 { return nil, errors.New("tokens must be greater than 0") } // Ensure customer tokens record exists _, err := p.customerTokensRepo.EnsureCustomerTokens(ctx, customerID, entities.TokenType(tokenType)) if err != nil { return nil, fmt.Errorf("failed to ensure customer tokens: %w", err) } // Add tokens err = p.customerTokensRepo.AddTokens(ctx, customerID, entities.TokenType(tokenType), tokens) if err != nil { return nil, fmt.Errorf("failed to add tokens: %w", err) } // Get updated customer tokens customerTokens, err := p.customerTokensRepo.GetByCustomerIDAndType(ctx, customerID, entities.TokenType(tokenType)) if err != nil { return nil, fmt.Errorf("failed to get updated customer tokens: %w", err) } return mappers.ToCustomerTokensResponse(customerTokens), nil } // DeductTokens deducts tokens from a customer's balance func (p *CustomerTokensProcessor) DeductTokens(ctx context.Context, customerID uuid.UUID, tokenType string, tokens int64) (*models.CustomerTokensResponse, error) { if tokens <= 0 { return nil, errors.New("tokens must be greater than 0") } // Get current customer tokens customerTokens, err := p.customerTokensRepo.GetByCustomerIDAndType(ctx, customerID, entities.TokenType(tokenType)) if err != nil { return nil, fmt.Errorf("customer tokens not found: %w", err) } if customerTokens.Balance < tokens { return nil, errors.New("insufficient tokens balance") } // Deduct tokens err = p.customerTokensRepo.DeductTokens(ctx, customerID, entities.TokenType(tokenType), tokens) if err != nil { return nil, fmt.Errorf("failed to deduct tokens: %w", err) } // Get updated customer tokens updatedCustomerTokens, err := p.customerTokensRepo.GetByCustomerIDAndType(ctx, customerID, entities.TokenType(tokenType)) if err != nil { return nil, fmt.Errorf("failed to get updated customer tokens: %w", err) } return mappers.ToCustomerTokensResponse(updatedCustomerTokens), nil }