base_distributor.go 44 KB

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