base_distributor.go 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291
  1. package base
  2. import (
  3. "context"
  4. "database/sql"
  5. "encoding/json"
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "os"
  10. "path"
  11. "strconv"
  12. "strings"
  13. "time"
  14. "github.com/gogf/gf/container/garray"
  15. "dashoo.cn/opms_libary/micro_srv"
  16. "dashoo.cn/opms_libary/myerrors"
  17. "dashoo.cn/opms_libary/plugin/dingtalk"
  18. "github.com/gogf/gf/database/gdb"
  19. "github.com/gogf/gf/frame/g"
  20. "github.com/gogf/gf/os/gcron"
  21. "github.com/gogf/gf/os/glog"
  22. "github.com/gogf/gf/os/gtime"
  23. "github.com/gogf/gf/util/gconv"
  24. "github.com/gogf/gf/util/gvalid"
  25. "dashoo.cn/micro/app/dao/base"
  26. contractdao "dashoo.cn/micro/app/dao/contract"
  27. projdao "dashoo.cn/micro/app/dao/proj"
  28. model "dashoo.cn/micro/app/model/base"
  29. contractmodel "dashoo.cn/micro/app/model/contract"
  30. projmodel "dashoo.cn/micro/app/model/proj"
  31. workflowModel "dashoo.cn/micro/app/model/workflow"
  32. "dashoo.cn/micro/app/service"
  33. workflowService "dashoo.cn/micro/app/service/workflow"
  34. "dashoo.cn/opms_libary/plugin/dingtalk/message"
  35. )
  36. type distributorService struct {
  37. *service.ContextService
  38. Dao *base.BaseDistributorDao
  39. DynamicsDao *base.BaseDistributorDynamicsDao
  40. TargetDao *base.BaseDistributorTargetDao
  41. RecordDao *base.BaseDistributorRecordDao
  42. ProjDao *projdao.ProjBusinessDao
  43. ContractDao *contractdao.CtrContractDao
  44. }
  45. func NewDistributorService(ctx context.Context) (svc *distributorService, err error) {
  46. svc = new(distributorService)
  47. if svc.ContextService, err = svc.Init(ctx); err != nil {
  48. return nil, err
  49. }
  50. svc.Dao = base.NewBaseDistributorDao(svc.Tenant)
  51. svc.DynamicsDao = base.NewBaseDistributorDynamicsDao(svc.Tenant)
  52. svc.ProjDao = projdao.NewProjBusinessDao(svc.Tenant)
  53. svc.ContractDao = contractdao.NewCtrContractDao(svc.Tenant)
  54. svc.TargetDao = base.NewBaseDistributorTargetDao(svc.Tenant)
  55. svc.RecordDao = base.NewBaseDistributorRecordDao(svc.Tenant)
  56. return svc, nil
  57. }
  58. // GetList 经销商信息列表
  59. func (s *distributorService) GetList(ctx context.Context, req *model.BaseDistributorSearchReq) (total int, distributorList []*model.BaseDistributorListRsp, err error) {
  60. distributorModel := s.Dao.FieldsEx(s.Dao.C.DeletedTime)
  61. if garray.NewStrArrayFrom(s.CxtUser.Roles, true).Contains("SalesEngineer") {
  62. distributorModel = distributorModel.DataScope(s.Ctx, "belong_sale_id")
  63. }
  64. if req.DistCode != "" {
  65. distributorModel = distributorModel.WhereLike(s.Dao.C.DistCode, "%"+req.DistCode+"%")
  66. }
  67. if req.DistName != "" {
  68. distributorModel = distributorModel.WhereLike(s.Dao.C.DistName, "%"+req.DistName+"%")
  69. }
  70. if req.BelongSale != "" {
  71. distributorModel = distributorModel.WhereLike(s.Dao.C.BelongSale, "%"+req.BelongSale+"%")
  72. }
  73. if len(req.BelongSaleIdList) > 0 {
  74. distributorModel = distributorModel.WhereIn(s.Dao.C.BelongSaleId, req.BelongSaleIdList)
  75. }
  76. if len(req.ProvinceId) > 0 {
  77. distributorModel = distributorModel.WhereIn(s.Dao.C.ProvinceId, req.ProvinceId)
  78. }
  79. if req.DistType != "" {
  80. distributorModel = distributorModel.WhereIn(s.Dao.C.DistType, req.DistType)
  81. }
  82. total, err = distributorModel.Count()
  83. if err != nil {
  84. err = myerrors.DbError("获取总行数失败。")
  85. return
  86. }
  87. err = distributorModel.Page(req.GetPage()).Order("id desc").Scan(&distributorList)
  88. if req.WithStatistic {
  89. for i, dist := range distributorList {
  90. statistic, err := s.statistic(dist.Id)
  91. if err != nil {
  92. return 0, nil, err
  93. }
  94. distributorList[i].BaseDistributorStatistic = statistic
  95. }
  96. }
  97. return
  98. }
  99. func (s *distributorService) statistic(id int) (stat model.BaseDistributorStatistic, err error) {
  100. v, err := s.Dao.DB.GetValue("select count(*) from proj_business where distributor_id=? and appro_status ='30' and nbo_type in (10,20,30) and deleted_time is null", id)
  101. if err != nil {
  102. return stat, err
  103. }
  104. stat.ProjectNum = v.Int()
  105. v, err = s.Dao.DB.GetValue("select sum(est_trans_price) from proj_business where distributor_id=? and appro_status ='30' and nbo_type in (10,20,30) and deleted_time is null", id)
  106. if err != nil {
  107. return stat, err
  108. }
  109. stat.AllProductAmount = v.Float64()
  110. v, err = s.Dao.DB.GetValue("select count(distinct(b.id)) from ctr_contract a left join proj_business b on a.nbo_id=b.id where a.distributor_id=? and a.appro_status ='30' and b.appro_status ='30' and a.deleted_time is null and b.deleted_time is null", id)
  111. if err != nil {
  112. return stat, err
  113. }
  114. stat.SaledProjectNum = v.Int()
  115. v, err = s.Dao.DB.GetValue("select sum(contract_amount) from ctr_contract where distributor_id=? and appro_status='30' and deleted_time is null", id)
  116. if err != nil {
  117. return stat, err
  118. }
  119. stat.SaledAmount = v.Float64()
  120. v, err = s.Dao.DB.GetValue("select sum(contract_amount - collected_amount) from ctr_contract where distributor_id=? and appro_status='30' and deleted_time is null", id)
  121. if err != nil {
  122. return stat, err
  123. }
  124. stat.UnpaidAmount = v.Float64()
  125. v, err = s.Dao.DB.GetValue("select sum(invoice_amount) from ctr_contract where distributor_id=? and appro_status='30' and deleted_time is null", id)
  126. if err != nil {
  127. return stat, err
  128. }
  129. stat.InvoicedAmount = v.Float64()
  130. return
  131. }
  132. // 获取经销商编号
  133. func (s *distributorService) getDistributorCode(distCode string) (string, error) {
  134. sequence, err := service.Sequence(s.Dao.DB, "distributor_code")
  135. if err != nil {
  136. return "", err
  137. }
  138. return distCode + sequence, nil
  139. }
  140. // Create 经销商创建
  141. func (s *distributorService) Create(ctx context.Context, req *model.AddDistributor) (int64, error) {
  142. if req.DistType == "10" {
  143. if req.DistName == "" {
  144. return 0, myerrors.TipsError("经销商名称不能为空")
  145. }
  146. if req.ProvinceId == 0 {
  147. return 0, myerrors.TipsError("所属省份Id不能为空")
  148. }
  149. if req.ProvinceDesc == "" {
  150. return 0, myerrors.TipsError("所属省份名称不能为空")
  151. }
  152. if req.RegisterDistrict == "" {
  153. return 0, myerrors.TipsError("注册地不能为空")
  154. }
  155. if req.BelongSaleId == 0 {
  156. return 0, myerrors.TipsError("归属销售ID不能为空")
  157. }
  158. if req.BelongSale == "" {
  159. return 0, myerrors.TipsError("归属销售不能为空")
  160. }
  161. } else {
  162. if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
  163. return 0, err
  164. }
  165. }
  166. DistributorData := new(model.BaseDistributor)
  167. if err := gconv.Struct(req, DistributorData); err != nil {
  168. return 0, err
  169. }
  170. code, err := s.getDistributorCode("JXS")
  171. if err != nil {
  172. return 0, err
  173. }
  174. DistributorData.DistCode = code
  175. if DistributorData.DistType == "20" {
  176. DistributorData.ApproItem = "创建代理商"
  177. DistributorData.ApproStatus = "20"
  178. if req.ContractUrl != "" && req.ContractFileName == "" {
  179. return 0, myerrors.TipsError("合同文件名不能为空")
  180. }
  181. }
  182. service.SetCreatedInfo(DistributorData, s.GetCxtUserId(), s.GetCxtUserName())
  183. var id int64
  184. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  185. id, err = tx.InsertAndGetId("base_distributor", DistributorData)
  186. if err != nil {
  187. return err
  188. }
  189. DistributorData.Id = int(id)
  190. if DistributorData.DistType == "20" {
  191. err = s.createDingtalkProcess(ctx, DistributorData, req.ContractFileName)
  192. if err != nil {
  193. return err
  194. }
  195. }
  196. err = s.AddDynamicsByCurrentUser(tx, int(id), "创建经销商/代理商", map[string]interface{}{})
  197. return err
  198. })
  199. if txerr != nil {
  200. return 0, txerr
  201. }
  202. if req.ProvinceId == 0 || req.BelongSaleId == 0 || req.Capital == 0 || req.RegisterDistrict == "" || req.BusinessScope == "" || req.SaleNum == 0 || req.CustomerType == "" || req.ExistedProduct == "" || req.HistoryCustomer == "" {
  203. msg := g.MapStrStr{
  204. "msgTitle": "经销商信息完善提醒",
  205. "msgContent": fmt.Sprintf("<p>经销商:<a href='%s'>%s</a> 的必要信息未填写完整,请及时完善</p>", distUrl(*DistributorData), req.DistName),
  206. "msgType": "20",
  207. "recvUserIds": strconv.Itoa(req.BelongSaleId),
  208. "msgStatus": "10",
  209. "sendType": "10",
  210. }
  211. if err := service.CreateSystemMessage(msg); err != nil {
  212. g.Log().Error("经销商信息完善提醒异常:", err)
  213. }
  214. }
  215. return id, nil
  216. }
  217. func distUrl(ent model.BaseDistributor) string {
  218. if ent.DistType == "20" {
  219. return fmt.Sprintf("#/base/agentDetails?id=%d", ent.Id)
  220. }
  221. return fmt.Sprintf("#/base/info?id=%d", ent.Id)
  222. }
  223. var ProcessCodeDistProxyCreate = "PROC-9494B87D-DE96-49EE-B676-D3913911BE21" // 创建代理商
  224. func (s *distributorService) createDingtalkProcess(ctx context.Context, ent *model.BaseDistributor, contractFileName string) error {
  225. workflowSrv, err := workflowService.NewFlowService(ctx)
  226. if err != nil {
  227. return err
  228. }
  229. bizCode := strconv.Itoa(ent.Id)
  230. applyData := gconv.Map(ent)
  231. applyData["abstract"] = fmt.Sprintf("申请人:%v 创建代理商:%v ", s.GetCxtUserName(), ent.DistName)
  232. _, err = workflowSrv.CheckStartProcessInstance(bizCode, workflowModel.DistProxyCreate, "", applyData)
  233. if err != nil {
  234. g.Log().Error(err)
  235. return err
  236. }
  237. return err
  238. }
  239. // GetEntityById 详情
  240. func (s *distributorService) GetEntityById(id int64) (distributorInfo *model.BaseDistributorListRsp, err error) {
  241. err = s.Dao.Where(base.BaseProduct.C.Id, id).Scan(&distributorInfo)
  242. if err != nil {
  243. return nil, err
  244. }
  245. statistic, err := s.statistic(int(id))
  246. if err != nil {
  247. return nil, err
  248. }
  249. distributorInfo.BaseDistributorStatistic = statistic
  250. target, err := s.TargetDao.Where("dist_id = ?", id).Where("year = ?", time.Now().Year()).One()
  251. if err != nil {
  252. return nil, err
  253. }
  254. if target != nil {
  255. distributorInfo.YearTarget = target.Total
  256. }
  257. return
  258. }
  259. // UpdateById 修改数据
  260. func (s *distributorService) UpdateById(req *model.UpdateDistributorReq) (err error) {
  261. ent, err := s.Dao.Where("id = ", req.Id).One()
  262. if err != nil {
  263. g.Log().Error(err)
  264. return
  265. }
  266. if ent == nil {
  267. err = myerrors.TipsError("无修改数据")
  268. return
  269. }
  270. if ent.ApproStatus == "20" {
  271. err = myerrors.TipsError("不能修改待审核数据")
  272. return
  273. }
  274. distData := new(model.BaseDistributor)
  275. if err = gconv.Struct(req, distData); err != nil {
  276. return
  277. }
  278. service.SetUpdatedInfo(distData, s.GetCxtUserId(), s.GetCxtUserName())
  279. _, err = s.Dao.FieldsEx(s.Dao.C.DistCode, s.Dao.C.Id,
  280. s.Dao.C.CreatedName, s.Dao.C.CreatedBy, s.Dao.C.CreatedTime).WherePri(s.Dao.C.Id, req.Id).Update(distData)
  281. if err != nil {
  282. g.Log().Error(err)
  283. return
  284. }
  285. err = s.Dao.DB.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  286. err = s.AddDynamicsByCurrentUser(tx, req.Id, "更新经销商/代理商", map[string]interface{}{})
  287. return err
  288. })
  289. return
  290. }
  291. func (s *distributorService) ToProxy(ctx context.Context, req *model.DistributorToProxyReq) (err error) {
  292. validErr := gvalid.CheckStruct(ctx, req, nil)
  293. if validErr != nil {
  294. return myerrors.TipsError(validErr.Current().Error())
  295. }
  296. if req.ContractUrl != "" && req.ContractFileName == "" {
  297. return myerrors.TipsError("合同文件名不能为空")
  298. }
  299. ent, err := s.Dao.Where("id = ?", req.Id).One()
  300. if err != nil {
  301. return err
  302. }
  303. if ent == nil {
  304. return myerrors.TipsError(fmt.Sprintf("代理商/经销商不存在: %d", req.Id))
  305. }
  306. approvalData := model.ToProxyApproveData{
  307. CustomerType: req.CustomerType,
  308. ProxyStartTime: req.ProxyStartTime,
  309. ProxyEndTime: req.ProxyEndTime,
  310. ProxyDistrict: req.ProxyDistrict,
  311. ContractUrl: req.ContractUrl,
  312. OperatedId: s.CxtUser.Id,
  313. OperatedName: s.CxtUser.NickName,
  314. }
  315. approvalDataByte, err := json.Marshal(approvalData)
  316. if err != nil {
  317. return err
  318. }
  319. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  320. _, err = tx.Update("base_distributor", map[string]interface{}{
  321. "appro_status": "20",
  322. "appro_data": string(approvalDataByte),
  323. "appro_item": "经销商转代理商",
  324. }, "id = ?", req.Id)
  325. if err != nil {
  326. return err
  327. }
  328. return s.toProxyDingtalkProcess(ctx, ent, req)
  329. })
  330. return txerr
  331. }
  332. var ProcessCodeDistToProxy = "PROC-39C96165-131C-48EC-B8C0-AA528E0C9F3A" // 经销商转代理商
  333. func (s *distributorService) toProxyDingtalkProcess(ctx context.Context, ent *model.BaseDistributor, req *model.DistributorToProxyReq) error {
  334. cusTypeMap, err := service.GetDictDataByType(ctx, "cust_idy")
  335. if err != nil {
  336. return err
  337. }
  338. cusType := []string{}
  339. for _, t := range strings.Split(req.CustomerType, ",") {
  340. if v := cusTypeMap[t]; v != "" {
  341. cusType = append(cusType, v)
  342. }
  343. }
  344. custTypeByte, err := json.Marshal(cusType)
  345. if err != nil {
  346. return err
  347. }
  348. proxyTime := req.ProxyStartTime.Time.Format("2006/01/02") + "-" +
  349. req.ProxyEndTime.Time.Format("2006/01/02")
  350. workflowSrv, err := workflowService.NewFlowService(ctx)
  351. if err != nil {
  352. return err
  353. }
  354. bizCode := strconv.Itoa(ent.Id)
  355. applyData := gconv.Map(ent)
  356. applyData["abstract"] = fmt.Sprintf("申请人:%v 申请经销商转代理商:%v ", s.GetCxtUserName(), ent.DistName)
  357. applyData["custType"] = string(custTypeByte)
  358. applyData["proxyDistrict"] = req.ProxyDistrict
  359. applyData["proxyTime"] = proxyTime
  360. _, err = workflowSrv.CheckStartProcessInstance(bizCode, workflowModel.DistToProxy, "", applyData)
  361. if err != nil {
  362. g.Log().Error(err)
  363. return err
  364. }
  365. return err
  366. }
  367. func (s *distributorService) Renew(ctx context.Context, req *model.DistributorRenewReq) (err error) {
  368. validErr := gvalid.CheckStruct(ctx, req, nil)
  369. if validErr != nil {
  370. return myerrors.TipsError(validErr.Current().Error())
  371. }
  372. if req.ContractUrl != "" && req.ContractFileName == "" {
  373. return myerrors.TipsError("合同文件名不能为空")
  374. }
  375. ent, err := s.Dao.Where("id = ?", req.Id).One()
  376. if err != nil {
  377. return err
  378. }
  379. if ent == nil {
  380. return myerrors.TipsError(fmt.Sprintf("代理商/经销商不存在: %d", req.Id))
  381. }
  382. approvalData := model.RenewApproveData{
  383. CustomerType: req.CustomerType,
  384. ProxyStartTime: req.ProxyStartTime,
  385. ProxyEndTime: req.ProxyEndTime,
  386. ProxyDistrict: req.ProxyDistrict,
  387. ContractUrl: req.ContractUrl,
  388. OperatedId: s.CxtUser.Id,
  389. OperatedName: s.CxtUser.NickName,
  390. }
  391. approvalDataByte, err := json.Marshal(approvalData)
  392. if err != nil {
  393. return err
  394. }
  395. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  396. _, err = tx.Update("base_distributor", map[string]interface{}{
  397. "appro_status": "20",
  398. "appro_data": string(approvalDataByte),
  399. "appro_item": "代理商续签",
  400. }, "id = ?", req.Id)
  401. if err != nil {
  402. return err
  403. }
  404. return s.renewDingtalkProcess(ctx, ent, req)
  405. })
  406. return txerr
  407. }
  408. var ProcessCodeDistRenew = "PROC-33514974-4E38-430F-A852-D5694944F20B" // 代理商续签
  409. func (s *distributorService) renewDingtalkProcess(ctx context.Context, ent *model.BaseDistributor, req *model.DistributorRenewReq) error {
  410. cusTypeMap, err := service.GetDictDataByType(ctx, "cust_idy")
  411. if err != nil {
  412. return err
  413. }
  414. cusType := []string{}
  415. for _, t := range strings.Split(req.CustomerType, ",") {
  416. if v := cusTypeMap[t]; v != "" {
  417. cusType = append(cusType, v)
  418. }
  419. }
  420. custTypeByte, err := json.Marshal(cusType)
  421. if err != nil {
  422. return err
  423. }
  424. proxyTime := req.ProxyStartTime.Time.Format("2006/01/02") + "-" +
  425. req.ProxyEndTime.Time.Format("2006/01/02")
  426. workflowSrv, err := workflowService.NewFlowService(ctx)
  427. if err != nil {
  428. return err
  429. }
  430. bizCode := strconv.Itoa(ent.Id)
  431. applyData := gconv.Map(ent)
  432. applyData["abstract"] = fmt.Sprintf("申请人:%v 申请代理商:%v 续签", s.GetCxtUserName(), ent.DistName)
  433. applyData["custType"] = string(custTypeByte)
  434. applyData["proxyDistrict"] = req.ProxyDistrict
  435. applyData["proxyTime"] = proxyTime
  436. _, err = workflowSrv.CheckStartProcessInstance(bizCode, workflowModel.DistProxyRenew, "", applyData)
  437. if err != nil {
  438. g.Log().Error(err)
  439. return err
  440. }
  441. return err
  442. }
  443. func (s *distributorService) ToDist(ctx context.Context, req *model.DistributorToDistReq) (err error) {
  444. validErr := gvalid.CheckStruct(ctx, req, nil)
  445. if validErr != nil {
  446. return myerrors.TipsError(validErr.Current().Error())
  447. }
  448. ent, err := s.Dao.Where("id = ?", req.Id).One()
  449. if err != nil {
  450. return err
  451. }
  452. if ent == nil {
  453. return myerrors.TipsError(fmt.Sprintf("代理商/经销商不存在: %d", req.Id))
  454. }
  455. approvalData := model.ToDistApproveData{
  456. ToDistReason: req.ToDistReason,
  457. OperatedId: s.CxtUser.Id,
  458. OperatedName: s.CxtUser.NickName,
  459. }
  460. approvalDataByte, err := json.Marshal(approvalData)
  461. if err != nil {
  462. return err
  463. }
  464. txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
  465. _, err = tx.Update("base_distributor", map[string]interface{}{
  466. "appro_status": "20",
  467. "appro_data": string(approvalDataByte),
  468. "appro_item": "代理商转经销商",
  469. }, "id = ?", req.Id)
  470. if err != nil {
  471. return err
  472. }
  473. return s.toDistDingtalkProcess(ctx, ent, req)
  474. })
  475. return txerr
  476. }
  477. var ProcessCodeProxyToDist = "PROC-59A0E9F5-8233-41D5-B36D-021F3E8B48D2" // 代理商转经销商
  478. func (s *distributorService) toDistDingtalkProcess(ctx context.Context, ent *model.BaseDistributor, req *model.DistributorToDistReq) error {
  479. workflowSrv, err := workflowService.NewFlowService(ctx)
  480. if err != nil {
  481. return err
  482. }
  483. bizCode := strconv.Itoa(ent.Id)
  484. applyData := gconv.Map(ent)
  485. applyData["abstract"] = fmt.Sprintf("申请人:%v 申请代理商转经销商:%v ", s.GetCxtUserName(), ent.DistName)
  486. applyData["toDistReason"] = req.ToDistReason
  487. _, err = workflowSrv.CheckStartProcessInstance(bizCode, workflowModel.DistToDist, "", applyData)
  488. if err != nil {
  489. g.Log().Error(err)
  490. return err
  491. }
  492. return err
  493. }
  494. func (s *distributorService) TransRecord(ctx context.Context, req *model.DistributorTransRecordReq) (int, []*model.BaseDistributorRecord, error) {
  495. dao := s.RecordDao.As("a")
  496. if req.DistId != 0 {
  497. dao = dao.Where("a.dist_id = ?", req.DistId)
  498. }
  499. total, err := dao.Count()
  500. if err != nil {
  501. return 0, nil, err
  502. }
  503. if req.PageNum != 0 {
  504. dao = dao.Page(req.GetPage())
  505. }
  506. orderby := "a.created_time desc"
  507. if req.OrderBy != "" {
  508. orderby = req.OrderBy
  509. }
  510. dao = dao.Order(orderby)
  511. ents := []*model.BaseDistributorRecord{}
  512. err = dao.Structs(&ents)
  513. if err != nil && err != sql.ErrNoRows {
  514. return 0, nil, err
  515. }
  516. return total, ents, nil
  517. }
  518. func (s *distributorService) SysAdminTransferDistributor(ctx context.Context, req *model.SysAdminTransferDistributorReq) (err error) {
  519. // 校验用户是否有修改权限
  520. arr := garray.NewStrArrayFrom(s.CxtUser.Roles, true)
  521. if !arr.Contains("SysAdmin") {
  522. return myerrors.TipsError("权限不足")
  523. }
  524. var updateData = g.Map{}
  525. updateData[s.Dao.C.BelongSaleId] = req.UserId
  526. updateData[s.Dao.C.BelongSale] = req.UserName
  527. service.SetUpdatedInfo(updateData, s.GetCxtUserId(), s.GetCxtUserName())
  528. dynamicsList := make([]model.BaseDistributorDynamics, 0)
  529. for _, id := range req.Ids {
  530. dynamics := model.BaseDistributorDynamics{
  531. DistId: id,
  532. OpnPeopleId: s.GetCxtUserId(),
  533. OpnPeople: s.GetCxtUserName(),
  534. OpnDate: gtime.Now(),
  535. OpnType: "转移渠道",
  536. OpnContent: gconv.String(g.Map{"toUserId": req.UserId, "toUserNickName": req.UserName, "operName": s.GetCxtUserName()}),
  537. Remark: "",
  538. CreatedBy: s.GetCxtUserId(),
  539. CreatedName: s.GetCxtUserName(),
  540. }
  541. dynamicsList = append(dynamicsList, dynamics)
  542. }
  543. err = s.Dao.Transaction(s.Ctx, func(ctx context.Context, tx *gdb.TX) error {
  544. // 项目修改
  545. _, err = s.Dao.TX(tx).WherePri(req.Ids).FieldsEx(service.UpdateFieldEx...).Data(updateData).Update()
  546. if err != nil {
  547. return err
  548. }
  549. _, err = s.DynamicsDao.TX(tx).InsertAndGetId(dynamicsList)
  550. return err
  551. })
  552. return err
  553. }
  554. // DeleteByIds 删除
  555. func (s *distributorService) DeleteByIds(ids []int64) (err error) {
  556. _, err = s.Dao.WhereIn(s.Dao.C.Id, ids).Delete()
  557. if err != nil {
  558. return err
  559. }
  560. return
  561. }
  562. func (s *distributorService) AddDynamicsByCurrentUser(tx *gdb.TX, distId int, opnType string, content map[string]interface{}) error {
  563. contentByte, err := json.Marshal(content)
  564. if err != nil {
  565. return err
  566. }
  567. _, err = tx.InsertAndGetId("base_distributor_dynamics", model.BaseDistributorDynamics{
  568. DistId: distId,
  569. OpnPeopleId: s.GetCxtUserId(),
  570. OpnPeople: s.GetCxtUserName(),
  571. OpnDate: gtime.Now(),
  572. OpnType: opnType,
  573. OpnContent: string(contentByte),
  574. Remark: "",
  575. CreatedBy: s.GetCxtUserId(),
  576. CreatedName: s.GetCxtUserName(),
  577. CreatedTime: gtime.Now(),
  578. UpdatedBy: s.GetCxtUserId(),
  579. UpdatedName: s.GetCxtUserName(),
  580. UpdatedTime: gtime.Now(),
  581. })
  582. return err
  583. }
  584. func (s *distributorService) ContractList(ctx context.Context, req *model.DistributorContractListReq) (int, []*contractmodel.CtrContractListRsp, error) {
  585. dao := s.ContractDao.As("a")
  586. if req.DistId != 0 {
  587. dao = dao.Where("a.distributor_id = ?", req.DistId)
  588. }
  589. if req.SearchText != "" {
  590. likestr := fmt.Sprintf("%%%s%%", req.SearchText)
  591. dao = dao.Where("(a.contract_code LIKE ? || a.contract_name LIKE ? || a.cust_name LIKE ? || a.nbo_name LIKE ?)", likestr, likestr, likestr, likestr)
  592. }
  593. if req.ContractCode != "" {
  594. likestr := fmt.Sprintf("%%%s%%", req.ContractCode)
  595. dao = dao.Where("a.contract_code like ?", likestr)
  596. }
  597. if req.ContractName != "" {
  598. likestr := fmt.Sprintf("%%%s%%", req.ContractName)
  599. dao = dao.Where("a.contract_name like ?", likestr)
  600. }
  601. if req.CustId != 0 {
  602. dao = dao.Where("a.cust_id = ?", req.CustId)
  603. }
  604. if req.CustName != "" {
  605. likestr := fmt.Sprintf("%%%s%%", req.CustName)
  606. dao = dao.Where("a.cust_name like ?", likestr)
  607. }
  608. if req.NboId != 0 {
  609. dao = dao.Where("a.nbo_id = ?", req.NboId)
  610. }
  611. if req.NboName != "" {
  612. likestr := fmt.Sprintf("%%%s%%", req.NboName)
  613. dao = dao.Where("a.nbo_name like ?", likestr)
  614. }
  615. if req.ApproStatus != "" {
  616. dao = dao.Where("a.appro_status = ?", req.ApproStatus)
  617. }
  618. if req.ContractType != "" {
  619. dao = dao.Where("a.contract_type = ?", req.ContractType)
  620. }
  621. if req.InchargeId != 0 {
  622. dao = dao.Where("a.incharge_id = ?", req.InchargeId)
  623. }
  624. if req.InchargeName != "" {
  625. likestr := fmt.Sprintf("%%%s%%", req.InchargeName)
  626. dao = dao.Where("a.incharge_name like ?", likestr)
  627. }
  628. if req.SignatoryId != 0 {
  629. dao = dao.Where("a.signatory_id = ?", req.SignatoryId)
  630. }
  631. if req.SignatoryName != "" {
  632. likestr := fmt.Sprintf("%%%s%%", req.SignatoryName)
  633. dao = dao.Where("a.signatory_name like ?", likestr)
  634. }
  635. if req.DistributorName != "" {
  636. likestr := fmt.Sprintf("%%%s%%", req.DistributorName)
  637. dao = dao.Where("a.distributor_name like ?", likestr)
  638. }
  639. if req.BeginTime != "" {
  640. dao = dao.Where("a.created_time > ?", req.BeginTime)
  641. }
  642. if req.EndTime != "" {
  643. dao = dao.Where("a.created_time < ?", req.EndTime)
  644. }
  645. total, err := dao.Count()
  646. if err != nil {
  647. return 0, nil, err
  648. }
  649. if req.PageNum != 0 {
  650. dao = dao.Page(req.GetPage())
  651. }
  652. orderby := "a.created_time desc"
  653. if req.OrderBy != "" {
  654. orderby = req.OrderBy
  655. }
  656. dao = dao.Order(orderby)
  657. ents := []*contractmodel.CtrContractListRsp{}
  658. err = dao.Structs(&ents)
  659. if err != nil && err != sql.ErrNoRows {
  660. return 0, nil, err
  661. }
  662. return total, ents, nil
  663. }
  664. func (s *distributorService) ProjectList(ctx context.Context, req *model.DistributorProjectListReq) (int, []*projmodel.ProjBusiness, error) {
  665. dao := &s.ProjDao.ProjBusinessDao
  666. if req.DistId != 0 {
  667. dao = dao.Where("distributor_id = ?", req.DistId)
  668. }
  669. if req.SearchText != "" {
  670. likestr := fmt.Sprintf("%%%s%%", req.SearchText)
  671. dao = dao.Where("(cust_name LIKE ? || nbo_name LIKE ?)", likestr, likestr)
  672. }
  673. if req.NboName != "" {
  674. likestr := fmt.Sprintf("%%%s%%", req.NboName)
  675. dao = dao.Where("nbo_name like ?", likestr)
  676. }
  677. if req.CustName != "" {
  678. likestr := fmt.Sprintf("%%%s%%", req.CustName)
  679. dao = dao.Where("cust_name like ?", likestr)
  680. }
  681. if req.CreatedTimeStart != nil {
  682. dao = dao.Where("created_time > ?", req.CreatedTimeStart)
  683. }
  684. if req.CreatedTimeEnd != nil {
  685. dao = dao.Where("created_time < ?", req.CreatedTimeEnd)
  686. }
  687. total, err := dao.Count()
  688. if err != nil {
  689. return 0, nil, err
  690. }
  691. if req.PageNum != 0 {
  692. dao = dao.Page(req.GetPage())
  693. }
  694. orderby := "created_time desc"
  695. if req.OrderBy != "" {
  696. orderby = req.OrderBy
  697. }
  698. dao = dao.Order(orderby)
  699. ents := []*projmodel.ProjBusiness{}
  700. err = dao.Structs(&ents)
  701. if err != nil && err != sql.ErrNoRows {
  702. return 0, nil, err
  703. }
  704. return total, ents, nil
  705. }
  706. func (s *distributorService) DynamicsList(ctx context.Context, req *model.DistributorDynamicsListReq) (int, interface{}, error) {
  707. dao := &s.DynamicsDao.BaseDistributorDynamicsDao
  708. if req.SearchText != "" {
  709. likestr := fmt.Sprintf("%%%s%%", req.SearchText)
  710. dao = dao.Where("(opn_people LIKE ? || opn_content LIKE ?)", likestr, likestr)
  711. }
  712. if req.DistId != 0 {
  713. dao = dao.Where("dist_id = ?", req.DistId)
  714. }
  715. if req.OpnPeopleId != 0 {
  716. dao = dao.Where("opn_people_id = ?", req.OpnPeopleId)
  717. }
  718. if req.OpnPeople != "" {
  719. likestr := fmt.Sprintf("%%%s%%", req.OpnPeople)
  720. dao = dao.Where("opn_people like ?", likestr)
  721. }
  722. if req.OpnType != "" {
  723. dao = dao.Where("opn_type = ?", req.OpnType)
  724. }
  725. if req.BeginTime != "" {
  726. dao = dao.Where("created_time > ?", req.BeginTime)
  727. }
  728. if req.EndTime != "" {
  729. dao = dao.Where("created_time < ?", req.EndTime)
  730. }
  731. total, err := dao.Count()
  732. if err != nil {
  733. return 0, nil, err
  734. }
  735. if req.PageNum != 0 {
  736. dao = dao.Page(req.GetPage())
  737. }
  738. orderby := "created_time desc"
  739. if req.OrderBy != "" {
  740. orderby = req.OrderBy
  741. }
  742. dao = dao.Order(orderby)
  743. ents := []*model.BaseDistributorDynamics{}
  744. err = dao.Structs(&ents)
  745. if err != nil && err != sql.ErrNoRows {
  746. return 0, nil, err
  747. }
  748. ret := map[string][]*model.BaseDistributorDynamics{}
  749. for _, ent := range ents {
  750. date := ent.OpnDate.Format("Y-m-d")
  751. ret[date] = append(ret[date], ent)
  752. }
  753. return total, ret, err
  754. }
  755. func DownFile(url string) ([]byte, error) {
  756. r, err := http.Get(url)
  757. if err != nil {
  758. return nil, err
  759. }
  760. if r.StatusCode != http.StatusOK {
  761. return nil, fmt.Errorf("DownFile from %s StatusCode %d", url, r.StatusCode)
  762. }
  763. defer r.Body.Close()
  764. return ioutil.ReadAll(r.Body)
  765. }
  766. // '审核状态 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销'
  767. func ApprovalProxyCreate(ctx context.Context, flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  768. tenant, err := micro_srv.GetTenant(ctx)
  769. if err != nil {
  770. return fmt.Errorf("获取租户码异常:%s", err.Error())
  771. }
  772. distdao := base.NewBaseDistributorDao(tenant)
  773. entId, err := strconv.Atoi(flow.BizCode)
  774. if err != nil {
  775. return fmt.Errorf("创建代理商钉钉审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  776. }
  777. ent, err := distdao.Where("id = ?", entId).One()
  778. if err != nil {
  779. return err
  780. }
  781. if ent == nil {
  782. return fmt.Errorf("代理商不存在:%s Id: %d", flow.BizCode, flow.Id)
  783. }
  784. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  785. return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  786. }
  787. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  788. return fmt.Errorf("无法识别的 Result :%s", msg.Result)
  789. }
  790. if msg.ProcessType == "terminate" {
  791. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  792. "appro_status": "50",
  793. "appro_data": "",
  794. }).Update()
  795. return err
  796. }
  797. pass := msg.Result == "agree"
  798. if !pass {
  799. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  800. "appro_status": "40",
  801. "appro_data": "",
  802. }).Update()
  803. return err
  804. }
  805. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  806. "appro_status": "30",
  807. "appro_data": "",
  808. }).Update()
  809. return err
  810. }
  811. func ApprovalDistToProxy(ctx context.Context, flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  812. tenant, err := micro_srv.GetTenant(ctx)
  813. if err != nil {
  814. return fmt.Errorf("获取租户码异常:%s", err.Error())
  815. }
  816. distdao := base.NewBaseDistributorDao(tenant)
  817. entId, err := strconv.Atoi(flow.BizCode)
  818. if err != nil {
  819. return fmt.Errorf("经销商转代理商钉钉审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  820. }
  821. ent, err := distdao.Where("id = ?", entId).One()
  822. if err != nil {
  823. return err
  824. }
  825. if ent == nil {
  826. return fmt.Errorf("经销商不存在:%s Id: %d", flow.BizCode, flow.Id)
  827. }
  828. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  829. return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  830. }
  831. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  832. return fmt.Errorf("无法识别的 Result :%s", msg.Result)
  833. }
  834. if msg.ProcessType == "terminate" {
  835. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  836. "appro_status": "50",
  837. "appro_data": "",
  838. }).Update()
  839. return err
  840. }
  841. pass := msg.Result == "agree"
  842. if !pass {
  843. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  844. "appro_status": "40",
  845. "appro_data": "",
  846. }).Update()
  847. return err
  848. }
  849. approData := model.ToProxyApproveData{}
  850. err = json.Unmarshal([]byte(ent.ApproData), &approData)
  851. if err != nil {
  852. return fmt.Errorf("经销商转代理商钉钉审批 ApproData 解析异常:%s Id: %d ApproData:%s", flow.BizCode, flow.Id, ent.ApproData)
  853. }
  854. txerr := distdao.DB.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  855. _, err = tx.Update("base_distributor", map[string]interface{}{
  856. "dist_type": "20",
  857. "appro_status": "30",
  858. "appro_data": "",
  859. "customer_type": approData.CustomerType,
  860. "proxy_start_time": approData.ProxyStartTime,
  861. "proxy_end_time": approData.ProxyEndTime,
  862. "proxy_district": approData.ProxyDistrict,
  863. "contract_url": approData.ContractUrl,
  864. }, "id = ?", ent.Id)
  865. if err != nil {
  866. return err
  867. }
  868. _, err = tx.Insert("base_distributor_record", model.BaseDistributorRecord{
  869. DistId: ent.Id,
  870. DistType: "20",
  871. BusinessScope: ent.BusinessScope,
  872. CustomerType: approData.CustomerType,
  873. ProxyDistrict: approData.ProxyDistrict,
  874. ProxyStartTime: approData.ProxyStartTime,
  875. ProxyEndTime: approData.ProxyEndTime,
  876. ContractUrl: approData.ContractUrl,
  877. ExistedProduct: ent.ExistedProduct,
  878. HistoryCustomer: ent.HistoryCustomer,
  879. ToDistReason: "",
  880. Remark: "",
  881. CreatedBy: approData.OperatedId,
  882. CreatedName: approData.OperatedName,
  883. CreatedTime: gtime.Now(),
  884. UpdatedBy: approData.OperatedId,
  885. UpdatedName: approData.OperatedName,
  886. UpdatedTime: gtime.Now(),
  887. })
  888. if err != nil {
  889. return err
  890. }
  891. err = addDynamicsByCurrentUser(tx, ent.Id, "转为代理商",
  892. approData, approData.OperatedId, approData.OperatedName)
  893. if err != nil {
  894. return err
  895. }
  896. return nil
  897. })
  898. return txerr
  899. }
  900. func ApprovalDistRenew(ctx context.Context, flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  901. tenant, err := micro_srv.GetTenant(ctx)
  902. if err != nil {
  903. return fmt.Errorf("获取租户码异常:%s", err.Error())
  904. }
  905. distdao := base.NewBaseDistributorDao(tenant)
  906. entId, err := strconv.Atoi(flow.BizCode)
  907. if err != nil {
  908. return fmt.Errorf("代理商续签钉钉审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  909. }
  910. ent, err := distdao.Where("id = ?", entId).One()
  911. if err != nil {
  912. return err
  913. }
  914. if ent == nil {
  915. return fmt.Errorf("代理商不存在:%s Id: %d", flow.BizCode, flow.Id)
  916. }
  917. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  918. return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  919. }
  920. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  921. return fmt.Errorf("无法识别的 Result :%s", msg.Result)
  922. }
  923. if msg.ProcessType == "terminate" {
  924. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  925. "appro_status": "50",
  926. "appro_data": "",
  927. }).Update()
  928. return err
  929. }
  930. pass := msg.Result == "agree"
  931. if !pass {
  932. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  933. "appro_status": "40",
  934. "appro_data": "",
  935. }).Update()
  936. return err
  937. }
  938. approData := model.RenewApproveData{}
  939. err = json.Unmarshal([]byte(ent.ApproData), &approData)
  940. if err != nil {
  941. return fmt.Errorf("代理商续签钉钉审批 ApproData 解析异常:%s Id: %d ApproData:%s", flow.BizCode, flow.Id, ent.ApproData)
  942. }
  943. txerr := distdao.DB.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  944. _, err = tx.Update("base_distributor", map[string]interface{}{
  945. "appro_status": "30",
  946. "appro_data": "",
  947. "customer_type": approData.CustomerType,
  948. "proxy_start_time": approData.ProxyStartTime,
  949. "proxy_end_time": approData.ProxyEndTime,
  950. "proxy_district": approData.ProxyDistrict,
  951. "contract_url": approData.ContractUrl,
  952. }, "id = ?", ent.Id)
  953. if err != nil {
  954. return err
  955. }
  956. _, err = tx.Insert("base_distributor_record", model.BaseDistributorRecord{
  957. DistId: ent.Id,
  958. DistType: "20",
  959. BusinessScope: ent.BusinessScope,
  960. CustomerType: approData.CustomerType,
  961. ProxyDistrict: approData.ProxyDistrict,
  962. ProxyStartTime: approData.ProxyStartTime,
  963. ProxyEndTime: approData.ProxyEndTime,
  964. ContractUrl: approData.ContractUrl,
  965. ExistedProduct: ent.ExistedProduct,
  966. HistoryCustomer: ent.HistoryCustomer,
  967. ToDistReason: "",
  968. Remark: "",
  969. CreatedBy: approData.OperatedId,
  970. CreatedName: approData.OperatedName,
  971. CreatedTime: gtime.Now(),
  972. UpdatedBy: approData.OperatedId,
  973. UpdatedName: approData.OperatedName,
  974. UpdatedTime: gtime.Now(),
  975. })
  976. if err != nil {
  977. return err
  978. }
  979. err = addDynamicsByCurrentUser(tx, ent.Id, "续签代理商",
  980. approData, approData.OperatedId, approData.OperatedName)
  981. if err != nil {
  982. return err
  983. }
  984. return nil
  985. })
  986. return txerr
  987. }
  988. func ApprovalDistToDist(ctx context.Context, flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  989. tenant, err := micro_srv.GetTenant(ctx)
  990. if err != nil {
  991. return fmt.Errorf("获取租户码异常:%s", err.Error())
  992. }
  993. distdao := base.NewBaseDistributorDao(tenant)
  994. entId, err := strconv.Atoi(flow.BizCode)
  995. if err != nil {
  996. return fmt.Errorf("代理商转经销商钉钉审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  997. }
  998. ent, err := distdao.Where("id = ?", entId).One()
  999. if err != nil {
  1000. return err
  1001. }
  1002. if ent == nil {
  1003. return fmt.Errorf("代理商不存在:%s Id: %d", flow.BizCode, flow.Id)
  1004. }
  1005. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  1006. return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  1007. }
  1008. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  1009. return fmt.Errorf("无法识别的 Result :%s", msg.Result)
  1010. }
  1011. if msg.ProcessType == "terminate" {
  1012. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  1013. "appro_status": "50",
  1014. "appro_data": "",
  1015. }).Update()
  1016. return err
  1017. }
  1018. pass := msg.Result == "agree"
  1019. if !pass {
  1020. _, err = distdao.Where("id = ?", entId).Data(map[string]interface{}{
  1021. "appro_status": "40",
  1022. "appro_data": "",
  1023. }).Update()
  1024. return err
  1025. }
  1026. approData := model.ToDistApproveData{}
  1027. err = json.Unmarshal([]byte(ent.ApproData), &approData)
  1028. if err != nil {
  1029. return fmt.Errorf("代理商转经销商钉钉审批 ApproData 解析异常:%s Id: %d ApproData:%s", flow.BizCode, flow.Id, ent.ApproData)
  1030. }
  1031. txerr := distdao.DB.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  1032. _, err = tx.Update("base_distributor", map[string]interface{}{
  1033. "dist_type": "10",
  1034. "appro_status": "30",
  1035. "appro_data": "",
  1036. }, "id = ?", ent.Id)
  1037. if err != nil {
  1038. return err
  1039. }
  1040. _, err = tx.Insert("base_distributor_record", model.BaseDistributorRecord{
  1041. DistId: ent.Id,
  1042. DistType: "10",
  1043. BusinessScope: ent.BusinessScope,
  1044. CustomerType: ent.CustomerType,
  1045. ProxyDistrict: "",
  1046. ProxyStartTime: nil,
  1047. ProxyEndTime: nil,
  1048. ContractUrl: "",
  1049. ExistedProduct: ent.ExistedProduct,
  1050. HistoryCustomer: ent.HistoryCustomer,
  1051. ToDistReason: approData.ToDistReason,
  1052. Remark: "",
  1053. CreatedBy: approData.OperatedId,
  1054. CreatedName: approData.OperatedName,
  1055. CreatedTime: gtime.Now(),
  1056. UpdatedBy: approData.OperatedId,
  1057. UpdatedName: approData.OperatedName,
  1058. UpdatedTime: gtime.Now(),
  1059. })
  1060. if err != nil {
  1061. return err
  1062. }
  1063. err = addDynamicsByCurrentUser(tx, ent.Id, "转为经销商",
  1064. approData, approData.OperatedId, approData.OperatedName)
  1065. if err != nil {
  1066. return err
  1067. }
  1068. return nil
  1069. })
  1070. return txerr
  1071. }
  1072. func addDynamicsByCurrentUser(tx *gdb.TX, distId int, opnType string, content interface{}, operatedId int, opreatedName string) error {
  1073. contentByte, err := json.Marshal(content)
  1074. if err != nil {
  1075. return err
  1076. }
  1077. _, err = tx.InsertAndGetId("base_distributor_dynamics", model.BaseDistributorDynamics{
  1078. DistId: distId,
  1079. OpnPeopleId: operatedId,
  1080. OpnPeople: opreatedName,
  1081. OpnDate: gtime.Now(),
  1082. OpnType: opnType,
  1083. OpnContent: string(contentByte),
  1084. Remark: "",
  1085. CreatedBy: operatedId,
  1086. CreatedName: opreatedName,
  1087. CreatedTime: gtime.Now(),
  1088. UpdatedBy: operatedId,
  1089. UpdatedName: opreatedName,
  1090. UpdatedTime: gtime.Now(),
  1091. })
  1092. return err
  1093. }
  1094. func UploadDingtalk(uid, url, name string) ([]byte, error) {
  1095. if uid == "" {
  1096. return nil, fmt.Errorf("该用户钉钉 uid 为空")
  1097. }
  1098. filedata, err := DownFile(url)
  1099. if err != nil {
  1100. return nil, err
  1101. }
  1102. filepath := path.Join(os.TempDir(), name)
  1103. err = ioutil.WriteFile(filepath, filedata, 0644)
  1104. if err != nil {
  1105. return nil, fmt.Errorf("WriteFile %s %s", filepath, err)
  1106. }
  1107. defer os.Remove(filepath)
  1108. resp, err := dingtalk.Client.GetStorage().UploadFile(service.DingTalkSpaceId, uid, name, filepath)
  1109. if err != nil {
  1110. return nil, fmt.Errorf("钉钉上传文件异常 %s", err.Error())
  1111. }
  1112. file := []contractmodel.DingFileInfo{
  1113. {
  1114. SpaceId: resp.Dentry.SpaceId,
  1115. FileId: resp.Dentry.Id,
  1116. FileName: resp.Dentry.Name,
  1117. FileSize: resp.Dentry.Size,
  1118. FileType: resp.Dentry.Extension,
  1119. },
  1120. }
  1121. return json.Marshal(file)
  1122. }
  1123. func init() {
  1124. c := gcron.New()
  1125. // 每天凌晨2点执行
  1126. c.Add("0 0 2 * * *", notifyToComplete)
  1127. }
  1128. func notifyToComplete() {
  1129. defer func() {
  1130. if r := recover(); r != nil {
  1131. glog.Errorf("完善经销商定时提醒异常 %v", r)
  1132. }
  1133. }()
  1134. tenant := g.Config().GetString("micro_srv.tenant")
  1135. if tenant == "" {
  1136. glog.Error("定时任务租户码未设置,请前往配置")
  1137. return
  1138. }
  1139. dao := base.NewBaseDistributorDao(tenant)
  1140. created := gtime.Now().Add(-time.Hour * 24 * 30)
  1141. dist, err := dao.Where("province_id = 0 or belong_sale_id = 0 or capital = 0 or register_district = '' or business_scope = '' or sale_num = 0 or customer_type = '' or existed_product = '' or history_customer = ''").Where("created_time < ?", created).Where("dist_type = 10").All()
  1142. if err != nil {
  1143. glog.Errorf("完善经销商定时提醒异常 %s", err.Error())
  1144. return
  1145. }
  1146. if len(dist) == 0 {
  1147. return
  1148. }
  1149. extraUserId, err := service.UserIdByRoles(dao.DB, "SalesDirector", "SaleAssociate")
  1150. if err != nil {
  1151. glog.Errorf("查询销售助理销售总监异常 %s", err.Error())
  1152. return
  1153. }
  1154. glog.Infof("销售助理销售总监 %v", extraUserId)
  1155. for _, d := range dist {
  1156. recvUserIds := service.SliceIntDeduplication(extraUserId)
  1157. recvUserIds = append(recvUserIds, d.BelongSaleId)
  1158. recvUserIdString := []string{}
  1159. for _, uid := range recvUserIds {
  1160. recvUserIdString = append(recvUserIdString, strconv.Itoa(uid))
  1161. }
  1162. msg := g.MapStrStr{
  1163. "msgTitle": "经销商信息完善提醒",
  1164. "msgContent": fmt.Sprintf("<p>经销商:<a href='%s'>%s</a> 的必要信息未填写完整,请及时完善</p>", distUrl(*d), d.DistName),
  1165. "msgType": "20",
  1166. "recvUserIds": strings.Join(recvUserIdString, ","),
  1167. "msgStatus": "10",
  1168. "sendType": "10",
  1169. }
  1170. if err := service.CreateSystemMessage(msg); err != nil {
  1171. g.Log().Error("经销商信息完善提醒异常:%s", err)
  1172. }
  1173. }
  1174. }