business.go 40 KB

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