test-personnel-fields-20261012.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /**
  2. * 2026-10-12 人员新字段:档案保存、服刑暂停、死亡登记审批回读。
  3. * 暂停测完会恢复发放。死亡登记使用新建的「字段联测勿发放」,不改在册实发人员。
  4. */
  5. const http = require('http')
  6. function req(method, path, body) {
  7. return new Promise((resolve, reject) => {
  8. const data = body ? JSON.stringify(body) : null
  9. const headers = { 'Content-Type': 'application/json' }
  10. if (data) headers['Content-Length'] = Buffer.byteLength(data)
  11. const r = http.request({ hostname: '127.0.0.1', port: 8088, path: '/sjnmtybt' + path, method, headers }, (res) => {
  12. let buf = ''
  13. res.on('data', (c) => (buf += c))
  14. res.on('end', () => {
  15. try { resolve(JSON.parse(buf)) } catch (e) { reject(new Error(buf.slice(0, 400))) }
  16. })
  17. })
  18. r.on('error', reject)
  19. if (data) r.write(data)
  20. r.end()
  21. })
  22. }
  23. function idCard() {
  24. const body = '31011719500101' + String(100 + Math.floor(Math.random() * 800)).padStart(3, '0')
  25. const w = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  26. const m = '10X98765432'
  27. let s = 0
  28. for (let i = 0; i < 17; i++) s += Number(body[i]) * w[i]
  29. return body + m[s % 11]
  30. }
  31. function assert(cond, msg, extra) {
  32. if (!cond) {
  33. console.error('FAIL', msg, extra == null ? '' : JSON.stringify(extra))
  34. process.exitCode = 1
  35. } else {
  36. console.log('OK', msg)
  37. }
  38. }
  39. async function getPerson(id) {
  40. const j = await req('GET', '/api/personnel/' + encodeURIComponent(id))
  41. if (j.code !== 200) throw new Error('get ' + id + ' ' + (j.message || j.msg))
  42. return j.data
  43. }
  44. async function main() {
  45. const base = await getPerson('P33040')
  46. console.log('pauseTarget', base.id, base.name, base.bizStatus, base.updateTime)
  47. const saved = await req('POST', '/api/personnel', {
  48. id: base.id,
  49. name: base.name,
  50. idNumber: base.idNumber,
  51. townId: base.townId,
  52. villageId: base.villageId,
  53. expectedUpdateTime: base.updateTime,
  54. personType: '老年农民',
  55. householdDistrict: '松江区',
  56. householdTown: '叶榭镇',
  57. householdVillage: '井凌桥村',
  58. contactName: '联测联系人',
  59. contactPhone: '13800001111',
  60. insuranceJoinDate: '2010-05-01',
  61. benefitApplyDate: '2020-01-15',
  62. urbanMedicareConfirm: '未确认',
  63. personMark: '联测标示',
  64. localOrRemote: '同城',
  65. operatorRoleKey: 'admin',
  66. })
  67. assert(saved.code === 200, '档案字段保存', saved.message)
  68. const back = await getPerson('P33040')
  69. assert(back.personType === '老年农民', '人员类型回读', back.personType)
  70. assert(back.householdDistrict === '松江区', '户籍区县回读', back.householdDistrict)
  71. assert(back.householdTown === '叶榭镇', '户籍街镇回读', back.householdTown)
  72. assert(back.householdVillage === '井凌桥村', '户籍村居委回读', back.householdVillage)
  73. assert(back.contactName === '联测联系人', '联系人回读', back.contactName)
  74. assert(back.contactPhone === '13800001111', '联系电话回读', back.contactPhone)
  75. assert(String(back.insuranceJoinDate || '').startsWith('2010-05-01'), '参保日期回读', back.insuranceJoinDate)
  76. assert(back.personMark === '联测标示', '人员标示回读', back.personMark)
  77. assert(back.localOrRemote === '同城', '同城或异地回读', back.localOrRemote)
  78. assert(back.bizStatus === 'NORMAL', '档案保存不改业务状态', back.bizStatus)
  79. const bad = await req('POST', '/api/special-biz', {
  80. personnelId: 'P33040',
  81. bizType: 'PAUSE',
  82. reason: '服刑收监',
  83. amount: 0,
  84. operator: '联测',
  85. operatorRoleKey: 'social',
  86. })
  87. assert(bad.code !== 200, '服刑暂停缺刑期被拒绝', bad.message)
  88. let pause = await req('POST', '/api/special-biz', {
  89. personnelId: 'P33040',
  90. bizType: 'PAUSE',
  91. reason: '服刑收监',
  92. sentenceStart: '2024-03-01',
  93. sentenceEnd: '2026-03-01',
  94. amount: 0,
  95. operator: '联测',
  96. operatorRoleKey: 'social',
  97. })
  98. if (pause.code !== 200 && String(pause.message || '').includes('在途')) {
  99. const pending = await req('GET', '/api/special-biz/page?bizType=PAUSE&approveStatus=' + encodeURIComponent('待分管领导审批') + '&pageNum=1&pageSize=20')
  100. const hit = ((pending.data && pending.data.list) || []).find((p) => p.personnelId === 'P33040')
  101. pause = { code: hit ? 200 : 400, data: hit, message: hit ? '复用在途暂停单' : '没有在途暂停单' }
  102. }
  103. assert(pause.code === 200 && pause.data && pause.data.id, '暂停单创建', pause.message)
  104. const pauseId = pause.data && pause.data.id
  105. const pauseOk = await req('POST', '/api/special-biz/leader-approve', {
  106. bizId: pauseId,
  107. action: 'PASS',
  108. opinion: '联测通过暂停',
  109. operator: '联测领导',
  110. })
  111. assert(pauseOk.code === 200, '暂停审批通过', pauseOk.message)
  112. const paused = await getPerson('P33040')
  113. assert(paused.bizStatus === 'PAUSED', '暂停后业务状态', paused.bizStatus)
  114. assert(String(paused.sentenceStart || '').startsWith('2024-03-01'), '刑期开始写入', paused.sentenceStart)
  115. assert(String(paused.sentenceEnd || '').startsWith('2026-03-01'), '刑期结束写入', paused.sentenceEnd)
  116. assert(String(paused.changeReason || '').includes('服刑'), '变更原因写入', paused.changeReason)
  117. const resume = await req('POST', '/api/special-biz', {
  118. personnelId: 'P33040',
  119. bizType: 'RESUME',
  120. reason: '刑期届满恢复',
  121. operator: '联测',
  122. operatorRoleKey: 'social',
  123. })
  124. assert(resume.code === 200 && resume.data && resume.data.id, '恢复单创建', resume.message)
  125. const resumeOk = await req('POST', '/api/special-biz/leader-approve', {
  126. bizId: resume.data.id,
  127. action: 'PASS',
  128. opinion: '联测通过恢复',
  129. operator: '联测领导',
  130. })
  131. assert(resumeOk.code === 200, '恢复审批通过', resumeOk.message)
  132. const restored = await getPerson('P33040')
  133. assert(restored.bizStatus === 'NORMAL' || restored.bizStatus === 'NEW', '恢复后回到在发', restored.bizStatus)
  134. assert(String(restored.sentenceStart || '').startsWith('2024-03-01'), '恢复后刑期仍保留', restored.sentenceStart)
  135. assert(String(restored.changeReason || '').includes('恢复发放'), '恢复变更原因', restored.changeReason)
  136. const card = idCard()
  137. const created = await req('POST', '/api/personnel', {
  138. name: '字段联测勿发放',
  139. idNumber: card,
  140. townId: base.townId,
  141. villageId: base.villageId,
  142. bizStatus: 'NORMAL',
  143. source: '字段联测',
  144. retireQualifyType: 'WITHOUT_LAND',
  145. operatorRoleKey: 'admin',
  146. householdType: '农业',
  147. })
  148. assert(created.code === 200 && created.data && created.data.id, '新建死亡联测人员', created.message || card)
  149. const deathId = created.data && created.data.id
  150. console.log('deathTarget', deathId, card, created.data && created.data.bizStatus)
  151. const death = await req('POST', '/api/special-biz', {
  152. personnelId: deathId,
  153. bizType: 'FUNERAL',
  154. deathDate: '2026-10-02',
  155. reason: '死亡登记;死亡日期 2026-10-02;与逝者关系:子女',
  156. heirName: '联测继承人',
  157. heirIdNumber: idCard(),
  158. heirBankCard: '6222021234567890123',
  159. heirPhone: '13900002222',
  160. heirRelation: '子女',
  161. heirIdType: '居民身份证',
  162. heirBankName: '中国农业银行',
  163. heirHouseholdAddress: '上海市松江区叶榭镇联测路1号',
  164. heirAddress: '上海市松江区叶榭镇联测路2号',
  165. fileUrls: 'local://field-test-death.pdf',
  166. amount: 1,
  167. operator: '联测',
  168. operatorRoleKey: 'social',
  169. })
  170. assert(death.code === 200 && death.data && death.data.id, '死亡登记单创建', death.message)
  171. const deathOk = await req('POST', '/api/special-biz/leader-approve', {
  172. bizId: death.data && death.data.id,
  173. action: 'PASS',
  174. opinion: '联测通过死亡登记',
  175. operator: '联测领导',
  176. })
  177. assert(deathOk.code === 200, '死亡登记审批通过', deathOk.message)
  178. const dead = await getPerson(deathId)
  179. assert(dead.deathStatus === '已死亡', '死亡状态', dead.deathStatus)
  180. assert(String(dead.deathDate || '').startsWith('2026-10-02'), '死亡日期', dead.deathDate)
  181. assert(dead.cancelReason === '死亡', '注销原因', dead.cancelReason)
  182. assert(String(dead.cancelApplyDate || '').length >= 10, '注销申办日期', dead.cancelApplyDate)
  183. assert(dead.cancelDeathMonth === '202610', '注销死亡年月', dead.cancelDeathMonth)
  184. assert(dead.hasHeir === '是', '是否有继承人', dead.hasHeir)
  185. assert(dead.heirName === '联测继承人', '继承人姓名', dead.heirName)
  186. assert(dead.heirIdType === '居民身份证', '继承人证件类型', dead.heirIdType)
  187. assert(dead.heirBankName === '中国农业银行', '继承人银行名称', dead.heirBankName)
  188. assert(String(dead.heirHouseholdAddress || '').includes('联测路1号'), '继承人户籍地址', dead.heirHouseholdAddress)
  189. assert(String(dead.heirAddress || '').includes('联测路2号'), '继承人联系地址', dead.heirAddress)
  190. assert(dead.heirRelation === '子女', '与参保人关系', dead.heirRelation)
  191. console.log('deathStatusBiz', dead.bizStatus, 'cancelApply', dead.cancelApplyDate)
  192. }
  193. main().catch((e) => {
  194. console.error(e)
  195. process.exit(1)
  196. })