seal.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. package seal
  2. import (
  3. "errors"
  4. "fmt"
  5. "hongze/hongze_mobile_admin/models/custom"
  6. sealResp "hongze/hongze_mobile_admin/models/response/seal"
  7. "hongze/hongze_mobile_admin/models/tables/admin"
  8. "hongze/hongze_mobile_admin/models/tables/contract"
  9. "hongze/hongze_mobile_admin/models/tables/contract_approval"
  10. "hongze/hongze_mobile_admin/models/tables/contract_approval_record"
  11. "hongze/hongze_mobile_admin/models/tables/seal"
  12. "hongze/hongze_mobile_admin/services"
  13. contractService "hongze/hongze_mobile_admin/services/contract"
  14. "hongze/hongze_mobile_admin/utils"
  15. "mime/multipart"
  16. "strings"
  17. "time"
  18. )
  19. // AddSeal 添加用印
  20. func AddSeal(userId, contractId, fileNum int, userName, use, useCompanyName, companyName, creditCode, serviceType, sealType, remark, fileUrl string) (sealInfo *seal.Seal, err error) {
  21. if !strings.Contains(strings.Join(seal.EnumUse, ","), use) {
  22. err = errors.New("用印用途异常")
  23. return
  24. }
  25. if !strings.Contains(strings.Join(seal.EnumServiceType, ","), serviceType) {
  26. err = errors.New("业务类型异常")
  27. return
  28. }
  29. sealCode, err := seal.GetSealCode()
  30. if err != nil {
  31. return
  32. }
  33. sealInfo = &seal.Seal{
  34. Code: sealCode,
  35. UserId: userId,
  36. UserName: userName,
  37. Use: use,
  38. CompanyName: companyName,
  39. UseCompanyName: useCompanyName,
  40. CreditCode: creditCode,
  41. ServiceType: serviceType,
  42. SealType: sealType,
  43. Status: "待提交",
  44. Remark: remark,
  45. FileUrl: fileUrl,
  46. FileNum: fileNum,
  47. ContractId: contractId,
  48. ModifyTime: time.Now(),
  49. CreateTime: time.Now(),
  50. }
  51. err = seal.AddSeal(sealInfo)
  52. if err != nil {
  53. err = errors.New("新增用印失败")
  54. return
  55. }
  56. // 操作日志
  57. err = seal.AddSealOperationRecord(sealInfo.SealId, userId, 0, "apply", userName, "提交审批", "")
  58. if err != nil {
  59. err = errors.New("新增用印日志失败")
  60. return
  61. }
  62. return
  63. }
  64. // Edit 修改用印
  65. func Edit(sealId, userId, contractId, fileNum int, use, companyName, userCompanyName, creditCode, serviceType, sealType, remark, fileUrl, userName string) (sealInfo *seal.Seal, err error) {
  66. if !strings.Contains(strings.Join(seal.EnumUse, ","), use) {
  67. err = errors.New("用印用途异常")
  68. return
  69. }
  70. if !strings.Contains(strings.Join(seal.EnumServiceType, ","), serviceType) {
  71. err = errors.New("业务类型异常")
  72. return
  73. }
  74. //查询当前合同信息
  75. sealInfo, err = seal.GetSealInfoById(sealId)
  76. if err != nil {
  77. if err.Error() == utils.ErrNoRow() {
  78. err = errors.New(fmt.Sprint("根据用印编号:", sealId, " 找不到该用印"))
  79. }
  80. return
  81. }
  82. if sealInfo.UserId != userId {
  83. err = errors.New("当前账号无操作权限")
  84. return
  85. }
  86. ignoreStatus := []string{"待提交", "已撤回", "已驳回"}
  87. if !strings.Contains(strings.Join(ignoreStatus, ","), sealInfo.Status) {
  88. err = errors.New("用印状态异常,不允许修改,当前用印状态:" + sealInfo.Status)
  89. return
  90. }
  91. //sealId,userId int, userName, use, companyName, creditCode, serviceType, sealType, remark, fileUrl string
  92. sealInfo.Use = use
  93. sealInfo.CompanyName = companyName
  94. sealInfo.UseCompanyName = userCompanyName
  95. sealInfo.CreditCode = creditCode
  96. sealInfo.ServiceType = serviceType
  97. sealInfo.SealType = sealType
  98. sealInfo.Remark = remark
  99. sealInfo.FileUrl = fileUrl
  100. sealInfo.FileNum = fileNum
  101. sealInfo.ContractId = contractId
  102. sealInfo.CreateTime = time.Now() // 重提更新提交时间
  103. sealInfo.ModifyTime = time.Now()
  104. sealInfo.Status = "待提交" //用印状态
  105. err = sealInfo.Update([]string{"Use", "CompanyName", "UseCompanyName", "CreditCode", "ServiceType", "SealType", "Remark", "FileUrl", "FileNum", "ContractId", "CreateTime", "ModifyTime", "Status"})
  106. if err != nil {
  107. err = errors.New("新增用印日志失败")
  108. return
  109. }
  110. // 操作日志
  111. err = seal.AddSealOperationRecord(sealInfo.SealId, userId, 0, "edit", userName, "重提审批", "")
  112. if err != nil {
  113. err = errors.New("编辑用印日志失败")
  114. return
  115. }
  116. return
  117. }
  118. // CheckEdit 审批者修改用印
  119. func CheckEdit(sealInfo *seal.Seal, approvalInfo *contract_approval.ContractApproval, approvalRecord *contract_approval_record.ContractApprovalRecord, fileNum int, fileUrl, use, sealType, remark string, opUser *custom.AdminWx) (err error) {
  120. if !strings.Contains(strings.Join(seal.EnumUse, ","), use) {
  121. err = errors.New("用印用途异常")
  122. return
  123. }
  124. //判断是否是合规账号
  125. if opUser.RoleTypeCode != utils.ROLE_TYPE_CODE_COMPLIANCE {
  126. err = errors.New("当前账号无修改权限")
  127. return
  128. }
  129. //用印状态判断
  130. if sealInfo.Status != "待审批" {
  131. err = errors.New("用印状态异常,不允许修改,当前用印状态:" + sealInfo.Status)
  132. return
  133. }
  134. //变更字段判断
  135. updateCol := make([]string, 0)
  136. updateContent := make([]string, 0)
  137. if sealInfo.Use != use {
  138. updateCol = append(updateCol, "Use")
  139. updateContent = append(updateContent, "用印用途")
  140. }
  141. if sealInfo.SealType != sealType {
  142. updateCol = append(updateCol, "SealType")
  143. updateContent = append(updateContent, "加盖何种印章")
  144. }
  145. if sealInfo.Remark != remark {
  146. updateCol = append(updateCol, "Remark")
  147. updateContent = append(updateContent, "备注")
  148. }
  149. if sealInfo.FileNum != fileNum {
  150. updateCol = append(updateCol, "FileNum")
  151. updateContent = append(updateContent, "文件份数")
  152. }
  153. if sealInfo.FileUrl != fileUrl {
  154. updateCol = append(updateCol, "FileUrl")
  155. updateContent = append(updateContent, "文件附件")
  156. }
  157. fmt.Println(updateCol)
  158. if len(updateCol) <= 0 {
  159. err = errors.New("没有变更信息")
  160. return
  161. }
  162. content := "用印修改:" + opUser.RealName + "修改了" + strings.Join(updateContent, "、")
  163. // 通过盖章类型判断是否需要变更审批流程
  164. originFlowType := GetFlowTypeBySealType(sealInfo.SealType)
  165. reqFlowType := GetFlowTypeBySealType(sealType)
  166. //如果变更了盖章类型(涉及到审批流程变更),那么需要变更审批流
  167. //变更审批流:先驳回用印申请,再修改用印,再发消息给申请人,再替申请人重新发起申请,
  168. //然后遍历审批流程,当前操作人节点之前的全部审核通过,最后通过当前操作人的节点(改成如果一级审批人如果是自己,那么直接通过这一级审批,否则不通过,让审批单重走流程)
  169. if originFlowType != reqFlowType {
  170. //先驳回
  171. err = CheckReject(sealInfo, approvalInfo, approvalRecord, opUser, "")
  172. if err != nil {
  173. return
  174. }
  175. //修改用印申请,给申请人发消息
  176. sealInfo.Use = use
  177. sealInfo.SealType = sealType
  178. sealInfo.Remark = remark
  179. sealInfo.FileNum = fileNum
  180. sealInfo.FileUrl = fileUrl
  181. sealInfo.ModifyTime = time.Now()
  182. checkEdit(sealInfo, updateCol, approvalRecord.ContractApprovalRecordId, content, opUser)
  183. //重新获取最新的用印单
  184. sealInfo, tmpErr := seal.GetSealInfoById(sealInfo.SealId)
  185. if tmpErr != nil {
  186. err = tmpErr
  187. return
  188. }
  189. //重新发起申请
  190. err = CheckApply(sealInfo, opUser)
  191. if err != nil {
  192. return
  193. }
  194. } else { //修改用印基础信息 并 审批通过
  195. //修改用印申请,给申请人发消息
  196. sealInfo.Use = use
  197. sealInfo.SealType = sealType
  198. sealInfo.Remark = remark
  199. sealInfo.FileNum = fileNum
  200. sealInfo.FileUrl = fileUrl
  201. sealInfo.ModifyTime = time.Now()
  202. checkEdit(sealInfo, updateCol, approvalRecord.ContractApprovalRecordId, content, opUser)
  203. //审核通过
  204. err = Approved(sealInfo, approvalInfo, approvalRecord, opUser, "")
  205. }
  206. return
  207. }
  208. // checkEdit 审批人修改
  209. func checkEdit(sealInfo *seal.Seal, updateCol []string, approvalRecordId int, content string, opUser *custom.AdminWx) {
  210. _ = sealInfo.Update(updateCol)
  211. // 操作日志
  212. _ = seal.AddSealOperationRecord(sealInfo.SealId, opUser.AdminId, approvalRecordId, "edit", opUser.RealName, "审批人修改信息", "")
  213. //给用印人,发送修改消息
  214. sysUserMobile := ""
  215. sysUser, _ := admin.GetAdminById(opUser.AdminId)
  216. if sysUser != nil {
  217. sysUserMobile = sysUser.Mobile
  218. }
  219. go services.AddCompanyApprovalMessage(opUser.AdminId, sealInfo.UserId, 0, approvalRecordId, 3, sourceType, 2, sealInfo.CompanyName, content, content, sysUserMobile)
  220. return
  221. }
  222. // Invalid 作废用印
  223. func Invalid(sealId int, opUser *custom.AdminWx, isInvalidContract bool) (err error) {
  224. //查询当前用印信息
  225. sealInfo, err := seal.GetSealInfoById(sealId)
  226. if err != nil {
  227. if err.Error() == utils.ErrNoRow() {
  228. err = errors.New(fmt.Sprint("根据用印编号:", sealId, " 找不到初始用印"))
  229. }
  230. return
  231. }
  232. if sealInfo.UserId != opUser.AdminId && opUser.RoleTypeCode != utils.ROLE_TYPE_CODE_COMPLIANCE {
  233. err = errors.New("当前账号无操作权限")
  234. return
  235. }
  236. if sealInfo.Status != "已审批" {
  237. err = errors.New("用印状态异常,不允许作废,当前用印状态:" + sealInfo.Status)
  238. return
  239. }
  240. //如果删除状态 >0,那么代表已经被删除了
  241. if sealInfo.IsDelete > 0 {
  242. err = errors.New("该用印已删除")
  243. return
  244. }
  245. //用印作废
  246. err = seal.Invalid(sealInfo)
  247. if err != nil {
  248. return
  249. }
  250. // 操作日志
  251. err = seal.AddSealOperationRecord(sealInfo.SealId, opUser.AdminId, 0, "invalid", opUser.RealName, "作废审批", "")
  252. if err != nil {
  253. err = errors.New("新增用印日志失败")
  254. return
  255. }
  256. //如果是系统合同,同时需要同步作废合同时,那么逻辑处理
  257. if sealInfo.ContractId > 0 && isInvalidContract {
  258. err = contractService.InvalidContract(sealInfo.ContractId, opUser)
  259. if err != nil {
  260. utils.ApiLog.Println("作废用印时,同步作废合同失败,Err:", err.Error())
  261. }
  262. }
  263. //获取最近一次提交的审批单信息
  264. contractApproval, err := contract_approval.GetLastContractApprovalByContractId(sealInfo.SealId, "seal")
  265. if err != nil {
  266. err = nil
  267. return
  268. }
  269. //如果有提测信息,那么需要给对应的审批人发送消息
  270. if contractApproval != nil {
  271. //作废后需要给审批者发送消息
  272. contractApprovalRecordList, tmpErr := contract_approval_record.GetContractApprovalRecordListByContractApprovalId(contractApproval.ContractApprovalId)
  273. if tmpErr != nil {
  274. return
  275. }
  276. content := fmt.Sprint("作废", sealInfo.CompanyName, "用印申请")
  277. for _, contractApprovalRecord := range contractApprovalRecordList {
  278. if contractApprovalRecord.NodeType == "check" { //如果是审批人,那么需要发送消息给对方
  279. //操作人信息
  280. sysUserMobile := ""
  281. sysUser, _ := admin.GetAdminById(contractApprovalRecord.ApproveUserId)
  282. if sysUser != nil {
  283. sysUserMobile = sysUser.Mobile
  284. }
  285. go services.AddCompanyApprovalMessage(opUser.AdminId, contractApprovalRecord.ApproveUserId, 0, contractApprovalRecord.ContractApprovalRecordId, 3, sourceType, 2, sealInfo.CompanyName, content, content, sysUserMobile)
  286. }
  287. }
  288. }
  289. //添加操作日志
  290. //remark := "作废合同模板"
  291. //_ = contract_operation_record.AddContractOperationRecord(nowContract.ContractId, opUser.AdminId, 0, "invalid", opUser.RealName, remark)
  292. return
  293. }
  294. // UploadCheckBackFileByFile 上传签回用印附件(实际操作)
  295. func UploadCheckBackFileByFile(sealId int, ext string, fileMulti multipart.File, opUser *custom.AdminWx) (sealInfo *seal.Seal, err error) {
  296. //查询当前用印信息
  297. sealInfo, err = seal.GetSealInfoById(sealId)
  298. if err != nil {
  299. return
  300. }
  301. //用印状态判断
  302. if sealInfo.Status != "已审批" && sealInfo.Status != "已签回" {
  303. err = errors.New("用印状态异常,不允许上传签回用印附件,当前用印状态:" + sealInfo.Status)
  304. return
  305. }
  306. fileName := ``
  307. //保存的文件名
  308. fileName = sealInfo.CompanyName + "_" + sealInfo.Code + "(签回)"
  309. if sealInfo.ContractId > 0 {
  310. //获取合同信息
  311. contractInfo, tmpErr := contract.GetContractById(sealInfo.ContractId)
  312. if tmpErr != nil {
  313. err = tmpErr
  314. return
  315. }
  316. //保存的文件名
  317. fileName = contractInfo.CompanyName + "_" + contractInfo.ContractCode + "(签回)"
  318. }
  319. //非正式环境下,文件名上面还是加上随机数
  320. if utils.RunMode != "release" {
  321. fileName += "_" + utils.GetRandStringNoSpecialChar(10)
  322. }
  323. fileName += ext
  324. //上传到阿里云
  325. resourceUrl, err := services.UploadToOssAndFileName(fileMulti, fileName)
  326. if err != nil {
  327. err = errors.New("文件保存失败,Err:" + err.Error())
  328. return
  329. }
  330. sealInfo.CheckBackFileUrl = resourceUrl
  331. sealInfo.Status = "已签回"
  332. sealInfo.ModifyTime = time.Now()
  333. sealInfo.CheckBackFileTime = time.Now()
  334. err = sealInfo.Update([]string{"CheckBackFileUrl", "Status", "ModifyTime", "CheckBackFileTime"})
  335. if err != nil {
  336. return
  337. }
  338. return
  339. }
  340. // UploadCheckBackFile 上传签回用印附件(实际操作)
  341. func UploadCheckBackFile(sealId int, fileUrl string, opUser *custom.AdminWx) (sealInfo *seal.Seal, err error) {
  342. //查询当前用印信息
  343. sealInfo, err = seal.GetSealInfoById(sealId)
  344. if err != nil {
  345. return
  346. }
  347. //用印状态判断
  348. if sealInfo.Status != "已审批" && sealInfo.Status != "已签回" {
  349. err = errors.New("用印状态异常,不允许上传签回用印附件,当前用印状态:" + sealInfo.Status)
  350. return
  351. }
  352. sealInfo.CheckBackFileUrl = fileUrl
  353. sealInfo.Status = "已签回"
  354. sealInfo.ModifyTime = time.Now()
  355. sealInfo.CheckBackFileTime = time.Now()
  356. err = sealInfo.Update([]string{"CheckBackFileUrl", "Status", "ModifyTime", "CheckBackFileTime"})
  357. if err != nil {
  358. return
  359. }
  360. return
  361. }
  362. // GetOpButton 获取审批流和权限
  363. func GetOpButton(sealInfo *seal.Seal, contractApprovalInfo *contract_approval.ContractApproval, opUser *custom.AdminWx) (sealOpButton sealResp.OpButton, flowNodeListResp [][]contract_approval_record.ContractApprovalRecord, err error) {
  364. //审批流
  365. approvalRecordList, err := contract_approval_record.GetContractApprovalRecordListByContractApprovalId(contractApprovalInfo.ContractApprovalId)
  366. if err != nil {
  367. err = errors.New("获取审批失败,Err:" + err.Error())
  368. return
  369. }
  370. //待审批状态下,如果是自己发起的审批单,同时已经经过了一轮审批,那么标记为处理中
  371. if contractApprovalInfo.Status == "待审批" {
  372. if contractApprovalInfo.ApplyUserId == opUser.AdminId && contractApprovalInfo.CurrNodeId > contractApprovalInfo.StartNodeId {
  373. sealInfo.Status = "处理中"
  374. }
  375. }
  376. flowNodeMap := make(map[int][]contract_approval_record.ContractApprovalRecord, 0)
  377. keySort := make([]int, 0)
  378. for _, approvalRecord := range approvalRecordList {
  379. //如果当前节点正好是该节点,同时审批单状态是待审批状态,然后当前账号又有权限,该账号也正是审批人,那么允许审批操作
  380. if contractApprovalInfo.CurrNodeId == approvalRecord.NodeId && contractApprovalInfo.Status == "待审批" {
  381. if opUser.AdminId == approvalRecord.ApproveUserId && approvalRecord.NodeType == "check" {
  382. sealOpButton.Approval = true
  383. }
  384. //合规在审批过程中具有 部分修改权限
  385. if opUser.AdminId == approvalRecord.ApproveUserId && opUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE && approvalRecord.NodeType == "check" {
  386. sealOpButton.CheckEdit = true
  387. }
  388. }
  389. //如果当前节点正好是该节点,同时审批单状态又是第一层节点
  390. if contractApprovalInfo.CurrNodeId == approvalRecord.NodeId && approvalRecord.PrevNodeId == 0 && contractApprovalInfo.Status == "待审批" {
  391. //发起人具有撤回审批单权限
  392. if opUser.AdminId == sealInfo.UserId {
  393. sealOpButton.Cancel = true
  394. }
  395. }
  396. if tmpFlowNodeList, ok := flowNodeMap[approvalRecord.NodeId]; ok {
  397. flowNodeMap[approvalRecord.NodeId] = append(tmpFlowNodeList, *approvalRecord)
  398. } else {
  399. tmpFlowNodeList := make([]contract_approval_record.ContractApprovalRecord, 1)
  400. tmpFlowNodeList[0] = *approvalRecord
  401. flowNodeMap[approvalRecord.NodeId] = tmpFlowNodeList
  402. keySort = append(keySort, approvalRecord.NodeId)
  403. }
  404. //待审批状态下,如果当前审批节点就是操作人,审批节点超过当前审批节点,且节点类型是抄送人,,那么标记为处理中
  405. if contractApprovalInfo.Status == "待审批" {
  406. if approvalRecord.ApproveUserId == opUser.AdminId && approvalRecord.NodeId < contractApprovalInfo.CurrNodeId && approvalRecord.NodeType != "cc" {
  407. sealInfo.Status = "处理中"
  408. }
  409. }
  410. }
  411. for _, key := range keySort {
  412. flowNodeListResp = append(flowNodeListResp, flowNodeMap[key])
  413. }
  414. //作废权限
  415. if opUser.AdminId == sealInfo.UserId && sealInfo.Status == "已审批" {
  416. sealOpButton.Invalid = true
  417. }
  418. //是否具有签回合同用印权限
  419. uploadStatus := []string{"已审批", "已签回"}
  420. if opUser.RoleTypeCode == utils.ROLE_TYPE_CODE_COMPLIANCE && strings.Contains(strings.Join(uploadStatus, ","), sealInfo.Status) {
  421. sealOpButton.UploadFile = true
  422. }
  423. //编辑权限
  424. editStatus := []string{"已驳回", "待提交", "已撤回"}
  425. if opUser.AdminId == sealInfo.UserId && strings.Contains(strings.Join(editStatus, ","), sealInfo.Status) {
  426. sealOpButton.Edit = true
  427. }
  428. return
  429. }
  430. //根据用印id获取用印详情
  431. func GetSealDetailBySealId(sealId int, opUser *custom.AdminWx) (sealInfo *seal.Seal, flowNodeListResp [][]contract_approval_record.ContractApprovalRecord, opButton sealResp.OpButton, err error) {
  432. sealInfo, err = seal.GetSealInfoById(sealId)
  433. if err != nil {
  434. err = errors.New("获取合同详情失败,ERR:" + err.Error())
  435. return
  436. }
  437. //查询最近一次审批单信息
  438. lastApprovalInfo, err := contract_approval.GetLastContractApprovalByContractId(sealInfo.SealId, "seal")
  439. if err != nil {
  440. if err.Error() != utils.ErrNoRow() {
  441. err = errors.New("获取最近一次审批单信息失败,ERR:" + err.Error())
  442. }
  443. err = nil
  444. return
  445. }
  446. if lastApprovalInfo != nil {
  447. //获取审批操作和审批流数据
  448. tmpSealOpButton, tmpFlowNodeListResp, tmpErr := GetOpButton(sealInfo, lastApprovalInfo, opUser)
  449. if tmpErr != nil {
  450. err = errors.New("获取用印按钮权限、审批流程失败,Err:" + tmpErr.Error())
  451. return
  452. }
  453. opButton = tmpSealOpButton
  454. flowNodeListResp = tmpFlowNodeListResp
  455. }
  456. return
  457. }