business.go 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  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).Where(p.Dao.Columns.ApproStatus, ApprovalNotSubmit).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. data[p.Dao.Columns.NboType] = StatusReserve
  405. data[p.Dao.Columns.ApproStatus] = ApprovalOK
  406. // 从项目动态内获取变更信息
  407. var transferDynamics model.ProjBusinessDynamics
  408. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.Columns.BusId, business.Id)
  409. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.Columns.OpnType, OpnTransfer).OrderDesc("created_time").Scan(&transferDynamics)
  410. if err != nil {
  411. return err
  412. }
  413. changeData := gconv.Map(transferDynamics.OpnContent)
  414. data[p.Dao.Columns.SaleId] = changeData["saleId"]
  415. data[p.Dao.Columns.SaleName] = changeData["saleName"]
  416. data[p.Dao.Columns.Remark] = changeData["remark"]
  417. }
  418. // 项目修改
  419. _, err = p.Dao.WherePri(business.Id).Data(data).Update()
  420. // 添加项目动态
  421. dynamics := model.ProjBusinessDynamics{
  422. BusId: business.Id,
  423. OpnType: OpnTransferApproval,
  424. }
  425. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  426. if err != nil {
  427. return err
  428. }
  429. return err
  430. }
  431. // BusinessGradation 项目调级
  432. func (p *businessService) BusinessGradation(busId int, nboType, busType string) (*model.ProjBusiness, error) {
  433. business, err := p.Dao.WherePri(busId).Where(p.Dao.Columns.ApproStatus, ApprovalNotSubmit).One()
  434. if err != nil {
  435. return nil, err
  436. }
  437. if business == nil {
  438. return nil, myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  439. }
  440. if business.NboType == nboType {
  441. return nil, myerrors.TipsError("同级别无法进行调级。")
  442. }
  443. if business.NboType == StatusDeal {
  444. return nil, myerrors.TipsError("成交项目无法进行调级。")
  445. }
  446. if business.NboType == StatusReserve && nboType == StatusDeal {
  447. return nil, myerrors.TipsError("储备项目无法直接转为成交项目。")
  448. }
  449. if busType == "up" && gconv.Int(business.NboType) < gconv.Int(nboType) {
  450. return nil, myerrors.TipsError("项目级别错误。")
  451. }
  452. if busType == "down" && gconv.Int(business.NboType) > gconv.Int(nboType) {
  453. return nil, myerrors.TipsError("项目级别错误。")
  454. }
  455. return business, err
  456. }
  457. // BusinessUpgrade 项目升级
  458. func (p *businessService) BusinessUpgrade(req *model.BusinessUpgradeReq) error {
  459. business, err := p.BusinessGradation(req.Id, req.NboType, "up")
  460. if err != nil {
  461. return err
  462. }
  463. var upgradeType string
  464. switch true {
  465. case business.NboType == StatusC && req.NboType == StatusB:
  466. upgradeType = "option_0"
  467. case business.NboType == StatusB && req.NboType == StatusA:
  468. upgradeType = "option_1"
  469. case business.NboType == StatusC && req.NboType == StatusA:
  470. upgradeType = "option_2"
  471. default:
  472. return myerrors.TipsError("错误的升级类型")
  473. }
  474. fmt.Println(upgradeType)
  475. businessMap := g.Map{
  476. p.Dao.Columns.ApproStatus: ApprovalWaiting,
  477. }
  478. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  479. opnContent := gconv.Map(req)
  480. opnContent["origNboType"] = business.NboType
  481. opnContent["approStatus"] = ApprovalWaiting
  482. service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName())
  483. // 审批流
  484. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  485. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  486. // 更新项目调级
  487. _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update()
  488. if err != nil {
  489. return err
  490. }
  491. // 添加项目动态
  492. dynamics := model.ProjBusinessDynamics{
  493. BusId: business.Id,
  494. OpnType: OpnUpgrade,
  495. Remark: req.Remark,
  496. }
  497. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  498. if err != nil {
  499. return err
  500. }
  501. // OMS项目降级 审批
  502. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  503. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectUpGrade, &workflow.StartProcessInstanceRequest{
  504. ProcessCode: &BusinessUpgradeRequestProcessCode,
  505. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  506. {
  507. Id: utils.String("TextField-K2AD4O5B"),
  508. Name: utils.String("项目编码"),
  509. Value: utils.String(business.NboCode),
  510. },
  511. {
  512. Id: utils.String("TextField_BDLSECETVSG0"),
  513. Name: utils.String("项目名称"),
  514. Value: utils.String(business.NboName),
  515. },
  516. {
  517. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  518. Name: utils.String("升级类型"),
  519. Value: utils.String(upgradeType),
  520. },
  521. {
  522. Id: utils.String("TextField_1J9BJMOZ18F40"),
  523. Name: utils.String("客户名称"),
  524. Value: utils.String(business.CustName),
  525. },
  526. {
  527. Id: utils.String("NumberField_1F88MCD0W8KG0"),
  528. Name: utils.String("项目预算"),
  529. Value: utils.String(gconv.String(req.NboBudget)),
  530. },
  531. {
  532. Id: utils.String("TextField_1PWK6WHMGITC0"),
  533. Name: utils.String("经销商/代理商"),
  534. Value: utils.String(req.DistributorName),
  535. },
  536. {
  537. Id: utils.String("TextField_X4D3QGARU7K0"),
  538. Name: utils.String("支持内容"),
  539. Value: utils.String(req.TechnicalSupportContent),
  540. },
  541. {
  542. Id: utils.String("TextField_AEUWH63LJ0O0"),
  543. Name: utils.String("销售工程师"),
  544. Value: utils.String(business.SaleName),
  545. },
  546. {
  547. Id: utils.String("DDDateField_1FW1QZQYBZVK0"),
  548. Name: utils.String("采购时间"),
  549. Value: utils.String(gconv.String(req.PurchasingTime.Format("Y-m-d"))),
  550. },
  551. {
  552. Id: utils.String("DDSelectField_21ASEWDIB3MO0"),
  553. Name: utils.String("采购方式"),
  554. Value: utils.String(gconv.String(purchasingWayType[req.PurchasingWay])),
  555. },
  556. {
  557. Id: utils.String("DDSelectField_5R11VVM6GI00"),
  558. Name: utils.String("是否我司参数"),
  559. Value: utils.String(gconv.String(yesOrNoType[req.IsAdoptDashoo])),
  560. },
  561. },
  562. })
  563. if err != nil {
  564. g.Log().Error(err)
  565. return err
  566. }
  567. return err
  568. })
  569. return err
  570. }
  571. // BusinessUpgradeNotify 项目降级 审批结果通知
  572. func (p *businessService) BusinessUpgradeNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  573. business, err := p.checkDingTalkNotify(flow, msg)
  574. if err != nil {
  575. return err
  576. }
  577. var data = g.Map{}
  578. if msg.ProcessType == "terminate" {
  579. data[p.Dao.Columns.ApproStatus] = ApprovalReturn
  580. }
  581. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  582. data[p.Dao.Columns.ApproStatus] = ApprovalRejection
  583. }
  584. if msg.ProcessType == "finish" && msg.Result == "agree" {
  585. // 从项目动态内获取变更信息
  586. transferDynamics := new(model.ProjBusinessDynamics)
  587. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.Columns.BusId, business.Id)
  588. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.Columns.OpnType, OpnUpgrade).OrderDesc("created_time").Scan(transferDynamics)
  589. if err != nil {
  590. return err
  591. }
  592. data = utils.MapKeySnakeCamelCase(gconv.Map(transferDynamics.OpnContent), "snake")
  593. delete(data, "orig_nbo_type")
  594. delete(data, "updated_by")
  595. delete(data, "updated_name")
  596. delete(data, "updated_time")
  597. data[p.Dao.Columns.NboType] = StatusReserve
  598. data[p.Dao.Columns.ApproStatus] = ApprovalOK
  599. }
  600. // 项目修改
  601. _, err = p.Dao.WherePri(business.Id).Data(data).Update()
  602. // 添加项目动态
  603. dynamics := model.ProjBusinessDynamics{
  604. BusId: business.Id,
  605. OpnType: OpnUpgradeApproval,
  606. }
  607. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  608. if err != nil {
  609. return err
  610. }
  611. return nil
  612. }
  613. // BusinessDowngrade 项目降级
  614. func (p *businessService) BusinessDowngrade(req *model.BusinessDowngradeReq) error {
  615. business, err := p.BusinessGradation(req.Id, req.NboType, "down")
  616. if err != nil {
  617. return err
  618. }
  619. var downgradeType string
  620. switch true {
  621. case business.NboType == StatusB && req.NboType == StatusC:
  622. downgradeType = "option_0"
  623. case business.NboType == StatusA && req.NboType == StatusB:
  624. downgradeType = "option_1"
  625. case business.NboType == StatusA && req.NboType == StatusC:
  626. downgradeType = "option_2"
  627. case business.NboType == StatusA && req.NboType == StatusReserve:
  628. downgradeType = "option_YZMFJYQQK6O0"
  629. default:
  630. return myerrors.TipsError("错误的降级类型")
  631. }
  632. businessMap := g.Map{
  633. p.Dao.Columns.ApproStatus: ApprovalWaiting,
  634. }
  635. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  636. opnContent := gconv.Map(req)
  637. opnContent["origNboType"] = business.NboType
  638. opnContent["approStatus"] = ApprovalWaiting
  639. service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName())
  640. // 审批流
  641. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  642. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  643. // 更新项目调级
  644. _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update()
  645. if err != nil {
  646. return err
  647. }
  648. // 添加项目动态
  649. dynamics := model.ProjBusinessDynamics{
  650. BusId: business.Id,
  651. OpnType: OpnDowngrade,
  652. Remark: req.Remark,
  653. }
  654. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  655. if err != nil {
  656. return err
  657. }
  658. // OMS项目降级 审批
  659. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  660. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectDownGrade, &workflow.StartProcessInstanceRequest{
  661. ProcessCode: &BusinessDowngradeRequestProcessCode,
  662. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  663. {
  664. Id: utils.String("TextField-K2AD4O5B"),
  665. Name: utils.String("项目编码"),
  666. Value: utils.String(business.NboCode),
  667. },
  668. {
  669. Id: utils.String("TextField_BDLSECETVSG0"),
  670. Name: utils.String("项目名称"),
  671. Value: utils.String(business.NboName),
  672. },
  673. {
  674. Id: utils.String("TextField_1J9BJMOZ18F40"),
  675. Name: utils.String("客户名称"),
  676. Value: utils.String(business.CustName),
  677. },
  678. {
  679. Id: utils.String("TextField_GL7MQUB723K0"),
  680. Name: utils.String("所在省"),
  681. Value: utils.String(business.CustProvince),
  682. },
  683. {
  684. Id: utils.String("TextField_CFA88QQQUUO0"),
  685. Name: utils.String("所在市"),
  686. Value: utils.String(business.CustCity),
  687. },
  688. {
  689. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  690. Name: utils.String("降级类型"),
  691. Value: utils.String(downgradeType),
  692. },
  693. {
  694. Id: utils.String("TextField_X4D3QGARU7K0"),
  695. Name: utils.String("支持内容"),
  696. Value: utils.String(req.TechnicalSupportContent),
  697. },
  698. {
  699. Id: utils.String("TextField_AEUWH63LJ0O0"),
  700. Name: utils.String("销售工程师"),
  701. Value: utils.String(business.SaleName),
  702. },
  703. {
  704. Id: utils.String("TextareaField_PTGJOKD3J7K0"),
  705. Name: utils.String("降级原因"),
  706. Value: utils.String(req.Remark),
  707. },
  708. },
  709. })
  710. if err != nil {
  711. g.Log().Error(err)
  712. return err
  713. }
  714. return nil
  715. })
  716. return err
  717. }
  718. // BusinessDowngradeNotify 项目降级 审批结果通知
  719. func (p *businessService) BusinessDowngradeNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  720. business, err := p.checkDingTalkNotify(flow, msg)
  721. if err != nil {
  722. return err
  723. }
  724. var data = g.Map{}
  725. if msg.ProcessType == "terminate" {
  726. data[p.Dao.Columns.ApproStatus] = ApprovalReturn
  727. }
  728. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  729. data[p.Dao.Columns.ApproStatus] = ApprovalRejection
  730. }
  731. if msg.ProcessType == "finish" && msg.Result == "agree" {
  732. data[p.Dao.Columns.NboType] = StatusReserve
  733. data[p.Dao.Columns.ApproStatus] = ApprovalOK
  734. // 从项目动态内获取变更信息
  735. transferDynamics := new(model.ProjBusinessDynamics)
  736. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.Columns.BusId, business.Id)
  737. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.Columns.OpnType, OpnDowngrade).OrderDesc("created_time").Scan(transferDynamics)
  738. if err != nil {
  739. return err
  740. }
  741. changeData := gconv.Map(transferDynamics.OpnContent)
  742. data[p.Dao.Columns.NboType] = changeData["nboType"]
  743. data[p.Dao.Columns.TechnicalSupportName] = changeData["technicalSupportName"]
  744. data[p.Dao.Columns.TechnicalSupportContent] = changeData["technicalSupportContent"]
  745. data[p.Dao.Columns.TechnicalSupportTime] = changeData["technicalSupportTime"]
  746. data[p.Dao.Columns.Remark] = changeData["remark"]
  747. }
  748. // 项目修改
  749. _, err = p.Dao.WherePri(business.Id).Data(data).Update()
  750. // 添加项目动态
  751. dynamics := model.ProjBusinessDynamics{
  752. BusId: business.Id,
  753. OpnType: OpnDowngradeApproval,
  754. }
  755. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  756. if err != nil {
  757. return err
  758. }
  759. return nil
  760. }
  761. // SetPrimacyContact 项目设置首要联系人
  762. func (p *businessService) SetPrimacyContact(req *model.BusinessPrimacyContactReq) (err error) {
  763. business, err := p.Dao.Where(projDao.ProjBusiness.Columns.Id, req.Id).One()
  764. if err != nil {
  765. return err
  766. }
  767. if business == nil {
  768. return myerrors.TipsError("项目不存在。")
  769. }
  770. businessMap := g.Map{
  771. p.Dao.Columns.ContactId: req.ContactId,
  772. p.Dao.Columns.ContactName: req.ContactName,
  773. p.Dao.Columns.ContactPostion: req.ContactPostion,
  774. p.Dao.Columns.ContactTelephone: req.ContactTelephone,
  775. }
  776. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  777. opnContent := businessMap
  778. opnContent["origContactId"] = business.ContactId
  779. opnContent["origContactName"] = business.ContactName
  780. opnContent["origContactPostion"] = business.ContactPostion
  781. opnContent["origContactTelephone"] = business.ContactTelephone
  782. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  783. // 更新项目
  784. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.Columns.Id, req.Id).Data(businessMap).Update()
  785. if err != nil {
  786. return err
  787. }
  788. // 添加项目动态
  789. dynamics := model.ProjBusinessDynamics{
  790. BusId: req.Id,
  791. OpnType: OpnPrimacyContact,
  792. Remark: req.Remark,
  793. }
  794. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  795. return err
  796. })
  797. return err
  798. }
  799. // UpdateBusinessStatus 更新项目状态
  800. func (p *businessService) UpdateBusinessStatus(req *model.UpdateBusinessStatusReq) error {
  801. business, err := p.Dao.WherePri(req.Id).One()
  802. if err != nil {
  803. return err
  804. }
  805. if business == nil {
  806. return myerrors.TipsError("项目不存在。")
  807. }
  808. businessMap := g.Map{
  809. p.Dao.Columns.NboStatus: req.NboStatus,
  810. p.Dao.Columns.Remark: req.Remark,
  811. }
  812. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  813. opnContent := businessMap
  814. opnContent["origNboStatus"] = business.NboStatus
  815. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  816. // 更新项目
  817. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.Columns.Id, req.Id).Data(businessMap).Update()
  818. if err != nil {
  819. return err
  820. }
  821. // 添加项目动态
  822. dynamics := model.ProjBusinessDynamics{
  823. BusId: req.Id,
  824. OpnType: OpnStatus,
  825. Remark: req.Remark,
  826. }
  827. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  828. return err
  829. })
  830. return err
  831. }
  832. // CreateProjBusinessDynamics 创建项目动态
  833. func (p *businessService) CreateProjBusinessDynamics(tx *gdb.TX, dynamics model.ProjBusinessDynamics, opnContent interface{}) error {
  834. if v, ok := opnContent.(g.Map); ok {
  835. opnContent = utils.MapKeySnakeCamelCase(v)
  836. }
  837. // 添加项目动态
  838. dynamics.OpnPeopleId = p.GetCxtUserId()
  839. dynamics.OpnPeople = p.GetCxtUserName()
  840. dynamics.OpnDate = gtime.Now()
  841. dynamics.OpnContent = gconv.String(opnContent)
  842. service.SetCreatedInfo(&dynamics, p.GetCxtUserId(), p.GetCxtUserName())
  843. dao := projDao.NewProjBusinessDynamicsDao(p.Tenant).M
  844. if tx != nil {
  845. dao = dao.TX(tx)
  846. }
  847. _, err := dao.Insert(&dynamics)
  848. return err
  849. }
  850. // ConvertToReserve 转为储备项目
  851. func (p *businessService) ConvertToReserve(req *model.BusinessToReserveReq) error {
  852. business, err := p.Dao.WherePri(req.Id).Where(p.Dao.Columns.ApproStatus, ApprovalNotSubmit).One()
  853. if err != nil {
  854. return err
  855. }
  856. if business == nil {
  857. return myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  858. }
  859. // 审批流
  860. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  861. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  862. // 更新项目
  863. businessMap := g.Map{
  864. p.Dao.Columns.ApproStatus: ApprovalWaiting,
  865. p.Dao.Columns.ProjConversionTime: gtime.Now(),
  866. p.Dao.Columns.ProjConversionReason: req.ProjConversionReason,
  867. }
  868. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  869. _, err = p.Dao.TX(tx).WherePri(business.Id).Data(businessMap).Update()
  870. if err != nil {
  871. return err
  872. }
  873. // 添加项目动态
  874. dynamics := model.ProjBusinessDynamics{
  875. BusId: business.Id,
  876. OpnType: OpnToReserve,
  877. Remark: req.ProjConversionReason,
  878. }
  879. err = p.CreateProjBusinessDynamics(tx, dynamics, businessMap)
  880. if err != nil {
  881. return err
  882. }
  883. // OMS项目转储备 审批
  884. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  885. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, &workflow.StartProcessInstanceRequest{
  886. ProcessCode: &ConvertToReserveRequestProcessCode,
  887. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  888. {
  889. Id: utils.String("TextField-K2AD4O5B"),
  890. Name: utils.String("项目编码"),
  891. Value: utils.String(business.NboCode),
  892. },
  893. {
  894. Id: utils.String("TextField_CMH6TBXYR5S0"),
  895. Name: utils.String("项目名称"),
  896. Value: utils.String(business.NboName),
  897. },
  898. {
  899. Id: utils.String("TextField_YQBGGYHQPS00"),
  900. Name: utils.String("客户名称"),
  901. Value: utils.String(business.CustName),
  902. },
  903. {
  904. Id: utils.String("TextField_57000M1HBVO0"),
  905. Name: utils.String("项目级别"),
  906. Value: utils.String(nboType[business.NboType]),
  907. },
  908. {
  909. Id: utils.String("TextField_1NDD3TY8KJB40"),
  910. Name: utils.String("销售工程师"),
  911. Value: utils.String(business.SaleName),
  912. },
  913. {
  914. Id: utils.String("TextareaField_15KZFM4YHQ8W0"),
  915. Name: utils.String("转化原因"),
  916. Value: utils.String(req.ProjConversionReason),
  917. },
  918. },
  919. })
  920. if err != nil {
  921. g.Log().Error(err)
  922. return err
  923. }
  924. return nil
  925. })
  926. return err
  927. }
  928. // ConvertToReserveNotify 转为储备项目 审批结果通知
  929. func (p *businessService) ConvertToReserveNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  930. business, err := p.checkDingTalkNotify(flow, msg)
  931. if err != nil {
  932. return err
  933. }
  934. var data = g.Map{}
  935. if msg.ProcessType == "terminate" {
  936. data[p.Dao.Columns.ApproStatus] = ApprovalReturn
  937. }
  938. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  939. data[p.Dao.Columns.ApproStatus] = ApprovalRejection
  940. }
  941. if msg.ProcessType == "finish" && msg.Result == "agree" {
  942. data[p.Dao.Columns.NboType] = StatusReserve
  943. data[p.Dao.Columns.ApproStatus] = ApprovalOK
  944. }
  945. // 项目修改
  946. _, err = p.Dao.WherePri(business.Id).Data(data).Update()
  947. // 添加项目动态
  948. dynamics := model.ProjBusinessDynamics{
  949. BusId: business.Id,
  950. OpnType: OpnToReserveApproval,
  951. }
  952. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  953. if err != nil {
  954. return err
  955. }
  956. return err
  957. }
  958. // 钉钉审批通知检查
  959. func (p *businessService) checkDingTalkNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) (*model.ProjBusiness, error) {
  960. bizCode := strings.Split(flow.BizCode, ":")
  961. if len(bizCode) != 2 {
  962. return nil, fmt.Errorf("项目转储备审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  963. }
  964. nboCode := bizCode[0]
  965. busId, err := strconv.Atoi(bizCode[1])
  966. if err != nil {
  967. return nil, fmt.Errorf("项目转储备审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  968. }
  969. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  970. return nil, fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  971. }
  972. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  973. return nil, fmt.Errorf("无法识别的 Result :%s", msg.Result)
  974. }
  975. fmt.Println(msg)
  976. business, err := p.Dao.WherePri(busId).Where(p.Dao.Columns.NboCode, nboCode).One()
  977. if err != nil {
  978. return nil, err
  979. }
  980. if business == nil {
  981. return nil, fmt.Errorf("项目不存在:%s Id: %d", flow.BizCode, flow.Id)
  982. }
  983. return business, nil
  984. }