package service import ( "encoding/json" "fmt" "psi/database" "psi/models" systemReq "psi/models/request" systemRes "psi/models/response" "psi/utils" "time" "gorm.io/datatypes" "gorm.io/gorm" ) type SplitAccountDeductionLogService struct{} // GetSplitAccountDeductionLogList 获取分账扣钱日志列表 func (s *SplitAccountDeductionLogService) GetSplitAccountDeductionLogList(req systemReq.GetSplitAccountDeductionLogListRequest, db ...*gorm.DB) (*systemRes.SplitAccountDeductionLogListResponse, error) { databaseConn := database.OptionalDB(db...) if req.Page < 1 { req.Page = 1 } if req.PageSize < 1 || req.PageSize > 100 { req.PageSize = 20 } query := databaseConn.Model(&models.SplitAccountDeductionLog{}) if req.BusinessNo != "" { query = query.Where("business_no like ?", "%"+req.BusinessNo+"%") } if req.ConfigID != "" { query = query.Where("config_id = ?", req.ConfigID) } if req.StartCreatedAt != "" { query = query.Where("created_at >= ?", req.StartCreatedAt) } if req.EndCreatedAt != "" { query = query.Where("created_at <= ?", req.EndCreatedAt) } var total int64 if err := query.Count(&total).Error; err != nil { return nil, utils.NewError("查询总数失败") } var logs []models.SplitAccountDeductionLog offset := (req.Page - 1) * req.PageSize if err := query.Order("created_at DESC").Offset(offset).Limit(req.PageSize).Find(&logs).Error; err != nil { return nil, utils.NewError("查询分账扣钱日志列表失败") } var logItems []systemRes.SplitAccountDeductionLogItem for _, log := range logs { logItems = append(logItems, systemRes.ConvertSplitAccountDeductionLogToItem(log)) } return &systemRes.SplitAccountDeductionLogListResponse{ List: logItems, Total: total, Page: req.Page, PageSize: req.PageSize, }, nil } // GetSplitAccountDeductionLogDetail 获取分账扣钱日志详情 func (s *SplitAccountDeductionLogService) GetSplitAccountDeductionLogDetail(id int64, db ...*gorm.DB) (*models.SplitAccountDeductionLog, error) { databaseConn := database.OptionalDB(db...) var log models.SplitAccountDeductionLog result := databaseConn.Where("id = ?", id).First(&log) if result.Error != nil { return nil, utils.NewError("分账扣钱日志不存在") } return &log, nil } // CreateSplitAccountDeductionLog 创建分账扣钱日志 func (s *SplitAccountDeductionLogService) CreateSplitAccountDeductionLog(req systemReq.AddSplitAccountDeductionLogRequest, username string, db ...*gorm.DB) (int64, error) { databaseConn := database.OptionalDB(db...) var deductionDetails datatypes.JSON if req.DeductionDetails != "" { var temp interface{} if err := json.Unmarshal([]byte(req.DeductionDetails), &temp); err != nil { return 0, utils.NewError("扣款规则格式错误,不是合法的JSON") } deductionDetails, _ = json.Marshal(temp) } now := time.Now().Unix() log := models.SplitAccountDeductionLog{ BusinessNo: req.BusinessNo, ConfigID: req.ConfigID, ConfigName: req.ConfigName, DeductionDetails: deductionDetails, TotalAmount: *req.TotalAmount, DeductionAmount: *req.DeductionAmount, RemainingAmount: *req.RemainingAmount, CreatedBy: username, CreatedAt: now, UpdatedAt: now, } if err := databaseConn.Create(&log).Error; err != nil { return 0, utils.NewError("创建分账扣钱日志失败: " + err.Error()) } return log.ID, nil } // UpdateSplitAccountDeductionLog 更新分账扣钱日志 func (s *SplitAccountDeductionLogService) UpdateSplitAccountDeductionLog(req systemReq.UpdateSplitAccountDeductionLogRequest, username string, db ...*gorm.DB) error { databaseConn := database.OptionalDB(db...) var log models.SplitAccountDeductionLog result := databaseConn.Where("id = ?", req.ID).First(&log) if result.Error != nil { return utils.NewError("分账扣钱日志不存在") } updateData := make(map[string]interface{}) updateData["updated_at"] = time.Now().Unix() updateData["updated_by"] = username if req.BusinessNo != "" { updateData["business_no"] = req.BusinessNo } if req.ConfigID > 0 { updateData["config_id"] = req.ConfigID } if req.ConfigName != "" { updateData["config_name"] = req.ConfigName } if req.DeductionDetails != "" { var temp interface{} if err := json.Unmarshal([]byte(req.DeductionDetails), &temp); err != nil { return utils.NewError("扣款规则格式错误,不是合法的JSON") } deductionDetails, _ := json.Marshal(temp) updateData["deduction_details"] = datatypes.JSON(deductionDetails) } if req.TotalAmount > 0 { updateData["total_amount"] = req.TotalAmount } if req.DeductionAmount > 0 { updateData["deduction_amount"] = req.DeductionAmount } if req.RemainingAmount > 0 { updateData["remaining_amount"] = req.RemainingAmount } updateData["status"] = req.Status if err := databaseConn.Model(&log).Updates(updateData).Error; err != nil { return utils.NewError("更新分账扣钱日志失败: " + err.Error()) } return nil } // DeleteSplitAccountDeductionLog 删除分账扣钱日志 func (s *SplitAccountDeductionLogService) DeleteSplitAccountDeductionLog(req systemReq.DeleteSplitAccountDeductionLogRequest, username string, db ...*gorm.DB) error { databaseConn := database.OptionalDB(db...) var log models.SplitAccountDeductionLog result := databaseConn.Where("id = ?", req.ID).First(&log) if result.Error != nil { return utils.NewError("分账扣钱日志不存在") } if err := databaseConn.Delete(&log).Error; err != nil { return utils.NewError("删除分账扣钱日志失败: " + err.Error()) } return nil } // GetSplitAccountDeductionLogSummary 获取分账扣钱日志汇总 func (s *SplitAccountDeductionLogService) GetSplitAccountDeductionLogSummary(req systemReq.GetSplitAccountDeductionLogSummaryRequest, createdBy string, db ...*gorm.DB) (*systemRes.SplitAccountDeductionLogSummaryResponse, error) { databaseConn := database.OptionalDB(db...) if req.PageNum < 1 { req.PageNum = 1 } if req.PageSize < 1 || req.PageSize > 100 { req.PageSize = 20 } // 根据 createdBy 决定是否过滤 hasFilter := createdBy != "" // 先查询分组总数 var total int64 var countArgs []interface{} if hasFilter { countSQL := "SELECT COUNT(*) FROM (SELECT business_no FROM split_account_deduction_log WHERE created_by = ? GROUP BY business_no) AS t" countArgs = []interface{}{createdBy} fmt.Printf("[SQL] summary-count: %s | args: %v\n", countSQL, countArgs) if err := databaseConn.Raw(countSQL, countArgs...).Scan(&total).Error; err != nil { return nil, utils.NewError("查询汇总总数失败") } } else { countSQL := "SELECT COUNT(*) FROM (SELECT business_no FROM split_account_deduction_log GROUP BY business_no) AS t" fmt.Printf("[SQL] summary-count: %s\n", countSQL) if err := databaseConn.Raw(countSQL).Scan(&total).Error; err != nil { return nil, utils.NewError("查询汇总总数失败") } } // 查询分页数据 offset := (req.PageNum - 1) * req.PageSize type rawResult struct { BusinessNo string `gorm:"column:business_no"` ConfigName string `gorm:"column:config_name"` DeductionDetails datatypes.JSON `gorm:"column:deduction_details"` Total int64 `gorm:"column:total"` CreatedAt int64 `gorm:"column:created_at"` UpdatedAt int64 `gorm:"column:updated_at"` } var results []rawResult if hasFilter { dataSQL := `SELECT MAX(business_no) AS business_no, MAX(config_name) AS config_name, MAX(deduction_details) AS deduction_details, COUNT(*) AS total, MIN(created_at) AS created_at, MIN(updated_at) AS updated_at FROM split_account_deduction_log WHERE created_by = ? GROUP BY business_no ORDER BY business_no DESC LIMIT ? OFFSET ?` fmt.Printf("[SQL] summary-data: WHERE created_by = '%s' GROUP BY business_no ORDER BY business_no DESC LIMIT %d OFFSET %d\n", createdBy, req.PageSize, offset) if err := databaseConn.Raw(dataSQL, createdBy, req.PageSize, offset).Scan(&results).Error; err != nil { return nil, utils.NewError("查询分账扣钱日志汇总失败") } } else { dataSQL := `SELECT MAX(business_no) AS business_no, MAX(config_name) AS config_name, MAX(deduction_details) AS deduction_details, COUNT(*) AS total, MIN(created_at) AS created_at, MIN(updated_at) AS updated_at FROM split_account_deduction_log GROUP BY business_no ORDER BY business_no DESC LIMIT ? OFFSET ?` fmt.Printf("[SQL] summary-data: GROUP BY business_no ORDER BY business_no DESC LIMIT %d OFFSET %d\n", req.PageSize, offset) if err := databaseConn.Raw(dataSQL, req.PageSize, offset).Scan(&results).Error; err != nil { return nil, utils.NewError("查询分账扣钱日志汇总失败") } } var items []systemRes.SplitAccountDeductionLogSummaryItem for _, r := range results { var deductionDetails interface{} if r.DeductionDetails != nil { json.Unmarshal(r.DeductionDetails, &deductionDetails) } items = append(items, systemRes.SplitAccountDeductionLogSummaryItem{ BusinessNo: r.BusinessNo, ConfigName: r.ConfigName, DeductionDetails: deductionDetails, Total: r.Total, CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt, }) } return &systemRes.SplitAccountDeductionLogSummaryResponse{ List: items, Total: total, Page: req.PageNum, PageSize: req.PageSize, }, nil } // GetSplitAccountDeductionLogDetailList 获取分账扣钱日志详情列表 func (s *SplitAccountDeductionLogService) GetSplitAccountDeductionLogDetailList(req systemReq.GetSplitAccountDeductionLogDetailListRequest, createdBy string, db ...*gorm.DB) ([]systemRes.SplitAccountDeductionLogItem, error) { databaseConn := database.OptionalDB(db...) query := databaseConn.Where("business_no = ?", req.BusinessNo) if createdBy != "" { query = query.Where("created_by = ?", createdBy) fmt.Printf("[SQL] detail-list: SELECT * FROM split_account_deduction_log WHERE business_no = '%s' AND created_by = '%s' ORDER BY id ASC\n", req.BusinessNo, createdBy) } else { fmt.Printf("[SQL] detail-list: SELECT * FROM split_account_deduction_log WHERE business_no = '%s' ORDER BY id ASC\n", req.BusinessNo) } var logs []models.SplitAccountDeductionLog if err := query.Order("id ASC").Find(&logs).Error; err != nil { return nil, utils.NewError("查询分账扣钱日志详情列表失败") } var items []systemRes.SplitAccountDeductionLogItem for _, log := range logs { items = append(items, systemRes.ConvertSplitAccountDeductionLogToItem(log)) } return items, nil }