weaver-work-cli 0.1.28 → 0.1.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/dist/chunks/archive-U766FTFH.js +2537 -0
  2. package/dist/chunks/archive-oa-DMWEKX3L.js +1317 -0
  3. package/dist/chunks/asset-TCR7VDEV.js +2109 -0
  4. package/dist/chunks/attachment-content-AQNX5N3S.js +23 -0
  5. package/dist/chunks/blog-EVZWGDVM.js +2157 -0
  6. package/dist/chunks/caizhilian-JOWS6SL5.js +10087 -0
  7. package/dist/chunks/calendar-5WNCV66Q.js +1195 -0
  8. package/dist/chunks/chunk-2DUV44UX.js +15606 -0
  9. package/dist/chunks/chunk-324YPTC2.js +1607 -0
  10. package/dist/chunks/chunk-65QMVWHS.js +231 -0
  11. package/dist/chunks/chunk-6V7ZLF34.js +387 -0
  12. package/dist/chunks/chunk-AC7KJWC5.js +358 -0
  13. package/dist/chunks/chunk-AJ62BGAW.js +29 -0
  14. package/dist/chunks/chunk-BUSC6UAE.js +43 -0
  15. package/dist/chunks/chunk-CVZ2JOSW.js +62 -0
  16. package/dist/chunks/chunk-D4LTJSJD.js +477 -0
  17. package/dist/chunks/chunk-EG6ZU444.js +654 -0
  18. package/dist/chunks/chunk-EZALDOQH.js +383 -0
  19. package/dist/chunks/chunk-FMPJJYYI.js +106 -0
  20. package/dist/chunks/chunk-G2JSIUWF.js +769 -0
  21. package/dist/chunks/chunk-GCG2NMWR.js +703 -0
  22. package/dist/chunks/chunk-GPMFD4RD.js +75 -0
  23. package/dist/chunks/chunk-H3WDBYJW.js +508 -0
  24. package/dist/chunks/chunk-H6XSTSLM.js +2357 -0
  25. package/dist/chunks/chunk-J7RJTZSV.js +5556 -0
  26. package/dist/chunks/chunk-LUSPKZKY.js +53 -0
  27. package/dist/chunks/chunk-NIAJ5ZCG.js +73 -0
  28. package/dist/chunks/chunk-NOODWMCL.js +584 -0
  29. package/dist/chunks/chunk-OOUTBLZ4.js +51 -0
  30. package/dist/chunks/chunk-P26ZWSKU.js +73 -0
  31. package/dist/chunks/chunk-QWY6PGL6.js +3472 -0
  32. package/dist/chunks/chunk-R2IJAK7T.js +464 -0
  33. package/dist/chunks/chunk-R7O5PUWO.js +205 -0
  34. package/dist/chunks/chunk-RCGYCOMG.js +6962 -0
  35. package/dist/chunks/chunk-VZTXRG6X.js +403 -0
  36. package/dist/chunks/chunk-WHD4XMRP.js +161 -0
  37. package/dist/chunks/chunk-YLCYX7LE.js +371 -0
  38. package/dist/chunks/chunk-ZEDWSH32.js +68 -0
  39. package/dist/chunks/continuation-2CKSBLA6.js +11 -0
  40. package/dist/chunks/continuation-HZIZRZBX.js +13 -0
  41. package/dist/chunks/continuation-NLECEJPX.js +11 -0
  42. package/dist/chunks/ebuilder-form-NJ4YK6CC.js +2276 -0
  43. package/dist/chunks/ehr-MMYN36VA.js +5241 -0
  44. package/dist/chunks/employee-SAK2QYXX.js +11 -0
  45. package/dist/chunks/esb-HIWHOU7Q.js +141 -0
  46. package/dist/chunks/fna-KBACQTA5.js +1444 -0
  47. package/dist/chunks/host-3OHS5QUX.js +21 -0
  48. package/dist/chunks/host-IG6KEH5Q.js +19 -0
  49. package/dist/chunks/host-KQL5N4HO.js +23 -0
  50. package/dist/chunks/host-LLSZQCWR.js +17 -0
  51. package/dist/chunks/hrm-LYEC67ZQ.js +244 -0
  52. package/dist/chunks/im-RN2UKAEU.js +252 -0
  53. package/dist/chunks/invoice-EEPHLAF6.js +5179 -0
  54. package/dist/chunks/jiuchuanhui-WVVZYSJE.js +1940 -0
  55. package/dist/chunks/lazy-dispatch-MDOFFL2S.js +28 -0
  56. package/dist/chunks/mail-LNQLTF6L.js +2695 -0
  57. package/dist/chunks/meeting-XSD3BDVQ.js +504 -0
  58. package/dist/chunks/msg-parse-4GSQ2WTO.js +41 -0
  59. package/dist/chunks/okr-TMWTIU2K.js +2482 -0
  60. package/dist/chunks/plan-A2FSFA7T.js +2025 -0
  61. package/dist/chunks/project-T26QLBQF.js +1361 -0
  62. package/dist/chunks/registry-2VLUAESA.js +14 -0
  63. package/dist/chunks/registry-JCFEYXOE.js +18 -0
  64. package/dist/chunks/registry-NYPYMZXG.js +16 -0
  65. package/dist/chunks/registry-Q7OQJ3SU.js +19 -0
  66. package/dist/chunks/registry-ZJMJVWFA.js +19 -0
  67. package/dist/chunks/room-recommend-UR4ZDZS6.js +20 -0
  68. package/dist/chunks/schedule-5L2PM4M6.js +24 -0
  69. package/dist/chunks/state-Y2XBP6YE.js +15 -0
  70. package/dist/chunks/workflow-TR6PG2SL.js +245 -0
  71. package/dist/cmd/argv.js +45 -0
  72. package/dist/cmd/docs/index.js +3 -3
  73. package/dist/cmd/lazy-dispatch.js +20 -0
  74. package/dist/cmd/root.js +2 -4
  75. package/dist/cmd/setup/index.js +2 -2
  76. package/dist/cmd/skills/index.js +2 -2
  77. package/dist/core/package-paths.js +47 -0
  78. package/dist/index.js +163 -7
  79. package/dist/internal/e10/auth/xiaoe.js +3 -3
  80. package/dist/internal/e10/request-runtime.js +18 -62
  81. package/dist/internal/skills/detector.js +2 -2
  82. package/dist/shortcuts/contract/data/performance-catalog.js +1306 -0
  83. package/dist/shortcuts/contract/host.js +91 -35
  84. package/dist/shortcuts/contract/index.js +213 -0
  85. package/dist/shortcuts/contract/manifest.js +928 -0
  86. package/dist/shortcuts/contract/ooxml/docx.js +295 -0
  87. package/dist/shortcuts/contract/ooxml/xlsx.js +221 -0
  88. package/dist/shortcuts/contract/ooxml/zip.js +158 -0
  89. package/dist/shortcuts/contract/operations/assistant.js +1156 -0
  90. package/dist/shortcuts/contract/operations/clause-library.js +522 -0
  91. package/dist/shortcuts/contract/operations/compare.js +193 -0
  92. package/dist/shortcuts/contract/operations/credit-page.js +34 -0
  93. package/dist/shortcuts/contract/operations/flow.js +98 -0
  94. package/dist/shortcuts/contract/operations/page.js +66 -0
  95. package/dist/shortcuts/contract/operations/performance.js +733 -0
  96. package/dist/shortcuts/contract/operations/quote.js +557 -0
  97. package/dist/shortcuts/contract/operations/recommend.js +78 -0
  98. package/dist/shortcuts/contract/operations/registry.js +18 -0
  99. package/dist/shortcuts/contract/operations/review.js +83 -0
  100. package/dist/shortcuts/contract/operations/shared.js +37 -0
  101. package/dist/shortcuts/contract/operations/upload.js +108 -0
  102. package/dist/shortcuts/contract/operations/write.js +3 -2
  103. package/dist/shortcuts/index.js +140 -40
  104. package/dist/shortcuts/invoice/host.js +2 -1
  105. package/dist/shortcuts/invoice/manifest.js +36 -12
  106. package/dist/shortcuts/invoice/operations/issuing-qys.js +132 -36
  107. package/dist/shortcuts/invoice/operations/reim-auto.js +9 -0
  108. package/dist/shortcuts/invoice/operations/reim.js +81 -5
  109. package/dist/shortcuts/invoice/operations/shared.js +12 -5
  110. package/dist/shortcuts/meeting/host.js +45 -3
  111. package/dist/shortcuts/meeting/invitation/docx.js +442 -0
  112. package/dist/shortcuts/meeting/operations/attachment-content.js +418 -0
  113. package/dist/shortcuts/meeting/operations/attachment.js +442 -0
  114. package/dist/shortcuts/meeting/operations/eb/cache.js +57 -0
  115. package/dist/shortcuts/meeting/operations/eb/catalog.js +343 -28
  116. package/dist/shortcuts/meeting/operations/eb/conflict.js +372 -11
  117. package/dist/shortcuts/meeting/operations/eb/create-flow.js +710 -0
  118. package/dist/shortcuts/meeting/operations/eb/decision.js +47 -1
  119. package/dist/shortcuts/meeting/operations/eb/factory.js +129 -11
  120. package/dist/shortcuts/meeting/operations/eb/index.js +122 -2
  121. package/dist/shortcuts/meeting/operations/eb/room-recommend.js +378 -0
  122. package/dist/shortcuts/meeting/operations/eb/room-summary.js +84 -0
  123. package/dist/shortcuts/meeting/operations/eb/schedule.js +450 -0
  124. package/dist/shortcuts/meeting/operations/from-group-chat.js +576 -0
  125. package/dist/shortcuts/meeting/operations/invitation.js +458 -0
  126. package/dist/shortcuts/meeting/operations/minute-content.js +266 -0
  127. package/dist/shortcuts/meeting/operations/pipeline.js +489 -0
  128. package/dist/shortcuts/meeting/operations/qrcode.js +131 -0
  129. package/dist/shortcuts/meeting/operations/receipts.js +1 -1
  130. package/dist/shortcuts/meeting/operations/registry.js +18 -0
  131. package/dist/shortcuts/meeting/operations/summary.js +276 -0
  132. package/dist/shortcuts/meeting/operations/task-notify.js +325 -0
  133. package/dist/shortcuts/meeting/operations.js +42 -1
  134. package/dist/shortcuts/meeting/qr/encoder.js +427 -0
  135. package/dist/shortcuts/meeting/qr/render.js +103 -0
  136. package/dist/shortcuts/workflow/index.js +3 -0
  137. package/dist/shortcuts/workflow/operations/form.js +17 -5
  138. package/dist/shortcuts/workflow/operations/read.js +13 -6
  139. package/dist/shortcuts/workflow/operations/registry.js +2 -0
  140. package/dist/shortcuts/workflow/operations/todoSmartConvert/businessRules.js +331 -0
  141. package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +133 -0
  142. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +326 -0
  143. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +113 -0
  144. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +259 -0
  145. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoListRows.js +64 -0
  146. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoOutputPlanner.js +28 -0
  147. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.aggregate.js +70 -0
  148. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +267 -0
  149. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +392 -0
  150. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +165 -0
  151. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +448 -0
  152. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +348 -0
  153. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +222 -0
  154. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +66 -0
  155. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +502 -0
  156. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +540 -0
  157. package/docs/_catalog.md +1 -0
  158. package/docs/contract.md +39 -4
  159. package/docs/invoice.md +7 -7
  160. package/docs/todo-smart-convert/README.md +171 -0
  161. package/docs/todo-smart-convert/data-contract.md +236 -0
  162. package/docs/todo-smart-convert/mock/ai-todo-query-target.json +209 -0
  163. package/docs/todo-smart-convert/subgroup-rules.md +245 -0
  164. package/package.json +3 -2
  165. package/scripts/bundle.mjs +63 -0
  166. package/scripts/package-skill.mjs +1 -1
  167. package/skill-template/business-info.json +25 -4
  168. package/skill-template/domains/jinchengda.md +16 -3
  169. package/skill-template/domains/yepiaotong.md +3 -3
  170. package/skills/weaver-e10-jinchengda/SKILL.md +111 -31
  171. package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +7 -13
  172. package/skills/weaver-e10-jinchengda/references/contract-ai-assistant.md +150 -0
  173. package/skills/weaver-e10-jinchengda/references/contract-ai-review.md +87 -0
  174. package/skills/weaver-e10-jinchengda/references/contract-clause-library-crud.md +111 -0
  175. package/skills/weaver-e10-jinchengda/references/contract-clause-recommender.md +0 -15
  176. package/skills/weaver-e10-jinchengda/references/contract-clause-reference-save.md +0 -13
  177. package/skills/weaver-e10-jinchengda/references/contract-credit-page.md +50 -0
  178. package/skills/weaver-e10-jinchengda/references/contract-disabled-capabilities.md +4 -2
  179. package/skills/weaver-e10-jinchengda/references/contract-doc-compare.md +74 -0
  180. package/skills/weaver-e10-jinchengda/references/contract-flow-launch.md +84 -0
  181. package/skills/weaver-e10-jinchengda/references/contract-performance-query.md +29 -0
  182. package/skills/weaver-e10-jinchengda/references/contract-quote-to-contract.md +28 -0
  183. package/skills/weaver-e10-jinchengda/references/contract-request-status.md +2 -21
  184. package/skills/weaver-e10-jinchengda/references/contract-request-write.md +0 -24
  185. package/skills/weaver-e10-jinchengda/references/contract-signing-subjects.md +0 -15
  186. package/skills/weaver-e10-jinchengda/references/contract-subject-create.md +0 -17
  187. package/skills/weaver-e10-jinchengda/references/contract-template-recommend.md +70 -0
  188. package/skills/weaver-e10-jinchengda/references/contract-template-selector.md +0 -15
  189. package/skills/weaver-e10-jinchengda/references/contract-workflow-discovery.md +0 -15
  190. package/skills/weaver-e10-jinchengda/references/source-manifest.json +1168 -152
  191. package/skills/weaver-e10-meeting/SKILL.md +493 -17
  192. package/skills/weaver-e10-meeting/references/meeting-change.md +4 -4
  193. package/skills/weaver-e10-meeting/references/meeting-create.md +6 -6
  194. package/skills/weaver-e10-meeting/references/meeting-eb.md +503 -27
  195. package/skills/weaver-e10-meeting/references/meeting-invitation.md +113 -0
  196. package/skills/weaver-e10-meeting/references/meeting-lifecycle.md +6 -6
  197. package/skills/weaver-e10-meeting/references/meeting-minute-file.md +425 -0
  198. package/skills/weaver-e10-meeting/references/meeting-queries.md +4 -4
  199. package/skills/weaver-e10-meeting/references/meeting-receipts-signs.md +15 -15
  200. package/skills/weaver-e10-meeting/references/meeting-verification.md +19 -11
  201. package/skills/weaver-e10-meeting.zip +0 -0
  202. package/skills/weaver-e10-workflow/SKILL.md +23 -1
  203. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +282 -0
  204. package/skills/weaver-e10-workflow/scripts/todo-summary.cjs +695 -0
  205. package/skills/weaver-e10-yepiaotong/SKILL.md +15 -11
  206. package/skills/weaver-e10-yepiaotong/references/invoice-enterprise-list.md +1 -1
  207. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +10 -7
  208. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-form-fill-rules.md +41 -14
  209. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +54 -26
  210. package/skills/weaver-e10-yepiaotong/references/invoice-personal-list.md +6 -5
  211. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +14 -11
  212. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +97 -56
  213. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +84 -60
  214. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +142 -105
  215. package/skills/weaver-e10-yepiaotong/references/reim-matching-rules.md +53 -194
  216. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +7 -7
  217. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +164 -72
  218. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +8 -2
  219. package/templates/meeting/invitation.docx +0 -0
