base_distributor.go 38 KB

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