base_distributor.go 42 KB

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