@@ -1,13 +1,16 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { InvoiceCliError, invoiceValidationError } from '../errors.js';
2
3
  import { asNonEmptyString, assertBusinessSuccess } from './shared.js';
3
- const LEDGER_PATH = '/api/ebuilder/form/eblist/getData';
4
- const LEDGER_PAGE_ID = '1314988320430981804';
4
+ const LEDGER_PATH = '/api/ebuilder/form/list/getListDatas';
5
+ const LEDGER_LIST_ID = '1201416963938369627';
6
+ const LEDGER_PASS_ID = '1201416959744065575';
5
7
  const LEDGER_APP_ID = '846297243998732291';
6
- const LEDGER_MENU_ID = '5419015526244625718';
7
- const LEDGER_PAGE_TITLE = '5aWR57qm6ZSB5ZCI5ZCM5ZWG5ZOB5L h5oGv';
8
+ const LEDGER_MENU_ID = '5416292802968839298';
9
+ /** urlPageTitle:合同商品信息 */
10
+ const LEDGER_PAGE_TITLE = '5ZCI5ZCM5ZWG5ZOB5L+h5oGv';
8
11
  const LEDGER_PAGE_SIZE = 50;
9
12
  const LEDGER_MAX_PAGES = 40;
10
- /** 契约锁合同商品信息表:数据 key → 可读字段。 */
13
+ /** 待开票合同数据:数据 key → 可读字段。含契约锁、泛微及其他合同。 */
11
14
  export const QYS_LEDGER_FIELDS = [
12
15
  { id: '1314988311673275798', key: 'contractNo', label: '合同号', kind: 'text' },
13
16
  { id: '1314988311673275801', key: 'contractFlow', label: '合同审批流程', kind: 'relation' },
@@ -106,49 +109,136 @@ export function qysRowBlockers(row) {
106
109
  blockers.push('已废弃');
107
110
  return blockers;
108
111
  }
109
- async function fetchLedgerPage(host, pageNo, operation) {
110
- const fieldFilter = {
111
- cusMenuId: LEDGER_MENU_ID,
112
- urlPageTitle: LEDGER_PAGE_TITLE,
113
- [`appId_${LEDGER_PAGE_ID}`]: LEDGER_APP_ID,
114
- cusview: '0',
112
+ function parseSpan(value) {
113
+ if (typeof value === 'string' && value.trim().startsWith('[')) {
114
+ try {
115
+ return optionValue(JSON.parse(value));
116
+ }
117
+ catch {
118
+ return null;
119
+ }
120
+ }
121
+ return optionValue(value);
122
+ }
123
+ function cellText(data, display, key) {
124
+ const raw = data[key] !== undefined && data[key] !== null && data[key] !== '' ? data[key] : display[key];
125
+ return textValue(raw);
126
+ }
127
+ function moneyText(data, display, key) {
128
+ const text = cellText(data, display, key);
129
+ return text === null ? null : text.replace(/,/g, '');
130
+ }
131
+ /** 获取待开票合同数据:getListDatas 的 data / displayData 行,转成与旧列表相同的可读字段。 */
132
+ export function convertPendingLedgerRow(data, display = {}) {
133
+ const formDataId = textValue(data.form_data_id) ?? textValue(data.id);
134
+ if (!formDataId)
135
+ throw invoiceValidationError('ledger_row_invalid', '台账行缺少 form_data_id');
136
+ const statusText = textValue(display.data_status);
137
+ return {
138
+ formDataId,
139
+ title: textValue(data.name) ?? textValue(display.name),
140
+ dataStatus: statusText && !/^\d+$/u.test(statusText) ? statusText : null,
141
+ contractNo: cellText(data, display, 'hth'),
142
+ contractFlow: parseSpan(display.htsplcSpan),
143
+ contractCategory: cellText(data, display, 'htzl'),
144
+ productType: parseSpan(display.cplxSpan),
145
+ productTypeDetail: cellText(data, display, 'cplxmx'),
146
+ accountingCompany: parseSpan(display.hsgs_idSpan),
147
+ invoiceGroupFlag: cellText(data, display, 'kpfzbs'),
148
+ sourceFlag: cellText(data, display, 'lybs'),
149
+ flowDetailId: cellText(data, display, 'lcmxid'),
150
+ invoiceType: parseSpan(display.fplxSpan),
151
+ purchaserName: cellText(data, display, 'gmfmc'),
152
+ purchaserTaxNo: cellText(data, display, 'gmfsh'),
153
+ purchaserAddress: cellText(data, display, 'gmfdz'),
154
+ purchaserTel: cellText(data, display, 'gmfdh'),
155
+ purchaserBankName: cellText(data, display, 'gmfkhx'),
156
+ purchaserBankAccount: cellText(data, display, 'gmfkhxzh'),
157
+ invoiceItemName: cellText(data, display, 'kpmc'),
158
+ goodsName: cellText(data, display, 'spmc'),
159
+ revenueCode: cellText(data, display, 'spshflbm'),
160
+ taxRate: parseSpan(display.spslSpan),
161
+ specification: cellText(data, display, 'ggxh'),
162
+ unit: cellText(data, display, 'dw'),
163
+ quantity: cellText(data, display, 'spslkwk'),
164
+ unitPrice: moneyText(data, display, 'spdjkwk'),
165
+ amount: moneyText(data, display, 'kpje'),
166
+ uninvoicedAmount: moneyText(data, display, 'wkpje'),
167
+ invoicedAmount: moneyText(data, display, 'ykpje'),
168
+ invoicingAmount: moneyText(data, display, 'kpzje'),
169
+ amountDiffers: parseSpan(display.kpjeczcySpan),
170
+ thirdPartyPurchase: parseSpan(display.sfsfcgSpan),
171
+ invoiceNo: cellText(data, display, 'fphm'),
172
+ invoiceFlow: parseSpan(display.kplcidSpan),
173
+ invoiceDate: cellText(data, display, 'kpsj'),
174
+ discarded: parseSpan(display.sfzfSpan),
175
+ discardedDate: cellText(data, display, 'zfsj'),
176
+ contactName: cellText(data, display, 'khlxr'),
177
+ contactPhone: cellText(data, display, 'khlxdh'),
178
+ contactEmail: cellText(data, display, 'khlxyx'),
115
179
  };
116
- const result = await host.invoiceMultipartRequest({
180
+ }
181
+ async function fetchLedgerPage(host, pageNo, tableuid, operation) {
182
+ const result = await host.invoiceRequest({
117
183
  path: LEDGER_PATH,
118
- headers: { ebbusinessid: LEDGER_PAGE_ID },
119
- fields: {
120
- ...fieldFilter,
121
- filter: '[]',
122
- fieldFilter,
123
- pageFilter: { filter: {}, filterIsNull: true, esbFilter: [] },
124
- pageAppId: LEDGER_APP_ID,
125
- compId: 'e00e8244de584b369417a4fea31d7bed',
126
- pageId: LEDGER_PAGE_ID,
127
- pageNo: String(pageNo),
128
- pageSize: String(LEDGER_PAGE_SIZE),
129
- tableuid: 'a74d995bddd54a4f831551b468071632',
130
- refPluginPackageId: '933846626099339271',
131
- },
184
+ query: { passid: LEDGER_PASS_ID, cid: LEDGER_PASS_ID },
185
+ headers: { ebbusinessid: LEDGER_LIST_ID },
132
186
  operation,
187
+ body: {
188
+ current: pageNo,
189
+ pageSize: LEDGER_PAGE_SIZE,
190
+ requiredMatch: 1,
191
+ tableuid,
192
+ mapResult: '1',
193
+ recheckQuery: '1',
194
+ cusMenuId: LEDGER_MENU_ID,
195
+ urlPageTitle: LEDGER_PAGE_TITLE,
196
+ [`appId_${LEDGER_LIST_ID}`]: LEDGER_APP_ID,
197
+ searchParamData: {
198
+ searchType: '3',
199
+ quickSearchFields: {},
200
+ commonSearchFields: {},
201
+ type: 'and',
202
+ groupFields: {},
203
+ },
204
+ listId: LEDGER_LIST_ID,
205
+ isFollow: 0,
206
+ isShareToMe: 0,
207
+ filterCondition: {},
208
+ browser: 'Chrome',
209
+ },
133
210
  });
134
- assertBusinessSuccess(result, 'qys_ledger_query_failed', '契约锁开票台账查询失败');
135
- const list = result?.data?.list;
136
- if (!Array.isArray(list)) {
137
- throw new InvoiceCliError('api', 'qys_ledger_query_failed', '契约锁开票台账返回缺少 data.list', { exitCode: 1 });
211
+ assertBusinessSuccess(result, 'qys_ledger_query_failed', '获取待开票合同数据失败');
212
+ const payload = result?.data;
213
+ const dataRows = payload?.data;
214
+ const displayRows = payload?.displayData;
215
+ if (!Array.isArray(dataRows) || !Array.isArray(displayRows)) {
216
+ throw new InvoiceCliError('api', 'qys_ledger_query_failed', '获取待开票合同数据的返回缺少 data.data 或 data.displayData', { exitCode: 1 });
138
217
  }
139
- return list;
218
+ return dataRows.map((data, index) => ({
219
+ data,
220
+ display: displayRows[index] && typeof displayRows[index] === 'object' ? displayRows[index] : {},
221
+ }));
140
222
  }
141
- /** 接口返回的 count 恒为 0,只能按“本页未取满”判断结束。 */
223
+ /** total / hasMore 不可靠,按本页未取满或出现重复行结束。 */
142
224
  async function scanLedger(host, operation, visit) {
225
+ const tableuid = randomUUID().replace(/-/g, '');
226
+ const seen = new Set();
143
227
  let scanned = 0;
144
228
  for (let pageNo = 1; pageNo <= LEDGER_MAX_PAGES; pageNo += 1) {
145
- const page = await fetchLedgerPage(host, pageNo, operation);
146
- for (const raw of page) {
229
+ const page = await fetchLedgerPage(host, pageNo, tableuid, operation);
230
+ let fresh = 0;
231
+ for (const pair of page) {
232
+ const row = convertPendingLedgerRow(pair.data, pair.display);
233
+ if (seen.has(row.formDataId))
234
+ continue;
235
+ seen.add(row.formDataId);
236
+ fresh += 1;
147
237
  scanned += 1;
148
- if (visit(convertQysLedgerRow(raw)))
238
+ if (visit(row))
149
239
  return { scanned, complete: true };
150
240
  }
151
- if (page.length < LEDGER_PAGE_SIZE)
241
+ if (page.length < LEDGER_PAGE_SIZE || fresh === 0)
152
242
  return { scanned, complete: true };
153
243
  }
154
244
  return { scanned, complete: false };
@@ -198,6 +288,7 @@ export class QysLedgerGrouper {
198
288
  goodsNames: new Set(),
199
289
  taxRates: new Set(),
200
290
  specifications: new Set(),
291
+ sellerNames: new Set(),
201
292
  bankName: null,
202
293
  bankAccount: null,
203
294
  formDataIds: [],
@@ -207,6 +298,8 @@ export class QysLedgerGrouper {
207
298
  };
208
299
  this.groups.set(key, group);
209
300
  }
301
+ if (row.accountingCompany?.name)
302
+ group.sellerNames.add(row.accountingCompany.name);
210
303
  if (blocked) {
211
304
  group.blockedRows += 1;
212
305
  return;
@@ -255,6 +348,8 @@ export class QysLedgerGrouper {
255
348
  }
256
349
  if (!group.contractNo)
257
350
  warnings.push('台账行缺少合同号,无法按合同号发起开票流程');
351
+ if (group.sellerNames.size > 1)
352
+ warnings.push(`同组销售方(核算公司)不一致:${[...group.sellerNames].join('、')}`);
258
353
  if (group.invoiceTypes.size > 1)
259
354
  warnings.push(`同组发票类型不一致:${[...group.invoiceTypes].join('、')}`);
260
355
  if (group.purchaserTaxNos.size > 1)
@@ -277,6 +372,7 @@ export class QysLedgerGrouper {
277
372
  goodsNames: [...group.goodsNames],
278
373
  taxRates: [...group.taxRates],
279
374
  specifications: [...group.specifications],
375
+ sellerNames: [...group.sellerNames],
280
376
  rowCount: group.formDataIds.length,
281
377
  formDataIds: group.formDataIds,
282
378
  totalAmount: formatCents(group.amountCents),
@@ -592,9 +592,14 @@ export class InvoiceReimCandidatesListOperation {
592
592
  const includeRedReversed = input.include_red_reversed === true;
593
593
  const dateBegin = optionalEpochSeconds(input.date_begin, 'date_begin');
594
594
  const dateEnd = optionalEpochSeconds(input.date_end, 'date_end');
595
+ const consumptionBegin = optionalEpochSeconds(input.consumption_tm_begin, 'consumption_tm_begin');
596
+ const consumptionEnd = optionalEpochSeconds(input.consumption_tm_end, 'consumption_tm_end', { endOfDay: true });
595
597
  if (dateBegin !== undefined && dateEnd !== undefined && dateBegin > dateEnd) {
596
598
  throw invoiceValidationError('input_invalid', 'date_begin 不能晚于 date_end');
597
599
  }
600
+ if (consumptionBegin !== undefined && consumptionEnd !== undefined && consumptionBegin > consumptionEnd) {
601
+ throw invoiceValidationError('input_invalid', 'consumption_tm_begin 不能晚于 consumption_tm_end');
602
+ }
598
603
  const warnings = [];
599
604
  const kept = [];
600
605
  let total = 0;
@@ -616,6 +621,10 @@ export class InvoiceReimCandidatesListOperation {
616
621
  body.date_begin = dateBegin;
617
622
  if (dateEnd !== undefined)
618
623
  body.date_end = dateEnd;
624
+ if (consumptionBegin !== undefined)
625
+ body.consumption_tm_begin = consumptionBegin;
626
+ if (consumptionEnd !== undefined)
627
+ body.consumption_tm_end = consumptionEnd;
619
628
  const result = await host.invoiceRequest({ path: '/api/inc/sync', method: 'POST', body, operation: this.name });
620
629
  total = Number(result?.total ?? 0);
621
630
  const infos = Array.isArray(result?.infos) ? result.infos : [];
@@ -24,6 +24,26 @@ function optionalDate(value, name) {
24
24
  }
25
25
  return text;
26
26
  }
27
+ function formatUtcDate(date) {
28
+ const y = date.getUTCFullYear();
29
+ const m = String(date.getUTCMonth() + 1).padStart(2, '0');
30
+ const d = String(date.getUTCDate()).padStart(2, '0');
31
+ return `${y}-${m}-${d}`;
32
+ }
33
+ /** 按日历日加减,跨月、跨年按公历进位。 */
34
+ export function addCalendarDays(isoDate, offsetDays) {
35
+ const [year, month, day] = isoDate.split('-').map(Number);
36
+ return formatUtcDate(new Date(Date.UTC(year, (month ?? 1) - 1, (day ?? 1) + offsetDays)));
37
+ }
38
+ /** 东八区日历日。 */
39
+ export function shanghaiCalendarDate(offsetDays = 0, now = new Date()) {
40
+ const today = new Intl.DateTimeFormat('en-CA', { timeZone: 'Asia/Shanghai' }).format(now);
41
+ return offsetDays === 0 ? today : addCalendarDays(today, offsetDays);
42
+ }
43
+ /** 不传结束日用东八区当天;无论是否传入,发给接口前都再加 1 天。 */
44
+ function requestCreateDateEnd(value) {
45
+ return addCalendarDays(optionalDate(value, 'cusCreateDateEnd') ?? shanghaiCalendarDate(0), 1);
46
+ }
27
47
  function responseData(value) {
28
48
  return value && typeof value === 'object' && 'data' in value ? value.data : value;
29
49
  }
@@ -38,6 +58,32 @@ function resultEnvelope(value, workflowName) {
38
58
  },
39
59
  };
40
60
  }
61
+ const REQUEST_LIST_ITEM_FIELDS = [
62
+ 'requestid',
63
+ 'workflowid',
64
+ 'requestname',
65
+ 'flowStatus',
66
+ 'creatorId',
67
+ 'creatorName',
68
+ 'createTime',
69
+ ];
70
+ function projectRequestListItem(item) {
71
+ const source = item && typeof item === 'object' && !Array.isArray(item) ? item : {};
72
+ const projected = {};
73
+ for (const key of REQUEST_LIST_ITEM_FIELDS) {
74
+ if (source[key] !== undefined)
75
+ projected[key] = source[key];
76
+ }
77
+ return projected;
78
+ }
79
+ function projectRequestListResult(value) {
80
+ if (!value || typeof value !== 'object' || Array.isArray(value))
81
+ return value;
82
+ const record = value;
83
+ if (!Array.isArray(record.data))
84
+ return value;
85
+ return { ...record, data: record.data.map(projectRequestListItem) };
86
+ }
41
87
  const UNSAFE_JSON_INTEGER_ID = /("id"\s*:\s*)(-?\d{16,})(?=\s*[,}\]])/g;
42
88
  export function quoteEmployeeIdsInJsonText(text) {
43
89
  return text.replace(UNSAFE_JSON_INTEGER_ID, '$1"$2"');
@@ -177,18 +223,18 @@ export class InvoiceReimRequestsListOperation {
177
223
  async execute(input, { host }) {
178
224
  const body = {
179
225
  pageNo: integerInput(input.pageNo, 'pageNo', { min: 1, max: 10000 }),
180
- pageSize: integerInput(input.pageSize, 'pageSize', { min: 1, max: 200, defaultValue: 20 }),
226
+ pageSize: integerInput(input.pageSize, 'pageSize', { min: 1, max: 200, defaultValue: 100 }),
181
227
  };
182
228
  for (const [key, value] of Object.entries({
183
229
  requestname: optionalString(input.requestname, 'requestname'),
184
230
  cusCreateDateStart: optionalDate(input.cusCreateDateStart, 'cusCreateDateStart'),
185
- cusCreateDateEnd: optionalDate(input.cusCreateDateEnd, 'cusCreateDateEnd'),
231
+ cusCreateDateEnd: requestCreateDateEnd(input.cusCreateDateEnd),
186
232
  })) {
187
233
  if (value !== undefined)
188
234
  body[key] = value;
189
235
  }
190
236
  const result = await host.invoiceRequest({ path: '/api/inc/book/getRequestListByTabId', method: 'POST', body, operation: this.name });
191
- return resultEnvelope(result, 'invoice.reim.requests.list');
237
+ return resultEnvelope(projectRequestListResult(result), 'invoice.reim.requests.list');
192
238
  }
193
239
  }
194
240
  export class InvoiceReimWorkflowResolveOperation {
@@ -304,14 +350,30 @@ export class InvoiceReimEmployeeSuperiorsOperation {
304
350
  return employeeSuperiorsEnvelope(result);
305
351
  }
306
352
  }
353
+ function projectFieldSearchItems(value) {
354
+ const raw = Array.isArray(value) ? value : [];
355
+ const items = [];
356
+ const seen = new Set();
357
+ for (const item of raw) {
358
+ const record = item && typeof item === 'object' && !Array.isArray(item) ? item : {};
359
+ const id = String(record.id ?? record.value ?? '').trim();
360
+ const name = String(record.name ?? '').trim();
361
+ if (!id || !name || seen.has(id))
362
+ continue;
363
+ seen.add(id);
364
+ items.push({ id, name, value: id });
365
+ }
366
+ return items;
367
+ }
307
368
  export class InvoiceReimFieldSearchOperation {
308
369
  name = 'invoice.reim.field.search';
309
370
  async execute(input, { host }) {
371
+ const keywords = asNonEmptyString(input.keywords, 'keywords');
310
372
  const result = await host.invoiceRequest({
311
373
  path: '/api/government/formStructure/fieldRelateSearch',
312
374
  method: 'GET',
313
375
  query: {
314
- keywords: asNonEmptyString(input.keywords, 'keywords'),
376
+ keywords,
315
377
  fieldId: asNonEmptyString(input.fieldId, 'fieldId'),
316
378
  formModeType: 'wf',
317
379
  workflowId: asNonEmptyString(input.workflowId, 'workflowId'),
@@ -319,7 +381,21 @@ export class InvoiceReimFieldSearchOperation {
319
381
  },
320
382
  operation: this.name,
321
383
  });
322
- return resultEnvelope(result, 'invoice.reim.field.search');
384
+ assertBusinessSuccess(result, 'invoice.reim.field.search_failed', '搜索关联字段失败');
385
+ const items = projectFieldSearchItems(responseData(result));
386
+ const match = items.length === 0 ? 'none' : items.length === 1 ? 'unique' : 'multiple';
387
+ return {
388
+ status: 'COMPLETE',
389
+ data: {
390
+ result,
391
+ data: items,
392
+ keywords,
393
+ match,
394
+ items,
395
+ selected: match === 'unique' ? items[0] : null,
396
+ workflow: workflow(this.name, 'COMPLETE'),
397
+ },
398
+ };
323
399
  }
324
400
  }
325
401
  export class InvoiceReimFlowCreatePrepareOperation {
@@ -15,6 +15,8 @@ const LIST_FIELDS = new Set([
15
15
  'date_end',
16
16
  'create_tm_begin',
17
17
  'create_tm_end',
18
+ 'consumption_tm_begin',
19
+ 'consumption_tm_end',
18
20
  'payer_company',
19
21
  'buyer_company',
20
22
  'payer_taxno',
@@ -780,7 +782,9 @@ export async function listInvoices(input, host, flag) {
780
782
  };
781
783
  }
782
784
  /** 列表查询里 E10 只接受秒级 epoch 的时间字段(契约声明为 integer)。 */
783
- const EPOCH_FIELDS = new Set(['date_begin', 'date_end', 'create_tm_begin', 'create_tm_end']);
785
+ const EPOCH_FIELDS = new Set(['date_begin', 'date_end', 'create_tm_begin', 'create_tm_end', 'consumption_tm_begin']);
786
+ /** 日期字符串按当天 23:59:59(东八区)换算,已是秒级时间戳则原样透传。 */
787
+ const EPOCH_END_OF_DAY_FIELDS = new Set(['consumption_tm_end']);
784
788
  /** 列表查询里契约声明为 integer 的标量字段。 */
785
789
  const INTEGER_FIELDS = new Set(['page_size', 'start_pos', 'req_type', 'mask', 'mext']);
786
790
  /**
@@ -788,7 +792,7 @@ const INTEGER_FIELDS = new Set(['page_size', 'start_pos', 'req_type', 'mask', 'm
788
792
  * 同时接受 `YYYY-MM-DD`(按东八区零点换算,与 `invoice.reim.candidates.list` 一致)和已是秒级 epoch 的数字/数字串,
789
793
  * 避免把字符串日期原样透传给 `/api/inc/sync` 后被打成不透明的 400 系统错误。
790
794
  */
791
- export function epochSeconds(value, name) {
795
+ export function epochSeconds(value, name, options = {}) {
792
796
  if (typeof value === 'number') {
793
797
  if (Number.isInteger(value) && value >= 0)
794
798
  return value;
@@ -796,7 +800,8 @@ export function epochSeconds(value, name) {
796
800
  }
797
801
  const text = typeof value === 'string' ? value.trim() : '';
798
802
  if (DATE_PATTERN.test(text)) {
799
- const seconds = Math.floor(Date.parse(`${text}T00:00:00+08:00`) / 1000);
803
+ const clock = options.endOfDay ? 'T23:59:59+08:00' : 'T00:00:00+08:00';
804
+ const seconds = Math.floor(Date.parse(`${text}${clock}`) / 1000);
800
805
  if (!Number.isFinite(seconds))
801
806
  throw invoiceValidationError('input_invalid', `${name} 不是有效日期`);
802
807
  return seconds;
@@ -809,10 +814,10 @@ export function epochSeconds(value, name) {
809
814
  throw invoiceValidationError('input_invalid', `${name} 必须是 YYYY-MM-DD 或秒级时间戳`);
810
815
  }
811
816
  /** `epochSeconds` 的可选版本:undefined / null / 空串 一律视为未传。 */
812
- export function optionalEpochSeconds(value, name) {
817
+ export function optionalEpochSeconds(value, name, options = {}) {
813
818
  if (value === undefined || value === null || value === '')
814
819
  return undefined;
815
- return epochSeconds(value, name);
820
+ return epochSeconds(value, name, options);
816
821
  }
817
822
  /** 列表查询的整数标量归一:数字串转数字,非法值就地报 input_invalid 而不是透传到 E10 变成 400。 */
818
823
  function listInteger(key, value) {
@@ -827,6 +832,8 @@ function listInteger(key, value) {
827
832
  function normalizeListField(key, value) {
828
833
  if (key === 'sreim')
829
834
  return normalizeSreim(value);
835
+ if (EPOCH_END_OF_DAY_FIELDS.has(key))
836
+ return epochSeconds(value, key, { endOfDay: true });
830
837
  if (EPOCH_FIELDS.has(key))
831
838
  return epochSeconds(value, key);
832
839
  if (INTEGER_FIELDS.has(key))
@@ -110,6 +110,46 @@ export function createMeetingHost(ctx, dependencies = {}) {
110
110
  await ensureSession();
111
111
  return sessionContext;
112
112
  }
113
+ async function download(request) {
114
+ const session = await ensureSession();
115
+ const url = new URL(request.path, session.getBaseUrl());
116
+ for (const [key, value] of Object.entries(request.query ?? {})) {
117
+ if (value !== undefined && value !== null && String(value) !== '')
118
+ url.searchParams.set(key, String(value));
119
+ }
120
+ const controller = new AbortController();
121
+ const timer = setTimeout(() => controller.abort(), request.timeoutMs ?? 60_000);
122
+ try {
123
+ const response = await (dependencies.fetch || globalThis.fetch)(url.toString(), {
124
+ headers: {
125
+ accept: '*/*',
126
+ cookie: session.cookieHeader(),
127
+ eteamsid: session.eteamsId,
128
+ 'user-agent': session.uaHeader(),
129
+ origin: session.getBaseUrl(),
130
+ },
131
+ redirect: 'manual',
132
+ signal: controller.signal,
133
+ });
134
+ if (response.status === 401 || response.status === 302) {
135
+ throw meetingAuthError('session_expired', '登录态已失效:下载需有效登录态,请重新登录后重试', { httpStatus: response.status });
136
+ }
137
+ if (response.status !== 200) {
138
+ throw new MeetingCliError('api', 'download_failed', `下载失败 HTTP ${response.status}`, {
139
+ code: response.status,
140
+ exitCode: 1,
141
+ });
142
+ }
143
+ return {
144
+ buffer: Buffer.from(await response.arrayBuffer()),
145
+ contentType: response.headers.get('content-type') ?? '',
146
+ contentDisposition: response.headers.get('content-disposition') ?? '',
147
+ };
148
+ }
149
+ finally {
150
+ clearTimeout(timer);
151
+ }
152
+ }
113
153
  async function runtime() {
114
154
  return createE10RequestRuntime(ctx, await ensureSession(), {
115
155
  interceptors: dependencies.interceptors,
@@ -117,12 +157,12 @@ export function createMeetingHost(ctx, dependencies = {}) {
117
157
  });
118
158
  }
119
159
  async function request(request) {
120
- const { method, path, query, body, operation, headers: extraHeaders = {}, timeoutMs = 30_000 } = request;
160
+ const { method, path, query, body, formData, operation, headers: extraHeaders = {}, timeoutMs = 30_000 } = request;
121
161
  assertPath(path);
122
162
  // 标准版会议接口硬性约定(standalone skill 实测):不能带 workflow 专用头
123
163
  // (Referer: /workflow/newflow 等),否则 400 系统错误;等价于 standalone
124
164
  // 执行器的 --simple-header(仅 Content-Type + Cookie,由 runtime 托管)。
125
- const resolvedMethod = method || (body === undefined ? 'GET' : 'POST');
165
+ const resolvedMethod = method || (body === undefined && formData === undefined ? 'GET' : 'POST');
126
166
  let response;
127
167
  try {
128
168
  response = await (await runtime()).requestJson({
@@ -132,6 +172,8 @@ export function createMeetingHost(ctx, dependencies = {}) {
132
172
  path,
133
173
  query: omitEmptyQueryValues(query),
134
174
  body,
175
+ // 文件上传:multipart 体由 runtime 直接交给 fetch(不设 Content-Type,交给 fetch 生成 boundary)
176
+ ...(formData ? { formData } : {}),
135
177
  headers: { ...extraHeaders },
136
178
  // 会议接口存在裸数字长 ID(如 meetingExtend.mtId / creater),超 2^53 会被
137
179
  // JSON.parse 舍入;开启大整数保护后按字符串保留,保证 ID 回查不失真。
@@ -181,5 +223,5 @@ export function createMeetingHost(ctx, dependencies = {}) {
181
223
  }
182
224
  return response.value;
183
225
  }
184
- return { request, getSession };
226
+ return { request, getSession, download };
185
227
  }