package contract import ( "encoding/json" "errors" "fmt" "github.com/beego/beego/v2/client/orm" "hongze/hongze_mobile_admin/models/custom" contractCustom "hongze/hongze_mobile_admin/models/custom/contract" contractReq "hongze/hongze_mobile_admin/models/request/contract" contractResp "hongze/hongze_mobile_admin/models/response/contract" "hongze/hongze_mobile_admin/models/tables/company_report_permission" "hongze/hongze_mobile_admin/models/tables/contract" "hongze/hongze_mobile_admin/models/tables/contract_approval" "hongze/hongze_mobile_admin/models/tables/contract_approval_record" "hongze/hongze_mobile_admin/models/tables/contract_operation_record" "hongze/hongze_mobile_admin/models/tables/contract_relation" "hongze/hongze_mobile_admin/models/tables/contract_service_detail" "hongze/hongze_mobile_admin/models/tables/contract_service_template" "hongze/hongze_mobile_admin/services" "hongze/hongze_mobile_admin/utils" "mime/multipart" "reflect" "strings" "time" ) // InvalidContract 作废合同 func InvalidContract(contractId int, opUser *custom.AdminWx) (err error) { //查询当前合同信息 nowContract, err := contract.GetContractById(contractId) if err != nil { if err.Error() == utils.ErrNoRow() { err = errors.New(fmt.Sprint("根据合同编号:", contractId, " 找不到初始合同")) } return } if nowContract.SellerId != opUser.AdminId && opUser.RoleTypeCode != utils.ROLE_TYPE_CODE_COMPLIANCE { err = errors.New("当前账号无操作权限") return } if nowContract.Status != "已审批" { err = errors.New("合同状态异常,不允许作废,当前合同状态:" + nowContract.Status) return } //如果删除状态 >0,那么代表已经被删除了 if nowContract.IsDelete > 0 { err = errors.New("该合同已删除") return } //合同作废 err = contract.InvalidContract(nowContract) if err != nil { return } //添加操作日志 remark := "作废合同模板" _ = contract_operation_record.AddContractOperationRecord(nowContract.ContractId, opUser.AdminId, 0, "invalid", opUser.RealName, remark) //修改业务合同的已支付金额 if nowContract.ContractBusinessType == "代付合同" { go updateContractPaidPriceByPaymentOnBehalfContractId(nowContract.ContractId, -nowContract.Price) } return } // GetContractDetail 根据id获取合同详情(包含服务) func GetContractDetail(contractId int) (contractDetail *contract.ContractDetail, err error) { contractDetail, err = getContractDetail(contractId) if err != nil { if err.Error() == utils.ErrNoRow() { err = errors.New("找不到该合同") } return } relationContractDetailList := make([]*contract.ContractDetail, 0) switch contractDetail.ContractBusinessType { case "业务合同": tmpList, tmpErr := contract_relation.GetContractRelationListByRelationContractId(contractDetail.ContractId) if tmpErr != nil { err = errors.New("查询业务关联合同异常:" + tmpErr.Error()) return } //获取所有关联合同详情 for _, relationContract := range tmpList { tmpContractDetail, tmpErr := getContractDetail(relationContract.PaymentOnBehalfContractId) if tmpErr != nil { err = errors.New("查询业务关联合同详情异常:" + tmpErr.Error()) return } relationContractDetailList = append(relationContractDetailList, tmpContractDetail) } case "代付合同": tmpList, tmpErr := contract_relation.GetContractRelationListByPaymentOnBehalfContractId(contractDetail.ContractId) if tmpErr != nil { err = errors.New("查询代付关联合同异常:" + tmpErr.Error()) return } //获取所有关联合同详情 for _, relationContract := range tmpList { tmpContractDetail, tmpErr := getContractDetail(relationContract.ContractId) if tmpErr != nil { err = errors.New("查询业务关联合同详情异常:" + tmpErr.Error()) return } relationContractDetailList = append(relationContractDetailList, tmpContractDetail) } } contractDetail.RelationContractDetailList = relationContractDetailList return } // getContractDetail 根据id获取合同详情(包含服务) func getContractDetail(contractId int) (contractDetail *contract.ContractDetail, err error) { contractDetail, err = contract.GetContractDetailById(contractId) if err != nil { if err.Error() == utils.ErrNoRow() { err = errors.New("找不到该合同") } return } //获取合同服务内容详情 serviceList, err := contractCustom.GetContractServiceAndDetailList(contractId) if err != nil { err = errors.New(fmt.Sprint("查找合同服务异常", err)) return } // 权益合同主客观合并 if len(serviceList) > 0 && serviceList[0].ProductId == 2 { mergeList, e := EquityMergeSubjectAndObject(serviceList) if e != nil { err = errors.New(fmt.Sprint("合并权益合同服务异常", err)) return } serviceList = mergeList } newLen := len(serviceList) for i := 0; newLen > i; i++ { if serviceList[i].HasDetail == "是" { list, detailErr := contract_service_detail.GetContractServiceDetailListByServiceId(serviceList[i].ContractServiceId) if detailErr != nil { err = errors.New(fmt.Sprint("查找合同服务详情异常", detailErr)) return } serviceList[i].DetailList = list } } contractDetail.Service = serviceList return } // UploadCheckBackFileByFile 上传签回合同附件 func UploadCheckBackFileByFile(contractId int, ext string, fileMulti multipart.File, opUser *custom.AdminWx) (resourceUrl string, err error) { //获取合同信息 contractInfo, err := contract.GetContractById(contractId) if err != nil { return } //合同状态判断 if contractInfo.Status != "已审批" && contractInfo.Status != "已签回" { err = errors.New("合同状态异常,不允许上传签回合同附件,当前合同状态:" + contractInfo.Status) return } //保存的文件名 fileName := contractInfo.CompanyName + "_" + contractInfo.ContractCode + "(签回)" //非正式环境下,文件名上面还是加上随机数 if utils.RunMode != "release" { fileName += "_" + utils.GetRandStringNoSpecialChar(10) } fileName += ext //上传到阿里云 resourceUrl, err = services.UploadToOssAndFileName(fileMulti, fileName) if err != nil { err = errors.New("文件保存失败,Err:" + err.Error()) return } contractInfo.CheckBackFileUrl = resourceUrl contractInfo.Status = "已签回" contractInfo.ModifyTime = time.Now() contractInfo.CheckBackFileTime = time.Now() err = contractInfo.Update([]string{"CheckBackFileUrl", "Status", "ModifyTime", "CheckBackFileTime"}) if err != nil { return } //同步更新客户那边提交审批的合同 o := orm.NewOrm() sql := `update company_contract set img_url = ? where contract_code=? and source="系统合同" ` _, err = o.Raw(sql, contractInfo.CheckBackFileUrl, contractInfo.ContractCode).Exec() //添加操作日志 remark := "上传签回合同附件" _ = contract_operation_record.AddContractOperationRecord(contractInfo.ContractId, opUser.AdminId, 0, "upload", opUser.RealName, remark) return } // UploadCheckBackFile 更新上传签回合同附件 func UploadCheckBackFile(contractId int, fileUrl string, opUser *custom.AdminWx) (err error) { //获取合同信息 contractInfo, err := contract.GetContractById(contractId) if err != nil { return } //合同状态判断 if contractInfo.Status != "已审批" && contractInfo.Status != "已签回" { err = errors.New("合同状态异常,不允许上传签回合同附件,当前合同状态:" + contractInfo.Status) return } contractInfo.CheckBackFileUrl = fileUrl contractInfo.Status = "已签回" contractInfo.ModifyTime = time.Now() contractInfo.CheckBackFileTime = time.Now() err = contractInfo.Update([]string{"CheckBackFileUrl", "Status", "ModifyTime", "CheckBackFileTime"}) if err != nil { return } //同步更新客户那边提交审批的合同 o := orm.NewOrm() sql := `update company_contract set img_url = ? where contract_code=? and source="系统合同" ` _, err = o.Raw(sql, contractInfo.CheckBackFileUrl, contractInfo.ContractCode).Exec() //添加操作日志 remark := "上传签回合同附件" _ = contract_operation_record.AddContractOperationRecord(contractInfo.ContractId, opUser.AdminId, 0, "upload", opUser.RealName, remark) return } // GetOpButton 获取审批流和权限 func GetOpButton(contractInfo *contract.ContractDetail, contractApprovalInfo *contract_approval.ContractApproval, opUser *custom.AdminWx) (contractOpButton contractResp.OpButton, flowNodeListResp [][]contract_approval_record.ContractApprovalRecord, err error) { //审批流 approvalRecordList, err := contract_approval_record.GetContractApprovalRecordListByContractApprovalId(contractApprovalInfo.ContractApprovalId) if err != nil { err = errors.New("获取审批失败,Err:" + err.Error()) return } flowNodeMap := make(map[int][]contract_approval_record.ContractApprovalRecord, 0) keySort := make([]int, 0) for _, approvalRecord := range approvalRecordList { //如果当前节点正好是该节点,同时审批单状态是待审批状态,然后当前账号又有权限,该账号也正是审批人,那么允许审批操作 if contractApprovalInfo.CurrNodeId == approvalRecord.NodeId && contractApprovalInfo.Status == "待审批" { if opUser.AdminId == approvalRecord.ApproveUserId && approvalRecord.NodeType == "check" { contractOpButton.Approval = true } } if tmpFlowNodeList, ok := flowNodeMap[approvalRecord.NodeId]; ok { flowNodeMap[approvalRecord.NodeId] = append(tmpFlowNodeList, *approvalRecord) } else { tmpFlowNodeList := make([]contract_approval_record.ContractApprovalRecord, 1) tmpFlowNodeList[0] = *approvalRecord flowNodeMap[approvalRecord.NodeId] = tmpFlowNodeList keySort = append(keySort, approvalRecord.NodeId) } } for _, key := range keySort { flowNodeListResp = append(flowNodeListResp, flowNodeMap[key]) } //是否具有签回合同权限 uploadStatus := []string{"已审批", "已签回"} if opUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE && strings.Contains(strings.Join(uploadStatus, ","), contractInfo.Status) { contractOpButton.UploadFile = true } //作废权限 if (opUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE || opUser.AdminId == contractInfo.SellerId) && contractInfo.Status == "已审批" { contractOpButton.Invalid = true } return } // GetContractDetailByContractId 根据合同获取合同详情 func GetContractDetailByContractId(contractId int, opUser *custom.AdminWx) (contractInfo *contract.ContractDetail, flowNodeListResp [][]contract_approval_record.ContractApprovalRecord, opButton contractResp.OpButton, err error) { contractInfo, err = GetContractDetail(contractId) if err != nil { err = errors.New("获取合同详情失败,ERR:" + err.Error()) return } contractInfo.StartDateStr = contractInfo.StartDate.Format(utils.FormatDate) contractInfo.EndDateStr = contractInfo.EndDate.Format(utils.FormatDate) contractInfo.ModifyTimeStr = contractInfo.ModifyTime.Format(utils.FormatDateTime) contractInfo.CreateTimeStr = contractInfo.CreateTime.Format(utils.FormatDateTime) //合同中包含的产品权限 isNeedPermission := false //是否需要列出来套餐中的详细权限 for _, service := range contractInfo.Service { if service.ServiceTemplateId == 2 { //小套餐才需要列出来详细的权限 isNeedPermission = true } } if isNeedPermission { permissionLookList, _ := GetPermissionByContractService(contractInfo.ProductId, contractInfo.Service) contractInfo.PermissionLookList = permissionLookList } //查询最近一次审批单信息 lastApprovalInfo, err := contract_approval.GetLastContractApprovalByContractId(contractInfo.ContractId, "contract") if err != nil { if err.Error() != utils.ErrNoRow() { err = errors.New("获取最近一次审批单信息失败,ERR:" + err.Error()) } err = nil return } if lastApprovalInfo != nil { //审批操作权限,上传签回文件权限 tmpContractOpButton, tmpFlowNodeListResp, tmpErr := GetOpButton(contractInfo, lastApprovalInfo, opUser) if tmpErr != nil { err = errors.New("获取合同按钮权限、审批流程失败,ERR:" + tmpErr.Error()) return } opButton = tmpContractOpButton flowNodeListResp = tmpFlowNodeListResp } return } // GetProductCelData 获取品种列数据(因为前端可以随意插入列数据,所以需要根据列名来搜索对应的品种列) func GetProductCelData(detail contract_service_detail.ContractServiceDetail, tableCel *contractReq.AddContractServiceDetailReq) (err error) { t := reflect.TypeOf(detail) v := reflect.ValueOf(detail) for k := 0; k < t.NumField(); k++ { //获取结构体的参数名 tmpName := t.Field(k).Name if strings.Contains(tmpName, "Col") { //获取结构体该参数名的值 tmpValue := v.Field(k).String() //如果值不为空的话,那么做下json转换 if tmpValue != "" { tmpErr := json.Unmarshal([]byte(tmpValue), tableCel) if tmpErr != nil { err = tmpErr continue } if tableCel.HeadName == "品种" { err = nil return } } } } return } // GetPermissionByContractService 通过合同服务,获取权限集合列表 func GetPermissionByContractService(productId int, serviceList []*contractCustom.ContractServiceAndDetail) (permissionList []*company_report_permission.PermissionLookList, err error) { //子权限切片集合 var permissionClassifyArr []string if productId == 1 { for _, v := range utils.PermissionFiccClassifyArr { permissionClassifyArr = append(permissionClassifyArr, v) } } else { permissionClassifyArr = append(permissionClassifyArr, "权益") } //获取已经勾选的的权限 checkPermissionIdMap, err := GetServicePermissionMap(serviceList) if err != nil { return } //遍历获取 for _, v := range permissionClassifyArr { checkList := make([]int, 0) plist := new(company_report_permission.PermissionLookList) items, tmpErr := company_report_permission.GetPermissionLookItems(productId, v) if tmpErr != nil { err = tmpErr return } for _, n := range items { if _, ok := checkPermissionIdMap[n.ChartPermissionId]; ok { checkList = append(checkList, n.ChartPermissionId) } } plist.Items = items plist.ClassifyName = v plist.CheckList = checkList permissionList = append(permissionList, plist) } return } // GetServicePermissionMap 获取合同服务中的权限id map func GetServicePermissionMap(serviceList []*contractCustom.ContractServiceAndDetail) (checkPermissionIdMap map[int]int, err error) { checkPermissionIdMap = make(map[int]int) //获取已经勾选的的权限 for _, contractService := range serviceList { //如果是权益,那么研选必要 if contractService.ProductId == 2 { chartPermissionId := 31 //研 选服务 checkPermissionIdMap[chartPermissionId] = chartPermissionId } //看看系统中有没有映射对应的权限,如果有的话,那么直接返回,没有那么可能是特殊服务,需要去遍历 if contractService.ChartPermissionId > 0 { checkPermissionIdMap[contractService.ChartPermissionId] = contractService.ChartPermissionId continue } switch contractService.ServiceTemplateId { case 1: //ficc 大套餐 for _, v := range utils.PermissionFiccClassifyArr { //大套餐中 市场策略暂时不作为勾选项 if v == "市场策略" { continue } items, tmpErr := company_report_permission.GetPermissionLookItems(1, v) if tmpErr != nil { err = tmpErr return } for _, n := range items { checkPermissionIdMap[n.ChartPermissionId] = n.ChartPermissionId } } case 2: //ficc小套餐 permissionValues := []string{ "FICC周报", "商品双周报+线上电话会讨论会
(由弘则的研究员主持线上讨论)", "数据点评", } for _, detail := range contractService.DetailList { var tableCel contractReq.AddContractServiceDetailReq tmpErr := json.Unmarshal([]byte(detail.Col1), &tableCel) if tmpErr != nil { err = tmpErr return } if strings.Contains(strings.Join(permissionValues, ","), tableCel.Value) { //获取品种列数据 var tableCel2 contractReq.AddContractServiceDetailReq tmpErr := GetProductCelData(*detail, &tableCel2) if tmpErr != nil { err = tmpErr return } for _, serviceId := range tableCel2.ValueId { checkPermissionIdMap[serviceId] = serviceId } } } case 4, 5, 6: //权益大套餐 permissionFiccClassifyArr := []string{"权益"} for _, v := range permissionFiccClassifyArr { items, tmpErr := company_report_permission.GetPermissionLookItems(2, v) if tmpErr != nil { err = tmpErr return } for _, n := range items { //如果是专家行业,那么 结束当前循环,进入下一循环(产品需求:专家行业不在里面) if n.ChartPermissionId == 29 { continue } checkPermissionIdMap[n.ChartPermissionId] = n.ChartPermissionId } } } } return } // 权益合同主客观合并 func EquityMergeSubjectAndObject(serviceList []*contractCustom.ContractServiceAndDetail) (mergeList []*contractCustom.ContractServiceAndDetail, err error) { mergeList = make([]*contractCustom.ContractServiceAndDetail, 0) // 获取模板列表 templateList, e := contract_service_template.GetAllContractServiceTemplateList() if e != nil { err = errors.New("获取合同服务模板异常, Err: " + e.Error()) return } templateMap := make(map[int]*contract_service_template.ContractServiceTemplate, 0) for _, v := range templateList { templateMap[v.ServiceTemplateId] = v } mergeArr := []string{"医药", "消费", "科技", "智造"} // 遍历原服务 serviceLen := len(serviceList) if serviceLen > 0 { needCheck := make([]*contractCustom.ContractServiceAndDetail, 0) for i := 0; i < serviceLen; i++ { sv := serviceList[i] if sv.ProductId != 2 { mergeList = serviceList return } // 判断是否包含主观客观 if utils.InArrayByStr(mergeArr, sv.Title) { needCheck = append(needCheck, sv) } else { if sv.Title != "主观" && sv.Title != "客观" { mergeList = append(mergeList, sv) } } } // 不需要合并 checkLen := len(needCheck) if checkLen == 0 { mergeList = serviceList return } for i := 0; i < checkLen; i++ { count := 0 parent := needCheck[i] parentId := parent.ServiceTemplateId // 检查需要合并的是否包含主客观 children := make([]*contractCustom.ContractServiceAndDetail, 0) for ii := 0; ii < serviceLen; ii++ { sv := serviceList[ii] temp := templateMap[sv.ServiceTemplateId] if temp.Pid == parentId { count += 1 sv.Title = fmt.Sprint(parent.Title, "(", sv.Title, ")") children = append(children, sv) } } // 均包含时只取二级套餐, 否则取主/客观 if count == 1 { mergeList = append(mergeList, children...) } else { mergeList = append(mergeList, parent) } } } return }