From d750bfe18db2ce0fde7453326bfcf3a01b7a44e5 Mon Sep 17 00:00:00 2001 From: suyl <770236076@qq.com> Date: Tue, 20 Jul 2021 17:21:38 +0800 Subject: [PATCH] aa --- controllers/print_controller.go | 3 +- dao/print_dao.go | 10 +++- dao/sim_dao.go | 81 +++++++++++++++++++++++++ main.go | 3 + model/model.go | 33 ++++++++++- services/api/api.go | 22 +++++++ services/misc/misc.go | 57 ++++++++++++++++++ services/print.go | 20 +++---- services/sim.go | 101 ++++++++++++++++++++++++++++++++ utils/utils.go | 60 +++++++++++++++++++ 10 files changed, 374 insertions(+), 16 deletions(-) create mode 100644 dao/sim_dao.go create mode 100644 services/api/api.go create mode 100644 services/misc/misc.go create mode 100644 services/sim.go diff --git a/controllers/print_controller.go b/controllers/print_controller.go index e375857..d87a43d 100644 --- a/controllers/print_controller.go +++ b/controllers/print_controller.go @@ -109,7 +109,6 @@ func UpdatePrinter(c *gin.Context) { AppID int `json:"app_id" form:"app_id" binding:"required"` PrintNo string `json:"print_no" form:"print_no" binding:"required"` //打印机编号 Name string `json:"name" form:"name"` //打印机备注,模糊 - SIM string `json:"sim" form:"sim"` //sim卡 Sound string `json:"sound" form:"sound"` //声音类型 Volume int `json:"volume" form:"volume"` //音量大小 }{} @@ -122,7 +121,7 @@ func UpdatePrinter(c *gin.Context) { return } if !callFunc(c, func() (retVal interface{}, errCode string, err error) { - err = services.UpdatePrinter(c, param.AppID, tokenInfo, param.PrintNo, param.Name, param.SIM, param.Sound, param.Volume) + err = services.UpdatePrinter(c, param.AppID, tokenInfo, param.PrintNo, param.Name, param.Sound, param.Volume) return retVal, "", err }) { return diff --git a/dao/print_dao.go b/dao/print_dao.go index 65cbd2c..b512723 100644 --- a/dao/print_dao.go +++ b/dao/print_dao.go @@ -7,7 +7,7 @@ import ( "time" ) -func GetPrinters(db *sqlx.DB, appID int, printNo string) (printers []*model.Printer, err error) { +func GetPrinters(db *sqlx.DB, appID int, printNo string, status int, statusNeq int) (printers []*model.Printer, err error) { sql := ` SELECT * FROM printer @@ -22,6 +22,14 @@ func GetPrinters(db *sqlx.DB, appID int, printNo string) (printers []*model.Prin sql += " AND print_no = ?" sqlParams = append(sqlParams, printNo) } + if status != 0 { + sql += " AND status = ?" + sqlParams = append(sqlParams, status) + } + if statusNeq != 0 { + sql += " AND status <> ?" + sqlParams = append(sqlParams, statusNeq) + } if err = db.Select(&printers, sql, sqlParams...); err == nil { return printers, err } diff --git a/dao/sim_dao.go b/dao/sim_dao.go new file mode 100644 index 0000000..178f3cb --- /dev/null +++ b/dao/sim_dao.go @@ -0,0 +1,81 @@ +package dao + +import ( + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-print/model" + "github.com/jmoiron/sqlx" + "time" +) + +func GetSimFlowExpend(db *sqlx.DB, iccid string, createdAtBegin, createdAtEnd time.Time) (simFlowExpnd []*model.SimFlowExpend, err error) { + + return simFlowExpnd, err +} + +func GetSimFlowExpendSum(db *sqlx.DB, iccid string, createdAtBegin, createdAtEnd time.Time) (simFlowExpnd *model.SimFlowExpend, err error) { + var ( + simFlowExpnds []*model.SimFlowExpend + ) + sql := ` + SELECT SUM( + IF(flow_unit = 'KB', flow, + IF(flow_unit = 'MB', ROUND(flow * 1024)), + IF(flow_unit = "GB", ROUND(flow * 1024 * 1024), 0) + ) + ) flow, icc_id, 'KB' flow_unit + FROM sim_flow_expend + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if iccid != "" { + sql += " AND icc_id = ?" + sqlParams = append(sqlParams, iccid) + } + if !utils.IsTimeZero(createdAtBegin) { + sql += " AND created_at > ?" + sqlParams = append(sqlParams, createdAtBegin) + } + if !utils.IsTimeZero(createdAtEnd) { + sql += " AND created_at < ?" + sqlParams = append(sqlParams, createdAtEnd) + } + sql += " GROUP BY 2, 3" + if err = db.Select(&simFlowExpnds, sql, sqlParams); err == nil && len(simFlowExpnds) > 0 { + return simFlowExpnds[0], err + } + return simFlowExpnd, err +} + +func GetSimFlowIncomeSum(db *sqlx.DB, iccid string, createdAtBegin, createdAtEnd time.Time) (simFlowIncome *model.SimFlowIncome, err error) { + var ( + simFlowIncomes []*model.SimFlowIncome + ) + sql := ` + SELECT SUM( + IF(flow_unit = 'KB', flow, + IF(flow_unit = 'MB', ROUND(flow * 1024)), + IF(flow_unit = "GB", ROUND(flow * 1024 * 1024), 0) + ) + ) flow, icc_id, 'KB' flow_unit + FROM sim_flow_income + WHERE 1 = 1 + ` + sqlParams := []interface{}{} + if iccid != "" { + sql += " AND icc_id = ?" + sqlParams = append(sqlParams, iccid) + } + if !utils.IsTimeZero(createdAtBegin) { + sql += " AND created_at > ?" + sqlParams = append(sqlParams, createdAtBegin) + } + if !utils.IsTimeZero(createdAtEnd) { + sql += " AND created_at < ?" + sqlParams = append(sqlParams, createdAtEnd) + } + sql += " GROUP BY 2, 3" + if err = db.Select(&simFlowIncomes, sql, sqlParams); err == nil && len(simFlowIncomes) > 0 { + return simFlowIncomes[0], err + } + return simFlowIncome, err +} diff --git a/main.go b/main.go index 25899cb..b57bb70 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,8 @@ import ( "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" "git.rosy.net.cn/jx-print/routers" + _ "git.rosy.net.cn/jx-print/services/api" + "git.rosy.net.cn/jx-print/services/misc" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" @@ -40,6 +42,7 @@ func main() { r.Use(gin.Recovery()) r.Use(middleware()) routers.Init(r) + misc.Init() r.Run(":8999") } diff --git a/model/model.go b/model/model.go index 4ab31e6..4ba0976 100644 --- a/model/model.go +++ b/model/model.go @@ -8,13 +8,17 @@ const ( SessionKey = "jxCode" RegisterKey = "jxRegister" - PrinterStatusNormal = 0 //打印机状态正常 - PrinterStatusWithouPaper = 1 //缺纸 + PrinterStatusNormal = 1 //打印机状态正常 + PrinterStatusWithouPaper = 2 //缺纸 + PrinterStatusOverFlow = -2 //缺流量 PrinterOnline = 1 //在线 PrinterOffline = 0 //离线 StatusAll = -9 + + FlowIncomeTypeJX = 1 //表示每月自动划转 + FlowIncomeTypeUser = 2 //表示是用户自己冲的 ) const ( @@ -134,7 +138,7 @@ type Printer struct { Name string `json:"name"` //打印机备注名 Status int `json:"status"` //打印机状态 IsOnline int `json:"is_online" db:"is_online"` //1在线,0离线 - SIM string `json:"sim" db:"sim"` //sim卡号 + IccID string `json:"iccid" db:"icc_id"` //sim卡号 Sound string `json:"sound"` //声音类型 sounda ,b,c,d,e,f,g Volume int `json:"volume"` //音量,1-5 ,对应打印机2-10 } @@ -152,3 +156,26 @@ type PrintMsg struct { Status int `json:"status"` //打印状态 Comment string `json:"comment"` //失败原因 } + +//流量支出 +type SimFlowExpend struct { + ID int `json:"id" db:"id"` + CreatedAt *time.Time `json:"created_at" db:"created_at"` + UpdatedAt *time.Time `json:"updated_at" db:"updated_at"` + LastOperator string `json:"last_operator" db:"last_operator"` + IccID string `json:"iccid" db:"icc_id"` //sim卡iccid + Flow float64 `json:"flow"` //流量数 + FlowUnit string `json:"flowUnit"` //流量单位 +} + +//流量划入 +type SimFlowIncome struct { + ID int `json:"id" db:"id"` + CreatedAt *time.Time `json:"created_at" db:"created_at"` + UpdatedAt *time.Time `json:"updated_at" db:"updated_at"` + LastOperator string `json:"last_operator" db:"last_operator"` + IccID string `json:"iccid" db:"icc_id"` //sim卡iccid + Flow float64 `json:"flow"` //流量数 + FlowUnit string `json:"flowUnit"` //流量单位 + IncomeType int `json:"incomeType"` //1 表示系统每月自动划转,2 表示商户自己冲的 +} diff --git a/services/api/api.go b/services/api/api.go new file mode 100644 index 0000000..810ac65 --- /dev/null +++ b/services/api/api.go @@ -0,0 +1,22 @@ +package api + +import ( + "git.rosy.net.cn/baseapi/platformapi/tibiotapi" + aliyunsmsclient "github.com/KenmyZhang/aliyun-communicate" +) + +var ( + SMSClient *aliyunsmsclient.SmsClient + + TibiotAPI *tibiotapi.API +) + +func init() { + Init() // 这里必须要调用 +} + +// 这样写的原因是在测试时,可以重新读取配置文件 +func Init() { + TibiotAPI = tibiotapi.New("ruoxikeji", "Ruoxi@369") + SMSClient = aliyunsmsclient.New("http://dysmsapi.aliyuncs.com/") +} diff --git a/services/misc/misc.go b/services/misc/misc.go new file mode 100644 index 0000000..032487d --- /dev/null +++ b/services/misc/misc.go @@ -0,0 +1,57 @@ +package misc + +import ( + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-print/services" + putils "git.rosy.net.cn/jx-print/utils" + + "git.rosy.net.cn/jx-print/globals" + "time" +) + +func Init() { + ScheduleTimerFunc("SimFlowDaySettle", func() { + services.SimFlowMonthSettle() + services.SimFlowDaySettle() + }, []string{ + "00:05:00", + }) +} + +// 按时间序列循环 +func ScheduleTimerFunc(name string, handler func(), timeList []string) { + now := time.Now() + nextTime := putils.GetNextTimeFromList(now, timeList) + duration := nextTime.Sub(now) + 1*time.Second + globals.SugarLogger.Debugf("ScheduleTimerFunc, func:%s, duration:%v", name, duration) + utils.AfterFuncWithRecover(duration, func() { + globals.SugarLogger.Debugf("ScheduleTimerFunc func:%s", name) + handler() + ScheduleTimerFunc(name, handler, timeList) + }) +} + +// 按时间调度一次 +func ScheduleTimerFuncOnce(name string, handler func(interface{}), timeStr string, param interface{}) { + now := time.Now() + nextTime := putils.GetNextTimeFromList(now, []string{timeStr}) + duration := nextTime.Sub(now) + 1*time.Second + globals.SugarLogger.Debugf("ScheduleTimerFuncOnce, func:%s, duration:%v", name, duration) + utils.AfterFuncWithRecover(duration, func() { + globals.SugarLogger.Debugf("ScheduleTimerFuncOnce func:%s", name) + handler(param) + }) +} + +func ScheduleTimerFuncByInterval(handler func(), delay, inerval time.Duration) { + globals.SugarLogger.Debugf("ScheduleTimerFuncByInterval, delay:%v, inerval:%v", delay, inerval) + utils.AfterFuncWithRecover(delay, func() { + beginTime := time.Now() + handler() + delay = inerval - time.Now().Sub(beginTime) + if delay < time.Second { + delay = time.Second + } + ScheduleTimerFuncByInterval(handler, delay, inerval) + }) +} diff --git a/services/print.go b/services/print.go index 344a16f..747f924 100644 --- a/services/print.go +++ b/services/print.go @@ -38,7 +38,7 @@ func AddPrinters(c *gin.Context, tokenInfo *model.TokenInfo, appID int, printInf errs = append(errs, fmt.Errorf("请输入正确的打印机编号!print_no :%s 。", v.PrintNo)) continue } - printers, _ := dao.GetPrinters(db, appID, v.PrintNo) + printers, _ := dao.GetPrinters(db, appID, v.PrintNo, 0, 0) if len(printers) > 0 { errs = append(errs, fmt.Errorf("此打印机已被其他应用绑定!print_no :%s 。", v.PrintNo)) continue @@ -88,7 +88,7 @@ func DelPrinters(c *gin.Context, appID int, tokenInfo *model.TokenInfo, printNos errs = append(errs, fmt.Errorf("请输入正确的打印机编号!print_no :%s 。", v)) continue } - printers, _ := dao.GetPrinters(db, appID, v) + printers, _ := dao.GetPrinters(db, appID, v, 0, 0) if len(printers) == 0 { errs = append(errs, fmt.Errorf("未在该应用下查到此打印机!app_id: %d, print_no: %s", appID, v)) continue @@ -106,7 +106,7 @@ func DelPrinters(c *gin.Context, appID int, tokenInfo *model.TokenInfo, printNos return err } -func UpdatePrinter(c *gin.Context, appID int, tokenInfo *model.TokenInfo, printNo, name, sim, sound string, volume int) (err error) { +func UpdatePrinter(c *gin.Context, appID int, tokenInfo *model.TokenInfo, printNo, name, sound string, volume int) (err error) { var ( db = globals.GetDB() now = time.Now() @@ -116,7 +116,7 @@ func UpdatePrinter(c *gin.Context, appID int, tokenInfo *model.TokenInfo, printN return fmt.Errorf("未查询到此应用!app_id:%d", appID) } - printers, _ := dao.GetPrinters(db, appID, printNo) + printers, _ := dao.GetPrinters(db, appID, printNo, 0, 0) if len(printers) == 0 { return fmt.Errorf("未在该应用下查到此打印机!app_id: %d, print_no: %s", appID, printNo) } @@ -125,10 +125,10 @@ func UpdatePrinter(c *gin.Context, appID int, tokenInfo *model.TokenInfo, printN printer.Name = name fields = append(fields, "name") } - if sim != printer.SIM { - printer.SIM = sim - fields = append(fields, "sim") - } + //if sim != printer.IccID { + // printer.IccID = sim + // fields = append(fields, "iccid") + //} if sound != printer.Sound { printer.Sound = sound fields = append(fields, "sound") @@ -155,7 +155,7 @@ func TestPrint(c *gin.Context, appID int, tokenInfo *model.TokenInfo, printNo st if apps, _ := dao.GetApps(db, appID, tokenInfo.User.UserID, ""); len(apps) == 0 { return "", fmt.Errorf("未查询到此应用!app_id:%d", appID) } - printers, _ := dao.GetPrinters(db, appID, printNo) + printers, _ := dao.GetPrinters(db, appID, printNo, 0, 0) if len(printers) == 0 { return "", fmt.Errorf("未在该应用下查到此打印机!app_id: %d, print_no: %s", appID, printNo) } @@ -180,7 +180,7 @@ func GetPrintMessages(c *gin.Context, appID int, tokenInfo *model.TokenInfo, pri if apps, _ := dao.GetApps(db, appID, tokenInfo.User.UserID, ""); len(apps) == 0 { return nil, fmt.Errorf("未查询到此应用!app_id:%d", appID) } - printers, _ := dao.GetPrinters(db, appID, printNo) + printers, _ := dao.GetPrinters(db, appID, printNo, 0, 0) if len(printers) == 0 { return nil, fmt.Errorf("未在该应用下查到此打印机!app_id: %d, print_no: %s", appID, printNo) } diff --git a/services/sim.go b/services/sim.go new file mode 100644 index 0000000..be42ba7 --- /dev/null +++ b/services/sim.go @@ -0,0 +1,101 @@ +package services + +import ( + "git.rosy.net.cn/baseapi/platformapi/tibiotapi" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-print/dao" + "git.rosy.net.cn/jx-print/globals" + "git.rosy.net.cn/jx-print/model" + "git.rosy.net.cn/jx-print/services/api" + putils "git.rosy.net.cn/jx-print/utils" + + "time" +) + +//每日流量卡流量结算 +func SimFlowDaySettle() (err error) { + var ( + db = globals.GetDB() + now = time.Now() + monthBegin = utils.Str2Time(utils.Int2Str(now.Year()) + "-" + utils.Int2Str(int(now.Month())) + "-01 00:00:00") + monthEnd = monthBegin.AddDate(0, 0, -1).AddDate(0, 1, 0) + ) + globals.SugarLogger.Debugf("SimFlowDaySettle Begin monthBegin %v, monthEnd %v", monthBegin, monthEnd) + //月末好像不用算超不超了 + if now.Month().String() != now.AddDate(0, 0, -1).Month().String() { + return + } + //找出所有状态不为 超流量的打印机(iccid卡) + printers, _ := dao.GetPrinters(db, 0, "", 0, model.PrinterStatusOverFlow) + for _, v := range printers { + //查询前一日使用的流量数 + if v.IccID != "" { + flowExpend := &model.SimFlowExpend{ + IccID: v.IccID, + CreatedAt: &now, + UpdatedAt: &now, + LastOperator: "jxadmin", + } + var ( + getCardInfoResult *tibiotapi.IotDataResult + getCardInfoResultMonth *tibiotapi.IotDataMonthResult + ) + if getCardInfoResult, err = api.TibiotAPI.IotData(v.IccID, utils.Time2Str(utils.Time2Date(time.Now().AddDate(0, 0, -1)))); err == nil { + //表示还没有同步前一天的流量,只能自己算了 + if getCardInfoResult == nil || getCardInfoResult.SyncStatus == "1" || getCardInfoResult.CardFlow == "0KB" || getCardInfoResult.CardFlow == "" { //未同步 + //先查当月用的总的, 减去当月已经用的总的,就是昨天用的 + if getCardInfoResultMonth, err = api.TibiotAPI.IotDataMonth(v.IccID); err == nil { + //表示当月用的总的也还没同步。只有去查卡信息中的总流量使用,减去所有总使用,就是昨天用的。。太折磨了先不写 + if getCardInfoResultMonth == nil || getCardInfoResultMonth.CardFlow == "" || getCardInfoResultMonth.CardFlow == "0KB" { + //api.TibiotAPI.BatchQueryCardInfo(1) + } else { + sumExpend, _ := dao.GetSimFlowExpendSum(db, v.IccID, monthBegin, monthEnd) + cardFlow := putils.Flow2KB(putils.SplitFlowAndUnit(getCardInfoResultMonth.CardFlow)) + flowExpend.Flow, flowExpend.FlowUnit = putils.FlowKB2Other(cardFlow - sumExpend.Flow) + } + } + } else { + flowExpend.Flow, flowExpend.FlowUnit = putils.SplitFlowAndUnit(getCardInfoResult.CardFlow) + } + } + dao.Insert(db, flowExpend) + //算是否超了一个月的流量了 + //一个月总的收入流量 - 一个月总的支出流量 <= 0 + sumIncome, _ := dao.GetSimFlowIncomeSum(db, v.IccID, monthBegin, monthEnd) + sumExpend, _ := dao.GetSimFlowExpendSum(db, v.IccID, monthBegin, monthEnd) + if sumExpend.Flow-sumIncome.Flow <= 0 { + v.Status = model.PrinterStatusOverFlow + dao.Update(db, v, "Status") + } + } + } + return err +} + +//每月流量卡流量划转 +func SimFlowMonthSettle() { + var ( + db = globals.GetDB() + now = time.Now() + ) + //..每月1号划转 + if time.Now().Day() != 1 { + return + } + //找出所有有iccid 卡的 + printers, _ := dao.GetPrinters(db, 0, "", 0, model.PrinterStatusOverFlow) + for _, v := range printers { + if v.IccID != "" { + flowIncome := &model.SimFlowIncome{ + IccID: v.IccID, + CreatedAt: &now, + UpdatedAt: &now, + LastOperator: "jxadmin", + IncomeType: model.FlowIncomeTypeJX, + Flow: 30, + FlowUnit: "MB", + } + dao.Insert(db, flowIncome) + } + } +} diff --git a/utils/utils.go b/utils/utils.go index ae6aae7..c59001c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -5,10 +5,12 @@ import ( "encoding/json" "fmt" "git.rosy.net.cn/baseapi" + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-print/globals" "git.rosy.net.cn/jx-print/model" "github.com/dchest/captcha" "github.com/gin-gonic/gin" + "math" "math/rand" "net/http" "strings" @@ -33,6 +35,12 @@ func init() { var ( letterBytes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" letterBytesNum = "0123456789" + + flowUnitMap = map[string]string{ + "KB": "KB", + "MB": "MB", + "GB": "GB", + } ) func RandStringBytes(n int) string { @@ -192,3 +200,55 @@ func Format4Output(obj interface{}, isSingleLine bool) (retVal string) { } return retVal } + +func GetNextTimeFromList(now time.Time, timeList []string) (snapshotAt time.Time) { + dateStr := utils.Time2DateStr(now) + timeListLen := len(timeList) + selectTime := utils.Str2Time(utils.Time2DateStr(now.Add(24*time.Hour)) + " " + timeList[0]) + for k := range timeList { + v := timeList[timeListLen-k-1] + tmpTime := utils.Str2Time(dateStr + " " + v) + if tmpTime.Sub(now) < 0 { + break + } + selectTime = tmpTime + } + return selectTime +} + +func SplitFlowAndUnit(flowStr string) (flow float64, unit string) { + for _, v := range flowUnitMap { + if strings.Contains(flowStr, v) { + return utils.Str2Float64WithDefault(flowStr[:len(flowStr)-2], 0), flowStr[len(flowStr)-2:] + } + } + return flow, unit +} + +func Flow2KB(flow float64, unit string) (flowKB float64) { + if unit == "KB" { + return flow + } else if unit == "MB" { + return flow * 1024 + } else if unit == "GB" { + return flow * 1024 * 1024 + } + return flowKB +} + +func FlowKB2Other(flowKB float64) (flow float64, unit string) { + if flowKB < 1024 { + return flowKB, "KB" + } else { + flowMB := math.Round(flowKB / float64(1024)) + if flowMB < 1024 { + return flowMB, "MB" + } else { + flowGB := math.Round(flowMB / float64(1024)) + if flowGB < 1024 { + return flowGB, "GB" + } + } + } + return flow, unit +}