package service import ( "errors" "github.com/gin-gonic/gin" "go.uber.org/zap" "gorm.io/gorm" "log" "sfbase/global" "sfbase/utils" "sfis/db" "sfis/lock" "sfis/model" "sfis/model/response" "strconv" "sync" "time" ) func CreateUserProduct(appId string, productArr []map[string]interface{}, buyType int) (status int, haveProductId string, err error) { //取出用户锁 lock.MainLock.Lock() userLock := lock.UserLockMap[appId] lock.MainLock.Unlock() userLock.Lock() defer userLock.Unlock() var errs error haveProductId = "" //已经购买过的产品id for _, val := range productArr { productId := utils.IntAll(val["productId"]) costModel := utils.IntAll(val["costModel"]) leftNum := utils.IntAll(val["leftNum"]) tradeMoney := utils.IntAll(val["tradeMoney"]) * 100 userProduct := &model.UserProduct{} userProduct.AppID = appId userProduct.StartAt, _ = time.ParseInLocation("2006-01-02 15:04:05", utils.ObjToString(val["startTime"]), time.Local) userProduct.EndAt, _ = time.ParseInLocation("2006-01-02 15:04:05", utils.ObjToString(val["endTime"]), time.Local) userProduct.LeftNum = leftNum userProduct.CostModel = costModel userProduct.InterfaceStatus = utils.IntAll(val["interfaceStatus"]) userProduct.CallTimesLimitDay = utils.IntAll(val["callTimesLimitDay"]) userProduct.DataNumLimitOneTimes = utils.IntAll(val["dataNumOneTimes"]) userProduct.ProductID = productId userProductInfo := model.UserProduct{} product := model.Product{} //查询产品信息,获取购买时候产品单价、试用次数 err := db.GetSFISDB().Where("id = ?", productId).Find(&product).Error if err != nil { global.Logger.Error("CreateUserProduct查询product表出错:", zap.Any("err:", err)) return 0, haveProductId, err } historyUnitPrice := product.UnitPrice err = db.GetSFISDB().Where("product_id = ? and app_id = ?", productId, appId).Find(&userProductInfo).Error if err != nil { global.Logger.Error("CreateUserProduct查询user_product表出错:", zap.Any("err:", err)) return 0, haveProductId, err } //用户第一次购买产品 if userProductInfo.ID == 0 { errs = db.GetSFISDB().Transaction(func(tx *gorm.DB) error { rechargeAmount := 0 remark := "" //第一次购买产品赠送试用量 testNum := product.TestNum //扣费类型为扣余额,user_buy_record中tradeMoney金额为0 if costModel == 0 { rechargeAmount = tradeMoney leftNum += testNum } else if costModel == 1 { leftNum = 0 //扣余额,把赠送量转化成金额 freeMoney := testNum * product.UnitPrice log.Println(freeMoney, "freeMoney") remark = "充值金额为:" + strconv.Itoa(tradeMoney) + ",赠送金额为:" + strconv.Itoa(freeMoney) tradeMoney += freeMoney } userProduct.LeftNum = leftNum //生用户产品 err := tx.Create(userProduct).Error if err != nil { log.Printf("appID:[%s],productId:[%d] execute insert user_product error:[%v]", appId, productId, err) tx.Rollback() return err } userProductId := userProduct.ID //生成购买产品记录 err = tx.Exec("insert into user_buy_record (`app_id`,`product_id`,`user_product_id`,`before`,`after`,`trade_money`,`buy_type`,`history_unit_price`) values (?,?,?,?,?,?,?,?)", appId, productId, userProductId, 0, leftNum, rechargeAmount, buyType, historyUnitPrice).Error if err != nil { log.Printf("appID:[%s],productId[%d],trade_money:[%d] execute insert into user_buy_record error:[%v]", appId, productId, tradeMoney, err) tx.Rollback() return err } //扣费类型是扣余额,充值用户余额 if costModel == 1 { userAccount := model.UserAccount{} err = tx.First(&userAccount, model.UserAccount{AppID: appId}).Error if err != nil { log.Printf("appID:[%s],productId[%d],trade_money:[%d] execute find user_account error:[%v]", appId, productId, tradeMoney, err) tx.Rollback() return err } moneyBefore := userAccount.Money moneyAfter := userAccount.Money + tradeMoney //充值 err := tx.Exec("update user_account set money = ? WHERE `app_id` = ?", moneyAfter, appId).Error if err != nil { log.Printf("appID:[%s],money:[%d] execute update user_account error:[%v]", appId, moneyAfter, err) tx.Rollback() return err } //生充值记录 err = tx.Exec("insert into user_money_record (app_id,`before`,`after`,trade_money,remark) values (?,?,?,?,?)", appId, moneyBefore, moneyAfter, tradeMoney, remark).Error if err != nil { log.Printf("appID:[%s],trade_money:[%d] execute insert into user_money_record error:[%v]", appId, tradeMoney, err) tx.Rollback() return err } } return nil }) if errs == nil { global.Logger.Info("用户已购买产品失败:", zap.Any("appId:", appId), zap.Any("productId:", productId)) continue } } else { haveProductId += "[" + strconv.Itoa(productId) + "]" global.Logger.Info("用户已购买过该产品", zap.Any("appId:", appId), zap.Any("productId:", productId)) continue } } return 1, haveProductId, nil } func UserProductList(appId string, c *gin.Context) { userProduct := []model.UserProduct{} err := db.GetSFISDB().Where("app_id = ? and ", appId).Find(&userProduct).Error if err != nil { log.Printf("appID:[%s] find into user_product error:[%v]", appId, err) response.FailWithMessage("查询出错", c) } else { response.OkWithData(userProduct, c) } } //创建用户 func CreateUser(user model.User) (model.User, error) { var tempUser []model.User // 判断用户名是否重复 db.GetSFISDB().Where("name = ?", user.Name).Find(&tempUser) if len(tempUser) > 0 { global.Logger.Error("userCreate Error", zap.Any("user", user), zap.Any("error", "用户名已存在")) return user, errors.New("用户名已存在") } // 判断手机号是否重复 var tempUser_ []model.User db.GetSFISDB().Where("phone = ?", user.Phone).Find(&tempUser_) if len(tempUser_) > 0 { global.Logger.Error("userCreate Error", zap.Any("user", user), zap.Any("error", "手机号已存在")) return user, errors.New("手机号已存在") } errs := db.GetSFISDB().Transaction(func(tx *gorm.DB) error { // 新增用户 err := tx.Create(&user).Error if err != nil { global.Logger.Error("userCreate Error", zap.Any("user", user), zap.Any("error", err)) tx.Rollback() return err } // 初始化用户账户 userAccount := model.UserAccount{AppID: user.AppID, Money: 0} err = tx.Create(&userAccount).Error if err != nil { global.Logger.Error("userAccountInit Error", zap.Any("user", user), zap.Any("userAccount", userAccount), zap.Any("error", err)) tx.Rollback() return err } return nil }) if errs != nil { global.Logger.Error("userCreate Error", zap.Any("user", user), zap.Any("error", errs)) return user, errors.New("创建失败") } else { global.Logger.Info("userCreate Success", zap.Any("user", user)) // 生全局内存锁 lock.MainLock.Lock() lock.UserLockMap[user.AppID] = &sync.Mutex{} lock.MainLock.Unlock() return user, nil } }