charge_urge.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. // Copyright 2019 getensh.com. All rights reserved.
  2. // Use of this source code is governed by getensh.com.
  3. package charge
  4. import (
  5. "context"
  6. "encoding/json"
  7. "fmt"
  8. "git.getensh.com/common/gopkgs/database"
  9. "git.getensh.com/common/gopkgs/logger"
  10. "go.uber.org/zap"
  11. "google.golang.org/grpc/status"
  12. "gorm.io/gorm"
  13. "property-garden/errors"
  14. "property-garden/impl/v1/charge_utils"
  15. dbmodel "property-garden/model"
  16. "property-garden/parser"
  17. "property-garden/pb"
  18. pb_v1 "property-garden/pb/v1"
  19. "property-garden/utils"
  20. )
  21. func checkChargeUrgeParam(req *pb_v1.ChargeUrgeRequest) error {
  22. switch {
  23. case req.GardenId == 0:
  24. return status.Error(10003, "小区不能为空")
  25. case req.ObjId == 0:
  26. return status.Error(10003, "对象不能为空")
  27. case req.ObjType != charge_utils.ObjTypeHouse &&
  28. req.ObjType != charge_utils.ObjTypeSpace &&
  29. req.ObjType != charge_utils.ObjTypeVehicle:
  30. return status.Error(10003, "不支持的对象类型")
  31. }
  32. return nil
  33. }
  34. func getPublicOpenId(objId int64, objType int32, dbname string) ([]string, error) {
  35. houseId := int64(0)
  36. houseUid := int64(0)
  37. if objType == charge_utils.ObjTypeVehicle {
  38. vehicle := dbmodel.NewVehicle(dbname)
  39. where := map[string]interface{}{
  40. "id": objId,
  41. }
  42. err := vehicle.Find(database.DB(), where)
  43. if err != nil && err != gorm.ErrRecordNotFound {
  44. return nil, errors.DataBaseError
  45. }
  46. houseUid = vehicle.HouseholdUid
  47. } else {
  48. bind := dbmodel.NewChargeBind(dbname)
  49. where := map[string]interface{}{
  50. "obj_id": objId,
  51. "obj_type": objType,
  52. }
  53. err := bind.Find(database.DB(), where)
  54. if err != nil && err != gorm.ErrRecordNotFound {
  55. return nil, errors.DataBaseError
  56. }
  57. houseId = bind.HouseId
  58. }
  59. p := dbmodel.NewHouseApprovedGarden(dbname)
  60. where := map[string]interface{}{}
  61. if houseId > 0 {
  62. where["house_id"] = houseId
  63. }
  64. if houseUid > 0 {
  65. where["uid"] = houseUid
  66. }
  67. if len(where) == 0 {
  68. return nil, status.Error(10003, "未找到催缴对象")
  69. }
  70. list, err := p.List(database.DB(), where, nil, -1, -1)
  71. if err != nil {
  72. return nil, errors.DataBaseError
  73. }
  74. ret := []string{}
  75. for _, v := range list {
  76. if objType != charge_utils.ObjTypeHouse && v.UserType != 1 {
  77. continue
  78. }
  79. ret = append(ret, v.PublicOpenId)
  80. }
  81. if len(ret) == 0 {
  82. return nil, status.Error(10003, "住户未关注公众号,无法推送消息")
  83. }
  84. return ret, nil
  85. }
  86. func getPhoneAndPublicOpenId(objId int64, objType int32, dbname string) ([]string, []string, error) {
  87. houseId := int64(0)
  88. houseUid := int64(0)
  89. if objType == charge_utils.ObjTypeVehicle {
  90. vehicle := dbmodel.NewVehicle(dbname)
  91. where := map[string]interface{}{
  92. "id": objId,
  93. }
  94. err := vehicle.Find(database.DB(), where)
  95. if err != nil && err != gorm.ErrRecordNotFound {
  96. return nil, nil, errors.DataBaseError
  97. }
  98. houseUid = vehicle.HouseholdUid
  99. } else {
  100. bind := dbmodel.NewChargeBind(dbname)
  101. where := map[string]interface{}{
  102. "obj_id": objId,
  103. "obj_type": objType,
  104. }
  105. err := bind.Find(database.DB(), where)
  106. if err != nil && err != gorm.ErrRecordNotFound {
  107. return nil, nil, errors.DataBaseError
  108. }
  109. houseId = bind.HouseId
  110. }
  111. p := dbmodel.NewHouseApprovedGarden(dbname)
  112. where := map[string]interface{}{}
  113. if houseId > 0 {
  114. where["house_id"] = houseId
  115. }
  116. if houseUid > 0 {
  117. where["uid"] = houseUid
  118. }
  119. if len(where) == 0 {
  120. return nil, nil, status.Error(10003, "未找到催缴对象")
  121. }
  122. list, err := p.List(database.DB(), where, nil, -1, -1)
  123. if err != nil {
  124. return nil, nil, errors.DataBaseError
  125. }
  126. popenIds := []string{}
  127. phones := []string{}
  128. popenIdM := map[string]bool{}
  129. phoneM := map[string]bool{}
  130. for _, v := range list {
  131. if objType != charge_utils.ObjTypeHouse && v.UserType != 1 {
  132. continue
  133. }
  134. if _, ok := phoneM[v.Phone]; !ok && v.Phone != "" {
  135. phoneM[v.Phone] = true
  136. phones = append(phones, v.Phone)
  137. }
  138. if _, ok := popenIdM[v.PublicOpenId]; !ok && v.PublicOpenId != "" {
  139. popenIdM[v.PublicOpenId] = true
  140. popenIds = append(popenIds, v.PublicOpenId)
  141. }
  142. }
  143. return popenIds, phones, nil
  144. }
  145. var UrgeTitleM = map[int32]string{
  146. charge_utils.ObjTypeHouse: "您的房屋有欠费账单",
  147. charge_utils.ObjTypeSpace: "您的车位有欠费账单",
  148. charge_utils.ObjTypeVehicle: "您的车辆有欠费账单",
  149. }
  150. func getOneAvailable(msgArray [][3]int64, index int) int {
  151. if index >= len(msgArray) || index < 0 {
  152. return -1
  153. }
  154. if msgArray[index][1] > 0 {
  155. return index
  156. }
  157. if index+1 >= len(msgArray) {
  158. return -1
  159. }
  160. return index + 1
  161. }
  162. // 发送短信消息
  163. func sendMsgPhone(phones []string, gardenName string, msgArray [][3]int64) {
  164. index := 0
  165. for _, phone := range phones {
  166. index = getOneAvailable(msgArray, index)
  167. if index < 0 {
  168. break
  169. }
  170. mreq := pb_v1.TencentMsgSendRequest{
  171. Phone: phone,
  172. MsgType: 1,
  173. Datas: []string{gardenName},
  174. }
  175. _, err := pb.Thirdparty.TencentMsgSend(context.Background(), &mreq)
  176. if err != nil {
  177. logger.Error("func",
  178. zap.String("call", "pb.Garden.TencentMsgSend "),
  179. zap.String("error", err.Error()))
  180. continue
  181. }
  182. msgArray[index][1] = msgArray[index][1] - 1
  183. }
  184. }
  185. func getGardenAvailableMsgCount(gardenId int64) [][3]int64 {
  186. // 0:存套餐订单id
  187. // 1:存套餐订单剩余量(发一条短信自减)
  188. // 2:存套餐订单原始剩余量
  189. ret := [][3]int64{}
  190. mreq := pb_v1.MsgPackageOrderListRequest{
  191. Available: true,
  192. Status: 2,
  193. PageSize: -1,
  194. Page: -1,
  195. GardenId: gardenId,
  196. }
  197. mreply, err := pb.System.MsgPackageOrderList(context.Background(), &mreq)
  198. if err != nil {
  199. logger.Error("func",
  200. zap.String("call", "pb.System.MsgPackageOrderList"),
  201. zap.String("error", err.Error()))
  202. return ret
  203. }
  204. for _, v := range mreply.List {
  205. ret = append(ret, [3]int64{v.OrderId, v.MsgAvailableCount, v.MsgAvailableCount})
  206. }
  207. return ret
  208. }
  209. func gardenAvailableMsgDecrease(msgArray [][3]int64, gardenId int64) {
  210. mreq := pb_v1.MsgPackageOrderDecreaseRequest{GardenId: gardenId}
  211. for _, array := range msgArray {
  212. if array[2]-array[1] <= 0 {
  213. continue
  214. }
  215. mreq.Count = array[2] - array[1]
  216. mreq.OrderId = array[0]
  217. _, err := pb.System.MsgPackageOrderDecrease(context.Background(), &mreq)
  218. if err != nil {
  219. logger.Error("func",
  220. zap.String("call", "pb.System.MsgPackageOrderDecrease"),
  221. zap.String("error", err.Error()))
  222. }
  223. }
  224. }
  225. func ChargeUrge(ctx context.Context, req *pb_v1.ChargeUrgeRequest) (reply *pb_v1.ChargeUrgeReply, err error) {
  226. reply = &pb_v1.ChargeUrgeReply{}
  227. // 捕获各个task中的异常并返回给调用者
  228. defer func() {
  229. if r := recover(); r != nil {
  230. err = fmt.Errorf("%+v", r)
  231. e := &status.Status{}
  232. if er := json.Unmarshal([]byte(err.Error()), e); er != nil {
  233. logger.Error("err",
  234. zap.String("system_err", err.Error()),
  235. zap.Stack("stacktrace"))
  236. }
  237. }
  238. }()
  239. // 参数检查
  240. err = checkChargeUrgeParam(req)
  241. if err != nil {
  242. return nil, err
  243. }
  244. gardenInfo, err := charge_utils.GetGardenInfos([]int64{req.GardenId})
  245. if err != nil {
  246. return nil, err
  247. }
  248. gardenName := gardenInfo[req.GardenId].GardenName
  249. dbname := utils.GetGardenDbName(req.GardenId)
  250. openIds, phones, err := getPhoneAndPublicOpenId(req.ObjId, req.ObjType, dbname)
  251. if err != nil {
  252. return nil, err
  253. }
  254. title := UrgeTitleM[req.ObjType]
  255. remark := "详情请进入小程序查看"
  256. content := []*pb_v1.WxPublicMsgKeyValue{
  257. &pb_v1.WxPublicMsgKeyValue{Key: "first", Value: fmt.Sprintf("%s(%s)", title, gardenName)},
  258. &pb_v1.WxPublicMsgKeyValue{Key: "remark", Value: remark},
  259. }
  260. oneSuccess := false
  261. for i, v := range openIds {
  262. mreq := pb_v1.WxPublicMsgSendRequest{
  263. PublicOpenId: v,
  264. Content: content,
  265. TemplateId: parser.Conf.ThirdParty.Wx.PublicMsgTmpId,
  266. }
  267. _, err := pb.Thirdparty.WxPublicMsgSend(ctx, &mreq)
  268. if err == nil {
  269. oneSuccess = true
  270. continue
  271. }
  272. if !oneSuccess && err != nil && i == len(openIds)-1 {
  273. return nil, err
  274. }
  275. }
  276. // 短信消息
  277. if len(phones) > 0 {
  278. msgArray := getGardenAvailableMsgCount(req.GardenId)
  279. sendMsgPhone(phones, gardenName, msgArray)
  280. gardenAvailableMsgDecrease(msgArray, req.GardenId)
  281. }
  282. return reply, nil
  283. }