business.go 32 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.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).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. transferDynamics := 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(transferDynamics)
  595. if err != nil {
  596. return err
  597. }
  598. updateData := new(model.BusinessUpgradeReq)
  599. data = gconv.Map(gconv.Struct(transferDynamics.OpnContent, updateData))
  600. data[p.Dao.C.ApproStatus] = ApprovalOK
  601. }
  602. // 项目修改
  603. _, err = p.Dao.WherePri(business.Id).Data(data).Update()
  604. if err != nil {
  605. return err
  606. }
  607. // 添加项目动态
  608. dynamics := model.ProjBusinessDynamics{
  609. BusId: business.Id,
  610. OpnType: OpnUpgradeApproval,
  611. }
  612. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  613. if err != nil {
  614. return err
  615. }
  616. return nil
  617. }
  618. // BusinessDowngrade 项目降级
  619. func (p *businessService) BusinessDowngrade(req *model.BusinessDowngradeReq) error {
  620. business, err := p.BusinessGradation(req.Id, req.NboType, "down")
  621. if err != nil {
  622. return err
  623. }
  624. var downgradeType string
  625. switch true {
  626. case business.NboType == StatusB && req.NboType == StatusC:
  627. downgradeType = "option_0"
  628. case business.NboType == StatusA && req.NboType == StatusB:
  629. downgradeType = "option_1"
  630. case business.NboType == StatusA && req.NboType == StatusC:
  631. downgradeType = "option_2"
  632. case business.NboType == StatusA && req.NboType == StatusReserve:
  633. downgradeType = "option_YZMFJYQQK6O0"
  634. default:
  635. return myerrors.TipsError("错误的降级类型")
  636. }
  637. businessMap := g.Map{
  638. p.Dao.C.ApproStatus: ApprovalWaiting,
  639. }
  640. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  641. opnContent := gconv.Map(req)
  642. opnContent["origNboType"] = business.NboType
  643. opnContent["approStatus"] = ApprovalWaiting
  644. service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName())
  645. // 审批流
  646. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  647. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  648. // 更新项目调级
  649. _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update()
  650. if err != nil {
  651. return err
  652. }
  653. // 添加项目动态
  654. dynamics := model.ProjBusinessDynamics{
  655. BusId: business.Id,
  656. OpnType: OpnDowngrade,
  657. Remark: req.Remark,
  658. }
  659. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  660. if err != nil {
  661. return err
  662. }
  663. // OMS项目降级 审批
  664. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  665. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectDownGrade, "", &workflow.StartProcessInstanceRequest{
  666. ProcessCode: &BusinessDowngradeRequestProcessCode,
  667. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  668. {
  669. Id: utils.String("TextField-K2AD4O5B"),
  670. Name: utils.String("项目编码"),
  671. Value: utils.String(business.NboCode),
  672. },
  673. {
  674. Id: utils.String("TextField_BDLSECETVSG0"),
  675. Name: utils.String("项目名称"),
  676. Value: utils.String(business.NboName),
  677. },
  678. {
  679. Id: utils.String("TextField_1J9BJMOZ18F40"),
  680. Name: utils.String("客户名称"),
  681. Value: utils.String(business.CustName),
  682. },
  683. {
  684. Id: utils.String("TextField_GL7MQUB723K0"),
  685. Name: utils.String("所在省"),
  686. //Value: utils.String(business.CustProvince),
  687. },
  688. {
  689. Id: utils.String("TextField_CFA88QQQUUO0"),
  690. Name: utils.String("所在市"),
  691. //Value: utils.String(business.CustCity),
  692. },
  693. {
  694. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  695. Name: utils.String("降级类型"),
  696. Value: utils.String(downgradeType),
  697. },
  698. {
  699. Id: utils.String("TextField_X4D3QGARU7K0"),
  700. Name: utils.String("支持内容"),
  701. Value: utils.String(req.TechnicalSupportContent),
  702. },
  703. {
  704. Id: utils.String("TextField_AEUWH63LJ0O0"),
  705. Name: utils.String("销售工程师"),
  706. Value: utils.String(business.SaleName),
  707. },
  708. {
  709. Id: utils.String("TextareaField_PTGJOKD3J7K0"),
  710. Name: utils.String("降级原因"),
  711. Value: utils.String(req.Remark),
  712. },
  713. },
  714. })
  715. if err != nil {
  716. g.Log().Error(err)
  717. return err
  718. }
  719. return nil
  720. })
  721. return err
  722. }
  723. // BusinessDowngradeNotify 项目降级 审批结果通知
  724. func (p *businessService) BusinessDowngradeNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  725. business, err := p.checkDingTalkNotify(flow, msg)
  726. if err != nil {
  727. return err
  728. }
  729. var data = g.Map{}
  730. if msg.ProcessType == "terminate" {
  731. data[p.Dao.C.ApproStatus] = ApprovalReturn
  732. }
  733. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  734. data[p.Dao.C.ApproStatus] = ApprovalRejection
  735. }
  736. if msg.ProcessType == "finish" && msg.Result == "agree" {
  737. // 从项目动态内获取变更信息
  738. transferDynamics := new(model.ProjBusinessDynamics)
  739. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id)
  740. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnDowngrade).OrderDesc("created_time").Scan(transferDynamics)
  741. if err != nil {
  742. return err
  743. }
  744. updateData := new(model.BusinessDowngradeReq)
  745. data = gconv.Map(gconv.Struct(transferDynamics.OpnContent, updateData))
  746. data[p.Dao.C.ApproStatus] = ApprovalOK
  747. }
  748. // 项目修改
  749. _, err = p.Dao.WherePri(business.Id).Data(data).Update()
  750. if err != nil {
  751. return err
  752. }
  753. // 添加项目动态
  754. dynamics := model.ProjBusinessDynamics{
  755. BusId: business.Id,
  756. OpnType: OpnDowngradeApproval,
  757. }
  758. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  759. if err != nil {
  760. return err
  761. }
  762. return nil
  763. }
  764. // SetPrimacyContact 项目设置首要联系人
  765. func (p *businessService) SetPrimacyContact(req *model.BusinessPrimacyContactReq) (err error) {
  766. business, err := p.Dao.Where(projDao.ProjBusiness.C.Id, req.Id).One()
  767. if err != nil {
  768. return err
  769. }
  770. if business == nil {
  771. return myerrors.TipsError("项目不存在。")
  772. }
  773. businessMap := g.Map{
  774. p.Dao.C.ContactId: req.ContactId,
  775. p.Dao.C.ContactName: req.ContactName,
  776. p.Dao.C.ContactPostion: req.ContactPostion,
  777. p.Dao.C.ContactTelephone: req.ContactTelephone,
  778. }
  779. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  780. opnContent := businessMap
  781. opnContent["origContactId"] = business.ContactId
  782. opnContent["origContactName"] = business.ContactName
  783. opnContent["origContactPostion"] = business.ContactPostion
  784. opnContent["origContactTelephone"] = business.ContactTelephone
  785. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  786. // 更新项目
  787. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update()
  788. if err != nil {
  789. return err
  790. }
  791. // 添加项目动态
  792. dynamics := model.ProjBusinessDynamics{
  793. BusId: req.Id,
  794. OpnType: OpnPrimacyContact,
  795. Remark: req.Remark,
  796. }
  797. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  798. return err
  799. })
  800. return err
  801. }
  802. // UpdateBusinessStatus 更新项目状态
  803. func (p *businessService) UpdateBusinessStatus(req *model.UpdateBusinessStatusReq) error {
  804. business, err := p.Dao.WherePri(req.Id).One()
  805. if err != nil {
  806. return err
  807. }
  808. if business == nil {
  809. return myerrors.TipsError("项目不存在。")
  810. }
  811. businessMap := g.Map{
  812. p.Dao.C.NboStatus: req.NboStatus,
  813. p.Dao.C.Remark: req.Remark,
  814. }
  815. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  816. opnContent := businessMap
  817. opnContent["origNboStatus"] = business.NboStatus
  818. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  819. // 更新项目
  820. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update()
  821. if err != nil {
  822. return err
  823. }
  824. // 添加项目动态
  825. dynamics := model.ProjBusinessDynamics{
  826. BusId: req.Id,
  827. OpnType: OpnStatus,
  828. Remark: req.Remark,
  829. }
  830. err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  831. return err
  832. })
  833. return err
  834. }
  835. // CreateProjBusinessDynamics 创建项目动态
  836. func (p *businessService) CreateProjBusinessDynamics(tx *gdb.TX, dynamics model.ProjBusinessDynamics, opnContent interface{}) error {
  837. if v, ok := opnContent.(g.Map); ok {
  838. opnContent = utils.MapKeySnakeCamelCase(v)
  839. }
  840. // 添加项目动态
  841. dynamics.OpnPeopleId = p.GetCxtUserId()
  842. dynamics.OpnPeople = p.GetCxtUserName()
  843. dynamics.OpnDate = gtime.Now()
  844. dynamics.OpnContent = gconv.String(opnContent)
  845. service.SetCreatedInfo(&dynamics, p.GetCxtUserId(), p.GetCxtUserName())
  846. dao := projDao.NewProjBusinessDynamicsDao(p.Tenant).M
  847. if tx != nil {
  848. dao = dao.TX(tx)
  849. }
  850. _, err := dao.Insert(&dynamics)
  851. return err
  852. }
  853. // ConvertToReserve 转为储备项目
  854. func (p *businessService) ConvertToReserve(req *model.BusinessToReserveReq) error {
  855. business, err := p.Dao.WherePri(req.Id).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One()
  856. if err != nil {
  857. return err
  858. }
  859. if business == nil {
  860. return myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  861. }
  862. // 审批流
  863. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  864. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  865. // 更新项目
  866. businessMap := g.Map{
  867. p.Dao.C.ApproStatus: ApprovalWaiting,
  868. p.Dao.C.ProjConversionTime: gtime.Now(),
  869. p.Dao.C.ProjConversionReason: req.ProjConversionReason,
  870. }
  871. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  872. _, err = p.Dao.TX(tx).WherePri(business.Id).Data(businessMap).Update()
  873. if err != nil {
  874. return err
  875. }
  876. // 添加项目动态
  877. dynamics := model.ProjBusinessDynamics{
  878. BusId: business.Id,
  879. OpnType: OpnToReserve,
  880. Remark: req.ProjConversionReason,
  881. }
  882. err = p.CreateProjBusinessDynamics(tx, dynamics, businessMap)
  883. if err != nil {
  884. return err
  885. }
  886. // OMS项目转储备 审批
  887. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  888. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, "", &workflow.StartProcessInstanceRequest{
  889. ProcessCode: &ConvertToReserveRequestProcessCode,
  890. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  891. {
  892. Id: utils.String("TextField-K2AD4O5B"),
  893. Name: utils.String("项目编码"),
  894. Value: utils.String(business.NboCode),
  895. },
  896. {
  897. Id: utils.String("TextField_CMH6TBXYR5S0"),
  898. Name: utils.String("项目名称"),
  899. Value: utils.String(business.NboName),
  900. },
  901. {
  902. Id: utils.String("TextField_YQBGGYHQPS00"),
  903. Name: utils.String("客户名称"),
  904. Value: utils.String(business.CustName),
  905. },
  906. {
  907. Id: utils.String("TextField_57000M1HBVO0"),
  908. Name: utils.String("项目级别"),
  909. Value: utils.String(nboType[business.NboType]),
  910. },
  911. {
  912. Id: utils.String("TextField_1NDD3TY8KJB40"),
  913. Name: utils.String("销售工程师"),
  914. Value: utils.String(business.SaleName),
  915. },
  916. {
  917. Id: utils.String("TextareaField_15KZFM4YHQ8W0"),
  918. Name: utils.String("转化原因"),
  919. Value: utils.String(req.ProjConversionReason),
  920. },
  921. },
  922. })
  923. if err != nil {
  924. g.Log().Error(err)
  925. return err
  926. }
  927. return nil
  928. })
  929. return err
  930. }
  931. // ConvertToReserveNotify 转为储备项目 审批结果通知
  932. func (p *businessService) ConvertToReserveNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  933. business, err := p.checkDingTalkNotify(flow, msg)
  934. if err != nil {
  935. return err
  936. }
  937. var data = g.Map{}
  938. if msg.ProcessType == "terminate" {
  939. data[p.Dao.C.ApproStatus] = ApprovalReturn
  940. }
  941. if msg.ProcessType == "finish" && msg.Result != "refuse" {
  942. data[p.Dao.C.ApproStatus] = ApprovalRejection
  943. }
  944. if msg.ProcessType == "finish" && msg.Result == "agree" {
  945. data[p.Dao.C.NboType] = StatusReserve
  946. data[p.Dao.C.ApproStatus] = ApprovalOK
  947. }
  948. // 项目修改
  949. _, err = p.Dao.WherePri(business.Id).Data(data).Update()
  950. if err != nil {
  951. return err
  952. }
  953. // 添加项目动态
  954. dynamics := model.ProjBusinessDynamics{
  955. BusId: business.Id,
  956. OpnType: OpnToReserveApproval,
  957. }
  958. err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  959. if err != nil {
  960. return err
  961. }
  962. return err
  963. }
  964. // 钉钉审批通知检查
  965. func (p *businessService) checkDingTalkNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) (*model.ProjBusiness, error) {
  966. bizCode := strings.Split(flow.BizCode, ":")
  967. if len(bizCode) != 2 {
  968. return nil, fmt.Errorf("项目转储备审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  969. }
  970. nboCode := bizCode[0]
  971. busId, err := strconv.Atoi(bizCode[1])
  972. if err != nil {
  973. return nil, fmt.Errorf("项目转储备审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  974. }
  975. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  976. return nil, fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  977. }
  978. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  979. return nil, fmt.Errorf("无法识别的 Result :%s", msg.Result)
  980. }
  981. fmt.Println(msg)
  982. business, err := p.Dao.WherePri(busId).Where(p.Dao.C.NboCode, nboCode).One()
  983. if err != nil {
  984. return nil, err
  985. }
  986. if business == nil {
  987. return nil, fmt.Errorf("项目不存在:%s Id: %d", flow.BizCode, flow.Id)
  988. }
  989. return business, nil
  990. }