package bus_service import ( "context" "errors" "fmt" log "github.com/go-admin-team/go-admin-core/logger" "github.com/go-admin-team/go-admin-core/sdk/service" "go-admin/app/admin/models" "go-admin/app/admin/models/bus_models" "go-admin/common/global" "gorm.io/gorm" "math/rand" "time" ) type CooperativeService struct { service.Service } // GetCooperativeList 获取合作商列表 func (e *CooperativeService) GetCooperativeList(ctx context.Context, req bus_models.CooperativeListReq) ( bus_models.CooperativeListResp, error) { var cooperativeList []bus_models.BusCooperative var resp bus_models.CooperativeListResp page := req.Page - 1 if page < 0 { page = 0 } if req.PageSize == 0 { req.PageSize = 10 } // 构建查询条件 db := e.Orm.WithContext(ctx) if req.CooperativeNumber != "" { db = db.Where("cooperative_number = ?", req.CooperativeNumber) } if req.CooperativeName != "" { db = db.Where("cooperative_name LIKE ?", "%"+req.CooperativeName+"%") } if req.Status != 0 { db = db.Where("status = ?", req.Status) } // 查询合作商基本信息 if err := db.Offset(page * req.PageSize).Limit(req.PageSize).Find(&cooperativeList).Error; err != nil { return resp, errors.New("查询合作商列表失败") } // 获取所有合作商ID var cooperativeIDs []uint64 for _, c := range cooperativeList { cooperativeIDs = append(cooperativeIDs, c.ID) } // 查询所有关联的产品信息 var cooperativeProducts []bus_models.BusCooperativeProduct if len(cooperativeIDs) > 0 { err := e.Orm.WithContext(ctx). Where("cooperative_id IN (?)", cooperativeIDs). Find(&cooperativeProducts).Error if err != nil { return resp, errors.New("查询合作商产品信息失败") } } // 获取所有产品ID var productIDs []uint64 for _, cp := range cooperativeProducts { productIDs = append(productIDs, cp.ProductID) } // 查询产品详细信息 var products []bus_models.BusProduct if len(productIDs) > 0 { err := e.Orm.WithContext(ctx). Where("id IN (?)", productIDs). Find(&products).Error if err != nil { return resp, errors.New("查询产品信息失败") } } // 构建合作商ID到产品信息的映射 productMap := make(map[uint64][]bus_models.ProductDetail) for _, cp := range cooperativeProducts { for _, p := range products { if p.ID == cp.ProductID { productMap[cp.CooperativeID] = append(productMap[cp.CooperativeID], bus_models.ProductDetail{ ProductCode: p.ProductCode, ProductName: p.ProductName, Discount: cp.Discount, ProductID: p.ID, }) break } } } // 组装返回数据 for i := range cooperativeList { cooperativeList[i].Products = productMap[cooperativeList[i].ID] } resp.List = cooperativeList resp.Total = len(cooperativeList) resp.Page = page + 1 resp.PageSize = req.PageSize return resp, nil } // CreateCooperative 新建合作商(使用事务) func (e *CooperativeService) CreateCooperative(req bus_models.CreateCooperativeReq) (bus_models.CreateCooperativeResp, error) { var resp bus_models.CreateCooperativeResp // 开启事务 tx := e.Orm.Begin() defer func() { if r := recover(); r != nil { // 打印 panic 错误信息 log.Error("Panic recovered: %v", r) tx.Rollback() } }() // 1-新建系统用户 // 查询 role_id var roleID int err := tx.Model(&models.SysRole{}). Select("role_id"). Where("role_name = ?", global.CooperativeRoleName). Where("status = ?", global.SysRoleStatusOnUse). // 确保角色状态为正常 First(&roleID).Error if err != nil || roleID == 0 { tx.Rollback() return resp, errors.New("系统未创建合作商角色") } // **调用创建用户接口** var userPhone string if req.Tel == "" { userPhone = "13966668888" } else { userPhone = req.Tel } var sysUser models.SysUser var count int64 // 检查用户名是否已存在 err = tx.Model(&sysUser).Where("username = ?", req.Account).Count(&count).Error if err != nil { tx.Rollback() // 出现错误时回滚 return resp, errors.New("数据库错误:" + err.Error()) } if count > 0 { tx.Rollback() // 用户名已存在,回滚事务 return resp, errors.New("用户名已存在") } // 创建SysUser对象并插入 userReq := models.SysUser{ Username: req.Account, // 使用合作商账户作为用户名 Password: req.Password, // 直接使用合作商密码(前端已加密) NickName: req.CooperativeName, // 用合作商名称作为昵称 Phone: userPhone, // 绑定手机号 Email: userPhone + "@mail.com", // 默认邮箱 DeptId: global.DefaultDeptId, // 默认部门ID Status: global.SysUserStatusOnUse, // 默认状态 RoleId: roleID, // 默认角色ID } err = tx.Create(&userReq).Error if err != nil { tx.Rollback() // 创建用户失败,回滚事务 return resp, errors.New("创建用户失败:" + err.Error()) } // 2-创建合作商 cooperative := bus_models.BusCooperative{ CooperativeName: req.CooperativeName, Contact: req.Contact, Tel: req.Tel, Status: global.CooperativeStatusOnUse, Account: req.Account, Password: req.Password, Balance: req.Balance, Free: req.Free, Bond: req.Bond, CardHolder: req.CardHolder, Bank: req.Bank, CardID: req.CardID, TaxID: req.TaxID, UserId: userReq.UserId, } cooperative.CooperativeNumber, err = GenerateCooperativeNumber(e.Orm) if err != nil { return resp, err } if err := tx.Create(&cooperative).Error; err != nil { tx.Rollback() return resp, errors.New("创建合作商失败") } // 插入合作商产品信息 var cooperativeProducts []bus_models.BusCooperativeProduct for _, product := range req.Products { cooperativeProducts = append(cooperativeProducts, bus_models.BusCooperativeProduct{ CooperativeID: cooperative.ID, ProductID: product.ProductID, Discount: product.Discount, }) } if len(cooperativeProducts) > 0 { if err := tx.Create(&cooperativeProducts).Error; err != nil { tx.Rollback() return resp, errors.New("创建合作商产品失败") } } // 提交事务 if err := tx.Commit().Error; err != nil { return resp, errors.New("提交事务失败") } resp.CooperativeNumber = cooperative.CooperativeNumber return resp, nil } func (e *CooperativeService) EditCooperative(req bus_models.EditCooperativeReq) error { // 开启事务 tx := e.Orm.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 查找合作商 var cooperative bus_models.BusCooperative if err := tx.Where("cooperative_number = ?", req.CooperativeNumber).First(&cooperative).Error; err != nil { tx.Rollback() return errors.New("合作商不存在") } // 更新合作商信息 updateData := map[string]interface{}{ "cooperative_name": req.CooperativeName, "contact": req.Contact, "tel": req.Tel, "status": req.Status, "account": req.Account, "balance": req.Balance, "free": req.Free, "bond": req.Bond, "card_holder": req.CardHolder, "bank": req.Bank, "card_id": req.CardID, "tax_id": req.TaxID, } if req.Password != "" { updateData["password"] = req.Password } if err := tx.Model(&bus_models.BusCooperative{}).Where("cooperative_number = ?", req.CooperativeNumber). Updates(updateData).Error; err != nil { tx.Rollback() return errors.New("更新合作商信息失败") } // 获取数据库中的旧产品数据 var existingProducts []bus_models.BusCooperativeProduct tx.Where("cooperative_id = ?", cooperative.ID).Find(&existingProducts) // 旧数据转换为 map (ProductID => Discount) existingMap := make(map[uint64]float64) for _, p := range existingProducts { existingMap[p.ProductID] = p.Discount } // 计算需要更新、删除、插入的数据 newProductMap := make(map[uint64]float64) // (ProductID => Discount) var newProducts []bus_models.BusCooperativeProduct for _, product := range req.Products { newProductMap[product.ProductID] = product.Discount // 如果是新产品,或者折扣变化,则需要插入/更新 if discount, exists := existingMap[product.ProductID]; !exists || discount != product.Discount { newProducts = append(newProducts, bus_models.BusCooperativeProduct{ CooperativeID: cooperative.ID, ProductID: product.ProductID, Discount: product.Discount, }) } } // 删除不存在于新数据中的旧产品 var productIDsToDelete []uint64 for oldProductID := range existingMap { if _, exists := newProductMap[oldProductID]; !exists { productIDsToDelete = append(productIDsToDelete, oldProductID) } } if len(productIDsToDelete) > 0 { tx.Where("cooperative_id = ? AND product_id IN ?", cooperative.ID, productIDsToDelete).Delete(&bus_models.BusCooperativeProduct{}) } // 插入新的或有折扣变化的产品 if len(newProducts) > 0 { if err := tx.Create(&newProducts).Error; err != nil { tx.Rollback() return errors.New("添加/更新合作商产品信息失败") } } // 提交事务 if err := tx.Commit().Error; err != nil { return errors.New("提交事务失败") } return nil } // DeleteCooperative 删除合作商 func (e *CooperativeService) DeleteCooperative(req bus_models.DeleteCooperativeReq) error { // 开始事务 tx := e.Orm.Begin() // 1. 查询合作商的user_id var cooperative bus_models.BusCooperative err := tx.Where("cooperative_number = ?", req.CooperativeNumber).First(&cooperative).Error if err != nil { tx.Rollback() // 如果查询失败,回滚事务 return errors.New("查询合作商失败:" + err.Error()) } // 2. 如果user_id != 0,删除sys_user中的用户 if cooperative.UserId != 0 { var sysUser models.SysUser err = tx.Where("user_id = ?", cooperative.UserId).Delete(&sysUser).Error if err != nil { tx.Rollback() // 删除用户失败,回滚事务 return errors.New("删除用户失败:" + err.Error()) } } // 3. 删除合作商 err = tx.Where("cooperative_number = ?", req.CooperativeNumber).Delete(&bus_models.BusCooperative{}).Error if err != nil { tx.Rollback() // 删除合作商失败,回滚事务 return errors.New("删除合作商失败:" + err.Error()) } // 4. 提交事务 err = tx.Commit().Error if err != nil { tx.Rollback() // 提交事务失败,回滚 return errors.New("提交事务失败:" + err.Error()) } return nil } // GetCooperativeDetail 获取合作商详细信息,包括产品信息 func (e *CooperativeService) GetCooperativeDetail(ctx context.Context, req bus_models.CooperativeDetailReq) ( bus_models.CooperativeDetailResp, error) { var resp bus_models.CooperativeDetailResp var cooperative bus_models.BusCooperative // 查询合作商基本信息 db := e.Orm.WithContext(ctx).Where("cooperative_number = ?", req.CooperativeNumber) if err := db.First(&cooperative).Error; err != nil { return resp, errors.New("查询合作商详情失败") } // 查询该合作商的产品信息 var cooperativeProducts []bus_models.BusCooperativeProduct err := e.Orm.WithContext(ctx). Where("cooperative_id = ?", cooperative.ID). Find(&cooperativeProducts).Error if err != nil { return resp, errors.New("查询合作商产品信息失败") } // 根据产品ID查询产品名称和编码 var productIDs []uint64 for _, cp := range cooperativeProducts { productIDs = append(productIDs, cp.ProductID) } // 查询产品详细信息 var products []bus_models.BusProduct if len(productIDs) > 0 { err = e.Orm.WithContext(ctx). Where("id IN (?)", productIDs). Find(&products).Error if err != nil { return resp, errors.New("查询产品信息失败") } } // 将产品信息填充到响应中 var productDetails []bus_models.ProductDetail for _, cp := range cooperativeProducts { // 查找对应产品 for _, p := range products { if p.ID == cp.ProductID { // 确保ID匹配 productDetails = append(productDetails, bus_models.ProductDetail{ ProductCode: p.ProductCode, ProductName: p.ProductName, Discount: cp.Discount, }) break } } } // 填充合作商信息 resp.CooperativeNumber = cooperative.CooperativeNumber resp.CooperativeName = cooperative.CooperativeName resp.Contact = cooperative.Contact resp.Tel = cooperative.Tel resp.Status = cooperative.Status resp.Account = cooperative.Account resp.Balance = cooperative.Balance resp.Free = cooperative.Free resp.Bond = cooperative.Bond resp.CardHolder = cooperative.CardHolder resp.Bank = cooperative.Bank resp.CardID = cooperative.CardID resp.TaxID = cooperative.TaxID resp.Products = productDetails return resp, nil } // GenerateCooperativeNumber 生成唯一的合作商编号,日期 + 10位随机数 func GenerateCooperativeNumber(db *gorm.DB) (string, error) { // 获取当前日期(年月日) dateStr := time.Now().Format("20060102") // 格式为:YYYYMMDD // 生成一个10位随机数 rand.Seed(time.Now().UnixNano()) // 设置随机数种子 randomNum := rand.Int63n(10000000000) // 生成一个0到9999999999之间的随机数 // 将随机数转为固定长度的字符串,确保10位 randomNumStr := fmt.Sprintf("%010d", randomNum) // 确保为10位,不足补零 // 拼接日期和随机数 cooperativeNumber := fmt.Sprintf("%s%s", dateStr, randomNumStr) // 检查生成的合作商编号是否已存在 var count int64 err := db.Model(&bus_models.BusCooperative{}).Where("cooperative_number = ?", cooperativeNumber).Count(&count).Error if err != nil { return "", err } // 如果已存在,重新生成 if count > 0 { return GenerateCooperativeNumber(db) // 递归重新生成 } return cooperativeNumber, nil } // AdjustAccount 账户调整(加款/减款) func (e *CooperativeService) AdjustAccount(ctx context.Context, req bus_models.AdjustAccountReq) error { var cooperative bus_models.BusCooperative db := e.Orm.WithContext(ctx) // 查询合作商账户信息 if err := db.Where("cooperative_number = ?", req.CooperativeNumber).First(&cooperative).Error; err != nil { return errors.New("合作商账户不存在") } if req.Amount == 0 && req.GiftAmount == 0 { return nil } // 确保 transaction_type = 2 (减款) 时,金额是负的 if req.TransactionType == 2 { if req.Amount > 0 { req.Amount = -req.Amount } if req.GiftAmount > 0 { req.GiftAmount = -req.GiftAmount } } // 加款时需要 SourceFundingType,但减款时不需要 if req.TransactionType == 1 && req.SourceFundingType == 0 { return errors.New("加款时必须填写资金来源") } // 计算新的余额 newBalance := cooperative.Balance newFree := cooperative.Free if req.TransactionType == 2 { // 处理减款 newBalance += req.Amount newFree += req.GiftAmount if cooperative.Balance < -req.Amount { log.Info("账户余额不足,无法扣除普通余额") newBalance = 0 } if cooperative.Free < -req.GiftAmount { log.Info("赠送余额不足,无法扣除赠送余额") newFree = 0 } } else { // 处理加款 newBalance += req.Amount newFree += req.GiftAmount } // 开启事务,确保数据一致性 tx := db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 更新合作商账户余额 if err := tx.Model(&cooperative).Updates(map[string]interface{}{ "balance": newBalance, "free": newFree, }).Error; err != nil { tx.Rollback() return errors.New("更新账户余额失败") } // 记录交易信息 transaction := bus_models.BusCooperativeTransaction{ CooperativeID: cooperative.ID, Amount: req.Amount, GiftAmount: req.GiftAmount, SourceFundingType: req.SourceFundingType, Remark: req.Remark, } if err := tx.Create(&transaction).Error; err != nil { tx.Rollback() return errors.New("记录交易失败") } tx.Commit() return nil } // SetCooperativeStatus 在服务层更新合作商状态 func (e *CooperativeService) SetCooperativeStatus(req bus_models.SetCooperativeStatusReq) error { return e.Orm.Model(&bus_models.BusCooperative{}). Where("cooperative_number = ?", req.CooperativeNumber). Update("status", req.Status).Error } // QueryCooperativeProducts 查询合作商产品列表 func (e *CooperativeService) QueryCooperativeProducts(req bus_models.QueryCooperativeProductsReq) (*bus_models.QueryCooperativeProductsResp, error) { var cooperative bus_models.BusCooperative page := req.Page - 1 if page < 0 { page = 0 } if req.PageSize == 0 { req.PageSize = 10 } err := e.Orm.Where("cooperative_number = ?", req.CooperativeNumber).First(&cooperative).Error if err != nil { return nil, errors.New("合作商不存在") } var products []bus_models.ProductInfo var total int64 query := e.Orm.Table("bus_cooperative_product as cp"). Joins("JOIN bus_product as p ON cp.product_id = p.id"). Where("cp.cooperative_id = ?", cooperative.ID) // 获取总数 query.Count(&total) // 查询分页数据 query.Select("p.id as product_id,p.product_code, p.product_name, p.product_type, p.type, p.size, p.price, cp.discount, " + "p.retail_price, p.description, p.province, p.city, p.platform"). Offset(page * req.PageSize). Limit(req.PageSize). Find(&products) return &bus_models.QueryCooperativeProductsResp{ Total: int(total), Page: page + 1, PageSize: req.PageSize, List: products, }, nil } // UpdateCooperativeProductDiscount 批量更新合作商产品折扣 func (e *CooperativeService) UpdateCooperativeProductDiscount(req bus_models.UpdateProductDiscountReq) error { if len(req.Products) == 0 { return errors.New("产品列表不能为空") } var cooperative bus_models.BusCooperative err := e.Orm.Where("cooperative_number = ?", req.CooperativeNumber).First(&cooperative).Error if err != nil { return errors.New("合作商不存在") } tx := e.Orm.Begin() // 开始事务 for _, p := range req.Products { if p.Discount < 0 || p.Discount > 1 { tx.Rollback() return fmt.Errorf("产品ID %d 的折扣值不合法,必须在 0-1 之间", p.ProductID) } err := tx.Model(&bus_models.BusCooperativeProduct{}). Where("cooperative_id = ? AND product_id = ?", cooperative.ID, p.ProductID). Update("discount", p.Discount).Error if err != nil { tx.Rollback() return fmt.Errorf("更新产品ID %d 失败: %v", p.ProductID, err) } } if err := tx.Commit().Error; err != nil { tx.Rollback() return fmt.Errorf("提交事务失败: %v", err) } return nil }