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

118 lines
3.5 KiB
Go

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