194 lines
5.5 KiB
Go
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
|
|
}
|