business.go 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700
  1. package proj
  2. import (
  3. "context"
  4. platDao "dashoo.cn/micro/app/dao/plat"
  5. "github.com/gogf/gf/container/garray"
  6. "os"
  7. contractDao "dashoo.cn/micro/app/dao/contract"
  8. custDao "dashoo.cn/micro/app/dao/cust"
  9. projDao "dashoo.cn/micro/app/dao/proj"
  10. contractModel "dashoo.cn/micro/app/model/contract"
  11. model "dashoo.cn/micro/app/model/proj"
  12. workflowModel "dashoo.cn/micro/app/model/workflow"
  13. workflowService "dashoo.cn/micro/app/service/workflow"
  14. "dashoo.cn/opms_libary/plugin/dingtalk"
  15. "fmt"
  16. "strconv"
  17. "strings"
  18. "dashoo.cn/micro/app/service"
  19. "dashoo.cn/opms_libary/multipart"
  20. "dashoo.cn/opms_libary/myerrors"
  21. "dashoo.cn/opms_libary/plugin/dingtalk/message"
  22. "dashoo.cn/opms_libary/plugin/dingtalk/workflow"
  23. "dashoo.cn/opms_libary/utils"
  24. "github.com/gogf/gf/database/gdb"
  25. "github.com/gogf/gf/frame/g"
  26. "github.com/gogf/gf/os/gtime"
  27. "github.com/gogf/gf/util/gconv"
  28. "github.com/shopspring/decimal"
  29. )
  30. type businessService struct {
  31. *service.ContextService
  32. Dao *projDao.ProjBusinessDao
  33. ContactDao *projDao.ProjBusinessContactDao
  34. FollowDao *platDao.PlatFollowupDao
  35. fileDao *projDao.ProjBusinessFileDao
  36. }
  37. func NewBusinessService(ctx context.Context) (svc *businessService, err error) {
  38. svc = new(businessService)
  39. if svc.ContextService, err = svc.Init(ctx); err != nil {
  40. return nil, err
  41. }
  42. svc.Dao = projDao.NewProjBusinessDao(svc.Tenant)
  43. svc.ContactDao = projDao.NewProjBusinessContactDao(svc.Tenant)
  44. svc.FollowDao = platDao.NewPlatFollowupDao(svc.Tenant)
  45. svc.fileDao = projDao.NewProjBusinessFileDao(svc.Tenant)
  46. return svc, nil
  47. }
  48. func (p *businessService) GetList(req *model.ProjBusinessSearchReq) (total int, businessList []*model.ProjBusinessRes, err error) {
  49. db := p.Dao.As("proj").DataScope(p.Ctx, "sale_id")
  50. if req.NboName != "" {
  51. db = db.WhereLike("proj."+p.Dao.C.NboName, "%"+req.NboName+"%")
  52. }
  53. if req.CustName != "" {
  54. db = db.WhereLike("proj."+p.Dao.C.CustName, "%"+req.CustName+"%")
  55. }
  56. if req.SaleName != "" {
  57. db = db.WhereLike("proj."+p.Dao.C.SaleName, "%"+req.SaleName+"%")
  58. }
  59. if req.NboType != "" {
  60. db = db.Where("proj."+p.Dao.C.NboType, req.NboType)
  61. }
  62. if req.ProductLine != "" {
  63. db = db.Where("proj."+p.Dao.C.ProductLine, req.ProductLine)
  64. }
  65. if req.NboSource != "" {
  66. db = db.Where("proj."+p.Dao.C.NboSource, req.NboSource)
  67. }
  68. if req.DistributorName != "" {
  69. db = db.WhereLike("proj."+p.Dao.C.DistributorName, "%"+req.DistributorName+"%")
  70. }
  71. if req.BeginTime != "" {
  72. db = db.WhereGTE("proj."+p.Dao.C.FilingTime, req.BeginTime)
  73. }
  74. if req.EndTime != "" {
  75. db = db.WhereLTE("proj."+p.Dao.C.FilingTime, req.EndTime)
  76. }
  77. if req.ProvinceId != 0 {
  78. db = db.Where("proj."+p.Dao.C.CustProvinceId, req.ProvinceId)
  79. }
  80. total, err = db.Count()
  81. if err != nil {
  82. err = myerrors.DbError("获取总行数失败。")
  83. return
  84. }
  85. if req.NboType == StatusDeal {
  86. db = db.Unscoped().WhereNull(`proj.deleted_time`).
  87. LeftJoin(contractDao.CtrContract.Table, "contract", "`proj`.id=`contract`.nbo_id AND `contract`.`deleted_time` IS NULL ").
  88. Fields("`proj`.cust_city_id as cust_city_id,`contract`.contract_amount, `contract`.created_time as proj_closing_time")
  89. }
  90. db = db.Fields("`proj`.*")
  91. err = db.Page(req.GetPage()).OrderDesc("id").Scan(&businessList)
  92. return
  93. }
  94. func (p *businessService) GetEntityById(id int64) (business *model.ProjBusinessRes, err error) {
  95. err = p.Dao.Where(projDao.ProjBusiness.C.Id, id).Scan(&business)
  96. if err != nil {
  97. return nil, err
  98. }
  99. if business == nil {
  100. return nil, myerrors.TipsError("项目不存在")
  101. }
  102. return
  103. }
  104. func (p *businessService) GetBusinessInfoById(id int64) (business *model.ProjBusinessRes, err error) {
  105. err = p.Dao.Where(projDao.ProjBusiness.C.Id, id).Scan(&business)
  106. if err != nil {
  107. return nil, err
  108. }
  109. if business == nil {
  110. return nil, myerrors.TipsError("项目不存在")
  111. }
  112. business.FollowCount, err = p.FollowDao.Where(p.FollowDao.C.TargetType, "20").Where(p.FollowDao.C.TargetId, business.Id).Count()
  113. if err != nil {
  114. return nil, err
  115. }
  116. productList, err := p.GetBusinessProduct(id)
  117. if err != nil {
  118. return nil, err
  119. }
  120. if err := gconv.Structs(productList, &business.Products); err != nil {
  121. return nil, err
  122. }
  123. files, err := p.fileDao.Where(p.fileDao.C.BusId, id).WhereLike(p.fileDao.C.FileSource, "%报价单%").OrderDesc(p.fileDao.C.Id).Limit(1).All()
  124. if err != nil {
  125. return nil, err
  126. }
  127. business.QuotationFileList = files
  128. return
  129. }
  130. func (p *businessService) GetBusinessProduct(id int64) (productList []*model.ProjBusinessProduct, err error) {
  131. productDao := projDao.NewProjBusinessProductDao(p.Tenant)
  132. err = productDao.Where(productDao.ProjBusinessProductDao.C.BusId, id).Scan(&productList)
  133. return
  134. }
  135. func (p *businessService) GetBusinessDynamics(req *model.BusinessReq) (total int, result g.MapStrAny, err error) {
  136. result = make(g.MapStrAny, 0)
  137. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).ProjBusinessDynamicsDao.Where(projDao.ProjBusinessDynamics.C.BusId, req.BusId)
  138. total, err = dynamicsDao.Count()
  139. if err != nil {
  140. g.Log().Error(err)
  141. return
  142. }
  143. dynamicsList, err := dynamicsDao.Page(req.GetPage()).Order("created_time desc").All()
  144. if err != nil || dynamicsList == nil {
  145. return
  146. }
  147. // 数据树格式转换
  148. opnDateFlag := gtime.New(dynamicsList[0].OpnDate).Format("Y-m-d")
  149. for k, v := range dynamicsList {
  150. opnDate := gtime.New(v.OpnDate).Format("Y-m-d")
  151. if opnDateFlag == opnDate && k != 0 {
  152. result[opnDate] = append(result[opnDate].(g.ListStrAny), g.Map{
  153. "opnPeople": v.OpnPeople,
  154. "opnDate": v.OpnDate,
  155. "opnType": v.OpnType,
  156. "remark": v.Remark,
  157. "opnContent": gconv.Map(v.OpnContent),
  158. })
  159. } else {
  160. temp := make(g.ListStrAny, 0)
  161. temp = append(temp, g.Map{
  162. "opnPeople": v.OpnPeople,
  163. "opnDate": v.OpnDate,
  164. "opnType": v.OpnType,
  165. "remark": v.Remark,
  166. "opnContent": gconv.Map(v.OpnContent),
  167. })
  168. result[opnDate] = temp
  169. opnDateFlag = opnDate
  170. }
  171. }
  172. return
  173. }
  174. func (p *businessService) GetBusinessDynamicsList(req *model.BusinessDynamicsReq) (total int, list []map[string]interface{}, err error) {
  175. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, req.BusId)
  176. if req.OpnType != "" {
  177. dynamicsDao = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType+" = ?", req.OpnType)
  178. }
  179. total, err = dynamicsDao.Count()
  180. if err != nil {
  181. g.Log().Error(err)
  182. return
  183. }
  184. dynamicsList, err := dynamicsDao.Page(req.GetPage()).Order("created_time desc").All()
  185. for _, v := range dynamicsList {
  186. val := gconv.Map(v)
  187. val["opnContent"] = gconv.Map(v.OpnContent)
  188. list = append(list, val)
  189. }
  190. return
  191. }
  192. // 获取项目编号
  193. func (p *businessService) getNboCode(customerCode string) (string, error) {
  194. sequence, err := service.Sequence(p.Dao.DB, "nbo_code")
  195. if err != nil {
  196. return "", err
  197. }
  198. return customerCode + sequence, nil
  199. }
  200. func (p *businessService) Create(req *model.AddProjBusinessReq) (err error) {
  201. // 获取客户信息
  202. customer, err := custDao.NewCustCustomerDao(p.Tenant).WherePri(req.CustId).One()
  203. if err != nil {
  204. return err
  205. }
  206. if customer == nil {
  207. return myerrors.TipsError("客户不存在")
  208. }
  209. // 获取项目编号
  210. nboCode, err := p.getNboCode(customer.CustCode)
  211. if err != nil {
  212. return err
  213. }
  214. // 初始化项目信息
  215. business := new(model.ProjBusiness)
  216. if err = gconv.Struct(req, business); err != nil {
  217. return
  218. }
  219. business.NboCode = nboCode
  220. if business.NboType == "" {
  221. business.NboType = StatusC
  222. }
  223. business.ApproStatus = ApprovalWaiting
  224. business.CustProvinceId = customer.CustProvinceId
  225. business.CustProvince = customer.CustProvince
  226. business.CustCityId = customer.CustCityId
  227. business.CustCity = customer.CustCity
  228. business.CustRegionId = customer.CustRegionId
  229. business.CustRegion = customer.CustRegion
  230. business.DeptId = p.GetCxtUserDeptId()
  231. service.SetCreatedInfo(business, p.GetCxtUserId(), p.GetCxtUserName())
  232. business.FilingTime = business.CreatedTime
  233. productLine, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "sys_product_line", business.ProductLine)
  234. nboSource, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "proj_nbo_source", business.NboSource)
  235. salesModel, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "proj_sales_model", business.SalesModel)
  236. // 事务
  237. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  238. // 添加项目
  239. lastId, err := p.Dao.TX(tx).InsertAndGetId(business)
  240. if err != nil {
  241. return err
  242. }
  243. // 添加项目动态
  244. dynamics := model.ProjBusinessDynamics{
  245. BusId: int(lastId),
  246. OpnType: OpnCreate,
  247. Remark: business.Remark,
  248. }
  249. _, err = p.CreateProjBusinessDynamics(tx, dynamics, business)
  250. // 审批流
  251. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  252. // OMS项目转移 审批
  253. bizCode := business.NboCode + ":" + gconv.String(lastId)
  254. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectCreate, "", &workflow.StartProcessInstanceRequest{
  255. ProcessCode: &BusinessCreateRequestProcessCode,
  256. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  257. {
  258. Id: utils.String("TextField-K2AD4O5B"),
  259. Name: utils.String("项目编码"),
  260. Value: utils.String(business.NboCode),
  261. },
  262. {
  263. Id: utils.String("TextField_BDLSECETVSG0"),
  264. Name: utils.String("项目名称"),
  265. Value: utils.String(business.NboName),
  266. },
  267. {
  268. Id: utils.String("DDSelectField_213JKZA1OUO00"),
  269. Name: utils.String("产品线"),
  270. Value: utils.String(productLine),
  271. },
  272. {
  273. Id: utils.String("TextField_1J9BJMOZ18F40"),
  274. Name: utils.String("客户名称"),
  275. Value: utils.String(business.CustName),
  276. },
  277. {
  278. Id: utils.String("DDSelectField_6CQD451D3800"),
  279. Name: utils.String("项目来源"),
  280. Value: utils.String(nboSource),
  281. },
  282. {
  283. Id: utils.String("TextField_1UQFU5BUEWDC"),
  284. Name: utils.String("历史招标信息"),
  285. Value: utils.String(req.BidInfo),
  286. },
  287. {
  288. Id: utils.String("TextField_AEUWH63LJ0O0"),
  289. Name: utils.String("销售工程师"),
  290. Value: utils.String(business.SaleName),
  291. },
  292. {
  293. Id: utils.String("DDSelectField_34QSUGHO2SO0"),
  294. Name: utils.String("销售模式"),
  295. Value: utils.String(salesModel),
  296. },
  297. {
  298. Id: utils.String("TextField_1PWK6WHMGITC0"),
  299. Name: utils.String("经销商/代理商"),
  300. Value: utils.String(business.DistributorName),
  301. },
  302. {
  303. Id: utils.String("DDSelectField_5R11VVM6GI00"),
  304. Name: utils.String("是否为大项目"),
  305. Value: utils.String(yesOrNoType[business.IsBig]),
  306. },
  307. {
  308. Id: utils.String("TextareaField_1GEL8JJL3H5S0"),
  309. Name: utils.String("备注"),
  310. Value: utils.String(business.Remark),
  311. },
  312. },
  313. })
  314. if err != nil {
  315. g.Log().Error(err)
  316. return err
  317. }
  318. return err
  319. })
  320. return
  321. }
  322. // BusinessCreatedNotify 项目创建 审批结果通知
  323. func (p *businessService) BusinessCreatedNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  324. business, err := p.checkDingTalkNotify(flow, msg)
  325. if err != nil {
  326. return err
  327. }
  328. var data = g.Map{}
  329. if msg.ProcessType == "terminate" {
  330. data[p.Dao.C.ApproStatus] = ApprovalReturn
  331. }
  332. if msg.ProcessType == "finish" && msg.Result == "refuse" {
  333. data[p.Dao.C.ApproStatus] = ApprovalRejection
  334. }
  335. if msg.ProcessType == "finish" && msg.Result == "agree" {
  336. data[p.Dao.C.ApproStatus] = ApprovalOK
  337. }
  338. // 项目修改
  339. _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  340. if err != nil {
  341. return err
  342. }
  343. // 添加项目动态
  344. dynamics := model.ProjBusinessDynamics{
  345. BusId: business.Id,
  346. OpnType: OpnCreatedApproval,
  347. }
  348. _, err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  349. if err != nil {
  350. return err
  351. }
  352. return err
  353. }
  354. // setProductInfo 设置产品信息
  355. func (p *businessService) setProductInfo(busId int, productInfo []model.BusinessProduct) (total float64, products []*model.ProjBusinessProduct, err error) {
  356. products = make([]*model.ProjBusinessProduct, len(productInfo))
  357. if err = gconv.Structs(productInfo, &products); err != nil {
  358. return 0, nil, err
  359. }
  360. var totalPrice decimal.Decimal
  361. for _, v := range products {
  362. v.Id = 0
  363. v.BusId = busId
  364. v.TotalPrice = decimal.NewFromFloat(v.ProdPrice).Mul(decimal.NewFromInt(int64(v.ProdNum))).InexactFloat64()
  365. totalPrice = totalPrice.Add(decimal.NewFromFloat(v.TotalPrice))
  366. service.SetCreatedInfo(v, p.GetCxtUserId(), p.GetCxtUserName())
  367. }
  368. return totalPrice.InexactFloat64(), products, nil
  369. }
  370. // setBusinessContact 设置项目联系人
  371. func (p *businessService) setBusinessContact(tx *gdb.TX, contactList []model.SetBusinessContactReq) (err error) {
  372. for _, item := range contactList {
  373. count, err := p.ContactDao.Where(p.ContactDao.C.BusId, item.BusId).Where(p.ContactDao.C.ContactType, item.ContactType).Count()
  374. if err != nil {
  375. return err
  376. }
  377. if count == 0 {
  378. data := new(model.ProjBusinessContact)
  379. data.BusId = item.BusId
  380. data.ContactId = item.ContactId
  381. data.ContactType = item.ContactType
  382. service.SetCreatedInfo(data, p.GetCxtUserId(), p.GetCxtUserName())
  383. _, err = p.ContactDao.TX(tx).Data(data).Insert()
  384. if err != nil {
  385. return err
  386. }
  387. }
  388. }
  389. return
  390. }
  391. func (p *businessService) UpdateById(req *model.UpdateProjBusinessReq) error {
  392. record, err := p.Dao.WherePri(req.Id).Count()
  393. if err != nil {
  394. return err
  395. }
  396. if record == 0 {
  397. return myerrors.TipsError("项目不存在。")
  398. }
  399. // 设置产品信息
  400. totalPrice, products, err := p.setProductInfo(req.Id, req.Products)
  401. if err != nil {
  402. return err
  403. }
  404. // 设置默认联系人
  405. contactList := make([]model.SetBusinessContactReq, 0)
  406. if req.ContactId != 0 {
  407. contactList = append(contactList, model.SetBusinessContactReq{
  408. BusId: req.Id,
  409. ContactId: req.ContactId,
  410. ContactType: "10",
  411. })
  412. }
  413. if req.DealerSalesId != 0 {
  414. contactList = append(contactList, model.SetBusinessContactReq{
  415. BusId: req.Id,
  416. ContactId: req.DealerSalesId,
  417. ContactType: "20",
  418. })
  419. }
  420. // 设置项目信息
  421. req.EstTransPrice = totalPrice
  422. businessData := gconv.Map(req)
  423. service.SetUpdatedInfo(businessData, p.GetCxtUserId(), p.GetCxtUserName())
  424. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  425. // 更新项目
  426. updateFieldEx := append(service.UpdateFieldEx, p.Dao.C.SaleId, p.Dao.C.SaleName, p.Dao.C.NboType, p.Dao.C.NboCode)
  427. _, err = p.Dao.TX(tx).FieldsEx(updateFieldEx...).WherePri(projDao.ProjBusiness.C.Id, req.Id).Update(businessData)
  428. if err != nil {
  429. return err
  430. }
  431. // 删除项目产品
  432. _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Where(projDao.ProjBusinessProduct.C.BusId, req.Id).Delete()
  433. if err != nil {
  434. return err
  435. }
  436. // 添加项目产品
  437. _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Insert(products)
  438. if err != nil {
  439. return err
  440. }
  441. // 关联联系人
  442. err = p.setBusinessContact(tx, contactList)
  443. if err != nil {
  444. return err
  445. }
  446. // 添加项目动态
  447. dynamics := model.ProjBusinessDynamics{
  448. BusId: req.Id,
  449. OpnType: OpnUpdate,
  450. Remark: req.Remark,
  451. }
  452. _, err = p.CreateProjBusinessDynamics(tx, dynamics, req)
  453. return err
  454. })
  455. return err
  456. }
  457. // UpdateBusinessContactInfo 清理项目表联系人信息
  458. func (p *businessService) UpdateBusinessContactInfo(tx *gdb.TX, busId int, data g.Map) (err error) {
  459. fields := []interface{}{p.Dao.C.ContactId, p.Dao.C.ContactName, p.Dao.C.ContactPostion, p.Dao.C.ContactTelephone, p.Dao.C.DealerSalesId, p.Dao.C.DealerSalesName, p.Dao.C.DealerSalesContact}
  460. _, err = p.Dao.TX(tx).Fields(fields...).WherePri(busId).Data(data).Update()
  461. return
  462. }
  463. func (p *businessService) DeleteByIds(ids []int64) (err error) {
  464. _, err = p.Dao.WhereIn(projDao.ProjBusiness.C.Id, ids).Delete()
  465. return
  466. }
  467. // SysAdminBusinessTransfer 管理员项目转移销售(未涉及审批的)
  468. func (p *businessService) SysAdminBusinessTransfer(req *model.SysAdminBusinessTransferReq) error {
  469. // 校验用户是否有修改权限
  470. arr := garray.NewStrArrayFrom(p.CxtUser.Roles, true)
  471. if !arr.Contains("SysAdmin") {
  472. return myerrors.TipsError("权限不足")
  473. }
  474. businessList, err := p.Dao.WherePri(req.Ids).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).All()
  475. if err != nil {
  476. return err
  477. }
  478. if len(businessList) == 0 {
  479. return myerrors.TipsError("转移项目不能为空")
  480. }
  481. var updateData = g.Map{}
  482. updateData[p.Dao.C.SaleId] = req.UserId
  483. updateData[p.Dao.C.SaleName] = req.UserName
  484. updateData[p.Dao.C.Remark] = req.Remark
  485. service.SetUpdatedInfo(updateData, p.GetCxtUserId(), p.GetCxtUserName())
  486. // 添加项目动态
  487. for _, item := range businessList {
  488. err := p.Dao.Transaction(p.Ctx, func(ctx context.Context, tx *gdb.TX) error {
  489. // 项目修改
  490. _, err = p.Dao.TX(tx).WherePri(item.Id).FieldsEx(service.UpdateFieldEx...).Data(updateData).Update()
  491. if err != nil {
  492. return err
  493. }
  494. dynamics := model.ProjBusinessDynamics{
  495. BusId: item.Id,
  496. OpnType: OpnTransfer,
  497. Remark: req.Remark,
  498. }
  499. opnContent := gconv.Map(gconv.String(updateData))
  500. opnContent["origSaleId"] = item.SaleId
  501. opnContent["origSaleName"] = item.SaleName
  502. _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  503. if err != nil {
  504. g.Log().Error(err)
  505. return err
  506. }
  507. return nil
  508. })
  509. if err != nil {
  510. g.Log().Error(fmt.Sprintf("管理员转移项目销售:%v 由%v转移至%v失败", item.NboName, item.SaleName, req.UserName), err.Error())
  511. }
  512. }
  513. return nil
  514. }
  515. // BusinessTransfer 项目转移
  516. func (p *businessService) BusinessTransfer(req *model.BusinessTransferReq) error {
  517. business, err := p.Dao.WherePri(req.Id).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One()
  518. if err != nil {
  519. return err
  520. }
  521. if business == nil {
  522. return myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  523. }
  524. businessMap := g.Map{
  525. p.Dao.C.ApproStatus: ApprovalWaiting,
  526. }
  527. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  528. opnContent := gconv.Map(gconv.String(businessMap))
  529. opnContent["origSaleId"] = business.SaleId
  530. opnContent["origSaleName"] = business.SaleName
  531. opnContent["saleId"] = req.UserId
  532. opnContent["saleName"] = req.UserName
  533. opnContent["remark"] = req.Remark
  534. productLine, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "sys_product_line", business.ProductLine)
  535. // 审批流
  536. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  537. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  538. // 更新项目
  539. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update()
  540. if err != nil {
  541. return err
  542. }
  543. // 添加项目动态
  544. dynamics := model.ProjBusinessDynamics{
  545. BusId: req.Id,
  546. OpnType: OpnTransfer,
  547. Remark: req.Remark,
  548. }
  549. _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  550. if err != nil {
  551. g.Log().Error(err)
  552. return err
  553. }
  554. // OMS项目转移 审批
  555. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  556. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectTransfer, "", &workflow.StartProcessInstanceRequest{
  557. ProcessCode: &BusinessTransferRequestProcessCode,
  558. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  559. {
  560. Id: utils.String("TextField-K2AD4O5B"),
  561. Name: utils.String("项目编码"),
  562. Value: utils.String(business.NboCode),
  563. },
  564. {
  565. Id: utils.String("TextField_7EFHRQ9DDF80"),
  566. Name: utils.String("项目名称"),
  567. Value: utils.String(business.NboName),
  568. },
  569. {
  570. Id: utils.String("TextField_1T3DEY5FWV7K0"),
  571. Name: utils.String("客户名称"),
  572. Value: utils.String(business.CustName),
  573. },
  574. {
  575. Id: utils.String("TextField_QDU06LXYKK00"),
  576. Name: utils.String("所在省"),
  577. Value: utils.String(business.CustProvince),
  578. },
  579. {
  580. Id: utils.String("TextField_MVSOO6EG6YO0"),
  581. Name: utils.String("所在市"),
  582. Value: utils.String(business.CustCity),
  583. },
  584. {
  585. Id: utils.String("DDSelectField_6OMVO1JV0980"),
  586. Name: utils.String("产品线"),
  587. Value: utils.String(productLine),
  588. },
  589. {
  590. Id: utils.String("TextField_1E1WOYGKRTDS0"),
  591. Name: utils.String("项目级别"),
  592. Value: utils.String(nboType[business.NboType]),
  593. },
  594. {
  595. Id: utils.String("TextField_NRQXWLJ17HC0"),
  596. Name: utils.String("申请人"),
  597. Value: utils.String(p.GetCxtUserName()),
  598. },
  599. {
  600. Id: utils.String("TextField_GHSQYDGD13K0"),
  601. Name: utils.String("转移原因"),
  602. Value: utils.String(req.Remark),
  603. },
  604. {
  605. Id: utils.String("TextField_76P8FPHH0UC0"),
  606. Name: utils.String("接收人"),
  607. Value: utils.String(req.UserName),
  608. },
  609. },
  610. })
  611. if err != nil {
  612. g.Log().Error(err)
  613. return err
  614. }
  615. return nil
  616. })
  617. return err
  618. }
  619. // BusinessTransferNotify 项目转移 审批结果通知
  620. func (p *businessService) BusinessTransferNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  621. business, err := p.checkDingTalkNotify(flow, msg)
  622. if err != nil {
  623. return err
  624. }
  625. var data = g.Map{}
  626. if msg.ProcessType == "terminate" {
  627. data[p.Dao.C.ApproStatus] = ApprovalReturn
  628. }
  629. if msg.ProcessType == "finish" && msg.Result == "refuse" {
  630. data[p.Dao.C.ApproStatus] = ApprovalRejection
  631. }
  632. if msg.ProcessType == "finish" && msg.Result == "agree" {
  633. // 从项目动态内获取变更信息
  634. var transferDynamics model.ProjBusinessDynamics
  635. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id)
  636. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnTransfer).OrderDesc("created_time").Scan(&transferDynamics)
  637. if err != nil {
  638. return err
  639. }
  640. changeData := gconv.Map(transferDynamics.OpnContent)
  641. data[p.Dao.C.SaleId] = changeData["saleId"]
  642. data[p.Dao.C.SaleName] = changeData["saleName"]
  643. data[p.Dao.C.Remark] = changeData["remark"]
  644. data[p.Dao.C.ApproStatus] = ApprovalOK
  645. }
  646. // 项目修改
  647. _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  648. if err != nil {
  649. return err
  650. }
  651. // 添加项目动态
  652. dynamics := model.ProjBusinessDynamics{
  653. BusId: business.Id,
  654. OpnType: OpnTransferApproval,
  655. }
  656. _, err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  657. if err != nil {
  658. return err
  659. }
  660. return err
  661. }
  662. // BusinessGradation 项目调级
  663. func (p *businessService) BusinessGradation(busId int, nboType, busType string) (*model.ProjBusiness, error) {
  664. business, err := p.Dao.WherePri(busId).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One()
  665. if err != nil {
  666. return nil, err
  667. }
  668. if business == nil {
  669. return nil, myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  670. }
  671. if business.NboType == nboType {
  672. return nil, myerrors.TipsError("同级别无法进行调级。")
  673. }
  674. if business.NboType == StatusDeal {
  675. return nil, myerrors.TipsError("成交项目无法进行调级。")
  676. }
  677. if business.NboType == StatusReserve && nboType == StatusDeal {
  678. return nil, myerrors.TipsError("储备项目无法直接转为成交项目。")
  679. }
  680. if busType == "up" && gconv.Int(business.NboType) < gconv.Int(nboType) {
  681. return nil, myerrors.TipsError("项目级别错误。")
  682. }
  683. if busType == "down" && gconv.Int(business.NboType) > gconv.Int(nboType) {
  684. return nil, myerrors.TipsError("项目级别错误。")
  685. }
  686. return business, err
  687. }
  688. // BusinessUpgrade 项目升级
  689. func (p *businessService) BusinessUpgrade(req *model.BusinessUpgradeReq, fileMap map[string]*multipart.FileHeader) error {
  690. business, err := p.BusinessGradation(req.Id, req.NboType, "up")
  691. if err != nil {
  692. return err
  693. }
  694. businessMap := g.Map{p.Dao.C.ApproStatus: ApprovalWaiting}
  695. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  696. opnContent := gconv.Map(req)
  697. opnContent["origNboType"] = business.NboType
  698. opnContent["approStatus"] = ApprovalWaiting
  699. service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName())
  700. if fileMap == nil {
  701. fileMap = make(map[string]*multipart.FileHeader)
  702. }
  703. if (req.NboType == StatusA || req.NboType == StatusB) && !strings.HasPrefix(req.QuotationFile, "dingtalk") {
  704. fileMap["quotationFile"], err = service.DownloadTempFile(req.QuotationFile)
  705. if err != nil {
  706. return err
  707. }
  708. defer os.Remove(fileMap["quotationFile"].File.Name())
  709. }
  710. if req.NboType == StatusA && req.IsAdoptDashoo == "10" {
  711. fileMap["dashooParamFile"], err = service.DownloadTempFile(req.DashooParamFile)
  712. if err != nil {
  713. return err
  714. }
  715. defer os.Remove(fileMap["dashooParamFile"].File.Name())
  716. }
  717. contactList := make([]model.SetBusinessContactReq, 0)
  718. if req.ContactId != 0 {
  719. contactList = append(contactList, model.SetBusinessContactReq{
  720. BusId: req.Id,
  721. ContactId: req.ContactId,
  722. ContactType: "10",
  723. })
  724. }
  725. if req.DealerSalesId != 0 {
  726. contactList = append(contactList, model.SetBusinessContactReq{
  727. BusId: req.Id,
  728. ContactId: req.DealerSalesId,
  729. ContactType: "20",
  730. })
  731. }
  732. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  733. // 更新项目调级
  734. _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update()
  735. if err != nil {
  736. return err
  737. }
  738. // 关联联系人
  739. err = p.setBusinessContact(tx, contactList)
  740. if err != nil {
  741. return err
  742. }
  743. // 添加项目动态
  744. dynamics := model.ProjBusinessDynamics{
  745. BusId: business.Id,
  746. OpnType: OpnUpgrade,
  747. Remark: req.Remark,
  748. }
  749. _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  750. if err != nil {
  751. return err
  752. }
  753. err = p.BusUpgradeDingEvent(business, req, fileMap)
  754. return err
  755. })
  756. if err != nil {
  757. return err
  758. }
  759. return nil
  760. }
  761. // 获取项目的钉钉审批的升级类型
  762. func (p *businessService) getBusDingUpgradeType(dbNboType, reqNboType string) string {
  763. var upgradeType string
  764. switch true {
  765. case dbNboType == StatusReserve && reqNboType == StatusC: // 储备转C/option_0
  766. upgradeType = "储备转C"
  767. case dbNboType == StatusReserve && reqNboType == StatusB: // 储备转B/option_1
  768. upgradeType = "储备转B"
  769. case dbNboType == StatusReserve && reqNboType == StatusA: // 储备转A/option_KTAX3Y9K5340
  770. upgradeType = "储备转A"
  771. case dbNboType == StatusC && reqNboType == StatusB: // C转B/option_0
  772. upgradeType = "C转B"
  773. case dbNboType == StatusC && reqNboType == StatusA: // C转A/option_0
  774. upgradeType = "C转A"
  775. case dbNboType == StatusB && reqNboType == StatusA: // B转A/option_1
  776. upgradeType = "B转A"
  777. default:
  778. }
  779. return upgradeType
  780. }
  781. // BusUpgradeDingEvent 项目升级钉钉审批流调用
  782. func (p *businessService) BusUpgradeDingEvent(business *model.ProjBusiness, req *model.BusinessUpgradeReq, fileMap map[string]*multipart.FileHeader) error {
  783. var err error
  784. upgradeType := p.getBusDingUpgradeType(business.NboType, req.NboType)
  785. if upgradeType == "" {
  786. return myerrors.TipsError("错误的升级类型")
  787. }
  788. productLineMap, err := service.GetDictDataTreeByType(p.Ctx, "sys_product_line")
  789. if err != nil {
  790. return err
  791. }
  792. productLine := gconv.String(productLineMap.Get(business.ProductLine))
  793. dingProductList := make([][]*workflow.StartProcessInstanceRequestFormComponentValues, 0)
  794. for _, item := range req.Products {
  795. pInfo := make([]*workflow.StartProcessInstanceRequestFormComponentValues, 0)
  796. pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{
  797. Id: utils.String("TextField_8P2W917Q5I40"),
  798. Name: utils.String("产品编码"),
  799. Value: utils.String(item.ProdCode),
  800. })
  801. pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{
  802. Id: utils.String("TextField_1W2HGNQFLLA80"),
  803. Name: utils.String("产品名称"),
  804. Value: utils.String(item.ProdName),
  805. })
  806. pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{
  807. Id: utils.String("TextField_1OPT3MZL76GW0"),
  808. Name: utils.String("产品类别"),
  809. Value: utils.String(gconv.String(productLineMap.Get(item.ProdClass))),
  810. })
  811. pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{
  812. Id: utils.String("TextField_O405QBZMPW00"),
  813. Name: utils.String("产品单价"),
  814. Value: utils.String(gconv.String(item.ProdPrice)),
  815. })
  816. pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{
  817. Id: utils.String("TextField_23P54AZUW4SG0"),
  818. Name: utils.String("数量"),
  819. Value: utils.String(gconv.String(item.ProdNum)),
  820. })
  821. dingProductList = append(dingProductList, pInfo)
  822. }
  823. // 审批流
  824. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  825. // OMS项目升级 审批
  826. var dingReq *workflow.StartProcessInstanceRequest
  827. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  828. switch req.NboType {
  829. case StatusC:
  830. dingReq = &workflow.StartProcessInstanceRequest{
  831. ProcessCode: &BusinessUpgradeCRequestProcessCode,
  832. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  833. {
  834. Id: utils.String("TextField-K2AD4O5B"),
  835. Name: utils.String("项目编码"),
  836. Value: utils.String(business.NboCode),
  837. },
  838. {
  839. Id: utils.String("TextField_BDLSECETVSG0"),
  840. Name: utils.String("项目名称"),
  841. Value: utils.String(business.NboName),
  842. },
  843. {
  844. Id: utils.String("DDSelectField_1MJU37HGJX4W0"),
  845. Name: utils.String("产品线"),
  846. Value: utils.String(productLine),
  847. },
  848. {
  849. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  850. Name: utils.String("升级类型"),
  851. Value: utils.String(upgradeType),
  852. },
  853. {
  854. Id: utils.String("TextField_1J9BJMOZ18F40"),
  855. Name: utils.String("客户名称"),
  856. Value: utils.String(business.CustName),
  857. },
  858. {
  859. Id: utils.String("TextField_AEUWH63LJ0O0"),
  860. Name: utils.String("销售工程师"),
  861. Value: utils.String(business.SaleName),
  862. },
  863. {
  864. Id: utils.String("TextareaField_1LO81IKHH91C0"),
  865. Name: utils.String("转化原因"),
  866. Value: utils.String(req.ProjConversionReason),
  867. },
  868. },
  869. }
  870. case StatusB:
  871. quotationFile := make([]contractModel.DingFileInfo, 0)
  872. if len(fileMap) > 0 {
  873. for k, files := range fileMap {
  874. // 报价单
  875. if k == "quotationFile" {
  876. if quotationFile, err = p.txCreateBusinessDingTalkFile(business.Id, upgradeType, k, files); err != nil {
  877. return err
  878. }
  879. }
  880. }
  881. }
  882. if len(quotationFile) == 0 {
  883. return myerrors.TipsError("请上传报价单文件")
  884. }
  885. processCode := &BusinessUpgradeBRequestProcessCode
  886. dingReq = &workflow.StartProcessInstanceRequest{
  887. ProcessCode: processCode,
  888. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  889. {
  890. Id: utils.String("TextField-K2AD4O5B"),
  891. Name: utils.String("项目编码"),
  892. Value: utils.String(business.NboCode),
  893. },
  894. {
  895. Id: utils.String("TextField_BDLSECETVSG0"),
  896. Name: utils.String("项目名称"),
  897. Value: utils.String(business.NboName),
  898. },
  899. {
  900. Id: utils.String("DDSelectField_213JKZA1OUO00"),
  901. Name: utils.String("产品线"),
  902. Value: utils.String(productLine),
  903. },
  904. {
  905. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  906. Name: utils.String("升级类型"),
  907. Value: utils.String(upgradeType),
  908. },
  909. {
  910. Id: utils.String("TextField_1J9BJMOZ18F40"),
  911. Name: utils.String("客户名称"),
  912. Value: utils.String(business.CustName),
  913. },
  914. {
  915. Id: utils.String("NumberField_1F88MCD0W8KG0"),
  916. Name: utils.String("项目预算"),
  917. Value: utils.String(gconv.String(req.NboBudget)),
  918. },
  919. {
  920. Id: utils.String("TextField_1PWK6WHMGITC0"),
  921. Name: utils.String("渠道销售人员"),
  922. Value: utils.String(req.DealerSalesName),
  923. },
  924. {
  925. Id: utils.String("TextField_M06MZK20POG0"),
  926. Name: utils.String("渠道销售电话/微信"),
  927. Value: utils.String(req.DealerSalesContact),
  928. },
  929. {
  930. Id: utils.String("TextField_GL59OGH2Z1S0"),
  931. Name: utils.String("预计出货金额"),
  932. Value: utils.String(gconv.String(business.EstTransPrice)),
  933. },
  934. {
  935. Id: utils.String("TableField_1CGSRAWT8YG0"),
  936. Name: utils.String("产品列表"),
  937. Value: utils.String(gconv.String(dingProductList)),
  938. },
  939. {
  940. Id: utils.String("TextField_AEUWH63LJ0O0"),
  941. Name: utils.String("销售工程师"),
  942. Value: utils.String(business.SaleName),
  943. },
  944. {
  945. Id: utils.String("DDAttachment_KZPWZJS9GHO0"),
  946. Name: utils.String("上传报价单"),
  947. Value: utils.String(gconv.String(quotationFile)),
  948. },
  949. {
  950. Id: utils.String("TextareaField_1GEL8JJL3H5S0"),
  951. Name: utils.String("备注"),
  952. Value: utils.String(req.Remark),
  953. },
  954. },
  955. }
  956. case StatusA:
  957. var dashooParamFile []contractModel.DingFileInfo
  958. var quotationFile []contractModel.DingFileInfo
  959. if len(fileMap) > 0 {
  960. for k, files := range fileMap {
  961. // 报价单
  962. if k == "quotationFile" {
  963. if quotationFile, err = p.txCreateBusinessDingTalkFile(business.Id, upgradeType, k, files); err != nil {
  964. return err
  965. }
  966. }
  967. // 大数参数文件
  968. if k == "dashooParamFile" {
  969. if dashooParamFile, err = p.txCreateBusinessDingTalkFile(business.Id, upgradeType, k, files); err != nil {
  970. return err
  971. }
  972. }
  973. }
  974. }
  975. if strings.HasPrefix(req.QuotationFile, "dingtalk") {
  976. arr := strings.Split(req.QuotationFile, ":")
  977. quotationFile = append(quotationFile, contractModel.DingFileInfo{
  978. SpaceId: arr[1],
  979. FileId: arr[2],
  980. FileName: fmt.Sprintf("%v报价单", business.NboName),
  981. FileSize: 10,
  982. FileType: "",
  983. })
  984. }
  985. if len(quotationFile) == 0 {
  986. return myerrors.TipsError("请上传报价单文件")
  987. }
  988. processCode := &BusinessUpgradeARequestProcessCode
  989. dingReq = &workflow.StartProcessInstanceRequest{
  990. ProcessCode: processCode,
  991. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  992. {
  993. Id: utils.String("TextField-K2AD4O5B"),
  994. Name: utils.String("项目编码"),
  995. Value: utils.String(business.NboCode),
  996. },
  997. {
  998. Id: utils.String("TextField_BDLSECETVSG0"),
  999. Name: utils.String("项目名称"),
  1000. Value: utils.String(business.NboName),
  1001. },
  1002. {
  1003. Id: utils.String("DDSelectField_L4CSUVLU1NK"),
  1004. Name: utils.String("产品线"),
  1005. Value: utils.String(productLine),
  1006. },
  1007. {
  1008. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  1009. Name: utils.String("升级类型"),
  1010. Value: utils.String(upgradeType),
  1011. },
  1012. {
  1013. Id: utils.String("TextField_1J9BJMOZ18F40"),
  1014. Name: utils.String("客户名称"),
  1015. Value: utils.String(business.CustName),
  1016. },
  1017. {
  1018. Id: utils.String("DDSelectField_21ASEWDIB3MO0"),
  1019. Name: utils.String("采购方式"),
  1020. Value: utils.String(gconv.String(purchasingWayType[req.PurchasingWay])),
  1021. },
  1022. {
  1023. Id: utils.String("TextField_3AIYCSEQLQC0"),
  1024. Name: utils.String("资金来源"),
  1025. Value: utils.String(req.CapitalSource),
  1026. },
  1027. {
  1028. Id: utils.String("DDDateField_1FW1QZQYBZVK0"),
  1029. Name: utils.String("计划采购时间"),
  1030. Value: utils.String(gconv.String(req.PlanPurchaseTime.Format("Y-m-d"))),
  1031. },
  1032. {
  1033. Id: utils.String("TextField_1PWK6WHMGITC0"),
  1034. Name: utils.String("客户决策人"),
  1035. Value: utils.String(req.MakerName),
  1036. },
  1037. {
  1038. Id: utils.String("TextField_16RIJRRF8B340"),
  1039. Name: utils.String("客户决策部门"),
  1040. Value: utils.String(req.MakerDept),
  1041. },
  1042. {
  1043. Id: utils.String("TextField_7EE0LTUVUSK0"),
  1044. Name: utils.String("客户联系人"),
  1045. Value: utils.String(req.ContactName),
  1046. },
  1047. {
  1048. Id: utils.String("TextField_E8TFCZUBV940"),
  1049. Name: utils.String("客户联系人电话/微信"),
  1050. Value: utils.String(req.ContactTelephone),
  1051. },
  1052. {
  1053. Id: utils.String("DDSelectField_5R11VVM6GI00"),
  1054. Name: utils.String("是否我司参数"),
  1055. Value: utils.String(gconv.String(yesOrNoType[req.IsAdoptDashoo])),
  1056. },
  1057. {
  1058. Id: utils.String("DDAttachment_11Q7DBRKE6HC0"),
  1059. Name: utils.String("附件"),
  1060. Value: utils.String(gconv.String(dashooParamFile)),
  1061. },
  1062. {
  1063. Id: utils.String("TextField_FJI7GL9E8W80"),
  1064. Name: utils.String("竞争公司"),
  1065. Value: utils.String(req.Competitor),
  1066. },
  1067. {
  1068. Id: utils.String("TextField_1NC9MEUBDBR40"),
  1069. Name: utils.String("客户倾向厂家"),
  1070. Value: utils.String(req.CustomerIntentionFactory),
  1071. },
  1072. {
  1073. Id: utils.String("TextField_AEUWH63LJ0O0"),
  1074. Name: utils.String("销售工程师"),
  1075. Value: utils.String(business.SaleName),
  1076. },
  1077. {
  1078. Id: utils.String("DDAttachment_19Y01ZRBFWXS0"),
  1079. Name: utils.String("上传报价单"),
  1080. Value: utils.String(gconv.String(quotationFile)),
  1081. },
  1082. {
  1083. Id: utils.String("TextareaField_1GEL8JJL3H5S0"),
  1084. Name: utils.String("备注"),
  1085. Value: utils.String(req.Remark),
  1086. },
  1087. },
  1088. }
  1089. default:
  1090. return nil
  1091. }
  1092. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectUpGrade, "", dingReq)
  1093. if err != nil {
  1094. g.Log().Error(err)
  1095. return err
  1096. }
  1097. return nil
  1098. }
  1099. // 项目上传文件至钉钉
  1100. func (p *businessService) txCreateBusinessDingTalkFile(businessId int, upgradeType, fileType string, file *multipart.FileHeader) ([]contractModel.DingFileInfo, error) {
  1101. dingTalkFiles := make([]contractModel.DingFileInfo, 0)
  1102. //for _, file := range files {
  1103. resp, err := dingtalk.Client.GetStorage().UploadFile(service.DingTalkSpaceId, p.GetCxtUserDingtalkId(), file.FileName, file.File.Name())
  1104. if err != nil {
  1105. g.Log().Error(err)
  1106. return nil, myerrors.TipsError("钉钉上传文件异常")
  1107. }
  1108. typ := "项目" + upgradeType
  1109. if fileType == "quotationFile" {
  1110. typ += "上传报价单文件"
  1111. }
  1112. if fileType == "dashooParamFile" {
  1113. typ += "上传大数技术参数文件"
  1114. }
  1115. g.Log().Info(typ, resp)
  1116. dingTalkFiles = append(dingTalkFiles, contractModel.DingFileInfo{
  1117. SpaceId: resp.Dentry.SpaceId,
  1118. FileId: resp.Dentry.Id,
  1119. FileName: resp.Dentry.Name,
  1120. FileSize: resp.Dentry.Size,
  1121. FileType: resp.Dentry.Extension,
  1122. })
  1123. //}
  1124. err = p.txCreateBusinessFile(businessId, typ, dingTalkFiles)
  1125. if err != nil {
  1126. return nil, err
  1127. }
  1128. return dingTalkFiles, nil
  1129. }
  1130. // 采用大数参数文件记录
  1131. func (p *businessService) txCreateBusinessFile(busId int, fileSource string, files []contractModel.DingFileInfo) error {
  1132. dataList := make([]*model.ProjBusinessFile, 0)
  1133. for _, v := range files {
  1134. data := new(model.ProjBusinessFile)
  1135. data.BusId = busId
  1136. data.FileName = v.FileName
  1137. data.FileSource = fileSource
  1138. data.FileSize = gconv.String(v.FileSize)
  1139. data.FileUrl = strings.Join([]string{"dingtalk", v.SpaceId, v.FileId}, ":")
  1140. service.SetCreatedInfo(data, p.GetCxtUserId(), p.GetCxtUserName())
  1141. dataList = append(dataList, data)
  1142. }
  1143. _, err := projDao.NewProjBusinessFileDao(p.Tenant).Insert(&dataList)
  1144. return err
  1145. }
  1146. // BusinessUpgradeNotify 项目升级 审批结果通知
  1147. func (p *businessService) BusinessUpgradeNotify(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. var updateData *model.BusinessUpgradeReq
  1154. var remark string
  1155. if msg.ProcessType == "terminate" {
  1156. data[p.Dao.C.ApproStatus] = ApprovalReturn
  1157. }
  1158. if msg.ProcessType == "finish" && msg.Result == "refuse" {
  1159. data[p.Dao.C.ApproStatus] = ApprovalRejection
  1160. }
  1161. if msg.ProcessType == "finish" && msg.Result == "agree" {
  1162. // 从项目动态内获取变更信息
  1163. dynamics := new(model.ProjBusinessDynamics)
  1164. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id)
  1165. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnUpgrade).OrderDesc("created_time").Scan(dynamics)
  1166. if err != nil {
  1167. return err
  1168. }
  1169. updateData = new(model.BusinessUpgradeReq)
  1170. gconv.Struct(dynamics.OpnContent, updateData)
  1171. data = gconv.Map(updateData)
  1172. data[p.Dao.C.ApproStatus] = ApprovalOK
  1173. remarkMap := gconv.Map(dynamics.OpnContent)
  1174. remark = gconv.String(g.Map{"nboType": remarkMap["nboType"], "origNboType": remarkMap["origNboType"]})
  1175. }
  1176. err = p.Dao.Transaction(p.Ctx, func(ctx context.Context, tx *gdb.TX) error {
  1177. // 添加产品
  1178. if updateData != nil && (updateData.NboType == "20" || updateData.NboType == "10") {
  1179. // 设置产品信息
  1180. totalPrice, products, err := p.setProductInfo(updateData.Id, updateData.Products)
  1181. if err != nil {
  1182. return err
  1183. }
  1184. // 删除项目产品
  1185. _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Where(projDao.ProjBusinessProduct.C.BusId, updateData.Id).Delete()
  1186. if err != nil {
  1187. return err
  1188. }
  1189. // 添加项目产品
  1190. _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Insert(products)
  1191. if err != nil {
  1192. return err
  1193. }
  1194. data[p.Dao.C.EstTransPrice] = totalPrice
  1195. }
  1196. // 项目修改
  1197. _, err = p.Dao.TX(tx).WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  1198. if err != nil {
  1199. return err
  1200. }
  1201. // 添加项目动态
  1202. dynamics := model.ProjBusinessDynamics{
  1203. BusId: business.Id,
  1204. OpnType: OpnUpgradeApproval,
  1205. Remark: remark,
  1206. }
  1207. _, err = p.CreateProjBusinessDynamics(tx, dynamics, data)
  1208. if err != nil {
  1209. return err
  1210. }
  1211. return nil
  1212. })
  1213. if err != nil {
  1214. return err
  1215. }
  1216. return nil
  1217. }
  1218. // 获取项目的钉钉审批的降级类型
  1219. func (p *businessService) getBusDingDowngradeType(dbNboType, reqNboType string) string {
  1220. var downgradeType string
  1221. switch true {
  1222. case dbNboType == StatusB && reqNboType == StatusC: // B转C/option_0
  1223. downgradeType = "B转C"
  1224. case dbNboType == StatusA && reqNboType == StatusB: // A转B/option_1
  1225. downgradeType = "A转B"
  1226. case dbNboType == StatusA && reqNboType == StatusC: // A转C/option_2
  1227. downgradeType = "A转C"
  1228. case dbNboType == StatusA && reqNboType == StatusReserve: // A转储备/option_YZMFJYQQK6O0
  1229. downgradeType = "A转储备"
  1230. case dbNboType == StatusB && reqNboType == StatusReserve: // B转储备/option_232GR5NMFCSG0
  1231. downgradeType = "B转储备"
  1232. case dbNboType == StatusC && reqNboType == StatusReserve: // C转储备/option_1ZV2GJLDKQOW0
  1233. downgradeType = "C转储备"
  1234. default:
  1235. }
  1236. return downgradeType
  1237. }
  1238. // BusinessDowngrade 项目降级
  1239. func (p *businessService) BusinessDowngrade(req *model.BusinessDowngradeReq) error {
  1240. business, err := p.BusinessGradation(req.Id, req.NboType, "down")
  1241. if err != nil {
  1242. return err
  1243. }
  1244. downgradeType := p.getBusDingDowngradeType(business.NboType, req.NboType)
  1245. if downgradeType == "" {
  1246. return myerrors.TipsError("错误的降级类型")
  1247. }
  1248. businessMap := g.Map{
  1249. p.Dao.C.ApproStatus: ApprovalWaiting,
  1250. }
  1251. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  1252. opnContent := gconv.Map(req)
  1253. opnContent["origNboType"] = business.NboType
  1254. opnContent["approStatus"] = ApprovalWaiting
  1255. service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName())
  1256. productLine, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "sys_product_line", business.ProductLine)
  1257. // 审批流
  1258. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  1259. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  1260. // 更新项目调级
  1261. _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update()
  1262. if err != nil {
  1263. return err
  1264. }
  1265. // 添加项目动态
  1266. dynamics := model.ProjBusinessDynamics{
  1267. BusId: business.Id,
  1268. OpnType: OpnDowngrade,
  1269. Remark: req.Remark,
  1270. }
  1271. _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  1272. if err != nil {
  1273. return err
  1274. }
  1275. // OMS项目降级 审批
  1276. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  1277. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectDownGrade, "", &workflow.StartProcessInstanceRequest{
  1278. ProcessCode: &BusinessDowngradeRequestProcessCode,
  1279. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  1280. {
  1281. Id: utils.String("TextField-K2AD4O5B"),
  1282. Name: utils.String("项目编码"),
  1283. Value: utils.String(business.NboCode),
  1284. },
  1285. {
  1286. Id: utils.String("TextField_BDLSECETVSG0"),
  1287. Name: utils.String("项目名称"),
  1288. Value: utils.String(business.NboName),
  1289. },
  1290. {
  1291. Id: utils.String("TextField_1J9BJMOZ18F40"),
  1292. Name: utils.String("客户名称"),
  1293. Value: utils.String(business.CustName),
  1294. },
  1295. {
  1296. Id: utils.String("TextField_GL7MQUB723K0"),
  1297. Name: utils.String("所在省"),
  1298. Value: utils.String(business.CustProvince),
  1299. },
  1300. {
  1301. Id: utils.String("TextField_CFA88QQQUUO0"),
  1302. Name: utils.String("所在市"),
  1303. Value: utils.String(business.CustCity),
  1304. },
  1305. {
  1306. Id: utils.String("DDSelectField_VSA3U380ZK00"),
  1307. Name: utils.String("降级类型"),
  1308. Value: utils.String(downgradeType),
  1309. },
  1310. {
  1311. Id: utils.String("DDSelectField_1UCNHJ0P8C5C0"),
  1312. Name: utils.String("产品线"),
  1313. Value: utils.String(productLine),
  1314. },
  1315. {
  1316. Id: utils.String("TextField_X4D3QGARU7K0"),
  1317. Name: utils.String("支持内容"),
  1318. Value: utils.String("无"),
  1319. },
  1320. {
  1321. Id: utils.String("TextField_AEUWH63LJ0O0"),
  1322. Name: utils.String("销售工程师"),
  1323. Value: utils.String(business.SaleName),
  1324. },
  1325. {
  1326. Id: utils.String("TextareaField_PTGJOKD3J7K0"),
  1327. Name: utils.String("降级原因"),
  1328. Value: utils.String(req.Remark),
  1329. },
  1330. },
  1331. })
  1332. if err != nil {
  1333. g.Log().Error(err)
  1334. return err
  1335. }
  1336. return nil
  1337. })
  1338. return err
  1339. }
  1340. // BusinessDowngradeNotify 项目降级 审批结果通知
  1341. func (p *businessService) BusinessDowngradeNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  1342. business, err := p.checkDingTalkNotify(flow, msg)
  1343. if err != nil {
  1344. return err
  1345. }
  1346. var data = g.Map{}
  1347. var remark string
  1348. if msg.ProcessType == "terminate" {
  1349. data[p.Dao.C.ApproStatus] = ApprovalReturn
  1350. }
  1351. if msg.ProcessType == "finish" && msg.Result == "refuse" {
  1352. data[p.Dao.C.ApproStatus] = ApprovalRejection
  1353. }
  1354. if msg.ProcessType == "finish" && msg.Result == "agree" {
  1355. // 从项目动态内获取变更信息
  1356. dynamics := new(model.ProjBusinessDynamics)
  1357. dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id)
  1358. err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnDowngrade).OrderDesc("created_time").Scan(dynamics)
  1359. if err != nil {
  1360. return err
  1361. }
  1362. updateData := new(model.BusinessDowngradeReq)
  1363. gconv.Struct(dynamics.OpnContent, updateData)
  1364. data = gconv.Map(updateData)
  1365. data[p.Dao.C.ApproStatus] = ApprovalOK
  1366. remarkMap := gconv.Map(dynamics.OpnContent)
  1367. remark = gconv.String(g.Map{"nboType": remarkMap["nboType"], "origNboType": remarkMap["origNboType"]})
  1368. }
  1369. // 项目修改
  1370. _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  1371. if err != nil {
  1372. return err
  1373. }
  1374. // 添加项目动态
  1375. dynamics := model.ProjBusinessDynamics{
  1376. BusId: business.Id,
  1377. OpnType: OpnDowngradeApproval,
  1378. Remark: remark,
  1379. }
  1380. _, err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  1381. if err != nil {
  1382. return err
  1383. }
  1384. return nil
  1385. }
  1386. // SetPrimacyContact 项目设置首要联系人
  1387. func (p *businessService) SetPrimacyContact(req *model.BusinessPrimacyContactReq) (err error) {
  1388. business, err := p.Dao.Where(projDao.ProjBusiness.C.Id, req.Id).One()
  1389. if err != nil {
  1390. return err
  1391. }
  1392. if business == nil {
  1393. return myerrors.TipsError("项目不存在。")
  1394. }
  1395. businessMap := g.Map{
  1396. p.Dao.C.ContactId: req.ContactId,
  1397. p.Dao.C.ContactName: req.ContactName,
  1398. p.Dao.C.ContactPostion: req.ContactPostion,
  1399. p.Dao.C.ContactTelephone: req.ContactTelephone,
  1400. }
  1401. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  1402. opnContent := gconv.Map(gconv.String(businessMap))
  1403. opnContent["origContactId"] = business.ContactId
  1404. opnContent["origContactName"] = business.ContactName
  1405. opnContent["origContactPostion"] = business.ContactPostion
  1406. opnContent["origContactTelephone"] = business.ContactTelephone
  1407. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  1408. // 更新项目
  1409. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update()
  1410. if err != nil {
  1411. return err
  1412. }
  1413. // 添加项目动态
  1414. dynamics := model.ProjBusinessDynamics{
  1415. BusId: req.Id,
  1416. OpnType: OpnPrimacyContact,
  1417. Remark: req.Remark,
  1418. }
  1419. _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  1420. return err
  1421. })
  1422. return err
  1423. }
  1424. // UpdateBusinessStatus 更新项目状态
  1425. func (p *businessService) UpdateBusinessStatus(req *model.UpdateBusinessStatusReq) error {
  1426. business, err := p.Dao.WherePri(req.Id).One()
  1427. if err != nil {
  1428. return err
  1429. }
  1430. if business == nil {
  1431. return myerrors.TipsError("项目不存在。")
  1432. }
  1433. businessMap := g.Map{
  1434. p.Dao.C.NboStatus: req.NboStatus,
  1435. p.Dao.C.Remark: req.Remark,
  1436. }
  1437. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  1438. opnContent := gconv.Map(gconv.String(businessMap))
  1439. opnContent["origNboStatus"] = business.NboStatus
  1440. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  1441. // 更新项目
  1442. _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update()
  1443. if err != nil {
  1444. return err
  1445. }
  1446. // 添加项目动态
  1447. dynamics := model.ProjBusinessDynamics{
  1448. BusId: req.Id,
  1449. OpnType: OpnStatus,
  1450. Remark: req.Remark,
  1451. }
  1452. _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent)
  1453. return err
  1454. })
  1455. return err
  1456. }
  1457. // CreateProjBusinessDynamics 创建项目动态
  1458. func (p *businessService) CreateProjBusinessDynamics(tx *gdb.TX, dynamics model.ProjBusinessDynamics, opnContent interface{}) (int64, error) {
  1459. if v, ok := opnContent.(g.Map); ok {
  1460. opnContent = utils.MapKeySnakeCamelCase(v)
  1461. }
  1462. // 添加项目动态
  1463. dynamics.OpnPeopleId = p.GetCxtUserId()
  1464. dynamics.OpnPeople = p.GetCxtUserName()
  1465. dynamics.OpnDate = gtime.Now()
  1466. dynamics.OpnContent = gconv.String(opnContent)
  1467. service.SetCreatedInfo(&dynamics, p.GetCxtUserId(), p.GetCxtUserName())
  1468. dao := projDao.NewProjBusinessDynamicsDao(p.Tenant).M
  1469. if tx != nil {
  1470. dao = dao.TX(tx)
  1471. }
  1472. lastId, err := dao.InsertAndGetId(&dynamics)
  1473. return lastId, err
  1474. }
  1475. // ConvertToReserve 转为储备项目
  1476. func (p *businessService) ConvertToReserve(req *model.BusinessToReserveReq) error {
  1477. business, err := p.Dao.WherePri(req.Id).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One()
  1478. if err != nil {
  1479. return err
  1480. }
  1481. if business == nil {
  1482. return myerrors.TipsError("项目已提交审批任务,无法重复提交。")
  1483. }
  1484. productLine, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "sys_product_line", business.ProductLine)
  1485. // 审批流
  1486. workflowSrv, _ := workflowService.NewFlowService(p.Ctx)
  1487. err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
  1488. // 更新项目
  1489. businessMap := g.Map{
  1490. p.Dao.C.ApproStatus: ApprovalWaiting,
  1491. p.Dao.C.ProjConversionTime: gtime.Now(),
  1492. p.Dao.C.ProjConversionReason: req.ProjConversionReason,
  1493. }
  1494. service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName())
  1495. _, err = p.Dao.TX(tx).WherePri(business.Id).Data(businessMap).Update()
  1496. if err != nil {
  1497. return err
  1498. }
  1499. // 添加项目动态
  1500. dynamics := model.ProjBusinessDynamics{
  1501. BusId: business.Id,
  1502. OpnType: OpnToReserve,
  1503. Remark: req.ProjConversionReason,
  1504. }
  1505. _, err = p.CreateProjBusinessDynamics(tx, dynamics, businessMap)
  1506. if err != nil {
  1507. return err
  1508. }
  1509. // OMS项目转储备 审批
  1510. bizCode := business.NboCode + ":" + strconv.Itoa(business.Id)
  1511. _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, "", &workflow.StartProcessInstanceRequest{
  1512. ProcessCode: &ConvertToReserveRequestProcessCode,
  1513. FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{
  1514. {
  1515. Id: utils.String("TextField-K2AD4O5B"),
  1516. Name: utils.String("项目编码"),
  1517. Value: utils.String(business.NboCode),
  1518. },
  1519. {
  1520. Id: utils.String("TextField_CMH6TBXYR5S0"),
  1521. Name: utils.String("项目名称"),
  1522. Value: utils.String(business.NboName),
  1523. },
  1524. {
  1525. Id: utils.String("TextField_YQBGGYHQPS00"),
  1526. Name: utils.String("客户名称"),
  1527. Value: utils.String(business.CustName),
  1528. },
  1529. {
  1530. Id: utils.String("DDSelectField_VBY9YAIOK5C0"),
  1531. Name: utils.String("项目级别"),
  1532. Value: utils.String(convertToReserveType[business.NboType]),
  1533. },
  1534. {
  1535. Id: utils.String("DDSelectField_1UVBB1LZHIJK0"),
  1536. Name: utils.String("产品线"),
  1537. Value: utils.String(productLine),
  1538. },
  1539. {
  1540. Id: utils.String("TextField_1NDD3TY8KJB40"),
  1541. Name: utils.String("销售工程师"),
  1542. Value: utils.String(business.SaleName),
  1543. },
  1544. {
  1545. Id: utils.String("TextareaField_15KZFM4YHQ8W0"),
  1546. Name: utils.String("转化原因"),
  1547. Value: utils.String(req.ProjConversionReason),
  1548. },
  1549. },
  1550. })
  1551. if err != nil {
  1552. g.Log().Error(err)
  1553. return err
  1554. }
  1555. return nil
  1556. })
  1557. return err
  1558. }
  1559. // ConvertToReserveNotify 转为储备项目 审批结果通知
  1560. func (p *businessService) ConvertToReserveNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
  1561. business, err := p.checkDingTalkNotify(flow, msg)
  1562. if err != nil {
  1563. return err
  1564. }
  1565. var data = g.Map{}
  1566. if msg.ProcessType == "terminate" {
  1567. data[p.Dao.C.ApproStatus] = ApprovalReturn
  1568. }
  1569. if msg.ProcessType == "finish" && msg.Result == "refuse" {
  1570. data[p.Dao.C.ApproStatus] = ApprovalRejection
  1571. }
  1572. if msg.ProcessType == "finish" && msg.Result == "agree" {
  1573. data[p.Dao.C.NboType] = StatusReserve
  1574. data[p.Dao.C.ApproStatus] = ApprovalOK
  1575. }
  1576. // 项目修改
  1577. _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update()
  1578. if err != nil {
  1579. return err
  1580. }
  1581. // 添加项目动态
  1582. dynamics := model.ProjBusinessDynamics{
  1583. BusId: business.Id,
  1584. OpnType: OpnToReserveApproval,
  1585. }
  1586. _, err = p.CreateProjBusinessDynamics(nil, dynamics, data)
  1587. if err != nil {
  1588. return err
  1589. }
  1590. return err
  1591. }
  1592. // 钉钉审批通知检查
  1593. func (p *businessService) checkDingTalkNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) (*model.ProjBusiness, error) {
  1594. bizCode := strings.Split(flow.BizCode, ":")
  1595. if len(bizCode) != 2 {
  1596. return nil, fmt.Errorf("项目审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  1597. }
  1598. nboCode := bizCode[0]
  1599. busId, err := strconv.Atoi(bizCode[1])
  1600. if err != nil {
  1601. return nil, fmt.Errorf("项目审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
  1602. }
  1603. if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
  1604. return nil, fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
  1605. }
  1606. if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
  1607. return nil, fmt.Errorf("无法识别的 Result :%s", msg.Result)
  1608. }
  1609. fmt.Println(msg)
  1610. business, err := p.Dao.WherePri(busId).Where(p.Dao.C.NboCode, nboCode).One()
  1611. if err != nil {
  1612. return nil, err
  1613. }
  1614. if business == nil {
  1615. return nil, fmt.Errorf("项目不存在:%s Id: %d", flow.BizCode, flow.Id)
  1616. }
  1617. return business, nil
  1618. }