apskel-pos-backend/internal/processor/voucher_processor.go
Aditya Siregar afa8782eb2 fix backend
2025-09-13 17:34:34 +07:00

194 lines
5.5 KiB
Go

package processor
import (
"apskel-pos-be/internal/mappers"
"apskel-pos-be/internal/models"
"apskel-pos-be/internal/repository"
"context"
"fmt"
)
type VoucherProcessor struct {
voucherRepo *repository.VoucherRepository
}
func NewVoucherProcessor(voucherRepo *repository.VoucherRepository) *VoucherProcessor {
return &VoucherProcessor{
voucherRepo: voucherRepo,
}
}
// GetRandomVouchersForSpin retrieves random vouchers for spin feature
func (p *VoucherProcessor) GetRandomVouchersForSpin(ctx context.Context, req *models.ListVouchersForSpinRequest) (*models.ListVouchersForSpinResponse, error) {
// Set default limit if not provided
limit := req.Limit
if limit <= 0 {
limit = 10 // Default limit
}
if limit > 50 {
limit = 50 // Max limit
}
// Get random vouchers from repository
vouchers, err := p.voucherRepo.GetRandomVouchers(ctx, limit)
if err != nil {
return nil, fmt.Errorf("failed to get random vouchers: %w", err)
}
// Convert to spin response format
voucherResponses := make([]models.VoucherSpinResponse, len(vouchers))
for i, voucher := range vouchers {
voucherResponses[i] = *mappers.VoucherEntityToSpinResponse(&voucher)
}
return &models.ListVouchersForSpinResponse{
Vouchers: voucherResponses,
Count: len(voucherResponses),
}, nil
}
// GetVoucherByID retrieves a voucher by ID
func (p *VoucherProcessor) GetVoucherByID(ctx context.Context, voucherID int64) (*models.VoucherResponse, error) {
voucher, err := p.voucherRepo.GetByID(ctx, voucherID)
if err != nil {
return nil, fmt.Errorf("voucher not found: %w", err)
}
return mappers.VoucherEntityToResponse(voucher), nil
}
// GetVoucherByCode retrieves a voucher by voucher code
func (p *VoucherProcessor) GetVoucherByCode(ctx context.Context, voucherCode string) (*models.VoucherResponse, error) {
voucher, err := p.voucherRepo.GetByVoucherCode(ctx, voucherCode)
if err != nil {
return nil, fmt.Errorf("voucher not found: %w", err)
}
return mappers.VoucherEntityToResponse(voucher), nil
}
// ListVouchers retrieves vouchers with pagination
func (p *VoucherProcessor) ListVouchers(ctx context.Context, page, limit int) (*models.PaginatedVoucherResponse, error) {
offset := (page - 1) * limit
vouchers, total, err := p.voucherRepo.List(ctx, offset, limit)
if err != nil {
return nil, fmt.Errorf("failed to list vouchers: %w", err)
}
// Convert to response format
voucherResponses := make([]models.VoucherResponse, len(vouchers))
for i, voucher := range vouchers {
voucherResponses[i] = *mappers.VoucherEntityToResponse(&voucher)
}
totalPages := int((total + int64(limit) - 1) / int64(limit))
return &models.PaginatedVoucherResponse{
Data: voucherResponses,
TotalCount: int(total),
Page: page,
Limit: limit,
TotalPages: totalPages,
}, nil
}
// GetRandomVouchersByRows retrieves random vouchers organized into rows
func (p *VoucherProcessor) GetRandomVouchersByRows(ctx context.Context, req *models.ListVouchersByRowsRequest) (*models.ListVouchersByRowsResponse, error) {
// Set default values if not provided
rows := req.Rows
if rows <= 0 {
rows = 4 // Default to 4 rows
}
if rows > 10 {
rows = 10 // Max 10 rows
}
// Get random vouchers organized by rows
voucherRows, err := p.voucherRepo.GetRandomVouchersByRows(ctx, rows, req.WinnerNumber)
if err != nil {
return nil, fmt.Errorf("failed to get random vouchers by rows: %w", err)
}
// Convert to response format and select winners
responseRows := make([]models.VoucherRow, len(voucherRows))
totalVouchers := 0
for i, row := range voucherRows {
vouchers := make([]models.VoucherSpinResponse, len(row))
// Select a winner from this row if there are vouchers
if len(row) > 0 {
var winnerIndex int
if req.WinnerNumber != nil {
// If winner_number is specified, try to find a voucher with that winner_number
// that is not already a winner, otherwise select any non-winner
winnerIndex = -1
for j, voucher := range row {
if voucher.WinnerNumber == *req.WinnerNumber && !voucher.IsWinner {
winnerIndex = j
break
}
}
// If no voucher with specified winner_number found, select any non-winner
if winnerIndex == -1 {
for j, voucher := range row {
if !voucher.IsWinner {
winnerIndex = j
break
}
}
}
// If still no non-winner found, select any voucher
if winnerIndex == -1 {
winnerIndex = 0
}
} else {
// If no winner_number specified, select any non-winner, otherwise any voucher
winnerIndex = -1
for j, voucher := range row {
if !voucher.IsWinner {
winnerIndex = j
break
}
}
if winnerIndex == -1 {
winnerIndex = 0
}
}
// Mark as winner in database if not already a winner
if !row[winnerIndex].IsWinner {
err := p.voucherRepo.MarkAsWinner(ctx, row[winnerIndex].ID)
if err != nil {
// Log error but continue - don't fail the entire request
fmt.Printf("Failed to mark voucher %d as winner: %v\n", row[winnerIndex].ID, err)
} else {
// Update the voucher object to reflect the change
row[winnerIndex].IsWinner = true
}
}
}
// Convert all vouchers to response format
for j, voucher := range row {
vouchers[j] = *mappers.VoucherEntityToSpinResponse(&voucher)
}
responseRows[i] = models.VoucherRow{
RowNumber: i + 1, // Row numbers start from 1
Vouchers: vouchers,
}
totalVouchers += len(row)
}
return &models.ListVouchersByRowsResponse{
Rows: responseRows,
TotalRows: len(responseRows),
TotalVouchers: totalVouchers,
}, nil
}