package proj import ( "context" contractDao "dashoo.cn/micro/app/dao/contract" custDao "dashoo.cn/micro/app/dao/cust" projDao "dashoo.cn/micro/app/dao/proj" contractModel "dashoo.cn/micro/app/model/contract" model "dashoo.cn/micro/app/model/proj" workflowModel "dashoo.cn/micro/app/model/workflow" workflowService "dashoo.cn/micro/app/service/workflow" "dashoo.cn/micro/app/service" "dashoo.cn/opms_libary/multipart" "dashoo.cn/opms_libary/myerrors" "dashoo.cn/opms_libary/plugin/dingtalk" "dashoo.cn/opms_libary/plugin/dingtalk/message" "dashoo.cn/opms_libary/plugin/dingtalk/workflow" "dashoo.cn/opms_libary/utils" "fmt" "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/gtime" "github.com/gogf/gf/util/gconv" "github.com/shopspring/decimal" "strconv" "strings" ) type businessService struct { *service.ContextService Dao *projDao.ProjBusinessDao } func NewBusinessService(ctx context.Context) (svc *businessService, err error) { svc = new(businessService) if svc.ContextService, err = svc.Init(ctx); err != nil { return nil, err } svc.Dao = projDao.NewProjBusinessDao(svc.Tenant) return svc, nil } func (p *businessService) GetList(req *model.ProjBusinessSearchReq) (total int, businessList []*model.ProjBusinessRes, err error) { db := p.Dao.As("proj").DataScope(p.Ctx, "sale_id") if req.NboName != "" { db = db.WhereLike("proj."+p.Dao.C.NboName, "%"+req.NboName+"%") } if req.CustName != "" { db = db.WhereLike("proj."+p.Dao.C.CustName, "%"+req.CustName+"%") } if req.SaleName != "" { db = db.WhereLike("proj."+p.Dao.C.SaleName, "%"+req.SaleName+"%") } if req.NboType != "" { db = db.Where("proj."+p.Dao.C.NboType, req.NboType) } if req.ProductLine != "" { db = db.Where("proj."+p.Dao.C.ProductLine, req.ProductLine) } if req.NboSource != "" { db = db.Where("proj."+p.Dao.C.NboSource, req.NboSource) } if req.DistributorName != "" { db = db.Where("proj."+p.Dao.C.DistributorName, "%"+req.DistributorName+"%") } if req.BeginTime != "" { db = db.WhereGTE("proj."+p.Dao.C.FilingTime, req.BeginTime) } if req.EndTime != "" { db = db.WhereLTE("proj."+p.Dao.C.FilingTime, req.EndTime) } total, err = db.Count() if err != nil { err = myerrors.DbError("获取总行数失败。") return } if req.NboType == StatusDeal { db = db.Unscoped().WhereNull(`proj.deleted_time`). LeftJoin(contractDao.CtrContract.Table, "contract", "`proj`.id=`contract`.nbo_id AND `contract`.`deleted_time` IS NULL "). Fields("`proj`.cust_city_id as cust_city_id,`contract`.contract_amount, `contract`.created_time as proj_closing_time") } db = db.Fields("`proj`.*") err = db.Page(req.PageNum, req.PageSize).OrderDesc("id").Scan(&businessList) return } func (p *businessService) GetEntityById(id int64) (business *model.ProjBusiness, err error) { err = p.Dao.Where(projDao.ProjBusiness.C.Id, id).Scan(&business) return } func (p *businessService) GetBusinessProduct(id int64) (productList []*model.ProjBusinessProduct, err error) { productDao := projDao.NewProjBusinessProductDao(p.Tenant) err = productDao.Where(productDao.ProjBusinessProductDao.C.BusId, id).Scan(&productList) return } func (p *businessService) GetBusinessDynamics(req *model.BusinessReq) (total int, result g.MapStrAny, err error) { result = make(g.MapStrAny, 0) dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).ProjBusinessDynamicsDao.Where(projDao.ProjBusinessDynamics.C.BusId, req.BusId) total, err = dynamicsDao.Count() if err != nil { g.Log().Error(err) return } dynamicsList, err := dynamicsDao.Page(req.GetPage()).Order("created_time desc").All() if err != nil || dynamicsList == nil { return } // 数据树格式转换 opnDateFlag := gtime.New(dynamicsList[0].OpnDate).Format("Y-m-d") for k, v := range dynamicsList { opnDate := gtime.New(v.OpnDate).Format("Y-m-d") if opnDateFlag == opnDate && k != 0 { result[opnDate] = append(result[opnDate].(g.ListStrAny), g.Map{ "opnPeople": v.OpnPeople, "opnDate": v.OpnDate, "opnType": v.OpnType, "remark": v.Remark, "opnContent": gconv.Map(v.OpnContent), }) } else { temp := make(g.ListStrAny, 0) temp = append(temp, g.Map{ "opnPeople": v.OpnPeople, "opnDate": v.OpnDate, "opnType": v.OpnType, "remark": v.Remark, "opnContent": gconv.Map(v.OpnContent), }) result[opnDate] = temp } } return } func (p *businessService) GetBusinessDynamicsList(req *model.BusinessDynamicsReq) (total int, list []map[string]interface{}, err error) { dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, req.BusId) if req.OpnType != "" { dynamicsDao = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType+" = ?", req.OpnType) } total, err = dynamicsDao.Count() if err != nil { g.Log().Error(err) return } dynamicsList, err := dynamicsDao.Page(req.GetPage()).Order("created_time desc").All() for _, v := range dynamicsList { val := gconv.Map(v) val["opnContent"] = gconv.Map(v.OpnContent) list = append(list, val) } return } // 获取项目编号 func (p *businessService) getNboCode(customerCode string) (string, error) { sequence, err := service.Sequence(p.Dao.DB, "nbo_code") if err != nil { return "", err } return customerCode + sequence, nil } func (p *businessService) Create(req *model.AddProjBusinessReq) (err error) { // 获取客户信息 customer, err := custDao.NewCustCustomerDao(p.Tenant).WherePri(req.CustId).One() if err != nil { return err } if customer == nil { return myerrors.TipsError("客户不存在") } // 设置默认联系人 contact := g.Map{ projDao.ProjBusinessContact.C.ContactId: req.ContactId, } service.SetCreatedInfo(contact, p.GetCxtUserId(), p.GetCxtUserName()) // 设置产品信息 totalPrice, products, err := p.setProductInfo(0, req.Products) if err != nil { return err } // 获取项目编号 nboCode, err := p.getNboCode(customer.CustCode) if err != nil { return err } // 初始化项目信息 businessData := new(model.ProjBusiness) if err = gconv.Struct(req, businessData); err != nil { return } businessData.NboCode = nboCode //businessData.NboStatus = StatusOK businessData.NboType = StatusC businessData.ApproStatus = ApprovalNotSubmit businessData.EstTransPrice = totalPrice businessData.CustProvinceId = customer.CustProvinceId businessData.CustProvince = customer.CustProvince businessData.CustCityId = customer.CustCityId businessData.CustCity = customer.CustCity businessData.CustRegionId = customer.CustRegionId businessData.CustRegion = customer.CustRegion businessData.DeptId = p.GetCxtUserDeptId() service.SetCreatedInfo(businessData, p.GetCxtUserId(), p.GetCxtUserName()) businessData.FilingTime = businessData.CreatedTime // 事务 err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 添加项目 lastId, err := p.Dao.TX(tx).InsertAndGetId(businessData) if err != nil { return err } // 创建了联系人 contact[projDao.ProjBusinessContact.C.BusId] = lastId _, err = projDao.NewProjBusinessContactDao(p.Tenant).TX(tx).Insert(contact) if err != nil { return err } // 处理项目产品信息 for _, v := range products { v.BusId = int(lastId) } // 添加项目产品 _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Insert(products) if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: int(lastId), OpnType: OpnCreate, Remark: businessData.Remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, businessData) return err }) return } // setProductInfo 设置产品信息 func (p *businessService) setProductInfo(busId int, productInfo []model.BusinessProduct) (total float64, products []*model.ProjBusinessProduct, err error) { products = make([]*model.ProjBusinessProduct, len(productInfo)) if err = gconv.Structs(productInfo, &products); err != nil { return 0, nil, err } var totalPrice decimal.Decimal for _, v := range products { v.Id = 0 v.BusId = busId v.TotalPrice = decimal.NewFromFloat(v.ProdPrice).Mul(decimal.NewFromInt(int64(v.ProdNum))).InexactFloat64() totalPrice = totalPrice.Add(decimal.NewFromFloat(v.TotalPrice)) service.SetCreatedInfo(v, p.GetCxtUserId(), p.GetCxtUserName()) } return totalPrice.InexactFloat64(), products, nil } func (p *businessService) UpdateById(req *model.UpdateProjBusinessReq) error { record, err := p.Dao.WherePri(req.Id).Count() if err != nil { return err } if record == 0 { return myerrors.TipsError("项目不存在。") } // 设置产品信息 totalPrice, products, err := p.setProductInfo(req.Id, req.Products) if err != nil { return err } // 设置默认联系人 contact := g.Map{ projDao.ProjBusinessContact.C.BusId: req.Id, projDao.ProjBusinessContact.C.ContactId: req.ContactId, } contactFlag, err := projDao.NewProjBusinessContactDao(p.Tenant).Where(contact).Count() if err != nil { return err } if contactFlag == 0 { service.SetCreatedInfo(contact, p.GetCxtUserId(), p.GetCxtUserName()) } // 设置项目信息 req.EstTransPrice = totalPrice businessData := gconv.Map(req) service.SetUpdatedInfo(businessData, p.GetCxtUserId(), p.GetCxtUserName()) err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 更新项目 updateFieldEx := append(service.UpdateFieldEx, p.Dao.C.SaleId, p.Dao.C.SaleName) _, err = p.Dao.TX(tx).FieldsEx(updateFieldEx...).WherePri(projDao.ProjBusiness.C.Id, req.Id).Update(businessData) if err != nil { return err } // 删除项目产品 _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Where(projDao.ProjBusinessProduct.C.BusId, req.Id).Delete() if err != nil { return err } // 添加项目产品 _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Insert(products) if err != nil { return err } // 关联联系人 if contactFlag == 0 { _, err = projDao.NewProjBusinessContactDao(p.Tenant).TX(tx).Insert(contact) if err != nil { return err } } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: req.Id, OpnType: OpnUpdate, Remark: req.Remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, req) return err }) return err } func (p *businessService) DeleteByIds(ids []int64) (err error) { _, err = p.Dao.WhereIn(projDao.ProjBusiness.C.Id, ids).Delete() return } // BusinessTransfer 项目转移 func (p *businessService) BusinessTransfer(req *model.BusinessTransferReq) error { business, err := p.Dao.WherePri(req.Id).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One() if err != nil { return err } if business == nil { return myerrors.TipsError("项目已提交审批任务,无法重复提交。") } businessMap := g.Map{ p.Dao.C.ApproStatus: ApprovalWaiting, } service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName()) opnContent := businessMap opnContent["origSaleId"] = business.SaleId opnContent["origSaleName"] = business.SaleName opnContent["saleId"] = req.UserId opnContent["saleName"] = req.UserName opnContent["remark"] = req.Remark // 审批流 workflowSrv, _ := workflowService.NewFlowService(p.Ctx) err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 更新项目 _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: req.Id, OpnType: OpnTransfer, Remark: req.Remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent) if err != nil { g.Log().Error(err) return err } // OMS项目转移 审批 bizCode := business.NboCode + ":" + strconv.Itoa(business.Id) _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectTransfer, "", &workflow.StartProcessInstanceRequest{ ProcessCode: &BusinessTransferRequestProcessCode, FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{ { Id: utils.String("TextField-K2AD4O5B"), Name: utils.String("项目编码"), Value: utils.String(business.NboCode), }, { Id: utils.String("TextField_7EFHRQ9DDF80"), Name: utils.String("项目名称"), Value: utils.String(business.NboName), }, { Id: utils.String("TextField_1T3DEY5FWV7K0"), Name: utils.String("客户名称"), Value: utils.String(business.CustName), }, { Id: utils.String("TextField_QDU06LXYKK00"), Name: utils.String("所在省"), Value: utils.String(business.CustProvince), }, { Id: utils.String("TextField_MVSOO6EG6YO0"), Name: utils.String("所在市"), Value: utils.String(business.CustCity), }, { Id: utils.String("TextField_1E1WOYGKRTDS0"), Name: utils.String("项目级别"), Value: utils.String(nboType[business.NboType]), }, { Id: utils.String("TextField_NRQXWLJ17HC0"), Name: utils.String("申请人"), Value: utils.String(p.GetCxtUserName()), }, { Id: utils.String("TextField_GHSQYDGD13K0"), Name: utils.String("转移原因"), Value: utils.String(req.Remark), }, { Id: utils.String("TextField_76P8FPHH0UC0"), Name: utils.String("接收人"), Value: utils.String(req.UserName), }, }, }) if err != nil { g.Log().Error(err) return err } return nil }) return err } // BusinessTransferNotify 项目转移 审批结果通知 func (p *businessService) BusinessTransferNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error { business, err := p.checkDingTalkNotify(flow, msg) if err != nil { return err } var data = g.Map{} if msg.ProcessType == "terminate" { data[p.Dao.C.ApproStatus] = ApprovalReturn } if msg.ProcessType == "finish" && msg.Result == "refuse" { data[p.Dao.C.ApproStatus] = ApprovalRejection } if msg.ProcessType == "finish" && msg.Result == "agree" { // 从项目动态内获取变更信息 var transferDynamics model.ProjBusinessDynamics dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id) err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnTransfer).OrderDesc("created_time").Scan(&transferDynamics) if err != nil { return err } changeData := gconv.Map(transferDynamics.OpnContent) data[p.Dao.C.SaleId] = changeData["saleId"] data[p.Dao.C.SaleName] = changeData["saleName"] data[p.Dao.C.Remark] = changeData["remark"] data[p.Dao.C.ApproStatus] = ApprovalOK } // 项目修改 _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: business.Id, OpnType: OpnTransferApproval, } _, err = p.CreateProjBusinessDynamics(nil, dynamics, data) if err != nil { return err } return err } // BusinessGradation 项目调级 func (p *businessService) BusinessGradation(busId int, nboType, busType string) (*model.ProjBusiness, error) { business, err := p.Dao.WherePri(busId).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One() if err != nil { return nil, err } if business == nil { return nil, myerrors.TipsError("项目已提交审批任务,无法重复提交。") } if business.NboType == nboType { return nil, myerrors.TipsError("同级别无法进行调级。") } if business.NboType == StatusDeal { return nil, myerrors.TipsError("成交项目无法进行调级。") } if business.NboType == StatusReserve && nboType == StatusDeal { return nil, myerrors.TipsError("储备项目无法直接转为成交项目。") } if busType == "up" && gconv.Int(business.NboType) < gconv.Int(nboType) { return nil, myerrors.TipsError("项目级别错误。") } if busType == "down" && gconv.Int(business.NboType) > gconv.Int(nboType) { return nil, myerrors.TipsError("项目级别错误。") } return business, err } // BusinessUpgrade 项目升级 func (p *businessService) BusinessUpgrade(req *model.BusinessUpgradeReq, args *multipart.MultipartFile) error { business, err := p.BusinessGradation(req.Id, req.NboType, "up") if err != nil { return err } businessMap := g.Map{ p.Dao.C.ApproStatus: ApprovalWaiting, } service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName()) opnContent := gconv.Map(req) opnContent["origNboType"] = business.NboType opnContent["approStatus"] = ApprovalWaiting service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName()) err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 更新项目调级 _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: business.Id, OpnType: OpnUpgrade, Remark: req.Remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent) if err != nil { return err } //err = p.BusUpgradeDingEvent(business, req, args) return err }) return err } // 获取项目的钉钉审批的升级类型 func (p *businessService) getBusDingUpgradeType(dbNboType, reqNboType string) string { var upgradeType string switch true { case dbNboType == StatusReserve && reqNboType == StatusC: // 储备转C/option_0 upgradeType = "储备转C" case dbNboType == StatusReserve && reqNboType == StatusB: // 储备转B/option_1 upgradeType = "储备转B" case dbNboType == StatusReserve && reqNboType == StatusA: // 储备转A/option_KTAX3Y9K5340 upgradeType = "储备转A" case dbNboType == StatusC && reqNboType == StatusB: // C转B/option_0 upgradeType = "C转B" case dbNboType == StatusC && reqNboType == StatusA: // C转A/option_0 upgradeType = "C转A" case dbNboType == StatusB && reqNboType == StatusA: // B转A/option_1 upgradeType = "B转A" default: } return upgradeType } // BusUpgradeDingEvent 项目升级钉钉审批流调用 func (p *businessService) BusUpgradeDingEvent(business *model.ProjBusiness, req *model.BusinessUpgradeReq, args *multipart.MultipartFile) error { upgradeType := p.getBusDingUpgradeType(business.NboType, req.NboType) if upgradeType == "" { return myerrors.TipsError("错误的升级类型") } // 审批流 workflowSrv, _ := workflowService.NewFlowService(p.Ctx) // OMS项目升级 审批 var err error var dingReq *workflow.StartProcessInstanceRequest bizCode := business.NboCode + ":" + strconv.Itoa(business.Id) switch req.NboType { case StatusC: dingReq = &workflow.StartProcessInstanceRequest{ ProcessCode: &BusinessUpgradeCRequestProcessCode, FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{ { Id: utils.String("TextField-K2AD4O5B"), Name: utils.String("项目编码"), Value: utils.String(business.NboCode), }, { Id: utils.String("TextField_BDLSECETVSG0"), Name: utils.String("项目名称"), Value: utils.String(business.NboName), }, { Id: utils.String("DDSelectField_VSA3U380ZK00"), Name: utils.String("升级类型"), Value: utils.String(upgradeType), }, { Id: utils.String("TextField_1J9BJMOZ18F40"), Name: utils.String("客户名称"), Value: utils.String(business.CustName), }, { Id: utils.String("TextField_AEUWH63LJ0O0"), Name: utils.String("销售工程师"), Value: utils.String(business.SaleName), }, { Id: utils.String("TextareaField_1LO81IKHH91C0"), Name: utils.String("转化原因"), Value: utils.String(req.ProjConversionReason), }, }, } case StatusB: processCode := &BusinessUpgradeBRequestProcessCode dingReq = &workflow.StartProcessInstanceRequest{ ProcessCode: processCode, FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{ { Id: utils.String("TextField-K2AD4O5B"), Name: utils.String("项目编码"), Value: utils.String(business.NboCode), }, { Id: utils.String("TextField_BDLSECETVSG0"), Name: utils.String("项目名称"), Value: utils.String(business.NboName), }, { Id: utils.String("DDSelectField_VSA3U380ZK00"), Name: utils.String("升级类型"), Value: utils.String(upgradeType), }, { Id: utils.String("TextField_1J9BJMOZ18F40"), Name: utils.String("客户名称"), Value: utils.String(business.CustName), }, { Id: utils.String("NumberField_1F88MCD0W8KG0"), Name: utils.String("项目预算"), Value: utils.String(gconv.String(req.NboBudget)), }, { Id: utils.String("TextField_1PWK6WHMGITC0"), Name: utils.String("经销商/代理商"), Value: utils.String(req.DistributorName), }, { Id: utils.String("TextField_X4D3QGARU7K0"), Name: utils.String("支持内容"), Value: utils.String(req.TechnicalSupportContent), }, { Id: utils.String("TextField_AEUWH63LJ0O0"), Name: utils.String("销售工程师"), Value: utils.String(business.SaleName), }, { Id: utils.String("DDDateField_1FW1QZQYBZVK0"), Name: utils.String("采购时间"), Value: utils.String(gconv.String(req.PurchasingTime.Format("Y-m-d"))), }, { Id: utils.String("DDSelectField_21ASEWDIB3MO0"), Name: utils.String("采购方式"), Value: utils.String(gconv.String(purchasingWayType[req.PurchasingWay])), }, { Id: utils.String("DDSelectField_5R11VVM6GI00"), Name: utils.String("是否我司参数"), Value: utils.String(gconv.String(yesOrNoType[req.IsAdoptDashoo])), }, { Id: utils.String("TextareaField_1GEL8JJL3H5S0"), Name: utils.String("备注"), Value: utils.String(req.Remark), }, }, } case StatusA: resp, err := dingtalk.Client.GetStorage().UploadFile(spaceId, p.GetCxtUserDingtalkId(), args.FileName, args.File.Name()) if err != nil { return fmt.Errorf("钉钉上传文件异常 %s", err.Error()) } g.Log().Info("项目转A类提交大数参数文件", resp) file := []contractModel.DingFileInfo{{ SpaceId: resp.Dentry.SpaceId, FileId: resp.Dentry.Id, FileName: resp.Dentry.Name, FileSize: resp.Dentry.Size, FileType: resp.Dentry.Extension, }} err = p.txCreateBusinessFile(business.Id, file) if err != nil { return err } processCode := &BusinessUpgradeARequestProcessCode dingReq = &workflow.StartProcessInstanceRequest{ ProcessCode: processCode, FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{ { Id: utils.String("TextField-K2AD4O5B"), Name: utils.String("项目编码"), Value: utils.String(business.NboCode), }, { Id: utils.String("TextField_BDLSECETVSG0"), Name: utils.String("项目名称"), Value: utils.String(business.NboName), }, { Id: utils.String("DDSelectField_VSA3U380ZK00"), Name: utils.String("升级类型"), Value: utils.String(upgradeType), }, { Id: utils.String("TextField_1J9BJMOZ18F40"), Name: utils.String("客户名称"), Value: utils.String(business.CustName), }, { Id: utils.String("NumberField_1F88MCD0W8KG0"), Name: utils.String("项目预算"), Value: utils.String(gconv.String(req.NboBudget)), }, { Id: utils.String("TextField_1PWK6WHMGITC0"), Name: utils.String("经销商/代理商"), Value: utils.String(req.DistributorName), }, { Id: utils.String("TextField_X4D3QGARU7K0"), Name: utils.String("支持内容"), Value: utils.String(req.TechnicalSupportContent), }, { Id: utils.String("TextField_AEUWH63LJ0O0"), Name: utils.String("销售工程师"), Value: utils.String(business.SaleName), }, { Id: utils.String("DDDateField_1FW1QZQYBZVK0"), Name: utils.String("采购时间"), Value: utils.String(gconv.String(req.PurchasingTime.Format("Y-m-d"))), }, { Id: utils.String("DDSelectField_21ASEWDIB3MO0"), Name: utils.String("采购方式"), Value: utils.String(gconv.String(purchasingWayType[req.PurchasingWay])), }, { Id: utils.String("DDSelectField_5R11VVM6GI00"), Name: utils.String("是否我司参数"), Value: utils.String(gconv.String(yesOrNoType[req.IsAdoptDashoo])), }, { Id: utils.String("DDAttachment_11Q7DBRKE6HC0"), Name: utils.String("附件"), Value: utils.String(gconv.String(file)), }, { Id: utils.String("TextareaField_1GEL8JJL3H5S0"), Name: utils.String("备注"), Value: utils.String(req.Remark), }, }, } default: return nil } _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectUpGrade, "", dingReq) if err != nil { g.Log().Error(err) return err } return nil } // 采用大数参数文件记录 func (p *businessService) txCreateBusinessFile(busId int, files []contractModel.DingFileInfo) error { dataList := make([]model.ProjBusinessFile, 0) for _, v := range files { data := new(model.ProjBusinessFile) data.BusId = busId data.FileName = v.FileName data.FileSource = "项目转为A类采用大数参数文件" data.FileSize = gconv.String(v.FileSize) data.FileUrl = strings.Join([]string{"dingtalk", v.SpaceId, v.FileId}, ":") service.SetCreatedInfo(data, p.GetCxtUserId(), p.GetCxtUserName()) dataList = append(dataList) } _, err := projDao.NewProjBusinessFileDao(p.Tenant).Insert(&dataList) return err } // BusinessUpgradeNotify 项目升级 审批结果通知 func (p *businessService) BusinessUpgradeNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error { business, err := p.checkDingTalkNotify(flow, msg) if err != nil { return err } var data = g.Map{} if msg.ProcessType == "terminate" { data[p.Dao.C.ApproStatus] = ApprovalReturn } if msg.ProcessType == "finish" && msg.Result == "refuse" { data[p.Dao.C.ApproStatus] = ApprovalRejection } if msg.ProcessType == "finish" && msg.Result == "agree" { // 从项目动态内获取变更信息 dynamics := new(model.ProjBusinessDynamics) dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id) err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnUpgrade).OrderDesc("created_time").Scan(dynamics) if err != nil { return err } updateData := new(model.BusinessUpgradeReq) gconv.Struct(dynamics.OpnContent, updateData) data = gconv.Map(updateData) data[p.Dao.C.ApproStatus] = ApprovalOK } // 项目修改 _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: business.Id, OpnType: OpnUpgradeApproval, } _, err = p.CreateProjBusinessDynamics(nil, dynamics, data) if err != nil { return err } return nil } // 获取项目的钉钉审批的降级类型 func (p *businessService) getBusDingDowngradeType(dbNboType, reqNboType string) string { var downgradeType string switch true { case dbNboType == StatusB && reqNboType == StatusC: // B转C/option_0 downgradeType = "B转C" case dbNboType == StatusA && reqNboType == StatusB: // A转B/option_1 downgradeType = "A转B" case dbNboType == StatusA && reqNboType == StatusC: // A转C/option_2 downgradeType = "A转C" case dbNboType == StatusA && reqNboType == StatusReserve: // A转储备/option_YZMFJYQQK6O0 downgradeType = "A转储备" case dbNboType == StatusB && reqNboType == StatusReserve: // B转储备/option_232GR5NMFCSG0 downgradeType = "B转储备" case dbNboType == StatusC && reqNboType == StatusReserve: // C转储备/option_1ZV2GJLDKQOW0 downgradeType = "C转储备" default: } return downgradeType } // BusinessDowngrade 项目降级 func (p *businessService) BusinessDowngrade(req *model.BusinessDowngradeReq) error { business, err := p.BusinessGradation(req.Id, req.NboType, "down") if err != nil { return err } downgradeType := p.getBusDingDowngradeType(business.NboType, req.NboType) if downgradeType == "" { return myerrors.TipsError("错误的降级类型") } businessMap := g.Map{ p.Dao.C.ApproStatus: ApprovalWaiting, } service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName()) opnContent := gconv.Map(req) opnContent["origNboType"] = business.NboType opnContent["approStatus"] = ApprovalWaiting service.SetUpdatedInfo(opnContent, p.GetCxtUserId(), p.GetCxtUserName()) // 审批流 workflowSrv, _ := workflowService.NewFlowService(p.Ctx) err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 更新项目调级 _, err = p.Dao.TX(tx).WherePri(req.Id).Data(businessMap).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: business.Id, OpnType: OpnDowngrade, Remark: req.Remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent) if err != nil { return err } // OMS项目降级 审批 bizCode := business.NboCode + ":" + strconv.Itoa(business.Id) _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectDownGrade, "", &workflow.StartProcessInstanceRequest{ ProcessCode: &BusinessDowngradeRequestProcessCode, FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{ { Id: utils.String("TextField-K2AD4O5B"), Name: utils.String("项目编码"), Value: utils.String(business.NboCode), }, { Id: utils.String("TextField_BDLSECETVSG0"), Name: utils.String("项目名称"), Value: utils.String(business.NboName), }, { Id: utils.String("TextField_1J9BJMOZ18F40"), Name: utils.String("客户名称"), Value: utils.String(business.CustName), }, { Id: utils.String("TextField_GL7MQUB723K0"), Name: utils.String("所在省"), Value: utils.String(business.CustProvince), }, { Id: utils.String("TextField_CFA88QQQUUO0"), Name: utils.String("所在市"), Value: utils.String(business.CustCity), }, { Id: utils.String("DDSelectField_VSA3U380ZK00"), Name: utils.String("降级类型"), Value: utils.String(downgradeType), }, { Id: utils.String("TextField_X4D3QGARU7K0"), Name: utils.String("支持内容"), Value: utils.String(req.TechnicalSupportContent), }, { Id: utils.String("TextField_AEUWH63LJ0O0"), Name: utils.String("销售工程师"), Value: utils.String(business.SaleName), }, { Id: utils.String("TextareaField_PTGJOKD3J7K0"), Name: utils.String("降级原因"), Value: utils.String(req.Remark), }, }, }) if err != nil { g.Log().Error(err) return err } return nil }) return err } // BusinessDowngradeNotify 项目降级 审批结果通知 func (p *businessService) BusinessDowngradeNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error { business, err := p.checkDingTalkNotify(flow, msg) if err != nil { return err } var data = g.Map{} if msg.ProcessType == "terminate" { data[p.Dao.C.ApproStatus] = ApprovalReturn } if msg.ProcessType == "finish" && msg.Result == "refuse" { data[p.Dao.C.ApproStatus] = ApprovalRejection } if msg.ProcessType == "finish" && msg.Result == "agree" { // 从项目动态内获取变更信息 dynamics := new(model.ProjBusinessDynamics) dynamicsDao := projDao.NewProjBusinessDynamicsDao(p.Tenant).Where(projDao.ProjBusinessDynamics.C.BusId, business.Id) err = dynamicsDao.Where(projDao.ProjBusinessDynamics.C.OpnType, OpnDowngrade).OrderDesc("created_time").Scan(dynamics) if err != nil { return err } updateData := new(model.BusinessDowngradeReq) gconv.Struct(dynamics.OpnContent, updateData) data = gconv.Map(updateData) data[p.Dao.C.ApproStatus] = ApprovalOK } // 项目修改 _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: business.Id, OpnType: OpnDowngradeApproval, } _, err = p.CreateProjBusinessDynamics(nil, dynamics, data) if err != nil { return err } return nil } // SetPrimacyContact 项目设置首要联系人 func (p *businessService) SetPrimacyContact(req *model.BusinessPrimacyContactReq) (err error) { business, err := p.Dao.Where(projDao.ProjBusiness.C.Id, req.Id).One() if err != nil { return err } if business == nil { return myerrors.TipsError("项目不存在。") } businessMap := g.Map{ p.Dao.C.ContactId: req.ContactId, p.Dao.C.ContactName: req.ContactName, p.Dao.C.ContactPostion: req.ContactPostion, p.Dao.C.ContactTelephone: req.ContactTelephone, } service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName()) opnContent := businessMap opnContent["origContactId"] = business.ContactId opnContent["origContactName"] = business.ContactName opnContent["origContactPostion"] = business.ContactPostion opnContent["origContactTelephone"] = business.ContactTelephone err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 更新项目 _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: req.Id, OpnType: OpnPrimacyContact, Remark: req.Remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent) return err }) return err } // UpdateBusinessStatus 更新项目状态 func (p *businessService) UpdateBusinessStatus(req *model.UpdateBusinessStatusReq) error { business, err := p.Dao.WherePri(req.Id).One() if err != nil { return err } if business == nil { return myerrors.TipsError("项目不存在。") } businessMap := g.Map{ p.Dao.C.NboStatus: req.NboStatus, p.Dao.C.Remark: req.Remark, } service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName()) opnContent := businessMap opnContent["origNboStatus"] = business.NboStatus err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 更新项目 _, err = p.Dao.TX(tx).WherePri(projDao.ProjBusiness.C.Id, req.Id).Data(businessMap).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: req.Id, OpnType: OpnStatus, Remark: req.Remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent) return err }) return err } // CreateProjBusinessDynamics 创建项目动态 func (p *businessService) CreateProjBusinessDynamics(tx *gdb.TX, dynamics model.ProjBusinessDynamics, opnContent interface{}) (int64, error) { if v, ok := opnContent.(g.Map); ok { opnContent = utils.MapKeySnakeCamelCase(v) } // 添加项目动态 dynamics.OpnPeopleId = p.GetCxtUserId() dynamics.OpnPeople = p.GetCxtUserName() dynamics.OpnDate = gtime.Now() dynamics.OpnContent = gconv.String(opnContent) service.SetCreatedInfo(&dynamics, p.GetCxtUserId(), p.GetCxtUserName()) dao := projDao.NewProjBusinessDynamicsDao(p.Tenant).M if tx != nil { dao = dao.TX(tx) } lastId, err := dao.InsertAndGetId(&dynamics) return lastId, err } // ConvertToReserve 转为储备项目 func (p *businessService) ConvertToReserve(req *model.BusinessToReserveReq) error { business, err := p.Dao.WherePri(req.Id).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).One() if err != nil { return err } if business == nil { return myerrors.TipsError("项目已提交审批任务,无法重复提交。") } // 审批流 workflowSrv, _ := workflowService.NewFlowService(p.Ctx) err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 更新项目 businessMap := g.Map{ p.Dao.C.ApproStatus: ApprovalWaiting, p.Dao.C.ProjConversionTime: gtime.Now(), p.Dao.C.ProjConversionReason: req.ProjConversionReason, } service.SetUpdatedInfo(businessMap, p.GetCxtUserId(), p.GetCxtUserName()) _, err = p.Dao.TX(tx).WherePri(business.Id).Data(businessMap).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: business.Id, OpnType: OpnToReserve, Remark: req.ProjConversionReason, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, businessMap) if err != nil { return err } // OMS项目转储备 审批 bizCode := business.NboCode + ":" + strconv.Itoa(business.Id) _, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, "", &workflow.StartProcessInstanceRequest{ ProcessCode: &ConvertToReserveRequestProcessCode, FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{ { Id: utils.String("TextField-K2AD4O5B"), Name: utils.String("项目编码"), Value: utils.String(business.NboCode), }, { Id: utils.String("TextField_CMH6TBXYR5S0"), Name: utils.String("项目名称"), Value: utils.String(business.NboName), }, { Id: utils.String("TextField_YQBGGYHQPS00"), Name: utils.String("客户名称"), Value: utils.String(business.CustName), }, { Id: utils.String("DDSelectField_VBY9YAIOK5C0"), Name: utils.String("项目级别"), Value: utils.String(convertToReserveType[business.NboType]), }, { Id: utils.String("TextField_1NDD3TY8KJB40"), Name: utils.String("销售工程师"), Value: utils.String(business.SaleName), }, { Id: utils.String("TextareaField_15KZFM4YHQ8W0"), Name: utils.String("转化原因"), Value: utils.String(req.ProjConversionReason), }, }, }) if err != nil { g.Log().Error(err) return err } return nil }) return err } // ConvertToReserveNotify 转为储备项目 审批结果通知 func (p *businessService) ConvertToReserveNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error { business, err := p.checkDingTalkNotify(flow, msg) if err != nil { return err } var data = g.Map{} if msg.ProcessType == "terminate" { data[p.Dao.C.ApproStatus] = ApprovalReturn } if msg.ProcessType == "finish" && msg.Result == "refuse" { data[p.Dao.C.ApproStatus] = ApprovalRejection } if msg.ProcessType == "finish" && msg.Result == "agree" { data[p.Dao.C.NboType] = StatusReserve data[p.Dao.C.ApproStatus] = ApprovalOK } // 项目修改 _, err = p.Dao.WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: business.Id, OpnType: OpnToReserveApproval, } _, err = p.CreateProjBusinessDynamics(nil, dynamics, data) if err != nil { return err } return err } // 钉钉审批通知检查 func (p *businessService) checkDingTalkNotify(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) (*model.ProjBusiness, error) { bizCode := strings.Split(flow.BizCode, ":") if len(bizCode) != 2 { return nil, fmt.Errorf("项目转储备审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id) } nboCode := bizCode[0] busId, err := strconv.Atoi(bizCode[1]) if err != nil { return nil, fmt.Errorf("项目转储备审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id) } if msg.ProcessType != "finish" && msg.ProcessType != "terminate" { return nil, fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType) } if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" { return nil, fmt.Errorf("无法识别的 Result :%s", msg.Result) } fmt.Println(msg) business, err := p.Dao.WherePri(busId).Where(p.Dao.C.NboCode, nboCode).One() if err != nil { return nil, err } if business == nil { return nil, fmt.Errorf("项目不存在:%s Id: %d", flow.BizCode, flow.Id) } return business, nil }