business.go 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. package proj
  2. import (
  3. "context"
  4. contractDao "dashoo.cn/micro/app/dao/contract"
  5. custDao "dashoo.cn/micro/app/dao/cust"
  6. projDao "dashoo.cn/micro/app/dao/proj"
  7. model "dashoo.cn/micro/app/model/proj"
  8. workflowModel "dashoo.cn/micro/app/model/workflow"
  9. "dashoo.cn/micro/app/service"
  10. workflowService "dashoo.cn/micro/app/service/workflow"
  11. "dashoo.cn/opms_libary/myerrors"
  12. "dashoo.cn/opms_libary/plugin/dingtalk/message"
  13. "dashoo.cn/opms_libary/plugin/dingtalk/workflow"
  14. "dashoo.cn/opms_libary/utils"
  15. "fmt"
  16. "github.com/gogf/gf/database/gdb"
  17. "github.com/gogf/gf/frame/g"
  18. "github.com/gogf/gf/os/gtime"
  19. "github.com/gogf/gf/util/gconv"
  20. "github.com/shopspring/decimal"
  21. "strconv"
  22. "strings"
  23. )
  24. type businessService struct {
  25. *service.ContextService
  26. Dao *projDao.ProjBusinessDao
  27. }
  28. func NewBusinessService(ctx context.Context) (svc *businessService, err error) {
  29. svc = new(businessService)
  30. if svc.ContextService, err = svc.Init(ctx); err != nil {
  31. return nil, err
  32. }
  33. svc.Dao = projDao.NewProjBusinessDao(svc.Tenant)
  34. return svc, nil
  35. }
  36. func (p *businessService) GetList(req *model.ProjBusinessSearchReq) (total int, businessList []*model.ProjBusinessRes, err error) {
  37. db := p.Dao.As("proj").DataScope(p.Ctx, "sale_id")
  38. if req.NboName != "" {
  39. db = db.WhereLike("proj."+p.Dao.C.NboName, "%"+req.NboName+"%")
  40. }
  41. if req.CustName != "" {
  42. db = db.WhereLike("proj."+p.Dao.C.CustName, "%"+req.CustName+"%")
  43. }
  44. if req.SaleName != "" {
  45. db = db.WhereLike("proj."+p.Dao.C.SaleName, "%"+req.SaleName+"%")
  46. }
  47. if req.NboType != "" {
  48. db = db.Where("proj."+p.Dao.C.NboType, req.NboType)
  49. }
  50. db = db
  51. total, err = db.Count()
  52. if err != nil {
  53. err = myerrors.DbError("获取总行数失败。")
  54. return
  55. }
  56. if req.NboType == StatusDeal {
  57. db = db.Unscoped().WhereNull(`proj.deleted_time`).
  58. LeftJoin(contractDao.CtrContract.Table, "contract", "`proj`.id=`contract`.nbo_id AND `contract`.`deleted_time` IS NULL ").
  59. Fields("`proj`.cust_city_id as cust_city_id,`contract`.contract_amount, `contract`.created_time as proj_closing_time")
  60. }
  61. db = db.Fields("`proj`.*")
  62. err = db.Page(req.PageNum, req.PageSize).OrderDesc("id").Scan(&businessList)
  63. return
  64. }
  65. func (p *businessService) GetEntityById(id int64) (business *model.ProjBusiness, err error) {
  66. err = p.Dao.Where(projDao.ProjBusiness.C.Id, id).Scan(&business)
  67. return
  68. }
  69. func (p *businessService) GetBusinessProduct(id int64) (productList []*model.ProjBusinessProduct, err error) {
  70. productDao := projDao.NewProjBusinessProductDao(p.Tenant)
  71. err = productDao.Where(productDao.ProjBusinessProductDao.C.BusId, id).Scan(&productList)
  72. return
  73. }
  74. func (p *businessService) GetBusinessDynamics(req *model.BusinessReq) (total int, result g.MapStrAny, err error) {
  75. result = make(g.MapStrAny, 0)
  76. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).ProjBusinessDynamicsDao.Where(projDao.ProjBusinessDynamics.C.BusId, req.BusId)
  77. total, err = dynamicsDao.Count()
  78. if err != nil {
  79. g.Log().Error(err)
  80. return
  81. }
  82. dynamicsList, err := dynamicsDao.Page(req.GetPage()).Order("created_time desc").All()
  83. if err != nil || dynamicsList == nil {
  84. return
  85. }
  86. // 数据树格式转换
  87. opnDateFlag := gtime.New(dynamicsList[0].OpnDate).Format("Y-m-d")
  88. for k, v := range dynamicsList {
  89. opnDate := gtime.New(v.OpnDate).Format("Y-m-d")
  90. if opnDateFlag == opnDate && k != 0 {
  91. result[opnDate] = append(result[opnDate].(g.ListStrAny), g.Map{
  92. "opnPeople": v.OpnPeople,
  93. "opnDate": v.OpnDate,
  94. "opnType": v.OpnType,
  95. "remark": v.Remark,
  96. "opnContent": gconv.Map(v.OpnContent),
  97. })
  98. } else {
  99. temp := make(g.ListStrAny, 0)
  100. temp = append(temp, g.Map{
  101. "opnPeople": v.OpnPeople,
  102. "opnDate": v.OpnDate,
  103. "opnType": v.OpnType,
  104. "remark": v.Remark,
  105. "opnContent": gconv.Map(v.OpnContent),
  106. })
  107. result[opnDate] = temp
  108. }
  109. }
  110. return
  111. }
  112. func (p *businessService) GetBusinessDynamicsList(req *model.BusinessDynamicsReq) (total int, list []map[string]interface{}, err error) {
  113. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, req.BusId)
  114. if req.OpnType != "" {
  115. dynamicsDao = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType+" = ?", req.OpnType)
  116. }
  117. total, err = dynamicsDao.Count()
  118. if err != nil {
  119. g.Log().Error(err)
  120. return
  121. }
  122. dynamicsList, err := dynamicsDao.Page(req.GetPage()).Order("created_time desc").All()
  123. for _, v := range dynamicsList {
  124. val := gconv.Map(v)
  125. val["opnContent"] = gconv.Map(v.OpnContent)
  126. list = append(list, val)
  127. }
  128. return
  129. }
  130. // 获取项目编号
  131. func (s *businessService) getNboCode(customerCode string) (string, error) {
  132. sequence, err := service.Sequence(s.Dao.DB, "nbo_code")
  133. if err != nil {
  134. return "", err
  135. }
  136. return customerCode + sequence, nil
  137. }
  138. func (p *businessService) Create(req *model.AddProjBusinessReq) (err error) {
  139. // 获取客户信息
  140. customer, err := custDao.NewCustCustomerDao(p.Tenant).WherePri(req.CustId).One()
  141. if err != nil {
  142. return err
  143. }
  144. if customer == nil {
  145. return myerrors.TipsError("客户不存在")
  146. }
  147. // 设置默认联系人
  148. contact := g.Map{
  149. projDao.ProjBusinessContact.C.ContactId: req.ContactId,
  150. }
  151. service.SetCreatedInfo(contact, p.GetCxtUserId(), p.GetCxtUserName())
  152. // 设置产品信息
  153. totalPrice, products, err := p.setProductInfo(0, req.Products)
  154. if err != nil {
  155. return err
  156. }
  157. // 获取项目编号
  158. nboCode, err := p.getNboCode(customer.CustCode)
  159. if err != nil {
  160. return err
  161. }
  162. // 初始化项目信息
  163. businessData := new(model.ProjBusiness)
  164. if err = gconv.Struct(req, businessData); err != nil {
  165. return
  166. }
  167. businessData.NboCode = nboCode
  168. //businessData.NboStatus = StatusOK
  169. businessData.NboType = StatusC
  170. businessData.ApproStatus = ApprovalNotSubmit
  171. businessData.EstTransPrice = totalPrice
  172. businessData.CustProvinceId = customer.CustProvinceId
  173. businessData.CustProvince = customer.CustProvince
  174. businessData.CustCityId = customer.CustCityId
  175. businessData.CustCity = customer.CustCity
  176. businessData.CustRegionId = customer.CustRegionId
  177. businessData.CustRegion = customer.CustRegion
  178. businessData.DeptId = p.GetCxtUserDeptId()
  179. service.SetCreatedInfo(businessData, p.GetCxtUserId(), p.GetCxtUserName())
  180. // 事务
  181. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  182. // 添加项目
  183. lastId, err := p.Dao.TX(tx).InsertAndGetId(businessData)
  184. if err != nil {
  185. return err
  186. }
  187. // 创建了联系人
  188. contact[projDao.ProjBusinessContact.C.BusId] = lastId
  189. _, err = projDao.NewProjBusinessContactDao(p.Tenant).TX(tx).Insert(contact)
  190. if err != nil {
  191. return err
  192. }
  193. // 处理项目产品信息
  194. for _, v := range products {
  195. v.BusId = int(lastId)
  196. }
  197. // 添加项目产品
  198. _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Insert(products)
  199. if err != nil {
  200. return err
  201. }
  202. // 添加项目动态
  203. dynamics := model.ProjBusinessDynamics{
  204. BusId: int(lastId),
  205. OpnType: OpnCreate,
  206. Remark: businessData.Remark,
  207. }
  208. err = p.CreateProjBusinessDynamics(tx, dynamics, businessData)
  209. return err
  210. })
  211. return
  212. }
  213. // setProductInfo 设置产品信息
  214. func (p *businessService) setProductInfo(busId int, productInfo []model.BusinessProduct) (total float64, products []*model.ProjBusinessProduct, err error) {
  215. products = make([]*model.ProjBusinessProduct, len(productInfo))
  216. if err = gconv.Structs(productInfo, &products); err != nil {
  217. return 0, nil, err
  218. }
  219. var totalPrice decimal.Decimal
  220. for _, v := range products {
  221. v.Id = 0
  222. v.BusId = busId
  223. v.TotalPrice = decimal.NewFromFloat(v.ProdPrice).Mul(decimal.NewFromInt(int64(v.ProdNum))).InexactFloat64()
  224. totalPrice = totalPrice.Add(decimal.NewFromFloat(v.TotalPrice))
  225. service.SetCreatedInfo(v, p.GetCxtUserId(), p.GetCxtUserName())
  226. }
  227. return totalPrice.InexactFloat64(), products, nil
  228. }
  229. func (p *businessService) UpdateById(req *model.UpdateProjBusinessReq) error {
  230. record, err := p.Dao.WherePri(req.Id).Count()
  231. if err != nil {
  232. return err
  233. }
  234. if record == 0 {
  235. return myerrors.TipsError("项目不存在。")
  236. }
  237. // 设置产品信息
  238. totalPrice, products, err := p.setProductInfo(req.Id, req.Products)
  239. if err != nil {
  240. return err
  241. }
  242. // 设置默认联系人
  243. contact := g.Map{
  244. projDao.ProjBusinessContact.C.BusId: req.Id,
  245. projDao.ProjBusinessContact.C.ContactId: req.ContactId,
  246. }
  247. contactFlag, err := projDao.NewProjBusinessContactDao(p.Tenant).Where(contact).Count()
  248. if err != nil {
  249. return err
  250. }
  251. if contactFlag == 0 {
  252. service.SetCreatedInfo(contact, p.GetCxtUserId(), p.GetCxtUserName())
  253. }
  254. // 设置项目信息
  255. req.EstTransPrice = totalPrice
  256. businessData := gconv.Map(req)
  257. service.SetUpdatedInfo(businessData, p.GetCxtUserId(), p.GetCxtUserName())
  258. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  259. // 更新项目
  260. _, err = p.Dao.TX(tx).FieldsEx(service.UpdateFieldEx...).WherePri(projDao.ProjBusiness.C.Id, req.Id).Update(businessData)
  261. if err != nil {
  262. return err
  263. }
  264. // 删除项目产品
  265. _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Where(projDao.ProjBusinessProduct.C.BusId, req.Id).Delete()
  266. if err != nil {
  267. return err
  268. }
  269. // 添加项目产品
  270. _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Insert(products)
  271. if err != nil {
  272. return err
  273. }
  274. // 关联联系人
  275. if contactFlag == 0 {
  276. _, err = projDao.NewProjBusinessContactDao(p.Tenant).TX(tx).Insert(contact)
  277. if err != nil {
  278. return err
  279. }
  280. }
  281. // 添加项目动态
  282. dynamics := model.ProjBusinessDynamics{
  283. BusId: req.Id,
  284. OpnType: OpnUpdate,
  285. Remark: req.Remark,
  286. }
  287. err = p.CreateProjBusinessDynamics(tx, dynamics, req)
  288. return err
  289. })
  290. return err
  291. }
  292. func (p *businessService) DeleteByIds(ids []int64) (err error) {
  293. _, err = p.Dao.WhereIn(projDao.ProjBusiness.C.Id, ids).Delete()
  294. return
  295. }
  296. // BusinessTransfer 项目转移
  297. func (p *businessService) BusinessTransfer(req *model.BusinessTransferReq) error {
  298. business, err := p.Dao.WherePri(req.Id).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One()
  299. if err != nil {
  300. return err
  301. }
  302. if business == nil {
  303. return myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  304. }
  305. businessMap := g.Map{
  306. p.Dao.C.ApproStatus: ApprovalWaiting,
  307. }
  308. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  309. opnContent := businessMap
  310. opnContent["origSaleId"] = business.SaleId
  311. opnContent["origSaleName"] = business.SaleName
  312. opnContent["saleId"] = req.UserId
  313. opnContent["saleName"] = req.UserName
  314. opnContent["remark"] = req.Remark
  315. // 审批流
  316. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  317. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  318. // 更新项目
  319. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update()
  320. if err != nil {
  321. return err
  322. }
  323. // 添加项目动态
  324. dynamics := model.ProjBusinessDynamics{
  325. BusId: req.Id,
  326. OpnType: OpnTransfer,
  327. Remark: req.Remark,
  328. }
  329. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  330. if err != nil {
  331. g.Log().Error(err)
  332. return err
  333. }
  334. // OMS项目转移 审批
  335. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  336. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectTransfer, "", &workflow.StartProcessInstanceRequest{
  337. ProcessCode: &BusinessTransferRequestProcessCode,
  338. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  339. {
  340. Id: utils.String("TextField-K2AD4O5B"),
  341. Name: utils.String("项目编码"),
  342. Value: utils.String(business.NboCode),
  343. },
  344. {
  345. Id: utils.String("TextField_7EFHRQ9DDF80"),
  346. Name: utils.String("项目名称"),
  347. Value: utils.String(business.NboName),
  348. },
  349. {
  350. Id: utils.String("TextField_1T3DEY5FWV7K0"),
  351. Name: utils.String("客户名称"),
  352. Value: utils.String(business.CustName),
  353. },
  354. {
  355. Id: utils.String("TextField_QDU06LXYKK00"),
  356. Name: utils.String("所在省"),
  357. Value: utils.String(business.CustProvince),
  358. },
  359. {
  360. Id: utils.String("TextField_MVSOO6EG6YO0"),
  361. Name: utils.String("所在市"),
  362. Value: utils.String(business.CustCity),
  363. },
  364. {
  365. Id: utils.String("TextField_1E1WOYGKRTDS0"),
  366. Name: utils.String("项目级别"),
  367. Value: utils.String(nboType[business.NboType]),
  368. },
  369. {
  370. Id: utils.String("TextField_NRQXWLJ17HC0"),
  371. Name: utils.String("申请人"),
  372. Value: utils.String(p.GetCxtUserName()),
  373. },
  374. {
  375. Id: utils.String("TextField_GHSQYDGD13K0"),
  376. Name: utils.String("转移原因"),
  377. Value: utils.String(req.Remark),
  378. },
  379. {
  380. Id: utils.String("TextField_76P8FPHH0UC0"),
  381. Name: utils.String("接收人"),
  382. Value: utils.String(req.UserName),
  383. },
  384. },
  385. })
  386. if err != nil {
  387. g.Log().Error(err)
  388. return err
  389. }
  390. return nil
  391. })
  392. return err
  393. }
  394. // BusinessTransferNotify 项目转移 审批结果通知
  395. func (p *businessService) BusinessTransferNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  396. business, err := p.checkDingTalkNotify(flow, msg)
  397. if err != nil {
  398. return err
  399. }
  400. var data = g.Map{}
  401. if msg.ProcessType == "terminate" {
  402. data[p.Dao.C.ApproStatus] = ApprovalReturn
  403. }
  404. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  405. data[p.Dao.C.ApproStatus] = ApprovalRejection
  406. }
  407. if msg.ProcessType == "finish" && msg.Result == "agree" {
  408. // 从项目动态内获取变更信息
  409. var transferDynamics model.ProjBusinessDynamics
  410. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id)
  411. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnTransfer).OrderDesc("created_time").Scan(&transferDynamics)
  412. if err != nil {
  413. return err
  414. }
  415. changeData := gconv.Map(transferDynamics.OpnContent)
  416. data[p.Dao.C.SaleId] = changeData["saleId"]
  417. data[p.Dao.C.SaleName] = changeData["saleName"]
  418. data[p.Dao.C.Remark] = changeData["remark"]
  419. data[p.Dao.C.ApproStatus] = ApprovalOK
  420. }
  421. // 项目修改
  422. _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  423. if err != nil {
  424. return err
  425. }
  426. // 添加项目动态
  427. dynamics := model.ProjBusinessDynamics{
  428. BusId: business.Id,
  429. OpnType: OpnTransferApproval,
  430. }
  431. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  432. if err != nil {
  433. return err
  434. }
  435. return err
  436. }
  437. // BusinessGradation 项目调级
  438. func (p *businessService) BusinessGradation(busId int, nboType, busType string) (*model.ProjBusiness, error) {
  439. business, err := p.Dao.WherePri(busId).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One()
  440. if err != nil {
  441. return nil, err
  442. }
  443. if business == nil {
  444. return nil, myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  445. }
  446. if business.NboType == nboType {
  447. return nil, myerrors.TipsError("同级别无法进行调级。")
  448. }
  449. if business.NboType == StatusDeal {
  450. return nil, myerrors.TipsError("成交项目无法进行调级。")
  451. }
  452. if business.NboType == StatusReserve && nboType == StatusDeal {
  453. return nil, myerrors.TipsError("储备项目无法直接转为成交项目。")
  454. }
  455. if busType == "up" && gconv.Int(business.NboType) < gconv.Int(nboType) {
  456. return nil, myerrors.TipsError("项目级别错误。")
  457. }
  458. if busType == "down" && gconv.Int(business.NboType) > gconv.Int(nboType) {
  459. return nil, myerrors.TipsError("项目级别错误。")
  460. }
  461. return business, err
  462. }
  463. // BusinessUpgrade 项目升级
  464. func (p *businessService) BusinessUpgrade(req *model.BusinessUpgradeReq) error {
  465. business, err := p.BusinessGradation(req.Id, req.NboType, "up")
  466. if err != nil {
  467. return err
  468. }
  469. var upgradeType string
  470. switch true {
  471. case business.NboType == StatusC && req.NboType == StatusB:
  472. upgradeType = "option_0"
  473. case business.NboType == StatusB && req.NboType == StatusA:
  474. upgradeType = "option_1"
  475. case business.NboType == StatusC && req.NboType == StatusA:
  476. upgradeType = "option_2"
  477. default:
  478. return myerrors.TipsError("错误的升级类型")
  479. }
  480. fmt.Println(upgradeType)
  481. businessMap := g.Map{
  482. p.Dao.C.ApproStatus: ApprovalWaiting,
  483. }
  484. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  485. opnContent := gconv.Map(req)
  486. opnContent["origNboType"] = business.NboType
  487. opnContent["approStatus"] = ApprovalWaiting
  488. service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName())
  489. // 审批流
  490. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  491. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  492. // 更新项目调级
  493. _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update()
  494. if err != nil {
  495. return err
  496. }
  497. // 添加项目动态
  498. dynamics := model.ProjBusinessDynamics{
  499. BusId: business.Id,
  500. OpnType: OpnUpgrade,
  501. Remark: req.Remark,
  502. }
  503. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  504. if err != nil {
  505. return err
  506. }
  507. // OMS项目降级 审批
  508. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  509. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectUpGrade, "", &workflow.StartProcessInstanceRequest{
  510. ProcessCode: &BusinessUpgradeRequestProcessCode,
  511. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  512. {
  513. Id: utils.String("TextField-K2AD4O5B"),
  514. Name: utils.String("项目编码"),
  515. Value: utils.String(business.NboCode),
  516. },
  517. {
  518. Id: utils.String("TextField_BDLSECETVSG0"),
  519. Name: utils.String("项目名称"),
  520. Value: utils.String(business.NboName),
  521. },
  522. {
  523. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  524. Name: utils.String("升级类型"),
  525. Value: utils.String(upgradeType),
  526. },
  527. {
  528. Id: utils.String("TextField_1J9BJMOZ18F40"),
  529. Name: utils.String("客户名称"),
  530. Value: utils.String(business.CustName),
  531. },
  532. {
  533. Id: utils.String("NumberField_1F88MCD0W8KG0"),
  534. Name: utils.String("项目预算"),
  535. Value: utils.String(gconv.String(req.NboBudget)),
  536. },
  537. {
  538. Id: utils.String("TextField_1PWK6WHMGITC0"),
  539. Name: utils.String("经销商/代理商"),
  540. Value: utils.String(req.DistributorName),
  541. },
  542. {
  543. Id: utils.String("TextField_X4D3QGARU7K0"),
  544. Name: utils.String("支持内容"),
  545. Value: utils.String(req.TechnicalSupportContent),
  546. },
  547. {
  548. Id: utils.String("TextField_AEUWH63LJ0O0"),
  549. Name: utils.String("销售工程师"),
  550. Value: utils.String(business.SaleName),
  551. },
  552. {
  553. Id: utils.String("DDDateField_1FW1QZQYBZVK0"),
  554. Name: utils.String("采购时间"),
  555. Value: utils.String(gconv.String(req.PurchasingTime.Format("Y-m-d"))),
  556. },
  557. {
  558. Id: utils.String("DDSelectField_21ASEWDIB3MO0"),
  559. Name: utils.String("采购方式"),
  560. Value: utils.String(gconv.String(purchasingWayType[req.PurchasingWay])),
  561. },
  562. {
  563. Id: utils.String("DDSelectField_5R11VVM6GI00"),
  564. Name: utils.String("是否我司参数"),
  565. Value: utils.String(gconv.String(yesOrNoType[req.IsAdoptDashoo])),
  566. },
  567. },
  568. })
  569. if err != nil {
  570. g.Log().Error(err)
  571. return err
  572. }
  573. return err
  574. })
  575. return err
  576. }
  577. // BusinessUpgradeNotify 项目降级 审批结果通知
  578. func (p *businessService) BusinessUpgradeNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  579. business, err := p.checkDingTalkNotify(flow, msg)
  580. if err != nil {
  581. return err
  582. }
  583. var data = g.Map{}
  584. if msg.ProcessType == "terminate" {
  585. data[p.Dao.C.ApproStatus] = ApprovalReturn
  586. }
  587. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  588. data[p.Dao.C.ApproStatus] = ApprovalRejection
  589. }
  590. if msg.ProcessType == "finish" && msg.Result == "agree" {
  591. // 从项目动态内获取变更信息
  592. dynamics := new(model.ProjBusinessDynamics)
  593. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id)
  594. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnUpgrade).OrderDesc("created_time").Scan(dynamics)
  595. if err != nil {
  596. return err
  597. }
  598. updateData := new(model.BusinessUpgradeReq)
  599. gconv.Struct(dynamics.OpnContent, updateData)
  600. data = gconv.Map(updateData)
  601. data[p.Dao.C.ApproStatus] = ApprovalOK
  602. }
  603. // 项目修改
  604. _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  605. if err != nil {
  606. return err
  607. }
  608. // 添加项目动态
  609. dynamics := model.ProjBusinessDynamics{
  610. BusId: business.Id,
  611. OpnType: OpnUpgradeApproval,
  612. }
  613. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  614. if err != nil {
  615. return err
  616. }
  617. return nil
  618. }
  619. // BusinessDowngrade 项目降级
  620. func (p *businessService) BusinessDowngrade(req *model.BusinessDowngradeReq) error {
  621. business, err := p.BusinessGradation(req.Id, req.NboType, "down")
  622. if err != nil {
  623. return err
  624. }
  625. var downgradeType string
  626. switch true {
  627. case business.NboType == StatusB && req.NboType == StatusC:
  628. downgradeType = "option_0"
  629. case business.NboType == StatusA && req.NboType == StatusB:
  630. downgradeType = "option_1"
  631. case business.NboType == StatusA && req.NboType == StatusC:
  632. downgradeType = "option_2"
  633. case business.NboType == StatusA && req.NboType == StatusReserve:
  634. downgradeType = "option_YZMFJYQQK6O0"
  635. default:
  636. return myerrors.TipsError("错误的降级类型")
  637. }
  638. businessMap := g.Map{
  639. p.Dao.C.ApproStatus: ApprovalWaiting,
  640. }
  641. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  642. opnContent := gconv.Map(req)
  643. opnContent["origNboType"] = business.NboType
  644. opnContent["approStatus"] = ApprovalWaiting
  645. service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName())
  646. // 审批流
  647. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  648. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  649. // 更新项目调级
  650. _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update()
  651. if err != nil {
  652. return err
  653. }
  654. // 添加项目动态
  655. dynamics := model.ProjBusinessDynamics{
  656. BusId: business.Id,
  657. OpnType: OpnDowngrade,
  658. Remark: req.Remark,
  659. }
  660. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  661. if err != nil {
  662. return err
  663. }
  664. // OMS项目降级 审批
  665. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  666. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectDownGrade, "", &workflow.StartProcessInstanceRequest{
  667. ProcessCode: &BusinessDowngradeRequestProcessCode,
  668. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  669. {
  670. Id: utils.String("TextField-K2AD4O5B"),
  671. Name: utils.String("项目编码"),
  672. Value: utils.String(business.NboCode),
  673. },
  674. {
  675. Id: utils.String("TextField_BDLSECETVSG0"),
  676. Name: utils.String("项目名称"),
  677. Value: utils.String(business.NboName),
  678. },
  679. {
  680. Id: utils.String("TextField_1J9BJMOZ18F40"),
  681. Name: utils.String("客户名称"),
  682. Value: utils.String(business.CustName),
  683. },
  684. {
  685. Id: utils.String("TextField_GL7MQUB723K0"),
  686. Name: utils.String("所在省"),
  687. Value: utils.String(business.CustProvince),
  688. },
  689. {
  690. Id: utils.String("TextField_CFA88QQQUUO0"),
  691. Name: utils.String("所在市"),
  692. Value: utils.String(business.CustCity),
  693. },
  694. {
  695. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  696. Name: utils.String("降级类型"),
  697. Value: utils.String(downgradeType),
  698. },
  699. {
  700. Id: utils.String("TextField_X4D3QGARU7K0"),
  701. Name: utils.String("支持内容"),
  702. Value: utils.String(req.TechnicalSupportContent),
  703. },
  704. {
  705. Id: utils.String("TextField_AEUWH63LJ0O0"),
  706. Name: utils.String("销售工程师"),
  707. Value: utils.String(business.SaleName),
  708. },
  709. {
  710. Id: utils.String("TextareaField_PTGJOKD3J7K0"),
  711. Name: utils.String("降级原因"),
  712. Value: utils.String(req.Remark),
  713. },
  714. },
  715. })
  716. if err != nil {
  717. g.Log().Error(err)
  718. return err
  719. }
  720. return nil
  721. })
  722. return err
  723. }
  724. // BusinessDowngradeNotify 项目降级 审批结果通知
  725. func (p *businessService) BusinessDowngradeNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  726. business, err := p.checkDingTalkNotify(flow, msg)
  727. if err != nil {
  728. return err
  729. }
  730. var data = g.Map{}
  731. if msg.ProcessType == "terminate" {
  732. data[p.Dao.C.ApproStatus] = ApprovalReturn
  733. }
  734. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  735. data[p.Dao.C.ApproStatus] = ApprovalRejection
  736. }
  737. if msg.ProcessType == "finish" && msg.Result == "agree" {
  738. // 从项目动态内获取变更信息
  739. dynamics := new(model.ProjBusinessDynamics)
  740. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id)
  741. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnDowngrade).OrderDesc("created_time").Scan(dynamics)
  742. if err != nil {
  743. return err
  744. }
  745. updateData := new(model.BusinessDowngradeReq)
  746. gconv.Struct(dynamics.OpnContent, updateData)
  747. data = gconv.Map(updateData)
  748. data[p.Dao.C.ApproStatus] = ApprovalOK
  749. }
  750. // 项目修改
  751. _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  752. if err != nil {
  753. return err
  754. }
  755. // 添加项目动态
  756. dynamics := model.ProjBusinessDynamics{
  757. BusId: business.Id,
  758. OpnType: OpnDowngradeApproval,
  759. }
  760. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  761. if err != nil {
  762. return err
  763. }
  764. return nil
  765. }
  766. // SetPrimacyContact 项目设置首要联系人
  767. func (p *businessService) SetPrimacyContact(req *model.BusinessPrimacyContactReq) (err error) {
  768. business, err := p.Dao.Where(projDao.ProjBusiness.C.Id, req.Id).One()
  769. if err != nil {
  770. return err
  771. }
  772. if business == nil {
  773. return myerrors.TipsError("项目不存在。")
  774. }
  775. businessMap := g.Map{
  776. p.Dao.C.ContactId: req.ContactId,
  777. p.Dao.C.ContactName: req.ContactName,
  778. p.Dao.C.ContactPostion: req.ContactPostion,
  779. p.Dao.C.ContactTelephone: req.ContactTelephone,
  780. }
  781. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  782. opnContent := businessMap
  783. opnContent["origContactId"] = business.ContactId
  784. opnContent["origContactName"] = business.ContactName
  785. opnContent["origContactPostion"] = business.ContactPostion
  786. opnContent["origContactTelephone"] = business.ContactTelephone
  787. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  788. // 更新项目
  789. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update()
  790. if err != nil {
  791. return err
  792. }
  793. // 添加项目动态
  794. dynamics := model.ProjBusinessDynamics{
  795. BusId: req.Id,
  796. OpnType: OpnPrimacyContact,
  797. Remark: req.Remark,
  798. }
  799. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  800. return err
  801. })
  802. return err
  803. }
  804. // UpdateBusinessStatus 更新项目状态
  805. func (p *businessService) UpdateBusinessStatus(req *model.UpdateBusinessStatusReq) error {
  806. business, err := p.Dao.WherePri(req.Id).One()
  807. if err != nil {
  808. return err
  809. }
  810. if business == nil {
  811. return myerrors.TipsError("项目不存在。")
  812. }
  813. businessMap := g.Map{
  814. p.Dao.C.NboStatus: req.NboStatus,
  815. p.Dao.C.Remark: req.Remark,
  816. }
  817. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  818. opnContent := businessMap
  819. opnContent["origNboStatus"] = business.NboStatus
  820. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  821. // 更新项目
  822. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update()
  823. if err != nil {
  824. return err
  825. }
  826. // 添加项目动态
  827. dynamics := model.ProjBusinessDynamics{
  828. BusId: req.Id,
  829. OpnType: OpnStatus,
  830. Remark: req.Remark,
  831. }
  832. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  833. return err
  834. })
  835. return err
  836. }
  837. // CreateProjBusinessDynamics 创建项目动态
  838. func (p *businessService) CreateProjBusinessDynamics(tx *gdb.TX, dynamics model.ProjBusinessDynamics, opnContent interface{}) error {
  839. if v, ok := opnContent.(g.Map); ok {
  840. opnContent = utils.MapKeySnakeCamelCase(v)
  841. }
  842. // 添加项目动态
  843. dynamics.OpnPeopleId = p.GetCxtUserId()
  844. dynamics.OpnPeople = p.GetCxtUserName()
  845. dynamics.OpnDate = gtime.Now()
  846. dynamics.OpnContent = gconv.String(opnContent)
  847. service.SetCreatedInfo(&dynamics, p.GetCxtUserId(), p.GetCxtUserName())
  848. dao := projDao.NewProjBusinessDynamicsDao(p.Tenant).M
  849. if tx != nil {
  850. dao = dao.TX(tx)
  851. }
  852. _, err := dao.Insert(&dynamics)
  853. return err
  854. }
  855. // ConvertToReserve 转为储备项目
  856. func (p *businessService) ConvertToReserve(req *model.BusinessToReserveReq) error {
  857. business, err := p.Dao.WherePri(req.Id).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One()
  858. if err != nil {
  859. return err
  860. }
  861. if business == nil {
  862. return myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  863. }
  864. // 审批流
  865. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  866. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  867. // 更新项目
  868. businessMap := g.Map{
  869. p.Dao.C.ApproStatus: ApprovalWaiting,
  870. p.Dao.C.ProjConversionTime: gtime.Now(),
  871. p.Dao.C.ProjConversionReason: req.ProjConversionReason,
  872. }
  873. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  874. _, err = p.Dao.TX(tx).WherePri(business.Id).Data(businessMap).Update()
  875. if err != nil {
  876. return err
  877. }
  878. // 添加项目动态
  879. dynamics := model.ProjBusinessDynamics{
  880. BusId: business.Id,
  881. OpnType: OpnToReserve,
  882. Remark: req.ProjConversionReason,
  883. }
  884. err = p.CreateProjBusinessDynamics(tx, dynamics, businessMap)
  885. if err != nil {
  886. return err
  887. }
  888. // OMS项目转储备 审批
  889. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  890. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, "", &workflow.StartProcessInstanceRequest{
  891. ProcessCode: &ConvertToReserveRequestProcessCode,
  892. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  893. {
  894. Id: utils.String("TextField-K2AD4O5B"),
  895. Name: utils.String("项目编码"),
  896. Value: utils.String(business.NboCode),
  897. },
  898. {
  899. Id: utils.String("TextField_CMH6TBXYR5S0"),
  900. Name: utils.String("项目名称"),
  901. Value: utils.String(business.NboName),
  902. },
  903. {
  904. Id: utils.String("TextField_YQBGGYHQPS00"),
  905. Name: utils.String("客户名称"),
  906. Value: utils.String(business.CustName),
  907. },
  908. {
  909. Id: utils.String("TextField_57000M1HBVO0"),
  910. Name: utils.String("项目级别"),
  911. Value: utils.String(nboType[business.NboType]),
  912. },
  913. {
  914. Id: utils.String("TextField_1NDD3TY8KJB40"),
  915. Name: utils.String("销售工程师"),
  916. Value: utils.String(business.SaleName),
  917. },
  918. {
  919. Id: utils.String("TextareaField_15KZFM4YHQ8W0"),
  920. Name: utils.String("转化原因"),
  921. Value: utils.String(req.ProjConversionReason),
  922. },
  923. },
  924. })
  925. if err != nil {
  926. g.Log().Error(err)
  927. return err
  928. }
  929. return nil
  930. })
  931. return err
  932. }
  933. // ConvertToReserveNotify 转为储备项目 审批结果通知
  934. func (p *businessService) ConvertToReserveNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  935. business, err := p.checkDingTalkNotify(flow, msg)
  936. if err != nil {
  937. return err
  938. }
  939. var data = g.Map{}
  940. if msg.ProcessType == "terminate" {
  941. data[p.Dao.C.ApproStatus] = ApprovalReturn
  942. }
  943. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  944. data[p.Dao.C.ApproStatus] = ApprovalRejection
  945. }
  946. if msg.ProcessType == "finish" && msg.Result == "agree" {
  947. data[p.Dao.C.NboType] = StatusReserve
  948. data[p.Dao.C.ApproStatus] = ApprovalOK
  949. }
  950. // 项目修改
  951. _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  952. if err != nil {
  953. return err
  954. }
  955. // 添加项目动态
  956. dynamics := model.ProjBusinessDynamics{
  957. BusId: business.Id,
  958. OpnType: OpnToReserveApproval,
  959. }
  960. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  961. if err != nil {
  962. return err
  963. }
  964. return err
  965. }
  966. // 钉钉审批通知检查
  967. func (p *businessService) checkDingTalkNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) (*model.ProjBusiness, error) {
  968. bizCode := strings.Split(flow.BizCode, ":")
  969. if len(bizCode) != 2 {
  970. return nil, fmt.Errorf("项目转储备审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  971. }
  972. nboCode := bizCode[0]
  973. busId, err := strconv.Atoi(bizCode[1])
  974. if err != nil {
  975. return nil, fmt.Errorf("项目转储备审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  976. }
  977. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  978. return nil, fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  979. }
  980. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  981. return nil, fmt.Errorf("无法识别的 Result :%s", msg.Result)
  982. }
  983. fmt.Println(msg)
  984. business, err := p.Dao.WherePri(busId).Where(p.Dao.C.NboCode, nboCode).One()
  985. if err != nil {
  986. return nil, err
  987. }
  988. if business == nil {
  989. return nil, fmt.Errorf("项目不存在:%s Id: %d", flow.BizCode, flow.Id)
  990. }
  991. return business, nil
  992. }