business.go 32 KB

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