telco_server/app/admin/service/bus_service/s_cooperative_manage.go

647 lines
18 KiB
Go
Raw Normal View History

2025-03-18 11:45:22 +00:00
package bus_service
import (
"context"
"errors"
"fmt"
2025-03-20 10:51:02 +00:00
log "github.com/go-admin-team/go-admin-core/logger"
2025-03-18 11:45:22 +00:00
"github.com/go-admin-team/go-admin-core/sdk/service"
2025-03-20 10:51:02 +00:00
"go-admin/app/admin/models"
2025-03-18 11:45:22 +00:00
"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
}
2025-03-20 10:51:02 +00:00
// 构建查询条件
2025-03-18 11:45:22 +00:00
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)
}
2025-03-20 10:51:02 +00:00
// 查询合作商基本信息
if err := db.Offset(page * req.PageSize).Limit(req.PageSize).Find(&cooperativeList).Error; err != nil {
2025-03-18 11:45:22 +00:00
return resp, errors.New("查询合作商列表失败")
}
2025-03-20 10:51:02 +00:00
// 获取所有合作商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]
}
2025-03-18 11:45:22 +00:00
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 {
2025-03-20 10:51:02 +00:00
// 打印 panic 错误信息
log.Error("Panic recovered: %v", r)
2025-03-18 11:45:22 +00:00
tx.Rollback()
}
}()
2025-03-20 10:51:02 +00:00
// 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-创建合作商
2025-03-18 11:45:22 +00:00
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,
2025-03-20 10:51:02 +00:00
UserId: userReq.UserId,
2025-03-18 11:45:22 +00:00
}
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 {
2025-03-20 10:51:02 +00:00
// 开始事务
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())
2025-03-18 11:45:22 +00:00
}
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
// 查询合作商基本信息
2025-03-20 10:51:02 +00:00
db := e.Orm.WithContext(ctx).Where("cooperative_number = ?", req.CooperativeNumber)
2025-03-18 11:45:22 +00:00
if err := db.First(&cooperative).Error; err != nil {
return resp, errors.New("查询合作商详情失败")
}
// 查询该合作商的产品信息
var cooperativeProducts []bus_models.BusCooperativeProduct
err := e.Orm.WithContext(ctx).
2025-03-20 10:51:02 +00:00
Where("cooperative_id = ?", cooperative.ID).
2025-03-18 11:45:22 +00:00
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
2025-03-20 10:51:02 +00:00
resp.CardHolder = cooperative.CardHolder
resp.Bank = cooperative.Bank
resp.CardID = cooperative.CardID
resp.TaxID = cooperative.TaxID
2025-03-18 11:45:22 +00:00
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
}
2025-03-20 10:51:02 +00:00
// 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("合作商账户不存在")
}
2025-03-21 08:40:10 +00:00
if req.Amount == 0 && req.GiftAmount == 0 {
return nil
}
2025-03-20 10:51:02 +00:00
// 确保 transaction_type = 2 (减款) 时,金额是负的
2025-03-21 08:40:10 +00:00
if req.TransactionType == 2 {
if req.Amount > 0 {
req.Amount = -req.Amount
}
if req.GiftAmount > 0 {
req.GiftAmount = -req.GiftAmount
}
2025-03-20 10:51:02 +00:00
}
// 加款时需要 SourceFundingType但减款时不需要
if req.TransactionType == 1 && req.SourceFundingType == 0 {
return errors.New("加款时必须填写资金来源")
}
// 计算新的余额
newBalance := cooperative.Balance
newFree := cooperative.Free
if req.TransactionType == 2 { // 处理减款
2025-03-21 08:40:10 +00:00
newBalance += req.Amount
newFree += req.GiftAmount
2025-03-20 10:51:02 +00:00
2025-03-21 08:40:10 +00:00
if cooperative.Balance < -req.Amount {
log.Info("账户余额不足,无法扣除普通余额")
2025-03-20 10:51:02 +00:00
newBalance = 0
}
2025-03-21 08:40:10 +00:00
if cooperative.Free < -req.GiftAmount {
log.Info("赠送余额不足,无法扣除赠送余额")
newFree = 0
}
2025-03-20 10:51:02 +00:00
} else { // 处理加款
newBalance += req.Amount
2025-03-21 08:40:10 +00:00
newFree += req.GiftAmount
2025-03-20 10:51:02 +00:00
}
// 开启事务,确保数据一致性
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,
2025-03-21 08:40:10 +00:00
Amount: req.Amount,
2025-03-20 10:51:02 +00:00
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
}
2025-03-21 08:40:10 +00:00
// 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
}