apskel-pos-backend/internal/processor/customer_tokens_processor.go
2025-09-17 19:30:17 +07:00

199 lines
6.4 KiB
Go

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
}