package repository import ( "apskel-pos-be/internal/entities" "context" "fmt" "github.com/google/uuid" "gorm.io/gorm" ) type CustomerTokensRepository struct { db *gorm.DB } func NewCustomerTokensRepository(db *gorm.DB) *CustomerTokensRepository { return &CustomerTokensRepository{db: db} } func (r *CustomerTokensRepository) Create(ctx context.Context, customerTokens *entities.CustomerTokens) error { return r.db.WithContext(ctx).Create(customerTokens).Error } func (r *CustomerTokensRepository) GetByID(ctx context.Context, id uuid.UUID) (*entities.CustomerTokens, error) { var customerTokens entities.CustomerTokens err := r.db.WithContext(ctx).Preload("Customer").Where("id = ?", id).First(&customerTokens).Error if err != nil { return nil, err } return &customerTokens, nil } func (r *CustomerTokensRepository) GetByCustomerIDAndType(ctx context.Context, customerID uuid.UUID, tokenType entities.TokenType) (*entities.CustomerTokens, error) { var customerTokens entities.CustomerTokens err := r.db.WithContext(ctx).Preload("Customer").Where("customer_id = ? AND token_type = ?", customerID, tokenType).First(&customerTokens).Error if err != nil { return nil, err } return &customerTokens, nil } func (r *CustomerTokensRepository) GetByCustomerID(ctx context.Context, customerID uuid.UUID) ([]entities.CustomerTokens, error) { var customerTokens []entities.CustomerTokens err := r.db.WithContext(ctx).Preload("Customer").Where("customer_id = ?", customerID).Find(&customerTokens).Error if err != nil { return nil, err } return customerTokens, nil } func (r *CustomerTokensRepository) List(ctx context.Context, offset, limit int, search, tokenType string, sortBy, sortOrder string) ([]entities.CustomerTokens, int64, error) { var customerTokens []entities.CustomerTokens var total int64 query := r.db.WithContext(ctx).Preload("Customer") if search != "" { searchTerm := "%" + search + "%" query = query.Joins("JOIN customers ON customer_tokens.customer_id = customers.id"). Where("customers.name ILIKE ? OR customers.email ILIKE ?", searchTerm, searchTerm) } if tokenType != "" { query = query.Where("token_type = ?", tokenType) } if err := query.Model(&entities.CustomerTokens{}).Count(&total).Error; err != nil { return nil, 0, err } if sortBy != "" { if sortOrder == "" { sortOrder = "asc" } query = query.Order(fmt.Sprintf("customer_tokens.%s %s", sortBy, sortOrder)) } else { query = query.Order("customer_tokens.created_at DESC") } err := query.Offset(offset).Limit(limit).Find(&customerTokens).Error if err != nil { return nil, 0, err } return customerTokens, total, nil } func (r *CustomerTokensRepository) Update(ctx context.Context, customerTokens *entities.CustomerTokens) error { return r.db.WithContext(ctx).Save(customerTokens).Error } func (r *CustomerTokensRepository) Delete(ctx context.Context, id uuid.UUID) error { return r.db.WithContext(ctx).Delete(&entities.CustomerTokens{}, id).Error } func (r *CustomerTokensRepository) AddTokens(ctx context.Context, customerID uuid.UUID, tokenType entities.TokenType, tokens int64) error { return r.db.WithContext(ctx).Model(&entities.CustomerTokens{}). Where("customer_id = ? AND token_type = ?", customerID, tokenType). Update("balance", gorm.Expr("balance + ?", tokens)).Error } func (r *CustomerTokensRepository) DeductTokens(ctx context.Context, customerID uuid.UUID, tokenType entities.TokenType, tokens int64) error { return r.db.WithContext(ctx).Model(&entities.CustomerTokens{}). Where("customer_id = ? AND token_type = ? AND balance >= ?", customerID, tokenType, tokens). Update("balance", gorm.Expr("balance - ?", tokens)).Error } func (r *CustomerTokensRepository) EnsureCustomerTokens(ctx context.Context, customerID uuid.UUID, tokenType entities.TokenType) (*entities.CustomerTokens, error) { customerTokens, err := r.GetByCustomerIDAndType(ctx, customerID, tokenType) if err == nil { return customerTokens, nil } if err != gorm.ErrRecordNotFound { return nil, err } // Create new customer tokens record newCustomerTokens := &entities.CustomerTokens{ CustomerID: customerID, TokenType: tokenType, Balance: 0, } err = r.Create(ctx, newCustomerTokens) if err != nil { return nil, err } return newCustomerTokens, nil }