269 lines
8.2 KiB
Go
269 lines
8.2 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"apskel-pos-be/internal/entities"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type CampaignRepository interface {
|
|
Create(ctx context.Context, campaign *entities.Campaign) error
|
|
GetByID(ctx context.Context, id string) (*entities.Campaign, error)
|
|
List(ctx context.Context, req *entities.ListCampaignsRequest) ([]entities.Campaign, int64, error)
|
|
Update(ctx context.Context, campaign *entities.Campaign) error
|
|
Delete(ctx context.Context, id string) error
|
|
GetActiveCampaigns(ctx context.Context) ([]entities.Campaign, error)
|
|
GetCampaignsForApp(ctx context.Context) ([]entities.Campaign, error)
|
|
}
|
|
|
|
type campaignRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewCampaignRepository(db *gorm.DB) CampaignRepository {
|
|
return &campaignRepository{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
func (r *campaignRepository) Create(ctx context.Context, campaign *entities.Campaign) error {
|
|
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
// Create campaign first
|
|
if err := tx.Create(campaign).Error; err != nil {
|
|
return fmt.Errorf("failed to create campaign: %w", err)
|
|
}
|
|
|
|
// Create campaign rules
|
|
if len(campaign.Rules) > 0 {
|
|
for i := range campaign.Rules {
|
|
campaign.Rules[i].CampaignID = campaign.ID
|
|
}
|
|
if err := tx.Create(&campaign.Rules).Error; err != nil {
|
|
return fmt.Errorf("failed to create campaign rules: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (r *campaignRepository) GetByID(ctx context.Context, id string) (*entities.Campaign, error) {
|
|
var campaign entities.Campaign
|
|
if err := r.db.WithContext(ctx).Preload("Rules").Where("id = ?", id).First(&campaign).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return nil, fmt.Errorf("campaign not found")
|
|
}
|
|
return nil, fmt.Errorf("failed to get campaign: %w", err)
|
|
}
|
|
return &campaign, nil
|
|
}
|
|
|
|
func (r *campaignRepository) List(ctx context.Context, req *entities.ListCampaignsRequest) ([]entities.Campaign, int64, error) {
|
|
var campaigns []entities.Campaign
|
|
var total int64
|
|
|
|
query := r.db.WithContext(ctx).Model(&entities.Campaign{})
|
|
|
|
// Apply filters
|
|
if req.Search != "" {
|
|
query = query.Where("name ILIKE ? OR description ILIKE ?", "%"+req.Search+"%", "%"+req.Search+"%")
|
|
}
|
|
|
|
if req.Type != "" {
|
|
query = query.Where("type = ?", req.Type)
|
|
}
|
|
|
|
if req.IsActive != nil {
|
|
query = query.Where("is_active = ?", *req.IsActive)
|
|
}
|
|
|
|
if req.ShowOnApp != nil {
|
|
query = query.Where("show_on_app = ?", *req.ShowOnApp)
|
|
}
|
|
|
|
if req.StartDate != nil {
|
|
query = query.Where("start_date >= ?", *req.StartDate)
|
|
}
|
|
|
|
if req.EndDate != nil {
|
|
query = query.Where("end_date <= ?", *req.EndDate)
|
|
}
|
|
|
|
// Count total records
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, 0, fmt.Errorf("failed to count campaigns: %w", err)
|
|
}
|
|
|
|
// Apply pagination
|
|
if req.Page > 0 && req.Limit > 0 {
|
|
offset := (req.Page - 1) * req.Limit
|
|
query = query.Offset(offset).Limit(req.Limit)
|
|
}
|
|
|
|
// Apply sorting
|
|
query = query.Order("position ASC, created_at DESC")
|
|
|
|
if err := query.Preload("Rules").Find(&campaigns).Error; err != nil {
|
|
return nil, 0, fmt.Errorf("failed to list campaigns: %w", err)
|
|
}
|
|
|
|
return campaigns, total, nil
|
|
}
|
|
|
|
func (r *campaignRepository) Update(ctx context.Context, campaign *entities.Campaign) error {
|
|
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
// Update campaign
|
|
if err := tx.Save(campaign).Error; err != nil {
|
|
return fmt.Errorf("failed to update campaign: %w", err)
|
|
}
|
|
|
|
// Delete existing rules
|
|
if err := tx.Where("campaign_id = ?", campaign.ID).Delete(&entities.CampaignRule{}).Error; err != nil {
|
|
return fmt.Errorf("failed to delete existing campaign rules: %w", err)
|
|
}
|
|
|
|
// Create new rules
|
|
if len(campaign.Rules) > 0 {
|
|
for i := range campaign.Rules {
|
|
campaign.Rules[i].CampaignID = campaign.ID
|
|
}
|
|
if err := tx.Create(&campaign.Rules).Error; err != nil {
|
|
return fmt.Errorf("failed to create campaign rules: %w", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (r *campaignRepository) Delete(ctx context.Context, id string) error {
|
|
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
// Delete campaign (rules will be deleted by CASCADE)
|
|
if err := tx.Where("id = ?", id).Delete(&entities.Campaign{}).Error; err != nil {
|
|
return fmt.Errorf("failed to delete campaign: %w", err)
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (r *campaignRepository) GetActiveCampaigns(ctx context.Context) ([]entities.Campaign, error) {
|
|
var campaigns []entities.Campaign
|
|
now := "now()"
|
|
if err := r.db.WithContext(ctx).Where("is_active = ? AND start_date <= ? AND end_date >= ?", true, now, now).Preload("Rules").Find(&campaigns).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get active campaigns: %w", err)
|
|
}
|
|
return campaigns, nil
|
|
}
|
|
|
|
func (r *campaignRepository) GetCampaignsForApp(ctx context.Context) ([]entities.Campaign, error) {
|
|
var campaigns []entities.Campaign
|
|
now := "now()"
|
|
if err := r.db.WithContext(ctx).Where("is_active = ? AND show_on_app = ? AND start_date <= ? AND end_date >= ?", true, true, now, now).Preload("Rules").Order("position ASC").Find(&campaigns).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get campaigns for app: %w", err)
|
|
}
|
|
return campaigns, nil
|
|
}
|
|
|
|
// Campaign Rule Repository
|
|
type CampaignRuleRepository interface {
|
|
Create(ctx context.Context, rule *entities.CampaignRule) error
|
|
GetByID(ctx context.Context, id string) (*entities.CampaignRule, error)
|
|
List(ctx context.Context, req *entities.ListCampaignRulesRequest) ([]entities.CampaignRule, int64, error)
|
|
Update(ctx context.Context, rule *entities.CampaignRule) error
|
|
Delete(ctx context.Context, id string) error
|
|
GetByCampaignID(ctx context.Context, campaignID string) ([]entities.CampaignRule, error)
|
|
}
|
|
|
|
type campaignRuleRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewCampaignRuleRepository(db *gorm.DB) CampaignRuleRepository {
|
|
return &campaignRuleRepository{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
func (r *campaignRuleRepository) Create(ctx context.Context, rule *entities.CampaignRule) error {
|
|
if err := r.db.WithContext(ctx).Create(rule).Error; err != nil {
|
|
return fmt.Errorf("failed to create campaign rule: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *campaignRuleRepository) GetByID(ctx context.Context, id string) (*entities.CampaignRule, error) {
|
|
var rule entities.CampaignRule
|
|
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&rule).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return nil, fmt.Errorf("campaign rule not found")
|
|
}
|
|
return nil, fmt.Errorf("failed to get campaign rule: %w", err)
|
|
}
|
|
return &rule, nil
|
|
}
|
|
|
|
func (r *campaignRuleRepository) List(ctx context.Context, req *entities.ListCampaignRulesRequest) ([]entities.CampaignRule, int64, error) {
|
|
var rules []entities.CampaignRule
|
|
var total int64
|
|
|
|
query := r.db.WithContext(ctx).Model(&entities.CampaignRule{})
|
|
|
|
// Apply filters
|
|
if req.CampaignID != "" {
|
|
query = query.Where("campaign_id = ?", req.CampaignID)
|
|
}
|
|
|
|
if req.RuleType != "" {
|
|
query = query.Where("rule_type = ?", req.RuleType)
|
|
}
|
|
|
|
if req.RewardType != "" {
|
|
query = query.Where("reward_type = ?", req.RewardType)
|
|
}
|
|
|
|
// Count total records
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, 0, fmt.Errorf("failed to count campaign rules: %w", err)
|
|
}
|
|
|
|
// Apply pagination
|
|
if req.Page > 0 && req.Limit > 0 {
|
|
offset := (req.Page - 1) * req.Limit
|
|
query = query.Offset(offset).Limit(req.Limit)
|
|
}
|
|
|
|
// Apply sorting
|
|
query = query.Order("created_at DESC")
|
|
|
|
if err := query.Find(&rules).Error; err != nil {
|
|
return nil, 0, fmt.Errorf("failed to list campaign rules: %w", err)
|
|
}
|
|
|
|
return rules, total, nil
|
|
}
|
|
|
|
func (r *campaignRuleRepository) Update(ctx context.Context, rule *entities.CampaignRule) error {
|
|
if err := r.db.WithContext(ctx).Save(rule).Error; err != nil {
|
|
return fmt.Errorf("failed to update campaign rule: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *campaignRuleRepository) Delete(ctx context.Context, id string) error {
|
|
if err := r.db.WithContext(ctx).Where("id = ?", id).Delete(&entities.CampaignRule{}).Error; err != nil {
|
|
return fmt.Errorf("failed to delete campaign rule: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *campaignRuleRepository) GetByCampaignID(ctx context.Context, campaignID string) ([]entities.CampaignRule, error) {
|
|
var rules []entities.CampaignRule
|
|
if err := r.db.WithContext(ctx).Where("campaign_id = ?", campaignID).Find(&rules).Error; err != nil {
|
|
return nil, fmt.Errorf("failed to get campaign rules by campaign ID: %w", err)
|
|
}
|
|
return rules, nil
|
|
}
|