business.go 40 KB

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