Add Campaign
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"apskel-pos-be/internal/entities"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type RewardRepository interface {
|
||||
Create(ctx context.Context, reward *entities.Reward) error
|
||||
GetByID(ctx context.Context, id string) (*entities.Reward, error)
|
||||
List(ctx context.Context, req *entities.ListRewardsRequest) ([]entities.Reward, int64, error)
|
||||
Update(ctx context.Context, reward *entities.Reward) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
UpdateStock(ctx context.Context, id string, newStock int) error
|
||||
GetByRewardType(ctx context.Context, rewardType entities.RewardType) ([]entities.Reward, error)
|
||||
}
|
||||
|
||||
type rewardRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewRewardRepository(db *gorm.DB) RewardRepository {
|
||||
return &rewardRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *rewardRepository) Create(ctx context.Context, reward *entities.Reward) error {
|
||||
if err := r.db.WithContext(ctx).Create(reward).Error; err != nil {
|
||||
return fmt.Errorf("failed to create reward: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *rewardRepository) GetByID(ctx context.Context, id string) (*entities.Reward, error) {
|
||||
var reward entities.Reward
|
||||
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&reward).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, fmt.Errorf("reward not found")
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get reward: %w", err)
|
||||
}
|
||||
return &reward, nil
|
||||
}
|
||||
|
||||
func (r *rewardRepository) List(ctx context.Context, req *entities.ListRewardsRequest) ([]entities.Reward, int64, error) {
|
||||
var rewards []entities.Reward
|
||||
var total int64
|
||||
|
||||
query := r.db.WithContext(ctx).Model(&entities.Reward{})
|
||||
|
||||
// Apply filters
|
||||
if req.Search != "" {
|
||||
query = query.Where("name ILIKE ?", "%"+req.Search+"%")
|
||||
}
|
||||
|
||||
if req.RewardType != "" {
|
||||
query = query.Where("reward_type = ?", req.RewardType)
|
||||
}
|
||||
|
||||
if req.MinPoints != nil {
|
||||
query = query.Where("cost_points >= ?", *req.MinPoints)
|
||||
}
|
||||
|
||||
if req.MaxPoints != nil {
|
||||
query = query.Where("cost_points <= ?", *req.MaxPoints)
|
||||
}
|
||||
|
||||
if req.HasStock != nil {
|
||||
if *req.HasStock {
|
||||
query = query.Where("stock > 0 OR stock IS NULL")
|
||||
} else {
|
||||
query = query.Where("stock <= 0")
|
||||
}
|
||||
}
|
||||
|
||||
// Count total records
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to count rewards: %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(&rewards).Error; err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to list rewards: %w", err)
|
||||
}
|
||||
|
||||
return rewards, total, nil
|
||||
}
|
||||
|
||||
func (r *rewardRepository) Update(ctx context.Context, reward *entities.Reward) error {
|
||||
if err := r.db.WithContext(ctx).Save(reward).Error; err != nil {
|
||||
return fmt.Errorf("failed to update reward: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *rewardRepository) Delete(ctx context.Context, id string) error {
|
||||
if err := r.db.WithContext(ctx).Where("id = ?", id).Delete(&entities.Reward{}).Error; err != nil {
|
||||
return fmt.Errorf("failed to delete reward: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *rewardRepository) UpdateStock(ctx context.Context, id string, newStock int) error {
|
||||
if err := r.db.WithContext(ctx).Model(&entities.Reward{}).Where("id = ?", id).Update("stock", newStock).Error; err != nil {
|
||||
return fmt.Errorf("failed to update reward stock: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *rewardRepository) GetByRewardType(ctx context.Context, rewardType entities.RewardType) ([]entities.Reward, error) {
|
||||
var rewards []entities.Reward
|
||||
if err := r.db.WithContext(ctx).Where("reward_type = ?", rewardType).Find(&rewards).Error; err != nil {
|
||||
return nil, fmt.Errorf("failed to get rewards by type: %w", err)
|
||||
}
|
||||
return rewards, nil
|
||||
}
|
||||
Reference in New Issue
Block a user