package service import ( "bytes" "crypto/md5" "database/sql" "encoding/json" "errors" "fmt" "gopkg.in/mgo.v2/bson" "io/ioutil" "log" "math/rand" "net/http" "strconv" "strings" "sync" "time" "gopkg.in/guregu/null.v3" "xiaoniaokuaiyan.com/xiaoniao/config" "xiaoniaokuaiyan.com/xiaoniao/dal" "xiaoniaokuaiyan.com/xiaoniao/entity" "xiaoniaokuaiyan.com/xiaoniao/pay/wx" "xiaoniaokuaiyan.com/xiaoniao/util" ) type DeliverUserService struct { dal.IDeliverUserDal *WeixinService dal.IOrder } func (dus *DeliverUserService) GetOrderList(openid string, status, pageIndex, pageSize int) (interface{}, error) { if strings.Trim(openid, " ") == "" { return nil, errors.New("openid is required") } return dus.IDeliverUserDal.GetOrderList(openid, status, pageIndex, pageSize) } func (dus *DeliverUserService) GetOrderListV2(openid string, pageIndex, pageSize int) (interface{}, error) { if strings.Trim(openid, " ") == "" { return nil, errors.New("openid is required") } return dus.IDeliverUserDal.GetOrderListV2(openid, pageIndex, pageSize) } func (dus *DeliverUserService) GetOrderSign(orderId string) (interface{}, error) { return dus.IDeliverUserDal.GetOrderSign(orderId) } func (dus *DeliverUserService) SaveOrderSign(signItem *entity.OrderSign) (interface{}, error) { return dus.IDeliverUserDal.SaveOrderSign(signItem) } func (dus *DeliverUserService) RegistDU(duItem *entity.DeliverUser) (interface{}, error) { /*if duItem.Vcode == "" { return nil, errors.New("0::require vcode") } smsService := SMSService{dal.DefaultSMSCodeDal} _, err := smsService.ValidateCode(duItem.Tel, duItem.Vcode, 7) if err != nil { return nil, err }*/ r, err := dus.IDeliverUserDal.SaveDU(duItem) if err != nil { return nil, err } var ( firstVal string = "恭喜您成功注册小鸟快验护士平台" remarkVal string = "请尽快提交相关资料,现在提交还有金币奖励,可以随时提现哦~" toUser string = duItem.Openid phone = duItem.Tel createAt = time.Now().Format("2006-01-02 15:04:05") ) msg := map[string]interface{}{ "touser": &toUser, "template_id": "9AdS0lxgUUtFE-RxZE2gIYWZkTzdpivvyfwh5A3sRYo", "url": config.IniConf.Section("weixin").Key("wx.front_host").Value() + "/index/deliver", "data": map[string]interface{}{ "first": map[string]interface{}{ "value": &firstVal, "color": "#173177", }, "keyword1": map[string]interface{}{ "value": &phone, "color": "#173177", }, "keyword2": map[string]interface{}{ "value": &createAt, "color": "#173177", }, "remark": map[string]interface{}{ "value": &remarkVal, "color": "#173177", }, }, } buf, _ := json.Marshal(msg) _, err = dus.WeixinService.SendTpl(string(buf), "") return r, err } func (dus *DeliverUserService) UpdateDU(duItem *entity.DeliverUser) (interface{}, error) { return dus.IDeliverUserDal.UpdateDU(duItem) } func (dus *DeliverUserService) CheckExam(duser *entity.DeliverUser, questions []entity.ExamQuestion) (interface{}, error) { db := util.GetWriteSqlDB() var strIds string for _, q := range questions { strIds += fmt.Sprintf("%d,", q.Id) } strIds = strIds[0 : len(strIds)-1] strSql := "select id, answer from t_deliver_exam where id in(" + strIds + ");" var eqs = []entity.ExamQuestion{} err := db.Select(&eqs, strSql) if err != nil { return nil, err } if len(eqs) != len(questions) { return nil, errors.New("1::数据异常") } var ( validNum int = 0 ) for _, question := range questions { for _, eq := range eqs { if eq.Answer == question.InAnswer { validNum++ break } } } if validNum >= NOURSE_EXAME_PASS { strSql = "update t_deliver_user set process_staus = '7', grade='L3' where openid = ?" sqlResult, _ := db.Exec(strSql, duser.Openid) if ra, _ := sqlResult.RowsAffected(); ra < 1 { return nil, errors.New("2::数据更新失败") } //老1000,新500 /* //v1.之前修改不能重复考试添加分数,v2. 2020-12-31 去掉考试通过加分,直接审核通过加分。 var ( inviterID int myId int //count int ) db.Get(&inviterID, "select id from t_deliver_user t1 where exists (select 1 from t_deliver_user t2 where t1.openid = t2.invite_by and t2.openid = ? and LENGTH(t2.invite_by)>0)limit 1", duser.Openid) db.Get(&myId, "select id from t_deliver_user where openid = ? limit 1", duser.Openid) if inviterID > 0 && myId > 0 { //db.Get(&count, "select count(1) from t_deliver_score_bill where deliver_user_id = ? and type=?", myId, "INVITE_EXAM") //if count > 0 { //发出邀请的人 db.Exec("update t_deliver_account set score = score + 1000 where deliver_user_id = ?;", inviterID) db.Exec("insert into t_deliver_score_bill(deliver_user_id, type, score) values(?,?,?);", inviterID, "INVITE_F_EXAM", 1000) //被邀请的人 db.Exec("update t_deliver_account set score = score + 500 where deliver_user_id = ?;", myId) db.Exec("insert into t_deliver_score_bill(deliver_user_id, type, score) values(?,?,?);", myId, "INVITE_EXAM", 500) //} } */ } return validNum, nil } //const NOURSE_EXAME_NUMS int = 20 //const NOURSE_EXAME_PASS int = 18 // 总题数 const NOURSE_EXAME_NUMS int = 5 // 通过数 const NOURSE_EXAME_PASS int = 4 func (dus *DeliverUserService) GetExamList() (interface{}, error) { db := util.GetSqlDB() var simpleExams = []struct { Id int `db:"id"` Flag string `db:"flag"` }{} var idMapFlag = map[int]string{} strSql := "select id, flag from t_deliver_exam;" err := db.Select(&simpleExams, strSql) if err != nil { return nil, err } for _, se := range simpleExams { idMapFlag[se.Id] = se.Flag } var tempIds = map[int]interface{}{} var ( l = len(simpleExams) rn int ) for i := 0; i < NOURSE_EXAME_NUMS; i++ { for { rn = rand.Intn(l) + 1 if flag, ok := idMapFlag[rn]; ok && flag == "Y" { if _, ok = tempIds[rn]; !ok { tempIds[rn] = struct{}{} break } } } } strIds := "" for k, _ := range tempIds { strIds += fmt.Sprintf("%d,", k) } strIds = strIds[0 : len(strIds)-1] strSql = "select * from t_deliver_exam where id in(" + strIds + ") order by sortno asc;" questions := []entity.ExamQuestion{} err = db.Select(&questions, strSql) if err != nil { return nil, err } strSql = "select * from t_deliver_exam_option where exam_id in(" + strIds + ") and flag = 'Y';" var options = []entity.ExamOption{} err = db.Select(&options, strSql) if err != nil { return nil, err } for _, option := range options { for i, _ := range questions { if option.ExamId == questions[i].Id { questions[i].Options = append(questions[i].Options, option) break } } } return questions, nil } func (dus *DeliverUserService) GetStudyList(typ string) (interface{}, error) { db := util.GetSqlDB() var studyList = []entity.DeliverStudy{} strSql := "select * from t_deliver_study where typ = ? and flag = 'Y' order by sortno asc;" err := db.Select(&studyList, strSql, typ) return studyList, err } func (dus *DeliverUserService) GetStudyLog(openid string, typ string) (interface{}, error) { strSql := "select t1.* from t_deliver_study_log t1 left join t_deliver_study t2 on t2.id = t1.deliver_study_id where openid = ? and t2.typ = ?;" db := util.GetSqlDB() var logList = []entity.DeliverStudyLog{} err := db.Select(&logList, strSql, openid, typ) return logList, err } func (dus *DeliverUserService) AddStduyLog(slog entity.DeliverStudyLog) (interface{}, error) { db := util.GetWriteSqlDB() var ( now = time.Now() year = now.Year() month = now.Month() startDate = fmt.Sprintf("%d-%d-01", year, month) ) strSql := "select id from t_deliver_study_log where openid = ? and deliver_study_id = ? and create_time > ?;" var hasRead int err := db.Get(&hasRead, strSql, slog.Openid, slog.DeliverStudyId, startDate) strSql = "insert into t_deliver_study_log(openid, deliver_study_id) values(?,?);" sqlResult, _ := db.Exec(strSql, slog.Openid, slog.DeliverStudyId) if ra, _ := sqlResult.RowsAffected(); ra <= 0 { return false, nil } if hasRead == 0 && err == sql.ErrNoRows { var typ string err = db.Get(&typ, "select typ from t_deliver_study where id = ?", slog.DeliverStudyId) if err != nil { log.Println(err) } if err != nil && typ == "STUDY" { db.Exec("update t_deliver_account set score = score + 10 where deliver_user_id = ?;", slog.DeliverUserId) db.Exec("insert into t_deliver_score_bill(deliver_user_id, type, score) values(?,?,?);", slog.DeliverUserId, "STUDY_DATA", 10) } } return true, nil } func (dus *DeliverUserService) Get(openid string) (interface{}, error) { return dus.IDeliverUserDal.Get(openid) } func (dus *DeliverUserService) GetDispatchOrders(city string) (interface{}, error) { db := util.GetSqlDB() strSql := "select shortname from t_city where name = ?;" var shortName string db.Get(&shortName, strSql, strings.TrimRight(city, "市")) if shortName == "" { return nil, errors.New("1::can not resolve city") } strSql = `select t1.order_id, t2.address, t2.detail_address, t2.visit_date, t2.visit_time_range,t3.paynurse, GROUP_CONCAT(t5.sampling) as samplings from t_order_dispatch_pool t1 left join t_order t2 on t1.order_id = t2.id left join t_order_extra t3 on t2.id = t3.order_id left join t_order_product t4 on t3.order_id = t4.order_id left join t_product t5 on t4.product_id = t5.id where t1.order_id like '` + shortName + "%' group by t1.order_id;" var dorders = []struct { OrderId string `db:"order_id" json:"order_id"` Address string `db:"address" json:"address"` DetailAddress string `db:"detail_address" json:"detail_address"` VisitDate string `db:"visit_date" json:"visit_date"` VisitTimeRange string `db:"visit_time_range" json:"visit_time_range"` Samplings null.String `db:"samplings" json:"samplings"` PayNurse int `db:"paynurse" json:"paynurse"` }{} err := db.Select(&dorders, strSql) return dorders, err } //抢单 func (dus *DeliverUserService) ScrambleOrder(duId int, orderId string) (interface{}, error) { db := util.GetWriteSqlDB() strSql := "select order_id, t2.visit_date, t2.visit_time_range from t_order_dispatch_pool t1 left join t_order t2 on t1.order_id = t2.id where order_id = ?;" var sOrder = struct { OrderId string `db:"order_id"` VisitDate null.String `db:"visit_date" json:"visit_date"` VisitTimeRange null.String `db:"visit_time_range" json:"visit_time_range"` }{} db.Get(&sOrder, strSql, orderId) fmt.Println(sOrder) if sOrder.OrderId == "" { return false, errors.New("1::alredy scrambled") } var timeStr = fmt.Sprintf("%v", time.Now().UnixNano()) var upHash = md5.Sum([]byte(timeStr)) strSql = "update t_order_dispatch_pool set uphash = ? where order_id = ? and uphash is null;" tx := db.MustBegin() strHash := fmt.Sprintf("%x", upHash) sqlResult := tx.MustExec(strSql, strHash, orderId) if la, _ := sqlResult.RowsAffected(); la <= 0 { tx.Tx.Rollback() return false, nil } sqlResult = tx.MustExec("delete from t_order_dispatch_pool where order_id = ?", orderId) if la, _ := sqlResult.RowsAffected(); la <= 0 { tx.Tx.Rollback() return false, nil } strSql = "insert into t_order_deliver_user(order_id,deliver_user_id,career,visit_date,visit_time_range,create_at,get_type) values(?,?,?,?,?,?,?);" sqlResult = tx.MustExec(strSql, orderId, duId, "2", sOrder.VisitDate.String, sOrder.VisitTimeRange.String, time.Now().Format("2006-01-02 15:04:05"), "scramble") if la, _ := sqlResult.RowsAffected(); la <= 0 { tx.Tx.Rollback() return false, nil } tx.Commit() return true, nil } func (dus *DeliverUserService) AddWorkdays(duId int, wds []string) (interface{}, error) { if len(wds) == 0 { return false, nil } strSql := "insert into t_deliver_workday(deliver_user_id, date) values" for i, wd := range wds { strSql += fmt.Sprintf("(%d,'%s')", duId, wd) if i < len(wds)-1 { strSql += "," } } db := util.GetWriteSqlDB() sqlResult, err := db.Exec(strSql) if err != nil { return false, err } if la, err := sqlResult.RowsAffected(); la <= 0 { return false, err } go _insertMongo(fmt.Sprintf("%d", duId), strings.Join(wds, ","), 61) return true, nil } func (dus *DeliverUserService) CancelWorkdays(duId int, wds []string) (interface{}, error) { if len(wds) == 0 { return false, nil } var ( strDate string count int ) for i, wd := range wds { strDate += fmt.Sprintf("'%s'", wd) if i < len(wds)-1 { strDate += "," } } db := util.GetWriteSqlDB() strSql := "SELECT count(1) FROM t_order t WHERE id IN ( SELECT order_id FROM t_order_deliver_user t2 WHERE deliver_user_id = ? AND visit_date IN (" + strDate + ")) AND STATUS = '3'" db.Get(&count, strSql, duId) if count > 0 { return false, fmt.Errorf("日期已有预约") } strSql = "delete from t_deliver_workday where deliver_user_id = ? and date in(" + strDate + ");" sqlResult, err := db.Exec(strSql, duId) if err != nil { return false, err } if la, err := sqlResult.RowsAffected(); la <= 0 { return false, err } go _insertMongo(fmt.Sprintf("%d", duId), strings.Join(wds, ","), 62) return true, nil } func (dus *DeliverUserService) GetNurseWorkdays(duId int) (interface{}, error) { var wds = []string{} strSql := "select date from t_deliver_workday where deliver_user_id = ? and date >= ? order by date;" db := util.GetSqlDB() err := db.Select(&wds, strSql, duId, time.Now().Format("2006-01-02")) return wds, err } func (dus *DeliverUserService) GetBills(duId int, pageIndex, pageSize int) (interface{}, error) { return dus.IDeliverUserDal.GetBills(duId, pageIndex, pageSize) } func (dus *DeliverUserService) GetAccountInfo(duId int) (interface{}, error) { strSql := "select * from t_deliver_account where deliver_user_id = ?;" db := util.GetSqlDB() var cinfo = entity.DeliverAccount{} err := db.Get(&cinfo, strSql, duId) if err != nil { if err != sql.ErrNoRows { return nil, err } } vw, err := dus.getNurseValidWithdraw(duId) if err != nil { return nil, err } if cinfo.Remain > vw { cinfo.ValidWithdraw = vw } else { cinfo.ValidWithdraw = cinfo.Remain } return cinfo, nil } func (dus *DeliverUserService) getNurseValidWithdraw(duid int) (int, error) { strSql := "select sum(fee) from t_deliver_bill where deliver_user_id = ? and type ='withdraw' and (created_at between ? and ?);" db := util.GetSqlDB() var ( cwithdrawed null.Int dm = time.Now().Month() dy = time.Now().Year() sm string ) if dm < 10 { sm = fmt.Sprintf("0%d", dm) } else { sm = fmt.Sprintf("%d", dm) } startTime := fmt.Sprintf("%d-%s-01 00:00:00", dy, sm) endTime := time.Now().Format("2006-01-02 15:04:05") err := db.Get(&cwithdrawed, strSql, duid, startTime, endTime) if err != nil { return 0, err } maxVW := 80000 if !cwithdrawed.Valid { return maxVW, nil } if int(cwithdrawed.Int64) > maxVW { return 0, nil } else { return maxVW - int(cwithdrawed.Int64), nil } } //护士订单佣金收益提现 func (dus *DeliverUserService) NurseWithdraw(duId int, money int) (interface{}, error) { if money < 0 { return false, errors.New("wrong param") } var dinfo = struct { Remain int `db:"remain"` Openid string `db:"openid"` }{} var strSql = "select openid, remain from t_deliver_account t1 left join t_deliver_user t2 on t1.deliver_user_id = t2.id where deliver_user_id = ?;" db := util.GetWriteSqlDB() db.Get(&dinfo, strSql, duId) if dinfo.Openid == "" { return false, errors.New("miss openid") } if dinfo.Remain < money { return false, errors.New("1::money not enough") } vw, err := dus.getNurseValidWithdraw(duId) if err != nil { return nil, err } if vw < money { return false, errors.New("2::valid money not enough") } strSql = "update t_deliver_account set remain = remain -?, withdrawed = withdrawed + ? where deliver_user_id = ? and remain = ?;" tx := db.MustBegin() sqlResult, err := tx.Exec(strSql, money, money, duId, dinfo.Remain) if err != nil { return false, err } if la, err := sqlResult.RowsAffected(); la <= 0 { return false, err } wxJsSdk := wx.NewJsSdk() weixin := wx.NewWeixin(wx.DefaultConfig["appid"], wx.DefaultConfig["secret"]) nonceStr := wxJsSdk.GenerateNoncestr(32) billno := fmt.Sprintf("HB%s%s", time.Now().Format("20060102150405"), util.RandNumString(6)) reqItem := map[string]string{ "mch_id": wx.DefaultConfig["mch_id"], "nonce_str": nonceStr, "mch_billno": billno, "wxappid": wx.DefaultConfig["appid"], "send_name": "小鸟快验", "re_openid": dinfo.Openid, "total_amount": fmt.Sprintf("%d", money), "total_num": "1", "wishing": "感谢您的辛勤工作,祝提现愉快", "client_ip": "127.0.0.1", "act_name": "红包提现", "remark": "readpack", } sign := wxJsSdk.ComputePaySignature(reqItem, wx.DefaultConfig["apikey"]) reqItem["sign"] = sign rel, err := weixin.SendRedpack(reqItem, wx.DefaultConfig["cert_file"], wx.DefaultConfig["key_file"]) log.Println(rel) if err != nil { log.Println(err) } if rel["return_code"] == "SUCCESS" && rel["result_code"] == "SUCCESS" { tx.Exec("insert into t_deliver_bill(deliver_user_id, fee, type,billno,status) values(?,?,?,?,'300');", duId, money, "withdraw", billno) tx.Exec("insert into t_deliver_msg(deliver_user_id, title, content,created_at) values(?,?,?,?);", duId, "余额提取成功", fmt.Sprintf("您于%s成提取%d元,系统以微信红包的形式发送至您的微信账号,注意查收。", time.Now().Format("2006-01-02"), money/100), time.Now().Format("2006-01-02 15:04:05")) tx.Commit() } else { tx.Tx.Rollback() return false, fmt.Errorf("2::%s", rel["return_msg"]) } return true, nil } func (dus *DeliverUserService) NurseScoreWithdraw(duId int, money int) (interface{}, error) { if money < 0 { return false, errors.New("wrong param") } var dinfo = struct { ScoreCash int `db:"score_cash"` Openid string `db:"openid"` }{} var strSql = "select openid, score_cash from t_deliver_account t1 left join t_deliver_user t2 on t1.deliver_user_id = t2.id where deliver_user_id = ?;" db := util.GetWriteSqlDB() db.Get(&dinfo, strSql, duId) if dinfo.Openid == "" { return false, errors.New("miss openid") } if dinfo.ScoreCash < money { return false, errors.New("1::money not enough") } strSql = "update t_deliver_account set score_cash = score_cash -?, score_cashed = score_cashed + ? where deliver_user_id = ? and score_cash = ?;" tx := db.MustBegin() sqlResult, err := tx.Exec(strSql, money, money, duId, dinfo.ScoreCash) if err != nil { return false, err } if la, err := sqlResult.RowsAffected(); la <= 0 { return false, err } wxJsSdk := wx.NewJsSdk() weixin := wx.NewWeixin(wx.DefaultConfig["appid"], wx.DefaultConfig["secret"]) nonceStr := wxJsSdk.GenerateNoncestr(32) billno := fmt.Sprintf("HB%s%s", time.Now().Format("20060102150405"), util.RandNumString(6)) reqItem := map[string]string{ "mch_id": wx.DefaultConfig["mch_id"], "nonce_str": nonceStr, "mch_billno": billno, "wxappid": wx.DefaultConfig["appid"], "send_name": "小鸟快验", "re_openid": dinfo.Openid, "total_amount": fmt.Sprintf("%d", money), "total_num": "1", "wishing": "感谢您的辛勤工作,祝提现愉快", "client_ip": "127.0.0.1", "act_name": "金币兑换红包提现", "remark": "readpack", } sign := wxJsSdk.ComputePaySignature(reqItem, wx.DefaultConfig["apikey"]) reqItem["sign"] = sign rel, err := weixin.SendRedpack(reqItem, wx.DefaultConfig["cert_file"], wx.DefaultConfig["key_file"]) log.Println(rel) if err != nil { log.Println(err) } if rel["return_code"] == "SUCCESS" && rel["result_code"] == "SUCCESS" { tx.Exec("insert into t_deliver_score_bill(deliver_user_id, score, type,billno) values(?,?,?,?);", duId, money, "WITHDRAW", billno) tx.Exec("insert into t_deliver_msg(deliver_user_id, title, content,created_at) values(?,?,?,?);", duId, "金币提现成功", fmt.Sprintf("您于%s成提取%d元,系统以微信红包的形式发送至您的微信账号,注意查收。", time.Now().Format("2006-01-02"), money/100), time.Now().Format("2006-01-02 15:04:05")) tx.Commit() } else { tx.Tx.Rollback() return false, fmt.Errorf("2::%s", rel["return_msg"]) } return true, nil } func (dus *DeliverUserService) NurseMsg(duId int, pageIndex, pageSize int, city string) (interface{}, error) { db := util.GetSqlDB() var cityId int db.Get(&cityId, "select id from t_city where name = ?", strings.TrimRight(city, "市")) if cityId <= 0 { return nil, errors.New("1::unknow city") } return dus.IDeliverUserDal.GetMsg(duId, pageIndex, pageSize, cityId) } func (dus *DeliverUserService) UpdateNurseMsg(duId int) (interface{}, error) { strSql := "update t_deliver_msg set is_read = 'Y' where deliver_user_id = ?;" db := util.GetWriteSqlDB() sqlResult, err := db.Exec(strSql, duId) if err != nil { return nil, err } if la, _ := sqlResult.RowsAffected(); la <= 0 { return false, errors.New("1::更新失败") } return true, nil } func (dus *DeliverUserService) AddChatMsg(msgItem *entity.DeliverChatMsg) (interface{}, error) { db := util.GetWriteSqlDB() strSql := "insert into t_deliver_chat(fu,tu,message) values(?,?,?);" sqlResult, err := db.Exec(strSql, msgItem.From, msgItem.To, msgItem.Message) if err != nil { return nil, err } if la, _ := sqlResult.RowsAffected(); la <= 0 { return false, errors.New("1::保存失败") } return true, nil } func (dus *DeliverUserService) GetChatMsg(duId int, pageIndex int) (interface{}, error) { if pageIndex <= 0 { pageIndex = 1 } strSql := "select * from t_deliver_chat where fu = ? or tu = ? order by created_at desc limit ?,?;" db := util.GetSqlDB() var msgList = []entity.DeliverChatMsg{} err := db.Select(&msgList, strSql, duId, duId, (pageIndex-1)*20, 20) return msgList, err } func (dus *DeliverUserService) NurseSignIn(duId int) (interface{}, error) { continuousDay, isTodaySignin, err := dus.getNurseSignInDays(duId) if err != nil { return 0, err } if isTodaySignin { return 0, errors.New("1::alredy signin today") } var toAddScore = continuousDay + 1 if toAddScore > 7 { toAddScore = 7 } db := util.GetWriteSqlDB() tx := db.MustBegin() strSql := "insert into t_deliver_score_bill(deliver_user_id, type, score) values(?,?,?);" sqlResult, err := tx.Exec(strSql, duId, "SIGNIN", toAddScore*10) if err != nil { tx.Tx.Rollback() return 0, err } if ra, _ := sqlResult.RowsAffected(); ra <= 0 { tx.Tx.Rollback() return 0, nil } strSql = "update t_deliver_account set score = score + ? where deliver_user_id = ?;" sqlResult = tx.MustExec(strSql, toAddScore*10, duId) if ra, _ := sqlResult.RowsAffected(); ra <= 0 { tx.Tx.Rollback() return 0, errors.New("failed to update score") } tx.Commit() return toAddScore, nil } //func (dus *DeliverUserService) _updateScore(duId int, typ string, score int){} // get nurse continuous signin days func (dus *DeliverUserService) getNurseSignInDays(duId int) (int, bool, error) { var ( now = time.Now() startDate = now.AddDate(0, 0, -7).Format("2006-01-02") endDate = now.Format("2006-01-02") + " 23:59:59" ) strSql := "select created_at from t_deliver_score_bill where deliver_user_id = ? and type = 'SIGNIN' and created_at between ? and ? order by created_at desc;" db := util.GetSqlDB() var signInDays = []string{} err := db.Select(&signInDays, strSql, duId, startDate, endDate) if err != nil { return 0, false, err } if len(signInDays) == 0 { return 0, false, nil } continuousDay := 0 today_sign := false if signInDays[0] > now.Format("2006-01-02") { today_sign = true signInDays = signInDays[1:] continuousDay++ } for i, dtime := range signInDays { if dtime > now.AddDate(0, 0, -i-1).Format("2006-01-02") { continuousDay++ } else { break } } return continuousDay, today_sign, nil } func (dus *DeliverUserService) _hasAnswerDailyQuestion(duid int) bool { today := time.Now().Format("2006-01-02") strSql := "select count(*) from t_deliver_score_bill where type = 'DAILY_QUESTION' and created_at between ? and ? and deliver_user_id = ?" db := util.GetSqlDB() var hasAnswerDailyQuestion int db.Get(&hasAnswerDailyQuestion, strSql, today, today+" 23:59:59", duid) return hasAnswerDailyQuestion > 0 } func (dus *DeliverUserService) NurseScore(duId int) (interface{}, error) { strSql := "select score,score_cash from t_deliver_user t1 left join t_deliver_account t2 on t1.id = t2.deliver_user_id where t1.id = ?;" db := util.GetSqlDB() var scoreInfo = struct { Score null.Int `db:"score"` ScoreCash null.Int `db:"score_cash"` }{} err := db.Get(&scoreInfo, strSql, duId) if err != nil { return nil, err } continuousDay, isTodaySignin, err := dus.getNurseSignInDays(duId) if err != nil { return nil, err } var isFirstInvite int strSql = "select count(*) from t_deliver_user where invite_by in (select openid from t_deliver_user where id = ?);" db.Get(&isFirstInvite, strSql, duId) strSql = "select count(*) from t_deliver_score_bill where deliver_user_id = ? and type = 'ORDER';" var isCompleteFirstOrder int db.Get(&isCompleteFirstOrder, strSql, duId) return map[string]interface{}{ "score": scoreInfo.Score, "score_cash": scoreInfo.ScoreCash, "is_today_signin": isTodaySignin, "continuous_day": continuousDay, "is_first_invite": isFirstInvite > 0, "is_complete_first_order": isCompleteFirstOrder > 0, "is_answer_daily_question": dus._hasAnswerDailyQuestion(duId), }, nil } func (dus *DeliverUserService) GetScoreBill(duId, pageIndex, pageSize int, typ string) (interface{}, error) { return dus.IDeliverUserDal.GetScoreBill(duId, pageIndex, pageSize, typ) } func (dus *DeliverUserService) GetIFStatus(openid string, status string, pageIndex, pageSize int) (interface{}, error) { if pageSize <= 0 { pageSize = 5 } var strStatus string switch status { case "1": strStatus = "(1,2,3)" case "4": strStatus = "(4,5,6)" case "7": strStatus = "(7)" default: return nil, errors.New("1::wrong param status") } skip := (pageIndex - 1) * pageSize strSql := "select name, head_pic, process_staus,t2.nickname,t2.headimgurl from t_deliver_user t1 left join t_wechat_userinfo t2 on t1.openid = t2.openid where invite_by = ? and process_staus in" + strStatus + " order by create_at desc limit ?,? ;" db := util.GetSqlDB() var friends = []struct { Nickname null.String `json:"nickname"` HeadImgUrl null.String `json:"headimgurl"` Name string `json:"name"` HeadPic string `json:"head_pic"` Status string `json:"process_staus" db:"process_staus"` }{} err := db.Select(&friends, strSql, openid, skip, pageSize) if err != nil { return nil, err } //return friends, err var count int strSql = "select count(1) from t_deliver_user where invite_by = ? and process_staus in" + strStatus + "" err = db.Get(&count, strSql, openid) if err != nil { return nil, err } return map[string]interface{}{"data": friends, "total": count}, nil } var dailyQuestionMutex = &sync.Mutex{} func (dus *DeliverUserService) DailyQuestion() (interface{}, error) { dailyQuestionMutex.Lock() defer dailyQuestionMutex.Unlock() day := time.Now().Format("2006-01-02") v, _ := util.GetRedisValue("DAILIY_QUESTION") var ( lastDay string skipNums int ) if v != "" { temps := strings.Split(v, "*") if len(temps) < 2 { return nil, errors.New("config error") } lastDay = temps[0] skipNums, _ = strconv.Atoi(temps[1]) if lastDay != day { skipNums += 1 lastDay = day } } db := util.GetSqlDB() strSql := "select count(*) from t_deliver_exam where flag = 'Y';" var qnums int err := db.Get(&qnums, strSql) if err != nil { return nil, err } if qnums <= skipNums { skipNums = 0 } util.SetRedisValue("DAILIY_QUESTION", fmt.Sprintf("%s*%d", lastDay, skipNums), 0) strSql = "select * from t_deliver_exam where flag = 'Y' order by id asc limit ?,1;" question := &entity.ExamQuestion{} err = db.Get(question, strSql, skipNums) if err != nil && err != sql.ErrNoRows { return nil, err } strSql = "select * from t_deliver_exam_option where exam_id = ? and flag = 'Y' order by id asc;" var options = []entity.ExamOption{} err = db.Select(&options, strSql, question.Id) if err != nil { return nil, err } question.Options = options return question, nil } func (dus *DeliverUserService) CheckQuestion(duid int, question *entity.ExamQuestion) (interface{}, error) { if dus._hasAnswerDailyQuestion(duid) { return nil, errors.New("1::alredy answered") } strSql := "select answer from t_deliver_exam where id = ?;" db := util.GetSqlDB() var answer string err := db.Get(&answer, strSql, question.Id) var result = map[string]interface{}{ "check_result": false, } if err != nil { return result, err } if answer == question.InAnswer { db.Exec("update t_deliver_account set score = score + 100 where deliver_user_id = ?;", duid) db.Exec("insert into t_deliver_score_bill(deliver_user_id, type, score) values(?,?,?);", duid, "DAILY_QUESTION", 100) result["check_result"] = true return result, nil } else { db.Exec("update t_deliver_account set score = score + 20 where deliver_user_id = ?;", duid) db.Exec("insert into t_deliver_score_bill(deliver_user_id, type, score) values(?,?,?);", duid, "DAILY_QUESTION", 20) } result["right_answer"] = answer return result, nil } //qz 检测项录入 20200826 func (dus *DeliverUserService) DetectInfoAdd(params []entity.DetectInfoParam) (bool, error) { fmt.Println(params) dus.IOrder = dal.DefaultOrderDal //遍历params 根据 order_no 状态 ==3 查找 order 如果没有,终止并返回 order, err := dus.IOrder.Get(params[0].OrderId) if err != nil || order == nil { return false, errors.New("1::order record not found") } if order.Status != 3 { return false, errors.New("2::order status not 3") } age := order.Age //有生日取生日,没有生日取age birthAge, err := util.BirthDayToAge(order.Birthday) if err == nil { age = birthAge } var gender string switch order.Gender { case 1: gender = "男" case 2: gender = "女" default: gender = "" } db := util.GetWriteSqlDB() tx := db.MustBegin() var cdr entity.DetectInfoDB var sqlResult sql.Result for _, v := range params { //查询order_no detect_item_id 查询数据,如果没有就新建,有就更新 //获取 记录 判断各字段为空的情况 sql := "select order_no, detect_item_id, final, unit, refValue, age, gender, checker, approver, checkTime, createdAt, is_self, final_status, final_tip, extra from t_custom_detect_result where order_no= ? and detect_item_id= ?" err = db.Get(&cdr, sql, v.OrderId, v.DetectItemID) //存在数据就update 不存在就insert if err != nil { //insert sql = "insert t_custom_detect_result(order_no,detect_item_id,final,unit,refValue,age,gender,final_status,createdAt,is_self) values(?,?,?,?,?,?,?,?,?,?)" sqlResult, err = tx.Exec(sql, v.OrderId, v.DetectItemID, v.Final, v.Unit, v.RefValue, age, gender, v.Status, v.CreatedAt, v.IsSelf) } else { //update sql = "update t_custom_detect_result set final = ?,unit=?,refValue=?,age=?,gender=?,final_status=?,is_self=? where order_no=? and detect_item_id=?" sqlResult, err = tx.Exec(sql, v.Final, v.Unit, v.RefValue, age, gender, v.Status, v.IsSelf, v.OrderId, v.DetectItemID) } //执行结果 if err != nil { tx.Rollback() return false, err } if la, err := sqlResult.RowsAffected(); la <= 0 { fmt.Println(err) } } tx.Commit() return true, nil } func (dus *DeliverUserService) GetIsSkip(duId int, isSkip string) (bool, error) { strSql := "update t_deliver_user set is_skip = ?,update_time=? where id = ?;" db := util.GetWriteSqlDB() sqlResult, err := db.Exec(strSql, isSkip, time.Now().Format("2006-01-02 15:04:05"), duId) if err != nil { return false, err } if la, _ := sqlResult.RowsAffected(); la <= 0 { return false, errors.New("1::更新失败") } return true, nil } //20210819 护士出门签到200 发送验证码 func (dus *DeliverUserService) SendVCode(orderId string) error { const sms_key string = "xn:sms_key:" smsType := 25 vcode := generateValidateCode(6) strSql := "select * from t_sms_tpl where id = ?;" db := util.GetSqlDB() var smsTpl = struct { Content string `db:"content"` Id int `db:"id"` HasCode uint8 `db:"has_code"` CodeType int `db:"code_type"` }{} db.Get(&smsTpl, strSql, smsType) if smsTpl.Content == "" { return fmt.Errorf("1:: ordersign 200 err no sms_tpl by %d", smsType) } params := map[string]string{} params["code"] = vcode smsContent := strings.Replace(smsTpl.Content, "{code}", vcode, -1) //smsContent = strings.Replace()"您的订单【{OrderId}】" var item struct { Mobile string `db:"mobile"` VisitDate string `db:"visit_date"` TimeRange string `db:"visit_time_range"` VCode null.String `db:"vcode"` } //20210903 这里加了一个redis 锁,注意此处用法忽略了上完锁后没有设置过期时间就立刻挂掉的情况 client := util.GetRedis() client.Select(14) cmd := client.SetNX(sms_key+item.Mobile, "1") if !cmd.Val() || cmd.Err() != nil { log.Println(cmd.Err()) return fmt.Errorf("6:: redis error") } client.Expire(sms_key+item.Mobile, time.Second*3) defer client.Del(sms_key + item.Mobile) strSql = "select mobile,visit_date,visit_time_range,vcode from t_order where id = ? " db.Get(&item, strSql, orderId) if !util.IsMobile(item.Mobile) { return fmt.Errorf("2:: ordersign 200 err mobile %s by id %s ", item.Mobile, orderId) } //如果vcode 不为空,直接返回 if item.VCode.Valid && item.VCode.String != "" { return nil } strSql = "update t_order set vcode = ? where mobile = ? and visit_date = ? and visit_time_range = ?" //sqlResult, err := db.Exec(strSql, vcode, orderId) sqlResult, err := db.Exec(strSql, vcode, item.Mobile, item.VisitDate, item.TimeRange) if err != nil { return fmt.Errorf("4:: ordersign 200 err update order vcode err id %s err:%s", orderId, err.Error()) } if la, _ := sqlResult.RowsAffected(); la <= 0 { return fmt.Errorf("5:: ordersign 200 err update order vcode err id %s", orderId) } err = util.SendSMS(item.Mobile, smsContent) if err != nil { return fmt.Errorf("3:: ordersign 200 err send mobile %s err:%s", item.Mobile, err.Error()) } return nil } //20210819 护士签到201 校验证码 func (dus *DeliverUserService) VerifyCode(orderId, vCode string) error { stuff := struct { Code null.String `db:"vcode"` Source string `db:"source"` }{} db := util.GetSqlDB() strSql := "select vcode,source from t_order where id = ? limit 1" db.Get(&stuff, strSql, orderId) //fmt.Println(err) if stuff.Source != "jd-jyd" { //todo 判断jd-jyd 走流程 if vCode == getVcodeFromRedis() { return nil } if !strings.EqualFold(vCode, stuff.Code.String) { return fmt.Errorf("1:: ordersign 201 verify vcode err :your:%s, system:%s by id %s", vCode, stuff.Code.String, orderId) } return nil } else { //去京东核销 if vCode == getVcodeFromRedis()+"0" { return nil } err := HeXiaoToJD(orderId, vCode) if err != nil { return err } return nil } } func getVcodeFromRedis() string { //return "667043" return util.GetNurseCode() } //20210713 增加 t_deliver_workday 日志 func _insertMongo(name, data string, dbtype int) { db := util.GetMgoDB() if db == nil { return } defer db.Session.Close() err := db.C("t_log").Insert(bson.M{ "name": name, "type": dbtype, "data": data, "createby": "go", "create": time.Now().Format("2006-01-02 15:04:05"), }) if err != nil { fmt.Println(err) return } } //20220309 jd 核销 func HeXiaoToJD(orderId, code string) error { url := config.IniConf.Section("server").Key("jdapi").String() path := "/v2/hexiao" reader := bytes.NewReader([]byte(fmt.Sprintf(`{"order_id":"%s","random_code":"%s"}`, orderId, code))) resp, err := http.Post(url+path, "application/json", reader) if err != nil { return fmt.Errorf("access jdservice error:%s", err.Error()) } defer resp.Body.Close() resBuf, err := ioutil.ReadAll(resp.Body) if err != nil { return fmt.Errorf("response jdservice error:%s", err.Error()) } result := map[string]string{} err = json.Unmarshal(resBuf, &result) if err != nil { return fmt.Errorf("jsonUnmarshal jdservice error:%s", string(resBuf)) } if resCode := result["code"]; resCode != "0" { return fmt.Errorf("json jdservice error:%s", string(resBuf)) } return nil } // 20221009 护士加项产品获取考试试题 func (dus *DeliverUserService) GetProductExam(productid int) (interface{}, error) { sql := "select paper_id from t_product_question_map where product_id = ? limit 1" db := util.GetSqlDB() var err error defer fmt.Println(err) var paperId int db.Get(&paperId, sql, productid) if paperId == 0 { return nil, fmt.Errorf("1:: no exam by product_id %d", productid) } sql = "select id,name from t_product_question_title where paper_id = ? and flag = 1 order by sort_no" titles := []entity.ProductQuestion{} err = db.Select(&titles, sql, paperId) if len(titles) == 0 { return nil, fmt.Errorf("2:: no exam titles by product_id %d", productid) } var rn int tempIds := map[int]struct{}{} l := len(titles) num := NOURSE_EXAME_NUMS if num > l { num = l } for i := 0; i < num; i++ { for { rn = rand.Intn(l) //+ 1 if _, ok := tempIds[rn]; !ok { tempIds[rn] = struct{}{} break } } } var strTitleIds string //for k := range titles { // strTitleIds += fmt.Sprintf("%d,", titles[k].ID) //} for k := range tempIds { strTitleIds += fmt.Sprintf("%d,", titles[k].ID) } strTitleIds = strTitleIds[0 : len(strTitleIds)-1] sql = "select id,name from t_product_question_title where id in (" + strTitleIds + ") and flag = 1 order by sort_no" titles = []entity.ProductQuestion{} err = db.Select(&titles, sql) options := []entity.ProductOption{} sql = "select id ,name,title_id,value from t_product_question_option where title_id in (" + strTitleIds + ") and flag = 1" db.Select(&options, sql) if len(options) == 0 { return nil, fmt.Errorf("3:: no exam options by product_id %d", productid) } for i := range options { for j := range titles { if titles[j].ID == options[i].TitleId { titles[j].Options = append(titles[j].Options, options[i]) } } } return titles, nil } // 20221009 护士加项产品考试检查 func (dus *DeliverUserService) CheckProductExam(duId int, productId int, answers []entity.ProductQuestion) (interface{}, error) { db := util.GetSqlDB() // 20221017 这里不增加 is_delete 判断,会影响后续 strSql := "select count(1) from t_product_question_deliver where deliver_user_id = ? and product_id =? " var count int db.Get(&count, strSql, duId, productId) // 如果已经存在关系,表示考试通过 if count > 0 { return nil, nil } strIds := "" for _, q := range answers { strIds += fmt.Sprintf("%d,", q.ID) } strIds = strIds[0 : len(strIds)-1] var eqs = []entity.ProductQuestion{} //strSql = "select id, answer_value,paper_id from t_product_question_title where id in(" + strIds + ");" strSql = "select t.id, t.answer_value,t.paper_id from t_product_question_map m left join t_product_question_title t on m.paper_id = t.paper_id where m.product_id=? and t.id in (" + strIds + ")" //err := db.Select(&eqs, strSql) err := db.Select(&eqs, strSql, productId) if err != nil { return nil, err } if len(eqs) != len(answers) { return nil, fmt.Errorf("1::CheckProductExam data error your answer titles is %s productid is %d", strIds, productId) } paperId := eqs[0].PaperId for _, question := range answers { for _, eq := range eqs { if question.ID == eq.ID && eq.AnswerValue != question.InAnswerValue { return nil, fmt.Errorf("2:: title %d correct answer is %d your answer is %d", eq.ID, eq.AnswerValue, question.InAnswerValue) } } } strSql = fmt.Sprintf("insert into t_product_question_deliver (deliver_user_id,product_id,discount_price) select %d,%d, discount_price from t_product_question_map where product_id=? and paper_id=?", duId, productId) sqlResult, err := db.Exec(strSql, productId, paperId) if err != nil { return nil, fmt.Errorf("3:: t_product_question_deliver 创建数据失败 error:%s ,productid: %d, deliver_user_id: %d, paper_id: %d ", err.Error(), productId, duId, paperId) } if ra, _ := sqlResult.RowsAffected(); ra < 1 { return nil, fmt.Errorf("4:: t_product_question_deliver 创建数据失败 productid: %d, deliver_user_id: %d, paper_id: %d", productId, duId, paperId) } return nil, nil } // 20221011 护士加项产品列表 func (dus *DeliverUserService) GetDeliverProductList(pageIndex, pageSize int) (interface{}, error) { db := util.GetSqlDB() list := []struct { Id int `db:"id" json:"id"` Name string `db:"name" json:"name"` Picture null.String `db:"picture"` Price int `db:"price" json:"price"` DiscountPrice int `db:"discount_price" json:"discount_price"` WikiPath null.String `db:"wiki_path" json:"wiki_path"` TitleName null.String `db:"title_name" json:"title_name"` PaperId int `db:"paper_id" json:"paper_id"` }{} if pageIndex < 1 { pageIndex = 1 } if pageSize <= 0 { pageSize = 10 } limit := fmt.Sprintf(" limit %d,%d ", (pageIndex-1)*pageSize, pageSize) // 优惠的在前,按照创建时间倒叙 sql := "select p.id,p.name,p.picture,p.price,m.discount_price,m.wiki_path,pa.name as title_name ,m.paper_id,CASE WHEN m.paper_id > 0 THEN 1 ELSE 0 END AS flag from t_product_question_map m left join t_product p on p.id = m.product_id left join t_product_question_paper pa on m.paper_id = pa.id where m.is_delete = 0 order by flag DESC ,m.created_at desc " + limit db.Select(&list, sql) return list, nil } // 20221011 护士加项判断是否通过 func (*DeliverUserService) CheckDeliverPass(productId, duId int) (bool, error) { db := util.GetSqlDB() // 20221017 这里不增加 is_delete 判断,会影响后续 sql := "select count(1) from t_product_question_deliver where product_id = ? and deliver_user_id = ?" var count int db.Get(&count, sql, productId, duId) if count > 0 { return true, nil } return false, nil } func (*DeliverUserService) GetProductDiscount(productId, duId int) (int, error) { db := util.GetSqlDB() sql := "select discount_price from t_product_question_deliver where product_id = ? and deliver_user_id = ? and is_delete = 0" var discount int err := db.Get(&discount, sql, productId, duId) if err != nil { return 0, fmt.Errorf("1:: no discount by product_id: %d deliver_user_id: %d", productId, duId) } return discount, nil } // 20221017 根据产品id 获取知识库内容 func (*DeliverUserService) GetWikiByProductId(productId int) (interface{}, error) { db := util.GetSqlDB() sql := "select paper_id, wiki_path from t_product_question_map where product_id = ?" data := struct { PaperId int `db:"paper_id" json:"paper_id"` WikiPath null.String `db:"wiki_path" json:"wiki_path"` }{} err := db.Get(&data, sql, productId) if err != nil { return nil, fmt.Errorf("1:: no wiki by product_id %d", productId) } return data, nil }