contract.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. package contract
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/rdlucklib/rdluck_tools/orm"
  7. "hongze/hongze_mobile_admin/models/custom"
  8. contractCustom "hongze/hongze_mobile_admin/models/custom/contract"
  9. contractReq "hongze/hongze_mobile_admin/models/request/contract"
  10. contractResp "hongze/hongze_mobile_admin/models/response/contract"
  11. "hongze/hongze_mobile_admin/models/tables/company_report_permission"
  12. "hongze/hongze_mobile_admin/models/tables/contract"
  13. "hongze/hongze_mobile_admin/models/tables/contract_approval"
  14. "hongze/hongze_mobile_admin/models/tables/contract_approval_record"
  15. "hongze/hongze_mobile_admin/models/tables/contract_operation_record"
  16. "hongze/hongze_mobile_admin/models/tables/contract_relation"
  17. "hongze/hongze_mobile_admin/models/tables/contract_service_detail"
  18. "hongze/hongze_mobile_admin/services"
  19. "hongze/hongze_mobile_admin/utils"
  20. "mime/multipart"
  21. "reflect"
  22. "strings"
  23. "time"
  24. )
  25. // InvalidContract 作废合同
  26. func InvalidContract(contractId int, opUser *custom.AdminWx) (err error) {
  27. //查询当前合同信息
  28. nowContract, err := contract.GetContractById(contractId)
  29. if err != nil {
  30. if err.Error() == utils.ErrNoRow() {
  31. err = errors.New(fmt.Sprint("根据合同编号:", contractId, " 找不到初始合同"))
  32. }
  33. return
  34. }
  35. if nowContract.SellerId != opUser.AdminId && opUser.RoleTypeCode != utils.ROLE_TYPE_CODE_COMPLIANCE {
  36. err = errors.New("当前账号无操作权限")
  37. return
  38. }
  39. if nowContract.Status != "已审批" {
  40. err = errors.New("合同状态异常,不允许作废,当前合同状态:" + nowContract.Status)
  41. return
  42. }
  43. //如果删除状态 >0,那么代表已经被删除了
  44. if nowContract.IsDelete > 0 {
  45. err = errors.New("该合同已删除")
  46. return
  47. }
  48. //合同作废
  49. err = contract.InvalidContract(nowContract)
  50. if err != nil {
  51. return
  52. }
  53. //添加操作日志
  54. remark := "作废合同模板"
  55. _ = contract_operation_record.AddContractOperationRecord(nowContract.ContractId, opUser.AdminId, 0, "invalid", opUser.RealName, remark)
  56. //修改业务合同的已支付金额
  57. if nowContract.ContractBusinessType == "代付合同" {
  58. go updateContractPaidPriceByPaymentOnBehalfContractId(nowContract.ContractId, -nowContract.Price)
  59. }
  60. return
  61. }
  62. // GetContractDetail 根据id获取合同详情(包含服务)
  63. func GetContractDetail(contractId int) (contractDetail *contract.ContractDetail, err error) {
  64. contractDetail, err = getContractDetail(contractId)
  65. if err != nil {
  66. if err.Error() == utils.ErrNoRow() {
  67. err = errors.New("找不到该合同")
  68. }
  69. return
  70. }
  71. relationContractDetailList := make([]*contract.ContractDetail, 0)
  72. switch contractDetail.ContractBusinessType {
  73. case "业务合同":
  74. tmpList, tmpErr := contract_relation.GetContractRelationListByRelationContractId(contractDetail.ContractId)
  75. if tmpErr != nil {
  76. err = errors.New("查询业务关联合同异常:" + tmpErr.Error())
  77. return
  78. }
  79. //获取所有关联合同详情
  80. for _, relationContract := range tmpList {
  81. tmpContractDetail, tmpErr := getContractDetail(relationContract.PaymentOnBehalfContractId)
  82. if tmpErr != nil {
  83. err = errors.New("查询业务关联合同详情异常:" + tmpErr.Error())
  84. return
  85. }
  86. relationContractDetailList = append(relationContractDetailList, tmpContractDetail)
  87. }
  88. case "代付合同":
  89. tmpList, tmpErr := contract_relation.GetContractRelationListByPaymentOnBehalfContractId(contractDetail.ContractId)
  90. if tmpErr != nil {
  91. err = errors.New("查询代付关联合同异常:" + tmpErr.Error())
  92. return
  93. }
  94. //获取所有关联合同详情
  95. for _, relationContract := range tmpList {
  96. tmpContractDetail, tmpErr := getContractDetail(relationContract.ContractId)
  97. if tmpErr != nil {
  98. err = errors.New("查询业务关联合同详情异常:" + tmpErr.Error())
  99. return
  100. }
  101. relationContractDetailList = append(relationContractDetailList, tmpContractDetail)
  102. }
  103. }
  104. contractDetail.RelationContractDetailList = relationContractDetailList
  105. return
  106. }
  107. // getContractDetail 根据id获取合同详情(包含服务)
  108. func getContractDetail(contractId int) (contractDetail *contract.ContractDetail, err error) {
  109. contractDetail, err = contract.GetContractDetailById(contractId)
  110. if err != nil {
  111. if err.Error() == utils.ErrNoRow() {
  112. err = errors.New("找不到该合同")
  113. }
  114. return
  115. }
  116. //获取合同服务内容详情
  117. serviceList, err := contractCustom.GetContractServiceAndDetailList(contractId)
  118. if err != nil {
  119. err = errors.New(fmt.Sprint("查找合同服务异常", err))
  120. return
  121. }
  122. for i := 0; len(serviceList) > i; i++ {
  123. if serviceList[i].HasDetail == "是" {
  124. list, detailErr := contract_service_detail.GetContractServiceDetailListByServiceId(serviceList[i].ContractServiceId)
  125. if detailErr != nil {
  126. err = errors.New(fmt.Sprint("查找合同服务详情异常", detailErr))
  127. return
  128. }
  129. serviceList[i].DetailList = list
  130. }
  131. }
  132. contractDetail.Service = serviceList
  133. return
  134. }
  135. // UploadCheckBackFileByFile 上传签回合同附件
  136. func UploadCheckBackFileByFile(contractId int, ext string, fileMulti multipart.File, opUser *custom.AdminWx) (resourceUrl string, err error) {
  137. //获取合同信息
  138. contractInfo, err := contract.GetContractById(contractId)
  139. if err != nil {
  140. return
  141. }
  142. //合同状态判断
  143. if contractInfo.Status != "已审批" && contractInfo.Status != "已签回" {
  144. err = errors.New("合同状态异常,不允许上传签回合同附件,当前合同状态:" + contractInfo.Status)
  145. return
  146. }
  147. //保存的文件名
  148. fileName := contractInfo.CompanyName + "_" + contractInfo.ContractCode + "(签回)"
  149. //非正式环境下,文件名上面还是加上随机数
  150. if utils.RunMode != "release" {
  151. fileName += "_" + utils.GetRandStringNoSpecialChar(10)
  152. }
  153. fileName += ext
  154. //上传到阿里云
  155. resourceUrl, err = services.UploadToOssAndFileName(fileMulti, fileName)
  156. if err != nil {
  157. err = errors.New("文件保存失败,Err:" + err.Error())
  158. return
  159. }
  160. contractInfo.CheckBackFileUrl = resourceUrl
  161. contractInfo.Status = "已签回"
  162. contractInfo.ModifyTime = time.Now()
  163. contractInfo.CheckBackFileTime = time.Now()
  164. err = contractInfo.Update([]string{"CheckBackFileUrl", "Status", "ModifyTime", "CheckBackFileTime"})
  165. if err != nil {
  166. return
  167. }
  168. //同步更新客户那边提交审批的合同
  169. o := orm.NewOrm()
  170. sql := `update company_contract set img_url = ? where contract_code=? and source="系统合同" `
  171. _, err = o.Raw(sql, contractInfo.CheckBackFileUrl, contractInfo.ContractCode).Exec()
  172. //添加操作日志
  173. remark := "上传签回合同附件"
  174. _ = contract_operation_record.AddContractOperationRecord(contractInfo.ContractId, opUser.AdminId, 0, "upload", opUser.RealName, remark)
  175. return
  176. }
  177. // UploadCheckBackFile 更新上传签回合同附件
  178. func UploadCheckBackFile(contractId int, fileUrl string, opUser *custom.AdminWx) (err error) {
  179. //获取合同信息
  180. contractInfo, err := contract.GetContractById(contractId)
  181. if err != nil {
  182. return
  183. }
  184. //合同状态判断
  185. if contractInfo.Status != "已审批" && contractInfo.Status != "已签回" {
  186. err = errors.New("合同状态异常,不允许上传签回合同附件,当前合同状态:" + contractInfo.Status)
  187. return
  188. }
  189. contractInfo.CheckBackFileUrl = fileUrl
  190. contractInfo.Status = "已签回"
  191. contractInfo.ModifyTime = time.Now()
  192. contractInfo.CheckBackFileTime = time.Now()
  193. err = contractInfo.Update([]string{"CheckBackFileUrl", "Status", "ModifyTime", "CheckBackFileTime"})
  194. if err != nil {
  195. return
  196. }
  197. //同步更新客户那边提交审批的合同
  198. o := orm.NewOrm()
  199. sql := `update company_contract set img_url = ? where contract_code=? and source="系统合同" `
  200. _, err = o.Raw(sql, contractInfo.CheckBackFileUrl, contractInfo.ContractCode).Exec()
  201. //添加操作日志
  202. remark := "上传签回合同附件"
  203. _ = contract_operation_record.AddContractOperationRecord(contractInfo.ContractId, opUser.AdminId, 0, "upload", opUser.RealName, remark)
  204. return
  205. }
  206. // GetOpButton 获取审批流和权限
  207. func GetOpButton(contractInfo *contract.ContractDetail, contractApprovalInfo *contract_approval.ContractApproval, opUser *custom.AdminWx) (contractOpButton contractResp.OpButton, flowNodeListResp [][]contract_approval_record.ContractApprovalRecord, err error) {
  208. //审批流
  209. approvalRecordList, err := contract_approval_record.GetContractApprovalRecordListByContractApprovalId(contractApprovalInfo.ContractApprovalId)
  210. if err != nil {
  211. err = errors.New("获取审批失败,Err:" + err.Error())
  212. return
  213. }
  214. flowNodeMap := make(map[int][]contract_approval_record.ContractApprovalRecord, 0)
  215. keySort := make([]int, 0)
  216. for _, approvalRecord := range approvalRecordList {
  217. //如果当前节点正好是该节点,同时审批单状态是待审批状态,然后当前账号又有权限,该账号也正是审批人,那么允许审批操作
  218. if contractApprovalInfo.CurrNodeId == approvalRecord.NodeId && contractApprovalInfo.Status == "待审批" {
  219. if opUser.AdminId == approvalRecord.ApproveUserId && approvalRecord.NodeType == "check" {
  220. contractOpButton.Approval = true
  221. }
  222. }
  223. if tmpFlowNodeList, ok := flowNodeMap[approvalRecord.NodeId]; ok {
  224. flowNodeMap[approvalRecord.NodeId] = append(tmpFlowNodeList, *approvalRecord)
  225. } else {
  226. tmpFlowNodeList := make([]contract_approval_record.ContractApprovalRecord, 1)
  227. tmpFlowNodeList[0] = *approvalRecord
  228. flowNodeMap[approvalRecord.NodeId] = tmpFlowNodeList
  229. keySort = append(keySort, approvalRecord.NodeId)
  230. }
  231. }
  232. for _, key := range keySort {
  233. flowNodeListResp = append(flowNodeListResp, flowNodeMap[key])
  234. }
  235. //是否具有签回合同权限
  236. uploadStatus := []string{"已审批", "已签回"}
  237. if opUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE && strings.Contains(strings.Join(uploadStatus, ","), contractInfo.Status) {
  238. contractOpButton.UploadFile = true
  239. }
  240. //作废权限
  241. if (opUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE || opUser.AdminId == contractInfo.SellerId) && contractInfo.Status == "已审批" {
  242. contractOpButton.Invalid = true
  243. }
  244. return
  245. }
  246. // GetContractDetailByContractId 根据合同获取合同详情
  247. func GetContractDetailByContractId(contractId int, opUser *custom.AdminWx) (contractInfo *contract.ContractDetail, flowNodeListResp [][]contract_approval_record.ContractApprovalRecord, opButton contractResp.OpButton, err error) {
  248. contractInfo, err = GetContractDetail(contractId)
  249. if err != nil {
  250. err = errors.New("获取合同详情失败,ERR:" + err.Error())
  251. return
  252. }
  253. contractInfo.StartDateStr = contractInfo.StartDate.Format(utils.FormatDate)
  254. contractInfo.EndDateStr = contractInfo.EndDate.Format(utils.FormatDate)
  255. contractInfo.ModifyTimeStr = contractInfo.ModifyTime.Format(utils.FormatDateTime)
  256. contractInfo.CreateTimeStr = contractInfo.CreateTime.Format(utils.FormatDateTime)
  257. //合同中包含的产品权限
  258. isNeedPermission := false //是否需要列出来套餐中的详细权限
  259. for _, service := range contractInfo.Service {
  260. if service.ServiceTemplateId == 2 { //小套餐才需要列出来详细的权限
  261. isNeedPermission = true
  262. }
  263. }
  264. if isNeedPermission {
  265. permissionLookList, _ := GetPermissionByContractService(contractInfo.ProductId, contractInfo.Service)
  266. contractInfo.PermissionLookList = permissionLookList
  267. }
  268. //查询最近一次审批单信息
  269. lastApprovalInfo, err := contract_approval.GetLastContractApprovalByContractId(contractInfo.ContractId, "contract")
  270. if err != nil {
  271. if err.Error() != utils.ErrNoRow() {
  272. err = errors.New("获取最近一次审批单信息失败,ERR:" + err.Error())
  273. }
  274. err = nil
  275. return
  276. }
  277. if lastApprovalInfo != nil {
  278. //审批操作权限,上传签回文件权限
  279. tmpContractOpButton, tmpFlowNodeListResp, tmpErr := GetOpButton(contractInfo, lastApprovalInfo, opUser)
  280. if tmpErr != nil {
  281. err = errors.New("获取合同按钮权限、审批流程失败,ERR:" + tmpErr.Error())
  282. return
  283. }
  284. opButton = tmpContractOpButton
  285. flowNodeListResp = tmpFlowNodeListResp
  286. }
  287. return
  288. }
  289. // GetProductCelData 获取品种列数据(因为前端可以随意插入列数据,所以需要根据列名来搜索对应的品种列)
  290. func GetProductCelData(detail contract_service_detail.ContractServiceDetail, tableCel *contractReq.AddContractServiceDetailReq) (err error) {
  291. t := reflect.TypeOf(detail)
  292. v := reflect.ValueOf(detail)
  293. for k := 0; k < t.NumField(); k++ {
  294. //获取结构体的参数名
  295. tmpName := t.Field(k).Name
  296. if strings.Contains(tmpName, "Col") {
  297. //获取结构体该参数名的值
  298. tmpValue := v.Field(k).String()
  299. //如果值不为空的话,那么做下json转换
  300. if tmpValue != "" {
  301. tmpErr := json.Unmarshal([]byte(tmpValue), tableCel)
  302. if tmpErr != nil {
  303. err = tmpErr
  304. continue
  305. }
  306. if tableCel.HeadName == "品种" {
  307. err = nil
  308. return
  309. }
  310. }
  311. }
  312. }
  313. return
  314. }
  315. // GetPermissionByContractService 通过合同服务,获取权限集合列表
  316. func GetPermissionByContractService(productId int, serviceList []*contractCustom.ContractServiceAndDetail) (permissionList []*company_report_permission.PermissionLookList, err error) {
  317. //子权限切片集合
  318. var permissionClassifyArr []string
  319. if productId == 1 {
  320. for _, v := range utils.PermissionFiccClassifyArr {
  321. permissionClassifyArr = append(permissionClassifyArr, v)
  322. }
  323. } else {
  324. permissionClassifyArr = append(permissionClassifyArr, "权益")
  325. }
  326. //获取已经勾选的的权限
  327. checkPermissionIdMap, err := GetServicePermissionMap(serviceList)
  328. if err != nil {
  329. return
  330. }
  331. //遍历获取
  332. for _, v := range permissionClassifyArr {
  333. checkList := make([]int, 0)
  334. plist := new(company_report_permission.PermissionLookList)
  335. items, tmpErr := company_report_permission.GetPermissionLookItems(productId, v)
  336. if tmpErr != nil {
  337. err = tmpErr
  338. return
  339. }
  340. for _, n := range items {
  341. if _, ok := checkPermissionIdMap[n.ChartPermissionId]; ok {
  342. checkList = append(checkList, n.ChartPermissionId)
  343. }
  344. }
  345. plist.Items = items
  346. plist.ClassifyName = v
  347. plist.CheckList = checkList
  348. permissionList = append(permissionList, plist)
  349. }
  350. return
  351. }
  352. // GetServicePermissionMap 获取合同服务中的权限id map
  353. func GetServicePermissionMap(serviceList []*contractCustom.ContractServiceAndDetail) (checkPermissionIdMap map[int]int, err error) {
  354. checkPermissionIdMap = make(map[int]int)
  355. //获取已经勾选的的权限
  356. for _, contractService := range serviceList {
  357. //如果是权益,那么研选必要
  358. if contractService.ProductId == 2 {
  359. chartPermissionId := 31 //研 选服务
  360. checkPermissionIdMap[chartPermissionId] = chartPermissionId
  361. }
  362. //看看系统中有没有映射对应的权限,如果有的话,那么直接返回,没有那么可能是特殊服务,需要去遍历
  363. if contractService.ChartPermissionId > 0 {
  364. checkPermissionIdMap[contractService.ChartPermissionId] = contractService.ChartPermissionId
  365. continue
  366. }
  367. switch contractService.ServiceTemplateId {
  368. case 1: //ficc 大套餐
  369. for _, v := range utils.PermissionFiccClassifyArr {
  370. //大套餐中 市场策略暂时不作为勾选项
  371. if v == "市场策略" {
  372. continue
  373. }
  374. items, tmpErr := company_report_permission.GetPermissionLookItems(1, v)
  375. if tmpErr != nil {
  376. err = tmpErr
  377. return
  378. }
  379. for _, n := range items {
  380. checkPermissionIdMap[n.ChartPermissionId] = n.ChartPermissionId
  381. }
  382. }
  383. case 2: //ficc小套餐
  384. permissionValues := []string{
  385. "FICC周报", "商品双周报+线上电话会讨论会<br/>(由弘则的研究员主持线上讨论)", "数据点评",
  386. }
  387. for _, detail := range contractService.DetailList {
  388. var tableCel contractReq.AddContractServiceDetailReq
  389. tmpErr := json.Unmarshal([]byte(detail.Col1), &tableCel)
  390. if tmpErr != nil {
  391. err = tmpErr
  392. return
  393. }
  394. if strings.Contains(strings.Join(permissionValues, ","), tableCel.Value) {
  395. //获取品种列数据
  396. var tableCel2 contractReq.AddContractServiceDetailReq
  397. tmpErr := GetProductCelData(*detail, &tableCel2)
  398. if tmpErr != nil {
  399. err = tmpErr
  400. return
  401. }
  402. for _, serviceId := range tableCel2.ValueId {
  403. checkPermissionIdMap[serviceId] = serviceId
  404. }
  405. }
  406. }
  407. case 4, 5, 6: //权益大套餐
  408. permissionFiccClassifyArr := []string{"权益"}
  409. for _, v := range permissionFiccClassifyArr {
  410. items, tmpErr := company_report_permission.GetPermissionLookItems(2, v)
  411. if tmpErr != nil {
  412. err = tmpErr
  413. return
  414. }
  415. for _, n := range items {
  416. //如果是专家行业,那么 结束当前循环,进入下一循环(产品需求:专家行业不在里面)
  417. if n.ChartPermissionId == 29 {
  418. continue
  419. }
  420. checkPermissionIdMap[n.ChartPermissionId] = n.ChartPermissionId
  421. }
  422. }
  423. }
  424. }
  425. return
  426. }