charge_pre_pay_by_household.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  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. pb_v1 "property-garden/pb/v1"
  17. "property-garden/utils"
  18. "time"
  19. )
  20. func checkChargePrePayByHouseholdParam(req *pb_v1.ChargePrePayByHouseholdRequest) error {
  21. switch {
  22. case req.GardenId == 0:
  23. return status.Error(10003, "小区不能为空")
  24. case req.BindId == 0:
  25. return status.Error(10003, "房屋/车位/车辆没有绑定费用")
  26. case req.Months == 0:
  27. return status.Error(10003, "月数不能为空")
  28. case req.ShouldPayAmount == 0:
  29. return status.Error(10003, "应收金额不能为空")
  30. case req.PayAmount == 0:
  31. return status.Error(10003, "实收金额不能为空")
  32. case req.OpenId == "" || req.HouseholdUid == 0:
  33. return status.Error(10003, "用户信息不能为空")
  34. }
  35. return nil
  36. }
  37. type HouseholdPrePayBillParam struct {
  38. ChargeInfo *dbmodel.TChargeConf
  39. BindInfo *dbmodel.TChargeBind
  40. Start int64
  41. End int64
  42. Amount int64
  43. Desc string
  44. Comment string
  45. PayTime int64
  46. Order string
  47. PayType int32
  48. HouseholdUid int64
  49. PropertyPackageId int64
  50. PropertyPackageGiveMonths int64
  51. }
  52. func HouseholdPrePayBillAdd(param *HouseholdPrePayBillParam, db *gorm.DB, dbname string) (string, error) {
  53. ob := dbmodel.NewChargeBill(dbname)
  54. where := map[string]interface{}{
  55. "charge_bind_id": param.BindInfo.ID,
  56. "charge_end >=": param.End,
  57. }
  58. count, err := ob.Count(db, where, nil)
  59. if err != nil {
  60. return "", errors.DataBaseError
  61. }
  62. if count > 0 {
  63. return "", status.Error(10003, "待缴账单中已存在相同账单")
  64. }
  65. ob.SetTablePayed(dbname)
  66. count, err = ob.Count(db, where, nil)
  67. if err != nil {
  68. return "", errors.DataBaseError
  69. }
  70. if count > 0 {
  71. return "", status.Error(10003, "已缴账单中已存在相同账单")
  72. }
  73. bill := dbmodel.TChargeBill{
  74. ObjType: param.BindInfo.ObjType,
  75. ObjId: param.BindInfo.ObjId,
  76. ChargeId: param.BindInfo.ChargeId,
  77. ChargeBindId: param.BindInfo.ID,
  78. ChargeTimeType: param.ChargeInfo.ChargeTimeType,
  79. ChargeDesc: param.Desc,
  80. Comment: param.Comment,
  81. Amount: param.Amount,
  82. ChargePowerId: 0,
  83. ChargeType: param.ChargeInfo.ChargeType,
  84. ChargeName: param.ChargeInfo.ChargeName,
  85. Uid: param.HouseholdUid,
  86. PayMode: 2,
  87. PackageId: 0,
  88. ChargeEnd: param.End,
  89. ChargeStart: param.Start,
  90. OrderId: param.Order,
  91. PayTime: param.PayTime,
  92. HouseId: param.BindInfo.HouseId,
  93. ObjName: param.BindInfo.ObjName,
  94. LateFee: 0,
  95. PayType: param.PayType,
  96. Status: charge_utils.PayStatusUnPay,
  97. }
  98. if bill.ChargeType == charge_utils.ChargeTypeProperty &&
  99. param.PropertyPackageId > 0 &&
  100. param.PropertyPackageGiveMonths > 0 {
  101. bill.PackageId = param.PropertyPackageId
  102. bill.ChargeEnd = time.Unix(bill.ChargeEnd, 0).AddDate(0, int(param.PropertyPackageGiveMonths), 0).Unix()
  103. }
  104. bytes, _ := json.Marshal(bill)
  105. return string(bytes), nil
  106. }
  107. type HouseholdPrePayOrderParam struct {
  108. BillInfo string
  109. OrderId string
  110. ObjName string
  111. Now time.Time
  112. PrepayId string
  113. PropertyPackageId int64
  114. PropertyPackageGiveMonths int64
  115. ChargeType int32
  116. }
  117. func HouseholdPrePayOrderAdd(req *pb_v1.ChargePrePayByHouseholdRequest, param *HouseholdPrePayOrderParam, db *gorm.DB, dbname string, desc string) error {
  118. order := dbmodel.TChargeOrder{
  119. OrderId: param.OrderId,
  120. Comment: req.Comment,
  121. Amount: req.ShouldPayAmount,
  122. PayAmount: req.PayAmount,
  123. PayType: req.PayType,
  124. CreatedAt: param.Now,
  125. Uid: req.HouseholdUid,
  126. PackageId: 0,
  127. PrepayId: param.PrepayId,
  128. TransactionId: "",
  129. Status: charge_utils.PayStatusUnPay,
  130. PayingDesc: desc,
  131. PayTime: param.Now.Unix(),
  132. BillIds: "",
  133. OnlinePay: 1,
  134. OnlinePayBill: param.BillInfo,
  135. ObjName: param.ObjName,
  136. }
  137. if param.ChargeType == charge_utils.ChargeTypeProperty &&
  138. param.PropertyPackageId > 0 &&
  139. param.PropertyPackageGiveMonths > 0 {
  140. order.PackageId = param.PropertyPackageId
  141. }
  142. order.SetTable(dbname)
  143. err := order.Insert(db)
  144. if err != nil {
  145. return errors.DataBaseError
  146. }
  147. return nil
  148. }
  149. func ChargePrePayByHouseholdForVehicle(req *pb_v1.ChargePrePayByHouseholdRequest, bind *dbmodel.TChargeBind, dbname string, mchid string) (reply *pb_v1.ChargePrePayByHouseholdReply, err error) {
  150. // 是否有未缴账单
  151. reply = &pb_v1.ChargePrePayByHouseholdReply{}
  152. bill := dbmodel.NewChargeBill(dbname)
  153. where := map[string]interface{}{
  154. "charge_bind_id": req.BindId,
  155. }
  156. count, err := bill.Count(database.DB(), where, nil)
  157. if err != nil {
  158. return nil, errors.DataBaseError
  159. }
  160. if count > 0 {
  161. return nil, status.Error(10003, "当前费用有未缴账单,请先缴清欠费")
  162. }
  163. // 费用信息
  164. chargeInfo := dbmodel.NewChargeConf(dbname)
  165. where = map[string]interface{}{
  166. "id": bind.ChargeId,
  167. }
  168. err = chargeInfo.Find(database.DB(), where)
  169. if err != nil && err != gorm.ErrRecordNotFound {
  170. return nil, errors.DataBaseError
  171. }
  172. if chargeInfo.ID == 0 {
  173. return nil, errors.ErrRecordNotFound
  174. }
  175. // 获取月数对应的应缴费用
  176. shouldPayAmount, _, chargeDesc := charge_utils.PrePayInfo(chargeInfo, bind, req.Months)
  177. if req.ShouldPayAmount != shouldPayAmount {
  178. return nil, status.Error(10003, "应缴费用不一致")
  179. }
  180. // 账单开始和截止月份
  181. now := time.Now()
  182. start := int64(0)
  183. end := int64(0)
  184. if bind.Start == 0 {
  185. start = getTimeDayTimestamp(now)
  186. end = time.Unix(start, 0).AddDate(0, int(req.Months), 0).Unix()
  187. } else {
  188. if bind.End < getTimeDayTimestamp(now) {
  189. return nil, status.Error(10003, "当前费用已断缴,请到物业缴费")
  190. }
  191. start = bind.End
  192. end = time.Unix(start, 0).AddDate(0, int(req.Months), 0).Unix()
  193. }
  194. // 新增支付中账单
  195. oid, err := GenerateOrderId(req.GardenId, OrderTypeLife)
  196. if err != nil {
  197. return nil, err
  198. }
  199. param := HouseholdPrePayBillParam{
  200. ChargeInfo: chargeInfo,
  201. BindInfo: bind,
  202. Start: start,
  203. End: end,
  204. Amount: req.ShouldPayAmount,
  205. Desc: chargeDesc,
  206. Comment: req.Comment,
  207. PayTime: now.Unix(),
  208. Order: oid,
  209. PayType: req.PayType,
  210. HouseholdUid: req.HouseholdUid,
  211. }
  212. thirdPrepayId, thirdPrepayInfo, _, err := ThirdpartyPay(req.OpenId, req.InputIp, req.ShouldPayAmount, param.Order, charge_utils.ChargeTypeM[bind.ChargeType], mchid, false)
  213. if err != nil {
  214. return nil, err
  215. }
  216. db := database.DB().Begin()
  217. defer func() {
  218. if err != nil {
  219. db.Rollback()
  220. }
  221. }()
  222. billInfo, err := HouseholdPrePayBillAdd(&param, db, dbname)
  223. if err != nil {
  224. return nil, err
  225. }
  226. // 新增对应订单
  227. orderParam := HouseholdPrePayOrderParam{
  228. BillInfo: billInfo,
  229. OrderId: param.Order,
  230. ObjName: bind.ObjName,
  231. Now: now,
  232. PrepayId: thirdPrepayId,
  233. }
  234. err = HouseholdPrePayOrderAdd(req, &orderParam, db, dbname, "停车收费")
  235. if err != nil {
  236. return nil, err
  237. }
  238. // 修改绑定关系里的账单截止时间戳(收到回调后再修改)
  239. db.Commit()
  240. reply.OrderId = param.Order
  241. reply.PrepayInfo = thirdPrepayInfo
  242. return reply, nil
  243. }
  244. func GetPropertyPackageInfo(payMonths int64, packageId int64, dbname string) (int64, int64, error) {
  245. if packageId == 0 {
  246. return 0, 0, nil
  247. }
  248. p := dbmodel.NewPropertyPackage(dbname)
  249. where := map[string]interface{}{
  250. "id": packageId,
  251. }
  252. err := p.Find(database.DB(), where)
  253. if err != nil && err != gorm.ErrRecordNotFound {
  254. return 0, 0, errors.DataBaseError
  255. }
  256. if p.ID == 0 {
  257. return 0, 0, errors.ErrRecordNotFound
  258. }
  259. if p.Enable == 2 {
  260. return 0, 0, status.Error(10003, "套餐已禁用")
  261. }
  262. if p.PayMonths != payMonths {
  263. return 0, 0, status.Error(10003, "套餐不一致")
  264. }
  265. return packageId, p.GiveMonths, nil
  266. }
  267. func ChargePrePayByHousehold(ctx context.Context, req *pb_v1.ChargePrePayByHouseholdRequest) (reply *pb_v1.ChargePrePayByHouseholdReply, err error) {
  268. reply = &pb_v1.ChargePrePayByHouseholdReply{}
  269. // 捕获各个task中的异常并返回给调用者
  270. defer func() {
  271. if r := recover(); r != nil {
  272. err = fmt.Errorf("%+v", r)
  273. e := &status.Status{}
  274. if er := json.Unmarshal([]byte(err.Error()), e); er != nil {
  275. logger.Error("err",
  276. zap.String("system_err", err.Error()),
  277. zap.Stack("stacktrace"))
  278. }
  279. }
  280. }()
  281. // 参数检查
  282. err = checkChargePrePayByHouseholdParam(req)
  283. if err != nil {
  284. return nil, err
  285. }
  286. mchId, err := charge_utils.CheckMchPayMode(req.GardenId)
  287. if err != nil {
  288. return nil, err
  289. }
  290. dbname := utils.GetGardenDbName(req.GardenId)
  291. // 绑定关系信息
  292. bind := dbmodel.NewChargeBind(dbname)
  293. where := map[string]interface{}{
  294. "id": req.BindId,
  295. }
  296. err = bind.Find(database.DB(), where)
  297. if err != nil && err != gorm.ErrRecordNotFound {
  298. return nil, errors.DataBaseError
  299. }
  300. if bind.ID == 0 {
  301. return nil, errors.ErrRecordNotFound
  302. }
  303. if bind.ChargeType == charge_utils.ChargeTypeVehicle {
  304. return ChargePrePayByHouseholdForVehicle(req, bind, dbname, mchId)
  305. }
  306. propertyPackageId, propertyPackageGiveMonths := int64(0), int64(0)
  307. desc := ""
  308. if bind.ChargeType == charge_utils.ChargeTypeSpace {
  309. desc = "预存车位管理费"
  310. }
  311. if bind.ChargeType == charge_utils.ChargeTypeProperty {
  312. desc = "预存物业费"
  313. propertyPackageId, propertyPackageGiveMonths, err = GetPropertyPackageInfo(req.Months, req.PackageId, dbname)
  314. if err != nil {
  315. return nil, err
  316. }
  317. }
  318. // 是否有未缴账单
  319. bill := dbmodel.NewChargeBill(dbname)
  320. where = map[string]interface{}{
  321. "charge_bind_id": req.BindId,
  322. }
  323. count, err := bill.Count(database.DB(), where, nil)
  324. if err != nil {
  325. return nil, errors.DataBaseError
  326. }
  327. if count > 0 {
  328. return nil, status.Error(10003, "当前费用有未缴账单,请先缴清欠费")
  329. }
  330. // 费用信息
  331. chargeInfo := dbmodel.NewChargeConf(dbname)
  332. where = map[string]interface{}{
  333. "id": bind.ChargeId,
  334. }
  335. err = chargeInfo.Find(database.DB(), where)
  336. if err != nil && err != gorm.ErrRecordNotFound {
  337. return nil, errors.DataBaseError
  338. }
  339. if chargeInfo.ID == 0 {
  340. return nil, errors.ErrRecordNotFound
  341. }
  342. // 获取月数对应的应缴费用
  343. shouldPayAmount, _, chargeDesc := charge_utils.PrePayInfo(chargeInfo, bind, req.Months)
  344. if req.ShouldPayAmount != shouldPayAmount {
  345. return nil, status.Error(10003, "应缴费用不一致")
  346. }
  347. // 账单开始和截止月份
  348. start := int64(0)
  349. end := int64(0)
  350. if bind.BillLastTime > 0 {
  351. start = bind.BillLastTime
  352. end = time.Unix(bind.BillLastTime, 0).AddDate(0, int(req.Months), 0).Unix()
  353. } else {
  354. if bind.Start == 0 {
  355. return nil, status.Error(10003, "当前费用未生效,请先变更开始时间")
  356. }
  357. start = bind.Start
  358. end = time.Unix(start, 0).AddDate(0, int(req.Months), 0).Unix()
  359. }
  360. // 新增支付中账单
  361. now := time.Now()
  362. oid, err := GenerateOrderId(req.GardenId, OrderTypeLife)
  363. if err != nil {
  364. return nil, err
  365. }
  366. param := HouseholdPrePayBillParam{
  367. ChargeInfo: chargeInfo,
  368. BindInfo: bind,
  369. Start: start,
  370. End: end,
  371. Amount: req.ShouldPayAmount,
  372. Desc: chargeDesc,
  373. Comment: req.Comment,
  374. PayTime: now.Unix(),
  375. Order: oid,
  376. PayType: req.PayType,
  377. HouseholdUid: req.HouseholdUid,
  378. PropertyPackageId: propertyPackageId,
  379. PropertyPackageGiveMonths: propertyPackageGiveMonths,
  380. }
  381. thirdPrepayId, thirdPrepayInfo, _, err := ThirdpartyPay(req.OpenId, req.InputIp, req.ShouldPayAmount, param.Order, charge_utils.ChargeTypeM[bind.ChargeType], mchId, false)
  382. if err != nil {
  383. return nil, err
  384. }
  385. db := database.DB().Begin()
  386. defer func() {
  387. if err != nil {
  388. db.Rollback()
  389. }
  390. }()
  391. billInfo, err := HouseholdPrePayBillAdd(&param, db, dbname)
  392. if err != nil {
  393. return nil, err
  394. }
  395. // 新增对应订单
  396. orderParam := HouseholdPrePayOrderParam{
  397. BillInfo: billInfo,
  398. OrderId: param.Order,
  399. ObjName: bind.ObjName,
  400. Now: now,
  401. PrepayId: thirdPrepayId,
  402. PropertyPackageId: propertyPackageId,
  403. PropertyPackageGiveMonths: propertyPackageGiveMonths,
  404. ChargeType: bind.ChargeType,
  405. }
  406. err = HouseholdPrePayOrderAdd(req, &orderParam, db, dbname, desc)
  407. if err != nil {
  408. return nil, err
  409. }
  410. // 修改绑定关系里的账单截止时间戳(收到回调后再改)
  411. db.Commit()
  412. reply.OrderId = param.Order
  413. reply.PrepayInfo = thirdPrepayInfo
  414. return reply, nil
  415. }