package proj import ( "context" platDao "dashoo.cn/micro/app/dao/plat" "github.com/gogf/gf/container/garray" "os" 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/opms_libary/plugin/dingtalk" "fmt" "strconv" "strings" "dashoo.cn/micro/app/service" "dashoo.cn/opms_libary/multipart" "dashoo.cn/opms_libary/myerrors" "dashoo.cn/opms_libary/plugin/dingtalk/message" "dashoo.cn/opms_libary/plugin/dingtalk/workflow" "dashoo.cn/opms_libary/utils" "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" ) type businessService struct { *service.ContextService Dao *projDao.ProjBusinessDao ContactDao *projDao.ProjBusinessContactDao FollowDao *platDao.PlatFollowupDao fileDao *projDao.ProjBusinessFileDao } 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) svc.ContactDao = projDao.NewProjBusinessContactDao(svc.Tenant) svc.FollowDao = platDao.NewPlatFollowupDao(svc.Tenant) svc.fileDao = projDao.NewProjBusinessFileDao(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.CustId != 0 { // 客户-项目记录 查看已删除的项目记录 db = db.Where("proj."+p.Dao.C.CustId, req.CustId).Unscoped() } 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.WhereLike("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) } if req.ProvinceId != 0 { db = db.Where("proj."+p.Dao.C.CustProvinceId, req.ProvinceId) } 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.GetPage()).OrderDesc("id").Scan(&businessList) return } func (p *businessService) GetEntityById(id int64) (business *model.ProjBusinessRes, err error) { err = p.Dao.Where(projDao.ProjBusiness.C.Id, id).Scan(&business) if err != nil { return nil, err } if business == nil { return nil, myerrors.TipsError("项目不存在") } return } func (p *businessService) GetBusinessInfoById(id int64) (business *model.ProjBusinessRes, err error) { err = p.Dao.Where(projDao.ProjBusiness.C.Id, id).Scan(&business) if err != nil { return nil, err } if business == nil { return nil, myerrors.TipsError("项目不存在") } business.FollowCount, err = p.FollowDao.Where(p.FollowDao.C.TargetType, "20").Where(p.FollowDao.C.TargetId, business.Id).Count() if err != nil { return nil, err } productList, err := p.GetBusinessProduct(id) if err != nil { return nil, err } if err := gconv.Structs(productList, &business.Products); err != nil { return nil, err } files, err := p.fileDao.Where(p.fileDao.C.BusId, id).WhereLike(p.fileDao.C.FileSource, "%报价单%").OrderDesc(p.fileDao.C.Id).Limit(1).All() if err != nil { return nil, err } business.QuotationFileList = files 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 opnDateFlag = opnDate } } 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("客户不存在") } // 获取项目编号 nboCode, err := p.getNboCode(customer.CustCode) if err != nil { return err } // 初始化项目信息 business := new(model.ProjBusiness) if err = gconv.Struct(req, business); err != nil { return } business.NboCode = nboCode if business.NboType == "" { business.NboType = StatusC } business.ApproStatus = ApprovalWaiting business.CustProvinceId = customer.CustProvinceId business.CustProvince = customer.CustProvince business.CustCityId = customer.CustCityId business.CustCity = customer.CustCity business.CustRegionId = customer.CustRegionId business.CustRegion = customer.CustRegion business.DeptId = p.GetCxtUserDeptId() service.SetCreatedInfo(business, p.GetCxtUserId(), p.GetCxtUserName()) business.FilingTime = business.CreatedTime productLine, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "sys_product_line", business.ProductLine) nboSource, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "proj_nbo_source", business.NboSource) salesModel, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "proj_sales_model", business.SalesModel) // 事务 err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error { // 添加项目 lastId, err := p.Dao.TX(tx).InsertAndGetId(business) if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: int(lastId), OpnType: OpnCreate, Remark: business.Remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, business) // 审批流 workflowSrv, _ := workflowService.NewFlowService(p.Ctx) // OMS项目创建 审批 bizCode := business.NboCode + ":" + gconv.String(lastId) business.ApproType = BusinessCreateRequestProcessCode instanceId, err := workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectCreate, "", &workflow.StartProcessInstanceRequest{ ProcessCode: &business.ApproType, 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_213JKZA1OUO00"), Name: utils.String("产品线"), Value: utils.String(productLine), }, { Id: utils.String("TextField_1J9BJMOZ18F40"), Name: utils.String("客户名称"), Value: utils.String(business.CustName), }, { Id: utils.String("DDSelectField_6CQD451D3800"), Name: utils.String("项目来源"), Value: utils.String(nboSource), }, { Id: utils.String("TextField_1UQFU5BUEWDC"), Name: utils.String("历史招标信息"), Value: utils.String(req.BidInfo), }, { Id: utils.String("TextField_AEUWH63LJ0O0"), Name: utils.String("销售工程师"), Value: utils.String(business.SaleName), }, { Id: utils.String("DDSelectField_34QSUGHO2SO0"), Name: utils.String("销售模式"), Value: utils.String(salesModel), }, { Id: utils.String("TextField_1PWK6WHMGITC0"), Name: utils.String("经销商/代理商"), Value: utils.String(business.DistributorName), }, { Id: utils.String("DDSelectField_5R11VVM6GI00"), Name: utils.String("是否为大项目"), Value: utils.String(yesOrNoType[business.IsBig]), }, { Id: utils.String("TextareaField_1GEL8JJL3H5S0"), Name: utils.String("备注"), Value: utils.String(business.Remark), }, }, }) if err != nil { g.Log().Error(err) return err } // 更新项目审批信息 _, err = p.Dao.TX(tx).Data(g.Map{p.Dao.C.ApproType: business.ApproType, p.Dao.C.ApproInstanceId: instanceId}).Update() if err != nil { return err } return nil }) return } // BusinessCreatedNotify 项目创建 审批结果通知 func (p *businessService) BusinessCreatedNotify(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 data[p.Dao.C.DeletedTime] = gtime.Now() } if msg.ProcessType == "finish" && msg.Result == "agree" { 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: OpnCreatedApproval, } _, err = p.CreateProjBusinessDynamics(nil, dynamics, data) if err != nil { return err } return err } // 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 } // setBusinessContact 设置项目联系人 func (p *businessService) setBusinessContact(tx *gdb.TX, contactList []model.SetBusinessContactReq) (err error) { for _, item := range contactList { count, err := p.ContactDao.Where(p.ContactDao.C.BusId, item.BusId).Where(p.ContactDao.C.ContactType, item.ContactType).Count() if err != nil { return err } if count == 0 { data := new(model.ProjBusinessContact) data.BusId = item.BusId data.ContactId = item.ContactId data.ContactType = item.ContactType service.SetCreatedInfo(data, p.GetCxtUserId(), p.GetCxtUserName()) _, err = p.ContactDao.TX(tx).Data(data).Insert() if err != nil { return err } } } return } 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 } // 设置默认联系人 contactList := make([]model.SetBusinessContactReq, 0) if req.ContactId != 0 { contactList = append(contactList, model.SetBusinessContactReq{ BusId: req.Id, ContactId: req.ContactId, ContactType: "10", }) } if req.DealerSalesId != 0 { contactList = append(contactList, model.SetBusinessContactReq{ BusId: req.Id, ContactId: req.DealerSalesId, ContactType: "20", }) } // 设置项目信息 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, p.Dao.C.NboType, p.Dao.C.NboCode) _, 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 } // 关联联系人 err = p.setBusinessContact(tx, contactList) 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 } // UpdateBusinessContactInfo 清理项目表联系人信息 func (p *businessService) UpdateBusinessContactInfo(tx *gdb.TX, busId int, data g.Map) (err error) { 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} _, err = p.Dao.TX(tx).Fields(fields...).WherePri(busId).Data(data).Update() return } func (p *businessService) DeleteByIds(ids []int64) (err error) { _, err = p.Dao.WhereIn(projDao.ProjBusiness.C.Id, ids).Delete() return } // SysAdminBusinessTransfer 管理员项目转移销售(未涉及审批的) func (p *businessService) SysAdminBusinessTransfer(req *model.SysAdminBusinessTransferReq) error { // 校验用户是否有修改权限 arr := garray.NewStrArrayFrom(p.CxtUser.Roles, true) if !arr.Contains("SysAdmin") { return myerrors.TipsError("权限不足") } businessList, err := p.Dao.WherePri(req.Ids).WhereNot(p.Dao.C.ApproStatus, ApprovalWaiting).All() if err != nil { return err } if len(businessList) == 0 { return myerrors.TipsError("转移项目不能为空") } var updateData = g.Map{} updateData[p.Dao.C.SaleId] = req.UserId updateData[p.Dao.C.SaleName] = req.UserName updateData[p.Dao.C.Remark] = req.Remark service.SetUpdatedInfo(updateData, p.GetCxtUserId(), p.GetCxtUserName()) // 添加项目动态 for _, item := range businessList { err := p.Dao.Transaction(p.Ctx, func(ctx context.Context, tx *gdb.TX) error { // 项目修改 _, err = p.Dao.TX(tx).WherePri(item.Id).FieldsEx(service.UpdateFieldEx...).Data(updateData).Update() if err != nil { return err } dynamics := model.ProjBusinessDynamics{ BusId: item.Id, OpnType: OpnTransfer, Remark: req.Remark, } opnContent := gconv.Map(gconv.String(updateData)) opnContent["origSaleId"] = item.SaleId opnContent["origSaleName"] = item.SaleName _, err = p.CreateProjBusinessDynamics(tx, dynamics, opnContent) if err != nil { g.Log().Error(err) return err } return nil }) if err != nil { g.Log().Error(fmt.Sprintf("管理员转移项目销售:%v 由%v转移至%v失败", item.NboName, item.SaleName, req.UserName), err.Error()) } } return nil } // 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 := gconv.Map(gconv.String(businessMap)) opnContent["origSaleId"] = business.SaleId opnContent["origSaleName"] = business.SaleName opnContent["saleId"] = req.UserId opnContent["saleName"] = req.UserName opnContent["remark"] = req.Remark productLine, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "sys_product_line", business.ProductLine) // 审批流 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) business.ApproType = BusinessTransferRequestProcessCode instanceId, err := workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectTransfer, "", &workflow.StartProcessInstanceRequest{ ProcessCode: &business.ApproType, 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("DDSelectField_6OMVO1JV0980"), Name: utils.String("产品线"), Value: utils.String(productLine), }, { 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 } // 更新项目审批信息 _, err = p.Dao.TX(tx).Data(g.Map{p.Dao.C.ApproType: business.ApproType, p.Dao.C.ApproInstanceId: instanceId}).Update() if err != nil { 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, fileMap map[string]*multipart.FileHeader) 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()) if fileMap == nil { fileMap = make(map[string]*multipart.FileHeader) } if (req.NboType == StatusA || req.NboType == StatusB) && !strings.HasPrefix(req.QuotationFile, "dingtalk") { fileMap["quotationFile"], err = service.DownloadTempFile(req.QuotationFile) if err != nil { return err } defer os.Remove(fileMap["quotationFile"].File.Name()) } if req.NboType == StatusA && req.IsAdoptDashoo == "10" { fileMap["dashooParamFile"], err = service.DownloadTempFile(req.DashooParamFile) if err != nil { return err } defer os.Remove(fileMap["dashooParamFile"].File.Name()) } contactList := make([]model.SetBusinessContactReq, 0) if req.ContactId != 0 { contactList = append(contactList, model.SetBusinessContactReq{ BusId: req.Id, ContactId: req.ContactId, ContactType: "10", }) } if req.DealerSalesId != 0 { contactList = append(contactList, model.SetBusinessContactReq{ BusId: req.Id, ContactId: req.DealerSalesId, ContactType: "20", }) } 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 } // 关联联系人 err = p.setBusinessContact(tx, contactList) 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 } instanceId, err := p.BusUpgradeDingEvent(business, req, fileMap) if err != nil { return err } // 更新项目审批信息 _, err = p.Dao.TX(tx).Data(g.Map{p.Dao.C.ApproType: business.ApproType, p.Dao.C.ApproInstanceId: instanceId}).Update() if err != nil { return err } return nil }) if err != nil { return err } return nil } // 获取项目的钉钉审批的升级类型 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, fileMap map[string]*multipart.FileHeader) (instanceId string, err error) { upgradeType := p.getBusDingUpgradeType(business.NboType, req.NboType) if upgradeType == "" { return "", myerrors.TipsError("错误的升级类型") } productLineMap, err := service.GetDictDataTreeByType(p.Ctx, "sys_product_line") if err != nil { return "", err } productLine := gconv.String(productLineMap.Get(business.ProductLine)) dingProductList := make([][]*workflow.StartProcessInstanceRequestFormComponentValues, 0) for _, item := range req.Products { pInfo := make([]*workflow.StartProcessInstanceRequestFormComponentValues, 0) pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{ Id: utils.String("TextField_8P2W917Q5I40"), Name: utils.String("产品编码"), Value: utils.String(item.ProdCode), }) pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{ Id: utils.String("TextField_1W2HGNQFLLA80"), Name: utils.String("产品名称"), Value: utils.String(item.ProdName), }) pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{ Id: utils.String("TextField_1OPT3MZL76GW0"), Name: utils.String("产品类别"), Value: utils.String(gconv.String(productLineMap.Get(item.ProdClass))), }) pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{ Id: utils.String("TextField_O405QBZMPW00"), Name: utils.String("产品单价"), Value: utils.String(gconv.String(item.ProdPrice)), }) pInfo = append(pInfo, &workflow.StartProcessInstanceRequestFormComponentValues{ Id: utils.String("TextField_23P54AZUW4SG0"), Name: utils.String("数量"), Value: utils.String(gconv.String(item.ProdNum)), }) dingProductList = append(dingProductList, pInfo) } // 审批流 workflowSrv, _ := workflowService.NewFlowService(p.Ctx) // OMS项目升级 审批 var dingReq *workflow.StartProcessInstanceRequest bizCode := business.NboCode + ":" + strconv.Itoa(business.Id) switch req.NboType { case StatusC: business.ApproType = BusinessUpgradeCRequestProcessCode dingReq = &workflow.StartProcessInstanceRequest{ ProcessCode: &business.ApproType, 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_1MJU37HGJX4W0"), Name: utils.String("产品线"), Value: utils.String(productLine), }, { 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: quotationFile := make([]contractModel.DingFileInfo, 0) if len(fileMap) > 0 { for k, files := range fileMap { // 报价单 if k == "quotationFile" { if quotationFile, err = p.txCreateBusinessDingTalkFile(business.Id, upgradeType, k, files); err != nil { return "", err } } } } if len(quotationFile) == 0 { return "", myerrors.TipsError("请上传报价单文件") } business.ApproType = BusinessUpgradeBRequestProcessCode dingReq = &workflow.StartProcessInstanceRequest{ ProcessCode: &business.ApproType, 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_213JKZA1OUO00"), Name: utils.String("产品线"), Value: utils.String(productLine), }, { 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.DealerSalesName), }, { Id: utils.String("TextField_M06MZK20POG0"), Name: utils.String("渠道销售电话/微信"), Value: utils.String(req.DealerSalesContact), }, { Id: utils.String("TextField_GL59OGH2Z1S0"), Name: utils.String("预计出货金额"), Value: utils.String(gconv.String(business.EstTransPrice)), }, { Id: utils.String("TableField_1CGSRAWT8YG0"), Name: utils.String("产品列表"), Value: utils.String(gconv.String(dingProductList)), }, { Id: utils.String("TextField_AEUWH63LJ0O0"), Name: utils.String("销售工程师"), Value: utils.String(business.SaleName), }, { Id: utils.String("DDAttachment_KZPWZJS9GHO0"), Name: utils.String("上传报价单"), Value: utils.String(gconv.String(quotationFile)), }, { Id: utils.String("TextareaField_1GEL8JJL3H5S0"), Name: utils.String("备注"), Value: utils.String(req.Remark), }, }, } case StatusA: var dashooParamFile []contractModel.DingFileInfo var quotationFile []contractModel.DingFileInfo if len(fileMap) > 0 { for k, files := range fileMap { // 报价单 if k == "quotationFile" { if quotationFile, err = p.txCreateBusinessDingTalkFile(business.Id, upgradeType, k, files); err != nil { return "", err } } // 大数参数文件 if k == "dashooParamFile" { if dashooParamFile, err = p.txCreateBusinessDingTalkFile(business.Id, upgradeType, k, files); err != nil { return "", err } } } } if strings.HasPrefix(req.QuotationFile, "dingtalk") { arr := strings.Split(req.QuotationFile, ":") quotationFile = append(quotationFile, contractModel.DingFileInfo{ SpaceId: arr[1], FileId: arr[2], FileName: fmt.Sprintf("%v报价单", business.NboName), FileSize: 10, FileType: "", }) } if len(quotationFile) == 0 { return "", myerrors.TipsError("请上传报价单文件") } business.ApproType = BusinessUpgradeARequestProcessCode dingReq = &workflow.StartProcessInstanceRequest{ ProcessCode: &business.ApproType, 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_L4CSUVLU1NK"), Name: utils.String("产品线"), Value: utils.String(productLine), }, { 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("DDSelectField_21ASEWDIB3MO0"), Name: utils.String("采购方式"), Value: utils.String(gconv.String(purchasingWayType[req.PurchasingWay])), }, { Id: utils.String("TextField_3AIYCSEQLQC0"), Name: utils.String("资金来源"), Value: utils.String(req.CapitalSource), }, { Id: utils.String("DDDateField_1FW1QZQYBZVK0"), Name: utils.String("计划采购时间"), Value: utils.String(gconv.String(req.PlanPurchaseTime.Format("Y-m-d"))), }, { Id: utils.String("TextField_1PWK6WHMGITC0"), Name: utils.String("客户决策人"), Value: utils.String(req.MakerName), }, { Id: utils.String("TextField_16RIJRRF8B340"), Name: utils.String("客户决策部门"), Value: utils.String(req.MakerDept), }, { Id: utils.String("TextField_7EE0LTUVUSK0"), Name: utils.String("客户联系人"), Value: utils.String(req.ContactName), }, { Id: utils.String("TextField_E8TFCZUBV940"), Name: utils.String("客户联系人电话/微信"), Value: utils.String(req.ContactTelephone), }, { 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(dashooParamFile)), }, { Id: utils.String("TextField_FJI7GL9E8W80"), Name: utils.String("竞争公司"), Value: utils.String(req.Competitor), }, { Id: utils.String("TextField_1NC9MEUBDBR40"), Name: utils.String("客户倾向厂家"), Value: utils.String(req.CustomerIntentionFactory), }, { Id: utils.String("TextField_AEUWH63LJ0O0"), Name: utils.String("销售工程师"), Value: utils.String(business.SaleName), }, { Id: utils.String("DDAttachment_19Y01ZRBFWXS0"), Name: utils.String("上传报价单"), Value: utils.String(gconv.String(quotationFile)), }, { Id: utils.String("TextareaField_1GEL8JJL3H5S0"), Name: utils.String("备注"), Value: utils.String(req.Remark), }, }, } default: return "", nil } instanceId, err = workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectUpGrade, "", dingReq) if err != nil { g.Log().Error(err) return "", err } return instanceId, nil } // 项目上传文件至钉钉 func (p *businessService) txCreateBusinessDingTalkFile(businessId int, upgradeType, fileType string, file *multipart.FileHeader) ([]contractModel.DingFileInfo, error) { dingTalkFiles := make([]contractModel.DingFileInfo, 0) //for _, file := range files { resp, err := dingtalk.Client.GetStorage().UploadFile(service.DingTalkSpaceId, p.GetCxtUserDingtalkId(), file.FileName, file.File.Name()) if err != nil { g.Log().Error(err) return nil, myerrors.TipsError("钉钉上传文件异常") } typ := "项目" + upgradeType if fileType == "quotationFile" { typ += "上传报价单文件" } if fileType == "dashooParamFile" { typ += "上传大数技术参数文件" } g.Log().Info(typ, resp) dingTalkFiles = append(dingTalkFiles, 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(businessId, typ, dingTalkFiles) if err != nil { return nil, err } return dingTalkFiles, nil } // 采用大数参数文件记录 func (p *businessService) txCreateBusinessFile(busId int, fileSource string, 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 = fileSource 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, data) } _, 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{} var updateData *model.BusinessUpgradeReq var remark string 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 remarkMap := gconv.Map(dynamics.OpnContent) remark = gconv.String(g.Map{"nboType": remarkMap["nboType"], "origNboType": remarkMap["origNboType"]}) } err = p.Dao.Transaction(p.Ctx, func(ctx context.Context, tx *gdb.TX) error { // 添加产品 if updateData != nil && (updateData.NboType == "20" || updateData.NboType == "10") { // 设置产品信息 totalPrice, products, err := p.setProductInfo(updateData.Id, updateData.Products) if err != nil { return err } // 删除项目产品 _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Where(projDao.ProjBusinessProduct.C.BusId, updateData.Id).Delete() if err != nil { return err } // 添加项目产品 _, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Insert(products) if err != nil { return err } data[p.Dao.C.EstTransPrice] = totalPrice } // 项目修改 _, err = p.Dao.TX(tx).WherePri(business.Id).FieldsEx(service.UpdateFieldEx...).Data(data).Update() if err != nil { return err } // 添加项目动态 dynamics := model.ProjBusinessDynamics{ BusId: business.Id, OpnType: OpnUpgradeApproval, Remark: remark, } _, err = p.CreateProjBusinessDynamics(tx, dynamics, data) if err != nil { return err } return nil }) 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()) productLine, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "sys_product_line", business.ProductLine) // 审批流 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) business.ApproType = BusinessDowngradeRequestProcessCode instanceId, err := workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectDownGrade, "", &workflow.StartProcessInstanceRequest{ ProcessCode: &business.ApproType, 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("DDSelectField_1UCNHJ0P8C5C0"), Name: utils.String("产品线"), Value: utils.String(productLine), }, { Id: utils.String("TextField_X4D3QGARU7K0"), Name: utils.String("支持内容"), Value: utils.String("无"), }, { 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 } // 更新项目审批信息 _, err = p.Dao.TX(tx).Data(g.Map{p.Dao.C.ApproType: business.ApproType, p.Dao.C.ApproInstanceId: instanceId}).Update() if err != nil { 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{} var remark string 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 remarkMap := gconv.Map(dynamics.OpnContent) remark = gconv.String(g.Map{"nboType": remarkMap["nboType"], "origNboType": remarkMap["origNboType"]}) } // 项目修改 _, 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, Remark: remark, } _, 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 := gconv.Map(gconv.String(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 := gconv.Map(gconv.String(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("项目已提交审批任务,无法重复提交。") } productLine, _ := service.GetDictLabelByTypeAndValue(p.Ctx, "sys_product_line", business.ProductLine) // 审批流 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) business.ApproType = ConvertToReserveRequestProcessCode instanceId, err := workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, "", &workflow.StartProcessInstanceRequest{ ProcessCode: &business.ApproType, 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("DDSelectField_1UVBB1LZHIJK0"), Name: utils.String("产品线"), Value: utils.String(productLine), }, { 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 } // 更新项目审批信息 _, err = p.Dao.TX(tx).Data(g.Map{p.Dao.C.ApproType: business.ApproType, p.Dao.C.ApproInstanceId: instanceId}).Update() if err != nil { 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 }