diff --git a/app/db/db_master_amount.go b/app/db/db_master_amount.go index ed2882e..e5203fc 100644 --- a/app/db/db_master_amount.go +++ b/app/db/db_master_amount.go @@ -2,6 +2,7 @@ package db import ( "applet/app/db/model" + "applet/app/utils" "time" "xorm.io/xorm" ) @@ -23,6 +24,14 @@ func (masterAmountDb *MasterAmountDb) GetMasterAmount(id, types string) *model.M } return &data } +func (masterAmountDb *MasterAmountDb) GetMasterAmountList(args map[string]string) *[]model.MasterAmount { + var data = make([]model.MasterAmount, 0) + size := utils.StrToInt(args["size"]) + offet := (utils.StrToInt(args["p"]) - 1) * size + sess := masterAmountDb.Db.Where("last_month_amount>0") + sess.Limit(size, offet).OrderBy("id desc").Find(&data) + return &data +} func (masterAmountDb *MasterAmountDb) GetMasterAmountByListId(id string) *model.MasterAmount { var data model.MasterAmount get, err := masterAmountDb.Db.Where("id=?", id).Get(&data) diff --git a/app/db/db_master_last_month_amount_list.go b/app/db/db_master_last_month_amount_list.go new file mode 100644 index 0000000..93b1c27 --- /dev/null +++ b/app/db/db_master_last_month_amount_list.go @@ -0,0 +1,36 @@ +package db + +import ( + "applet/app/db/model" + "xorm.io/xorm" +) + +type MasterLastMonthAmountFlowDb struct { + Db *xorm.Engine `json:"db"` +} + +func (masterLastMonthAmountFlowDb *MasterLastMonthAmountFlowDb) Set() { // set方法 + masterLastMonthAmountFlowDb.Db = ZhimengDb +} + +func (masterLastMonthAmountFlowDb *MasterLastMonthAmountFlowDb) MasterLastMonthAmountListUpdate(id int, data *model.MasterLastMonthAmountFlow) bool { + get, err := masterLastMonthAmountFlowDb.Db.Where("id=?", id).Update(data) + if get == 0 || err != nil { + return false + } + return true +} +func (masterLastMonthAmountFlowDb *MasterLastMonthAmountFlowDb) MasterLastMonthAmountFlowInsert(data *model.MasterLastMonthAmountFlow) bool { + get, err := masterLastMonthAmountFlowDb.Db.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} +func MasterLastMonthAmountFlowInsertWithSess(sess *xorm.Session, data *model.MasterLastMonthAmountFlow) bool { + get, err := sess.InsertOne(data) + if get == 0 || err != nil { + return false + } + return true +} diff --git a/app/db/db_playlet_sale_order.go b/app/db/db_playlet_sale_order.go index f369fcb..62d4b14 100644 --- a/app/db/db_playlet_sale_order.go +++ b/app/db/db_playlet_sale_order.go @@ -3,6 +3,7 @@ package db import ( "applet/app/db/model" "applet/app/utils" + "fmt" "time" "xorm.io/xorm" ) @@ -64,6 +65,8 @@ func (playletSaleOrderDb *PlayletSaleOrderDb) GetPlayletVideoOrderList(args map[ settle_status 结算状态 oid 订单号 sort 排序 + is_to_settle 智盟结算 + to_settle_time 结算上月时间 */ var data = make([]model.PlayletSaleOrder, 0) size := utils.StrToInt(args["size"]) @@ -75,12 +78,19 @@ func (playletSaleOrderDb *PlayletSaleOrderDb) GetPlayletVideoOrderList(args map[ if args["end_time"] != "" { sess = sess.And("update_time>=?", args["end_time"]) } + if args["to_settle_time"] != "" { + sess = sess.And("create_time 0 { + e.OutErr(c, 400, e.NewErr(400, "每月"+withdrawalDay+"号提现")) + return + } var fee float64 = 0 if utils.StrToFloat64(withdrawalBili) > 0 { bili := utils.StrToFloat64(withdrawalBili) / 100 diff --git a/app/svc/svc_file_upload.go b/app/svc/svc_file_upload.go new file mode 100644 index 0000000..df57546 --- /dev/null +++ b/app/svc/svc_file_upload.go @@ -0,0 +1,68 @@ +package svc + +import ( + "applet/app/db" + "applet/app/e" + "applet/app/lib/qiniu" + "applet/app/md" + "applet/app/utils" + "errors" + "fmt" + "github.com/gin-gonic/gin" + "strings" + "time" +) + +// 请求文件上传 +func ImgReqUpload(c *gin.Context, uid, dirName, fname, callbackUrl string, fsize int64) (interface{}, error) { + ext := utils.FileExt(fname) + if err := initStg(c, fsize, ext); err != nil { + return nil, err + } + pureFileName := strings.Replace(fname, "."+ext, "", 1) + pureFileName += "-" + utils.RandString(6, utils.AnyToString(time.Now().UnixNano())) + newName := dirName + "/" + pureFileName + "." + ext + + f := &md.FileCallback{ + Uid: uid, + DirId: dirName, + FileName: newName, + } + return qiniu.ReqImgUpload(f, callbackUrl), nil +} + +func initStg(c *gin.Context, fsize int64, ext string) error { + // 获取上传配置 + fileCfg := make(map[string]string) + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + fileCfg[md.KEY_CFG_FILE_BUCKET] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_BUCKET) + fileCfg[md.KEY_CFG_FILE_HOST] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_HOST) + fileCfg[md.KEY_CFG_FILE_AK] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_AK) + fileCfg[md.KEY_CFG_FILE_SK] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_SK) + fileCfg[md.KEY_CFG_FILE_PVD] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_PVD) + fileCfg[md.KEY_CFG_FILE_MAX_SIZE] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_MAX_SIZE) + fileCfg[md.KEY_CFG_FILE_EXT] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_EXT) + fileCfg[md.KEY_CFG_FILE_SCHEME] = masterListCfgDb.MasterListCfgGetOneData("0", md.KEY_CFG_FILE_SCHEME) + utils.FilePutContents("initStg", fmt.Sprintf("[KEY_CFG_FILE_BUCKET]:%s ; [KEY_CFG_FILE_HOST]:%s ; [KEY_CFG_FILE_AK]::%s;"+ + " [KEY_CFG_FILE_SK]::%s, ;[KEY_CFG_FILE_PVD]::%s, ;[KEY_CFG_FILE_REGION]::%s, ;[KEY_CFG_FILE_MAX_SIZE]::%s, ;[KEY_CFG_FILE_EXT]::%s, ;[KEY_CFG_FILE_SCHEME]::%s, "+ + ">>>>>>>>>>>>>>>>>>>>", fileCfg[md.KEY_CFG_FILE_BUCKET], fileCfg[md.KEY_CFG_FILE_HOST], fileCfg[md.KEY_CFG_FILE_AK], fileCfg[md.KEY_CFG_FILE_SK], + fileCfg[md.KEY_CFG_FILE_PVD], fileCfg[md.KEY_CFG_FILE_REGION], fileCfg[md.KEY_CFG_FILE_MAX_SIZE], fileCfg[md.KEY_CFG_FILE_EXT], fileCfg[md.KEY_CFG_FILE_SCHEME])) + for _, v := range fileCfg { + if v == "" { + return errors.New("上传配置不完整") + } + } + + qiniu.Init(fileCfg[md.KEY_CFG_FILE_AK], fileCfg[md.KEY_CFG_FILE_SK], fileCfg[md.KEY_CFG_FILE_BUCKET], fileCfg[md.KEY_CFG_FILE_REGION], fileCfg[md.KEY_CFG_FILE_SCHEME]) + + // 检查文件大小限制 + if utils.StrToInt64(fileCfg[md.KEY_CFG_FILE_MAX_SIZE]) < fsize { + return e.NewErrCode(e.ERR_FILE_MAX_SIZE) + } + // 检查文件后缀 + if !strings.Contains(fileCfg[md.KEY_CFG_FILE_EXT], ext) { + return e.NewErrCode(e.ERR_FILE_EXT) + } + return nil +} diff --git a/app/task/init.go b/app/task/init.go index 38dbb54..b13da38 100644 --- a/app/task/init.go +++ b/app/task/init.go @@ -91,4 +91,8 @@ func initTasks() { jobs[taskMd.ZhimengCronPlayletAdvOrderYesterDay] = taskPlayletAdvOrderYesterday // jobs[taskMd.ZhimengCronPlayletAdvOrderYesterDayToMoney] = taskPlayletAdvOrderYesterdayToMoney // jobs[taskMd.ZhimengCronPlayletGoods] = taskPlayletGoods // + + jobs[taskMd.ZhimengCronPlayletOrderSettle] = taskPlayletOrderSettle // + jobs[taskMd.ZhimengCronMasterMonthSettle] = taskMasterMonthSettle // + } diff --git a/app/task/md/cron_key.go b/app/task/md/cron_key.go index 3405837..b71651d 100644 --- a/app/task/md/cron_key.go +++ b/app/task/md/cron_key.go @@ -9,4 +9,7 @@ const ( ZhimengCronPlayletAdvOrderMonth = "zhimeng_cron_playlet_adv_order_month" ZhimengCronPlayletAdvOrderYesterDayToMoney = "zhimeng_cron_playlet_adv_order_yesterday_to_money" ZhimengCronPlayletGoods = "zhimeng_cron_playlet_goods" + + ZhimengCronPlayletOrderSettle = "zhimeng_cron_playlet_order_settle" + ZhimengCronMasterMonthSettle = "zhimeng_cron_master_month_settle" ) diff --git a/app/task/svc/svc_master_month_settle.go b/app/task/svc/svc_master_month_settle.go new file mode 100644 index 0000000..0279a2c --- /dev/null +++ b/app/task/svc/svc_master_month_settle.go @@ -0,0 +1,83 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/utils" + "applet/app/utils/cache" + "fmt" + "time" +) + +func MasterMonthSettle() { + day := time.Now().Day() + masterListCfgDb := db.MasterListCfgDb{} + masterListCfgDb.Set() + withdrawalDay := masterListCfgDb.MasterListCfgGetOneData("0", "withdrawal_day") + if day < utils.StrToInt(withdrawalDay) { + return + } + args := map[string]string{ + "p": "1", + "size": "100", + } + masterAmountDb := db.MasterAmountDb{} + masterAmountDb.Set() + list := masterAmountDb.GetMasterAmountList(args) + if list == nil { + return + } + for _, v := range *list { + mutexKey := fmt.Sprintf("master_month_settle:%d", v.Id) + withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 1800, "NX") + if err != nil { + continue + } + if withdrawAvailable != "OK" { + continue + } + if utils.StrToFloat64(v.LastMonthAmount) <= 0 { + continue + } + oldAmount := v.Amount + oldLastMonthAmount := v.LastMonthAmount + v.Amount = utils.Float64ToStr(utils.StrToFloat64(v.Amount) + utils.StrToFloat64(v.LastMonthAmount)) + v.LastMonthAmount = "0" + update := masterAmountDb.MasterAmountUpdate(v.Id, &v) + if update == false { + continue + } + var tmp = model.MasterAmountFlow{ + Uid: v.Uid, + Time: time.Now(), + BeforeAmount: oldAmount, + Amount: oldLastMonthAmount, + AfterAmount: v.Amount, + Platform: "playlet", + Oid: utils.IntToStr(v.Id), + Title: "短剧上月结算佣金到账", + FlowType: "last_month_playlet_settle", + IncomeType: 0, + } + masterAmountFlowDb := db.MasterAmountFlowDb{} + masterAmountFlowDb.Set() + masterAmountFlowDb.MasterAmountFlowInsert(&tmp) + + var tmpLastMonth = model.MasterLastMonthAmountFlow{ + Uid: v.Uid, + Time: time.Now(), + BeforeAmount: oldLastMonthAmount, + Amount: oldLastMonthAmount, + AfterAmount: v.LastMonthAmount, + Platform: "playlet", + Oid: utils.IntToStr(v.Id), + Title: "短剧上月结算佣金转到余额", + FlowType: "last_month_playlet_settle", + IncomeType: 1, + } + masterLastMonthAmountFlowDb := db.MasterLastMonthAmountFlowDb{} + masterLastMonthAmountFlowDb.Set() + masterLastMonthAmountFlowDb.MasterLastMonthAmountFlowInsert(&tmpLastMonth) + + } +} diff --git a/app/task/svc/svc_playlet_order_settle.go b/app/task/svc/svc_playlet_order_settle.go new file mode 100644 index 0000000..5b51b7d --- /dev/null +++ b/app/task/svc/svc_playlet_order_settle.go @@ -0,0 +1,92 @@ +package svc + +import ( + "applet/app/db" + "applet/app/db/model" + "applet/app/utils" + "applet/app/utils/cache" + "fmt" + "time" +) + +func PlayletOrderSettle() { + day := time.Now().Day() + if day < 5 { + return + } + month := utils.GetTimeRange("current_month") + fmt.Println(month) + arg := map[string]string{ + "status": "订单结算", + "sort": "id desc", + "is_to_settle": "1", + "to_settle_time": time.Unix(month["start"], 0).Format("2006-01-02 15:04:05"), + "p": "1", + "size": "100", + } + playletSaleOrderDb := db.PlayletSaleOrderDb{} + playletSaleOrderDb.Set() + order := playletSaleOrderDb.GetPlayletVideoOrderList(arg) + if len(order) == 0 { + return + } + + for _, v := range order { + // 加锁 防止并发提取 + mutexKey := fmt.Sprintf("playlet_order_settle:%s", v.CustomOid) + withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 1800, "NX") + if err != nil { + continue + } + if withdrawAvailable != "OK" { + continue + } + if v.SettleTime > 0 { + continue + } + //加到上月结算 + if v.Uid == "" || v.Uid == "0" { + continue + } + masterDb := db.MasterDb{} + masterDb.Set() + master := masterDb.GetMaster(v.Uid) + if master == nil { + continue + } + masterAmountDb := db.MasterAmountDb{} + masterAmountDb.Set() + amount := masterAmountDb.GetMasterAmount(utils.IntToStr(master.Id), "playlet") + if amount == nil { + continue + } + if utils.StrToFloat64(v.Commission) <= 0 { + v.SettleTime = int(time.Now().Unix()) + playletSaleOrderDb.PlayletVideoOrderUpdate(v.Id, &v) + continue + } + oldAmount := amount.LastMonthAmount + amount.LastMonthAmount = utils.Float64ToStr(utils.StrToFloat64(amount.LastMonthAmount) + utils.StrToFloat64(v.Commission)) + update := masterAmountDb.MasterAmountUpdate(master.Id, amount) + if update == false { + continue + } + var tmp = model.MasterLastMonthAmountFlow{ + Uid: utils.IntToStr(master.Id), + Time: time.Now(), + BeforeAmount: oldAmount, + Amount: v.Commission, + AfterAmount: amount.LastMonthAmount, + Platform: "playlet", + Oid: v.Oid, + Title: "短剧订单结算", + FlowType: "playlet_settle", + } + masterLastMonthAmountFlowDb := db.MasterLastMonthAmountFlowDb{} + masterLastMonthAmountFlowDb.Set() + masterLastMonthAmountFlowDb.MasterLastMonthAmountFlowInsert(&tmp) + v.SettleTime = int(time.Now().Unix()) + playletSaleOrderDb.PlayletVideoOrderUpdate(v.Id, &v) + } + return +} diff --git a/app/task/task_master_month_settle.go b/app/task/task_master_month_settle.go new file mode 100644 index 0000000..2b576c4 --- /dev/null +++ b/app/task/task_master_month_settle.go @@ -0,0 +1,22 @@ +package task + +import ( + "applet/app/task/svc" + "math/rand" + "time" +) + +// +func taskMasterMonthSettle() { + for { + if len(ch) > workerNum { + time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) + } else { + goto START + } + } +START: + ch <- 1 + svc.MasterMonthSettle() + <-ch +} diff --git a/app/task/task_playlet_order_settle.go b/app/task/task_playlet_order_settle.go new file mode 100644 index 0000000..860612e --- /dev/null +++ b/app/task/task_playlet_order_settle.go @@ -0,0 +1,22 @@ +package task + +import ( + "applet/app/task/svc" + "math/rand" + "time" +) + +// +func taskPlayletOrderSettle() { + for { + if len(ch) > workerNum { + time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) + } else { + goto START + } + } +START: + ch <- 1 + svc.PlayletOrderSettle() + <-ch +} diff --git a/app/utils/time.go b/app/utils/time.go index 6860a57..9892463 100644 --- a/app/utils/time.go +++ b/app/utils/time.go @@ -168,11 +168,11 @@ func GetTimeRange(s string) map[string]int64 { // 明天 0点 etime = time.Date(t.Year(), t.Month(), t.Day()+1, 0, 0, 0, 0, t.Location()) case "current_month": - stime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) + stime = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location()) etime = time.Date(t.Year(), t.Month()+1, 0, 0, 0, 0, 0, t.Location()) case "last_month": - stime = time.Date(t.Year(), t.Month()-1, 0, 0, 0, 0, 0, t.Location()) - etime = time.Date(t.Year(), t.Month(), 0, 0, 0, 0, 0, t.Location()) + stime = time.Date(t.Year(), t.Month()-1, 1, 0, 0, 0, 0, t.Location()) + etime = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, t.Location()) } return map[string]int64{ diff --git a/go.mod b/go.mod index 1f943a3..e26ccf7 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,8 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/gomodule/redigo v2.0.0+incompatible github.com/makiuchi-d/gozxing v0.1.1 + github.com/mcuadros/go-defaults v1.2.0 + github.com/qiniu/api.v7/v7 v7.8.2 github.com/robfig/cron/v3 v3.0.1 github.com/sony/sonyflake v1.1.0 github.com/syyongx/php2go v0.9.7