weaver-work-cli 0.1.26 → 0.1.29

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 (163) hide show
  1. package/README.md +7 -2
  2. package/dist/cmd/setup/index.js +1 -1
  3. package/dist/internal/e10/auth/commands.js +1 -6
  4. package/dist/internal/e10/auth/messages.js +3 -0
  5. package/dist/internal/e10/auth/session.js +8 -0
  6. package/dist/internal/e10/auth-recovery.js +148 -0
  7. package/dist/internal/e10/client.js +47 -15
  8. package/dist/internal/e10/context.js +8 -8
  9. package/dist/internal/e10/index.js +1 -0
  10. package/dist/internal/e10/request-runtime.js +51 -9
  11. package/dist/shortcuts/archive/host.js +3 -2
  12. package/dist/shortcuts/archive/manifest.js +1 -1
  13. package/dist/shortcuts/archive-oa/host.js +2 -1
  14. package/dist/shortcuts/archive-oa/manifest.js +1 -1
  15. package/dist/shortcuts/asset/host.js +7 -6
  16. package/dist/shortcuts/blog/host.js +4 -3
  17. package/dist/shortcuts/caizhilian/host.js +3 -2
  18. package/dist/shortcuts/caizhilian/manifest.js +1 -1
  19. package/dist/shortcuts/calendar/host.js +2 -1
  20. package/dist/shortcuts/contract/host.js +34 -59
  21. package/dist/shortcuts/ehr/host.js +2 -1
  22. package/dist/shortcuts/esb/host.js +2 -1
  23. package/dist/shortcuts/fna/host.js +6 -3
  24. package/dist/shortcuts/fna/manifest.js +10 -5
  25. package/dist/shortcuts/fna/operations/expense-chart.js +162 -0
  26. package/dist/shortcuts/fna/operations/registry.js +2 -0
  27. package/dist/shortcuts/hrm/host.js +2 -1
  28. package/dist/shortcuts/im/host.js +3 -2
  29. package/dist/shortcuts/invoice/host.js +9 -7
  30. package/dist/shortcuts/invoice/manifest.js +23 -142
  31. package/dist/shortcuts/invoice/operations/issuing-qys.js +266 -203
  32. package/dist/shortcuts/invoice/operations/registry.js +1 -6
  33. package/dist/shortcuts/jiuchuanhui/host.js +2 -1
  34. package/dist/shortcuts/mail/host.js +2 -1
  35. package/dist/shortcuts/meeting/host.js +2 -1
  36. package/dist/shortcuts/meeting/operations/eb/conflict.js +78 -12
  37. package/dist/shortcuts/okr/host.js +2 -1
  38. package/dist/shortcuts/plan/host.js +2 -1
  39. package/dist/shortcuts/project/host.js +2 -1
  40. package/dist/shortcuts/workflow/host.js +3 -5
  41. package/dist/shortcuts/workflow/index.js +4 -1
  42. package/dist/shortcuts/workflow/operations/chatscene.js +4 -22
  43. package/dist/shortcuts/workflow/operations/form.js +281 -166
  44. package/dist/shortcuts/workflow/operations/read.js +39 -8
  45. package/dist/shortcuts/workflow/operations/registry.js +2 -0
  46. package/dist/shortcuts/workflow/operations/todoSmartConvert/businessRules.js +331 -0
  47. package/dist/shortcuts/workflow/operations/todoSmartConvert/detailFieldRules.js +133 -0
  48. package/dist/shortcuts/workflow/operations/todoSmartConvert/summaryCache.js +326 -0
  49. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailCache.js +113 -0
  50. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoDetailFetcher.js +259 -0
  51. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoListRows.js +64 -0
  52. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoOutputPlanner.js +28 -0
  53. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.aggregate.js +70 -0
  54. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.collect.js +267 -0
  55. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.core.js +392 -0
  56. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.detail.js +165 -0
  57. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.group.js +448 -0
  58. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.groupSummary.js +348 -0
  59. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.js +222 -0
  60. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.pipeline.js +66 -0
  61. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.smartGroup.js +502 -0
  62. package/dist/shortcuts/workflow/operations/todoSmartConvert/todoSmartConvert.summary.js +540 -0
  63. package/dist/shortcuts/workflow/stdout-compact.js +7 -0
  64. package/docs/SKILL.md +1 -1
  65. package/docs/_catalog.md +2 -1
  66. package/docs/agent-invoice.md +1 -1
  67. package/docs/caizhilian.md +1 -1
  68. package/docs/e10-auth.md +1 -1
  69. package/docs/fna.md +7 -3
  70. package/docs/invoice.md +4 -6
  71. package/docs/todo-smart-convert/README.md +171 -0
  72. package/docs/todo-smart-convert/data-contract.md +236 -0
  73. package/docs/todo-smart-convert/mock/ai-todo-query-target.json +209 -0
  74. package/docs/todo-smart-convert/subgroup-rules.md +245 -0
  75. package/package.json +1 -1
  76. package/scripts/package-skill.mjs +1 -1
  77. package/skill-template/business-info.json +4 -1
  78. package/skill-template/domains/caizhilian.md +2 -1
  79. package/skill-template/domains/qiyecheng.md +1 -0
  80. package/skill-template/domains/yepiaotong.md +6 -2
  81. package/skill-template/skill-template.md +1 -0
  82. package/skills/weaver-e10-blog/SKILL.md +6 -1
  83. package/skills/weaver-e10-blog/references/blog-query.md +3 -1
  84. package/skills/weaver-e10-caizhilian/SKILL.md +18 -9
  85. package/skills/weaver-e10-caizhilian/references/action-flow.md +70 -0
  86. package/skills/weaver-e10-caizhilian/references/agent-entry.md +6 -2
  87. package/skills/weaver-e10-caizhilian/references/auth-and-install.md +207 -0
  88. package/skills/weaver-e10-caizhilian/references/file-collection.md +56 -54
  89. package/skills/weaver-e10-caizhilian/references/file-upload.md +4 -4
  90. package/skills/weaver-e10-caizhilian/references/host-executor-prompt.md +32 -0
  91. package/skills/weaver-e10-caizhilian/references/host-platform-integration.md +46 -0
  92. package/skills/weaver-e10-caizhilian/references/rule-index.md +56 -0
  93. package/skills/weaver-e10-caizhilian/references/setting-attach.md +5 -16
  94. package/skills/weaver-e10-caizhilian/references/setting-backup.md +4 -13
  95. package/skills/weaver-e10-caizhilian/references/setting-encrypt.md +6 -15
  96. package/skills/weaver-e10-caizhilian/references/setting-storage-docs-summary.md +126 -0
  97. package/skills/weaver-e10-caizhilian/references/setting-storage-field-map.md +57 -0
  98. package/skills/weaver-e10-caizhilian/references/setting-storage.md +142 -482
  99. package/skills/weaver-e10-caizhilian/references/source-manifest.json +7 -7
  100. package/skills/weaver-e10-caizhilian/references/task-workflow.md +87 -0
  101. package/skills/weaver-e10-caizhilian/references/withheld.md +2 -2
  102. package/skills/weaver-e10-caizhilian/references/write-protocol.md +7 -0
  103. package/skills/weaver-e10-calendar/SKILL.md +6 -1
  104. package/skills/weaver-e10-esb/SKILL.md +8 -0
  105. package/skills/weaver-e10-esb/references/input-format.md +3 -1
  106. package/skills/weaver-e10-esb/references/source-manifest.json +5 -5
  107. package/skills/weaver-e10-hrm/SKILL.md +6 -1
  108. package/skills/weaver-e10-hrm/references/employee.md +1 -1
  109. package/skills/weaver-e10-hrm/references/org.md +1 -1
  110. package/skills/weaver-e10-hrm/references/position.md +1 -1
  111. package/skills/weaver-e10-jinchengda/SKILL.md +2 -1
  112. package/skills/weaver-e10-jinchengda/references/contract-agent-entry.md +1 -1
  113. package/skills/weaver-e10-jiuchuanhui/SKILL.md +6 -1
  114. package/skills/weaver-e10-jucailin/SKILL.md +6 -1
  115. package/skills/weaver-e10-jucailin/references/hr-contact.md +1 -1
  116. package/skills/weaver-e10-jucailin/references/salary.md +1 -1
  117. package/skills/weaver-e10-mail/SKILL.md +6 -1
  118. package/skills/weaver-e10-meeting/SKILL.md +11 -6
  119. package/skills/weaver-e10-meeting/references/meeting-eb.md +7 -3
  120. package/skills/weaver-e10-meeting/references/meeting-queries.md +3 -1
  121. package/skills/weaver-e10-meeting/references/meeting-verification.md +4 -2
  122. package/skills/weaver-e10-okr/SKILL.md +6 -1
  123. package/skills/weaver-e10-okr/references/source-manifest.json +5 -5
  124. package/skills/weaver-e10-plan/SKILL.md +6 -1
  125. package/skills/weaver-e10-plan/references/plan-overview-and-routing.md +3 -1
  126. package/skills/weaver-e10-plan/references/plan-report-query.md +3 -1
  127. package/skills/weaver-e10-plan/references/source-manifest.json +7 -7
  128. package/skills/weaver-e10-qiyecheng/SKILL.md +16 -6
  129. package/skills/weaver-e10-qiyecheng/references/catalog.md +6 -3
  130. package/skills/weaver-e10-qiyecheng/references/expense-center.md +2 -0
  131. package/skills/weaver-e10-qiyecheng/references/expense-chart.md +78 -0
  132. package/skills/weaver-e10-qiyecheng/references/source-manifest.json +87 -33
  133. package/skills/weaver-e10-shared/SKILL.md +37 -14
  134. package/skills/weaver-e10-shared/references/e10-auth-and-session.md +11 -8
  135. package/skills/weaver-e10-shared/references/non-interactive-environment.md +4 -4
  136. package/skills/weaver-e10-shared/references/weaver-e10-installation.md +3 -1
  137. package/skills/weaver-e10-wenshuding/SKILL.md +6 -1
  138. package/skills/weaver-e10-wenshuding/references/source-manifest.json +3 -3
  139. package/skills/weaver-e10-workflow/SKILL.md +23 -1
  140. package/skills/weaver-e10-workflow/references/source-manifest.json +1 -2
  141. package/skills/weaver-e10-workflow/references/todo-smart-convert.md +282 -0
  142. package/skills/weaver-e10-workflow/references/workflow-create.md +30 -55
  143. package/skills/weaver-e10-workflow/scripts/todo-summary.cjs +695 -0
  144. package/skills/weaver-e10-yepiaotong/SKILL.md +19 -17
  145. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-examples.md +75 -78
  146. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-form-fill-rules.md +179 -0
  147. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-workflow.md +238 -0
  148. package/skills/weaver-e10-yepiaotong/references/invoice-reim.md +7 -7
  149. package/skills/weaver-e10-yepiaotong/references/reim-api-reference.md +11 -5
  150. package/skills/weaver-e10-yepiaotong/references/reim-examples.md +55 -33
  151. package/skills/weaver-e10-yepiaotong/references/reim-form-fill-rules.md +102 -23
  152. package/skills/weaver-e10-yepiaotong/references/reim-phone-subsidy-rules.md +1 -1
  153. package/skills/weaver-e10-yepiaotong/references/reim-workflow.md +53 -42
  154. package/skills/weaver-e10-yepiaotong/references/source-manifest.json +94 -214
  155. package/skills/weaver-e10-yimiaoban/SKILL.md +9 -2
  156. package/skills/weaver-e10-yimiaoban/references/file-user-i18n.md +1 -1
  157. package/skills/weaver-e10-yimiaoban/references/msg-read.md +1 -1
  158. package/skills/weaver-e10-yimiaoban/references/source-manifest.json +9 -9
  159. package/skills/weaver-e10-ziguanjia/SKILL.md +6 -1
  160. package/dist/shortcuts/invoice/operations/issuing.js +0 -198
  161. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-field-rules.md +0 -161
  162. package/skills/weaver-e10-yepiaotong/references/invoice-issuing-qys-ledger.md +0 -66
  163. package/skills/weaver-e10-yepiaotong/references/invoice-issuing.md +0 -107
@@ -1,198 +0,0 @@
1
- import { invoiceConfirmationError, invoicePartialError, invoiceValidationError, isInvoiceNetworkError } from '../errors.js';
2
- import { asNonEmptyString, asObject, assertBusinessSuccess, objectFingerprint, sessionMatches, workflow, } from './shared.js';
3
- export const SELLER_TAX_NO = '9131000070322836XD';
4
- const SELLER_NAME = '上海泛微网络科技股份有限公司';
5
- const TAX_RATES = new Set([0, 0.01, 0.03, 0.05, 0.06, 0.09, 0.13]);
6
- function optionalText(value, name) {
7
- if (value === undefined || value === null || value === '')
8
- return undefined;
9
- return asNonEmptyString(value, name);
10
- }
11
- function money(value, name) {
12
- if (typeof value === 'number') {
13
- if (!Number.isFinite(value) || value < 0)
14
- throw invoiceValidationError('input_invalid', `${name} 必须是非负金额`);
15
- return value;
16
- }
17
- if (typeof value !== 'string' || !/^\d+(?:\.\d+)?$/u.test(value)) {
18
- throw invoiceValidationError('input_invalid', `${name} 必须是非负金额`);
19
- }
20
- return value;
21
- }
22
- function taxRate(value, name) {
23
- const parsed = typeof value === 'number' ? value : Number(value);
24
- if (!Number.isFinite(parsed) || !TAX_RATES.has(parsed)) {
25
- throw invoiceValidationError('input_invalid', `${name} 必须是合法税率:0、0.01、0.03、0.05、0.06、0.09 或 0.13`);
26
- }
27
- return typeof value === 'number' ? value : String(value);
28
- }
29
- function taxNo(value, name, { required = false } = {}) {
30
- const text = optionalText(value, name);
31
- if (text === undefined) {
32
- if (required)
33
- throw invoiceValidationError('input_invalid', `${name} 必填`);
34
- return undefined;
35
- }
36
- if (!/^[0-9A-Z]{15,20}$/u.test(text)) {
37
- throw invoiceValidationError('input_invalid', `${name} 必须是 15-20 位数字或大写字母`);
38
- }
39
- return text;
40
- }
41
- export function normalizeMode(value) {
42
- if (value !== 'issue' && value !== 'ledger') {
43
- throw invoiceValidationError('input_invalid', 'mode 必须是 issue 或 ledger');
44
- }
45
- return value;
46
- }
47
- function normalizeDetail(value, index) {
48
- const detail = structuredClone(asObject(value, `payload.details[${index}]`));
49
- detail.goodsName = asNonEmptyString(detail.goodsName, `payload.details[${index}].goodsName`);
50
- detail.taxRate = taxRate(detail.taxRate, `payload.details[${index}].taxRate`);
51
- detail.amount = money(detail.amount, `payload.details[${index}].amount`);
52
- detail.amountWithTax = money(detail.amountWithTax, `payload.details[${index}].amountWithTax`);
53
- if (detail.taxAmount !== undefined)
54
- detail.taxAmount = money(detail.taxAmount, `payload.details[${index}].taxAmount`);
55
- if (detail.revenueCode !== undefined && !/^\d{4,19}$/u.test(String(detail.revenueCode))) {
56
- throw invoiceValidationError('input_invalid', `payload.details[${index}].revenueCode 必须是数字编码`);
57
- }
58
- for (const key of ['quantity', 'unitPrice', 'unit', 'specification']) {
59
- if (detail[key] !== undefined && detail[key] !== null)
60
- detail[key] = String(detail[key]);
61
- }
62
- return detail;
63
- }
64
- export function normalizeMakeInvoicePayload(rawPayload, mode) {
65
- const payload = structuredClone(asObject(rawPayload, 'payload'));
66
- const purchaserName = asNonEmptyString(payload.purchaserName, 'payload.purchaserName');
67
- const invoiceType = asNonEmptyString(payload.invoiceType, 'payload.invoiceType');
68
- if (!['7', '8', '9', '10'].includes(invoiceType)) {
69
- throw invoiceValidationError('input_invalid', 'payload.invoiceType 必须是 7、8、9 或 10');
70
- }
71
- const specialInvoice = invoiceType === '8' || invoiceType === '10';
72
- const purchaserTaxNo = taxNo(payload.purchaserTaxNo, 'payload.purchaserTaxNo', { required: specialInvoice });
73
- if (!Array.isArray(payload.details) || !payload.details.length) {
74
- throw invoiceValidationError('input_invalid', 'payload.details 必须是非空数组');
75
- }
76
- const details = payload.details.map((item, index) => normalizeDetail(item, index));
77
- const normalized = {
78
- ...payload,
79
- taxNo: SELLER_TAX_NO,
80
- sellerName: SELLER_NAME,
81
- billingType: payload.billingType || '0',
82
- invoiceType,
83
- externalDocumentNo: asNonEmptyString(payload.externalDocumentNo, 'payload.externalDocumentNo'),
84
- sourceType: payload.sourceType || '4',
85
- asyncCallFlag: payload.asyncCallFlag || '1',
86
- invoiceMethod: payload.invoiceMethod || '5',
87
- taxSign: payload.taxSign || '1',
88
- personLogo: payload.personLogo || (purchaserTaxNo ? '0' : '1'),
89
- purchaserName,
90
- details,
91
- totalAmount: money(payload.totalAmount, 'payload.totalAmount'),
92
- taxAmount: money(payload.taxAmount, 'payload.taxAmount'),
93
- totalAmountWithTax: money(payload.totalAmountWithTax, 'payload.totalAmountWithTax'),
94
- };
95
- if (purchaserTaxNo !== undefined)
96
- normalized.purchaserTaxNo = purchaserTaxNo;
97
- for (const key of ['purchaserAddress', 'purchaserTel', 'purchaserBankName', 'purchaserBankAccount', 'remark', 'invoiceDate']) {
98
- if (payload[key] !== undefined && payload[key] !== null)
99
- normalized[key] = String(payload[key]);
100
- }
101
- if (mode === 'ledger')
102
- normalized.operateType = '5';
103
- else
104
- delete normalized.operateType;
105
- return normalized;
106
- }
107
- export function makeInvoicePreview(payload, mode) {
108
- return {
109
- mode,
110
- purchaserName: payload.purchaserName,
111
- purchaserTaxNo: payload.purchaserTaxNo || '',
112
- invoiceType: payload.invoiceType,
113
- externalDocumentNo: payload.externalDocumentNo,
114
- totalAmount: payload.totalAmount,
115
- taxAmount: payload.taxAmount,
116
- totalAmountWithTax: payload.totalAmountWithTax,
117
- detailCount: Array.isArray(payload.details) ? payload.details.length : 0,
118
- };
119
- }
120
- export class InvoiceIssuingMakePrepareOperation {
121
- name = 'invoice.issuing.make.prepare';
122
- async execute(input, { host, continuation }) {
123
- const mode = normalizeMode(input.mode);
124
- const payload = normalizeMakeInvoicePayload(input.payload, mode);
125
- const session = await host.getSession();
126
- const preview = makeInvoicePreview(payload, mode);
127
- const continuationToken = await continuation.issue({
128
- operation: 'invoice.issuing.make.apply',
129
- workflow: workflow('invoice.issuing.make', 'AWAITING_CONFIRMATION'),
130
- baseUrl: session.baseUrl,
131
- profile: session.profile,
132
- userId: session.userId,
133
- mode,
134
- fingerprint: objectFingerprint(payload),
135
- preview,
136
- });
137
- return {
138
- status: 'AWAITING_CONFIRMATION',
139
- data: {
140
- preview,
141
- normalizedPayload: payload,
142
- continuation: continuationToken,
143
- expiresInSeconds: 600,
144
- workflow: workflow('invoice.issuing.make', 'AWAITING_CONFIRMATION'),
145
- },
146
- };
147
- }
148
- }
149
- export class InvoiceIssuingMakeApplyOperation {
150
- name = 'invoice.issuing.make.apply';
151
- async execute(input, { host, continuation }) {
152
- if (input.confirm !== true)
153
- throw invoiceConfirmationError('invoice.issuing.make.apply', { hint: '重新调用时传入 confirm=true' });
154
- const lease = await continuation.verify(input.continuation, 'invoice.issuing.make.apply');
155
- const mode = normalizeMode(lease.mode);
156
- const payload = normalizeMakeInvoicePayload(input.payload, mode);
157
- if (typeof lease.fingerprint !== 'string')
158
- throw invoiceValidationError('continuation_invalid', '开票 continuation 缺少 payload 指纹');
159
- if (objectFingerprint(payload) !== lease.fingerprint)
160
- throw invoiceValidationError('target_changed', '开票载荷与确认时不一致,请重新准备');
161
- const session = await host.getSession();
162
- if (!sessionMatches(lease, session))
163
- throw invoiceValidationError('context_mismatch', '确认上下文已变化,请重新准备开票');
164
- let result;
165
- try {
166
- result = await host.invoiceRequest({ path: '/api/inc/book/open/makeInvoice', method: 'POST', body: { invoiceReq: payload }, operation: this.name, timeoutMs: 90_000 });
167
- }
168
- catch (error) {
169
- if (isInvoiceNetworkError(error)) {
170
- throw invoicePartialError('开票请求发送后连接中断,结果不确定,禁止自动重试', {
171
- preview: lease.preview,
172
- workflow: workflow('invoice.issuing.make', 'EXECUTING'),
173
- }, { stage: 'issuing-make' });
174
- }
175
- throw error;
176
- }
177
- assertBusinessSuccess(result, 'issuing_make_failed', '开票或存台账失败');
178
- const data = result?.data || {};
179
- if (!data.serialNo && !data.orderNo && mode === 'issue') {
180
- throw invoicePartialError('开票接口返回成功但缺少流水号,结果不确定', {
181
- preview: lease.preview,
182
- result,
183
- workflow: workflow('invoice.issuing.make', 'VERIFYING'),
184
- }, { stage: 'issuing-make-response' });
185
- }
186
- return {
187
- status: 'COMPLETE',
188
- data: {
189
- mode,
190
- serialNo: data.serialNo,
191
- orderNo: data.orderNo,
192
- ledgerOnly: mode === 'ledger',
193
- result,
194
- workflow: workflow('invoice.issuing.make', 'COMPLETE'),
195
- },
196
- };
197
- }
198
- }
@@ -1,161 +0,0 @@
1
- # 开票字段提取规则
2
-
3
- ## 什么时候读取
4
-
5
- AI 需要从用户输入中推断税率、计算金额、校验字段格式,或判断发票类型时读取本文件。
6
-
7
- ---
8
-
9
- ## 税率推断规则
10
-
11
- ### 13% — 销售货物、有形动产租赁
12
-
13
- | 关键词 | 典型商品 |
14
- |--------|---------|
15
- | 货物/商品/材料/配件/零件 | 各类实物商品 |
16
- | 设备/机器/仪器/电子产品 | 机械设备、电器 |
17
- | 食品/饮料/酒水/药品 | 食品医药 |
18
- | 服装/家具/钢材/水泥/建材 | 服装建材 |
19
- | 动产租赁/设备租赁 | 有形动产经营租赁 |
20
-
21
- ### 9% — 建筑服务、交通运输、不动产
22
-
23
- | 关键词 | 典型服务 |
24
- |--------|---------|
25
- | 建筑/施工/装修/安装/工程 | 建筑安装 |
26
- | 运输/物流/快递/搬运 | 交通运输 |
27
- | 不动产/房屋/房租/土地 | 不动产 |
28
- | 农产品/自来水/天然气 | 农产品等 |
29
-
30
- ### 6% — 现代服务、生活服务
31
-
32
- | 关键词 | 典型服务 |
33
- |--------|---------|
34
- | 咨询/顾问/策划/技术/研发 | 咨询技术 |
35
- | 软件/系统/SaaS/信息/数据 | 信息技术 |
36
- | 设计/广告/营销/培训 | 文化创意 |
37
- | 餐饮/住宿/旅游/物业 | 生活服务 |
38
- | 会计/审计/法律/检测 | 鉴证服务 |
39
- | 金融/保险/代理/中介 | 金融经纪 |
40
-
41
- ### 3% — 小规模纳税人
42
-
43
- 用户明确说"3%"或"小规模"时使用。
44
-
45
- ### 推断优先级
46
-
47
- 1. 用户明确指定的税率 → 最高优先
48
- 2. 商品名称关键词匹配 → 按上表
49
- 3. 多关键词冲突 → 取最相关(如"建筑材料"→13% 因为是货物销售)
50
- 4. 无法确定 → 展示常见选项让用户选
51
-
52
- ### 展示格式
53
-
54
- ```
55
- 根据商品名称"{goods_name}",AI 推断:
56
- - 适用税率:{X}%
57
- 其他常见税率:13%(货物)| 9%(建筑/交通)| 6%(服务)| 3%(小规模)
58
- 如税率不正确请告知,否则将按 {X}% 计算。
59
- ```
60
-
61
- 多个明细行时每行独立推断,一次性展示所有。
62
-
63
- ---
64
-
65
- ## 金额计算规则
66
-
67
- ### 已知含税金额
68
-
69
- ```
70
- 不含税金额 = round(含税金额 / (1 + 税率), 2)
71
- 税额 = 含税金额 - 不含税金额
72
- ```
73
-
74
- ### 已知不含税金额
75
-
76
- ```
77
- 税额 = round(不含税金额 × 税率, 2)
78
- 含税金额 = 不含税金额 + 税额
79
- ```
80
-
81
- ### 单价计算
82
-
83
- ```
84
- 不含税单价 = round(不含税金额 / 数量, 合理精度)
85
- ```
86
-
87
- ### 合计
88
-
89
- ```
90
- totalAmount = sum(每行 amount)
91
- taxAmount = sum(每行 taxAmount)
92
- totalAmountWithTax = sum(每行 amountWithTax)
93
- ```
94
-
95
- ### 尾差处理
96
-
97
- ```
98
- 允许尾差 = |amountWithTax - amount - taxAmount| <= 0.06
99
- ```
100
-
101
- 超出范围提示用户核实。
102
-
103
- ---
104
-
105
- ## 校验规则
106
-
107
- | 规则 | 说明 |
108
- |------|------|
109
- | 购方名称必填 | 所有发票类型 |
110
- | 购方税号 | 专票必填;普票可选;无税号时强制普票 |
111
- | 税号格式 | 15/18/20位,数字+大写字母。正则:`^[0-9A-Z]{15}$\|^[0-9A-Z]{18}$\|^[0-9A-Z]{20}$` |
112
- | 明细至少一行 | details 不能为空 |
113
- | 税率合法性 | 0 / 0.01 / 0.03 / 0.05 / 0.06 / 0.09 / 0.13 |
114
- | 金额平衡 | amountWithTax = amount + taxAmount(允许尾差 ≤ 0.06) |
115
- | 合计平衡 | 明细行 amount 之和 = totalAmount |
116
-
117
- ---
118
-
119
- ## 购方信息提取模式
120
-
121
- | 用户表述 | 提取目标 |
122
- |---------|---------|
123
- | "给XX公司开票" / "购方XX" | purchaserName |
124
- | "税号XXXX" / "纳税人识别号XXXX" | purchaserTaxNo |
125
- | "地址:XX路XX号" | purchaserAddress |
126
- | "电话XXX" | purchaserTel |
127
- | "开户行XX银行" | purchaserBankName |
128
- | "账号XXXX" | purchaserBankAccount |
129
-
130
- ### 从文档/图片提取
131
-
132
- | 位置 | 提取目标 |
133
- |------|---------|
134
- | 合同甲方/乙方/购买方 | purchaserName |
135
- | 统一社会信用代码 | purchaserTaxNo |
136
- | 联系地址/通讯地址 | purchaserAddress |
137
- | 联系电话 | purchaserTel |
138
- | 开户银行 | purchaserBankName |
139
- | 银行账号 | purchaserBankAccount |
140
-
141
- ---
142
-
143
- ## 商品明细提取
144
-
145
- ### 从 Excel 表头匹配
146
-
147
- | 表头关键词 | 映射字段 |
148
- |-----------|---------|
149
- | 商品名称/品名/项目名称 | goods_name |
150
- | 规格/规格型号 | specification |
151
- | 单位/计量单位 | unit |
152
- | 数量 | quantity |
153
- | 单价/不含税单价 | unit_price |
154
- | 金额/不含税金额/含税金额 | amount_raw |
155
- | 税率 | tax_rate |
156
-
157
- ### externalDocumentNo 生成规则
158
-
159
- 用户未提供时自动生成:`AI-{YYYYMMDD}-{HHmmss}-{4位随机}`
160
-
161
- 用户提供合同号/订单号时优先使用。
@@ -1,66 +0,0 @@
1
- # 契约锁开票台账开票
2
-
3
- ## 什么时候读取
4
-
5
- 用户要按契约锁合同开票、按合同号开票、从“契约锁合同商品信息”台账开票,或说“把 XX 公司那份合同开了”“开一下合同 20266105541 的票”时读取本文件。用户自己口述购方、金额、明细的开票不走本文件,改读 `invoice-issuing.md`。
6
-
7
- ## Operation
8
-
9
- | 阶段 | Operation | 风险 |
10
- | --- | --- | --- |
11
- | 查询待开票台账行 | `invoice.issuing.qys.list` | read |
12
- | 按台账行组装开票入参并预览 | `invoice.issuing.qys.prepare` | read-before-write |
13
- | 确认开票或存台账 | `invoice.issuing.make.apply` | high-risk-write |
14
- | 查询异步开票结果 | `invoice.issuing.result` | read |
15
-
16
- ## 组装规则(CLI 固化,Agent 不参与计算)
17
-
18
- - 一行台账开一张发票,外部单号固定为 `QYS-{formDataId}`。
19
- - 台账“开票金额”和“商品单价”是**不含税**金额:`taxSign="0"`,税额 = 金额 × 税率(四舍五入到分),价税合计 = 金额 + 税额。
20
- - 商品名称优先取“开票名称”,为空时取“商品名称”;税率取台账“商品税率”(如 `6.0%` → 0.06)。
21
- - 发票类型取台账“发票类型”的选项 ID(如全电专票 = `8`);购方名称、税号、地址、电话、开户行、账号按台账原值透传,空值不填。
22
- - 销方固定为上海泛微网络科技股份有限公司。
23
- - 已有发票号码、已关联开票流程、开票中金额大于 0 或已废弃的行,`qys.list` 默认不返回,`qys.prepare` 直接拒绝。
24
-
25
- Agent **不得**自行修改预览里的金额、税率、税号或商品名称。用户要改,先让用户去台账改数据,再重新 `qys.prepare`。
26
-
27
- ## 对话流程
28
-
29
- 1. 用户给出合同号时传 `contractNo`;给出公司名、合同名等线索时传 `keyword`。调用 `invoice.issuing.qys.list`。
30
- 2. 命中 0 行:告诉用户没有可开票的行;如果用户坚持该合同存在,可加 `includeIssued=true` 再查一次,展示 `blockers` 说明为什么不能开。
31
- 3. 命中多行:列出合同号、合同审批流程名称、购方名称、商品、开票金额(不含税)、税率,让用户选择。不要替用户选。
32
- 4. 用户选定后调用 `invoice.issuing.qys.prepare`,`mode` 默认 `issue`;用户说“先存台账/先不开”时用 `ledger`。
33
- 5. 向用户展示预览:合同号、合同审批流程名称、购方名称、购方税号、发票类型、商品名称、税率、不含税金额、税额、价税合计。`warnings` 非空时逐条列出并询问是否仍然继续。
34
- 6. 用户明确回复“确认开票”或同义确认后,把 `normalizedPayload` 原样作为 `payload`,连同 `continuation`、`confirm=true` 调用 `invoice.issuing.make.apply`。
35
- 7. 正式开票成功后,用 `preview.externalDocumentNo` 调一次 `invoice.issuing.result`:`SUCCESS` 时展示发票号码;`PENDING` 时说明开票中、稍后再查;`FAILED` 时展示 `returnMessage`。不要循环轮询。
36
-
37
- ## 命令
38
-
39
- Windows PowerShell:
40
-
41
- ```powershell
42
- weaver-work-cli --json invoice run invoice.issuing.qys.list --input-json '{"keyword":"南昌我爱我家"}'
43
- weaver-work-cli --json invoice run invoice.issuing.qys.prepare --input-json '{"formDataId":"1328267444527472669","mode":"issue"}'
44
- weaver-work-cli --json invoice run invoice.issuing.result --input-json '{"externalDocumentNo":"QYS-1328267444527472669"}'
45
- ```
46
-
47
- macOS/Linux(bash/zsh):
48
-
49
- ```bash
50
- weaver-work-cli --json invoice run invoice.issuing.qys.list --input-json '{"keyword":"南昌我爱我家"}'
51
- weaver-work-cli --json invoice run invoice.issuing.qys.prepare --input-json '{"formDataId":"1328267444527472669","mode":"issue"}'
52
- weaver-work-cli --json invoice run invoice.issuing.result --input-json '{"externalDocumentNo":"QYS-1328267444527472669"}'
53
- ```
54
-
55
- `invoice.issuing.make.apply` 的 `payload` 较长,按 `invoice-issuing.md` 的做法先把 `{"payload":<normalizedPayload>,"continuation":"<continuation>","confirm":true}` 写入 UTF-8 JSON 文件,再用 `--input <path>` 传入。
56
-
57
- ## 输出处理
58
-
59
- - `qys.list` 返回 `items[]`(可读字段 + `issuable` + `blockers`)、`matched`、`truncated`、`scanned`、`scanComplete`。`scanComplete=false` 表示台账超过扫描上限,需提醒用户结果可能不全。
60
- - `qys.prepare` 返回 `preview`、`warnings`、`ledgerRow`、`normalizedPayload`、`continuation`。只给用户看 `preview` 和 `warnings`,不要贴完整 JSON。
61
- - `make.apply` 失败或连接中断时按 `invoice-issuing.md` 处理,**禁止自动重试**;同一台账行的外部单号固定,重复提交会被后端识别。
62
-
63
- ## 注意
64
-
65
- - 当前版本开票后不会自动回写台账的发票号码、开票时间等字段;向用户说明需要在台账侧另行处理。
66
- - 正式开票是不可逆的高风险写入;同一 continuation 只服务一次确认,用户改了台账数据必须重新 `qys.prepare`。
@@ -1,107 +0,0 @@
1
- # 智能开票与存台账
2
-
3
- ## 什么时候读取
4
-
5
- 用户要求开票、开发票、开专票、开普票、填开发票、存台账,或已经给出开票字段并要求提交到业票通时读取本文件。
6
-
7
- ## Operation
8
-
9
- | 阶段 | Operation | 风险 |
10
- | --- | --- | --- |
11
- | 准备开票或存台账 | `invoice.issuing.make.prepare` | read-before-write |
12
- | 确认提交 | `invoice.issuing.make.apply` | high-risk-write |
13
-
14
- ## 输入要点
15
-
16
- `mode` 必填:
17
-
18
- - `issue`:正式开票,CLI 会确保 `operateType` 不传。
19
- - `ledger`:仅存入待开台账,CLI 会固定 `operateType="5"`。
20
-
21
- `payload` 是已整理好的 `MakeInvoiceReqDTO`。核心字段至少包括购方名称、发票类型、外部单号、金额合计和一条商品明细。专票或全电纸质专票必须提供购方税号。
22
-
23
- ### 购方信息补齐
24
-
25
- 修正后的资料包没有提供客户档案查询 operation。组装 payload 前,Agent 只能从用户输入、附件内容或对话上下文提取购方信息;资料不足时必须追问用户补齐,不要调用 `invoice.customer.*` 或绕过 CLI 查询原始接口。
26
-
27
- - 个人普票:`invoiceType="7"`,`personLogo="1"`,无需税号。
28
- - 企业专票或需要企业抬头时:必须由用户或附件提供购方名称、税号;地址、电话、开户行和账号有明确来源时才填入,没有来源不要编造。
29
- - 从附件提取购方信息前,必须先提醒用户文件内容可能进入当前大模型上下文,并可能发送到解析服务,等待明确确认后再处理。
30
-
31
- 销方为 CLI 内置固定值(当前版本固定为销方名称 `上海泛微网络科技股份有限公司`、销方税号 `9131000070322836XD`,非按当前 E10 租户动态解析),Agent 无需也不应自行构造或改写销方字段;CLI 会一并补齐 `billingType="0"`、`sourceType="4"`、`asyncCallFlag="1"`、`invoiceMethod="5"`、`taxSign="1"`。Agent 不要把 Cookie、ETEAMSID、业务 Token 或认证字段放入 payload。
32
-
33
- ## 命令
34
-
35
- 简单 payload 可直接传 `--input-json`。
36
-
37
- Windows PowerShell:
38
-
39
- ```powershell
40
- weaver-work-cli --json invoice run invoice.issuing.make.prepare --input-json '{"mode":"ledger","payload":{"invoiceType":"8","externalDocumentNo":"AI-EXAMPLE-001","purchaserName":"XX科技有限公司","purchaserTaxNo":"91310000MA1234AB56","totalAmount":100,"taxAmount":6,"totalAmountWithTax":106,"details":[{"goodsName":"信息技术咨询服务","revenueCode":"3040205","taxRate":0.06,"amount":100,"amountWithTax":106,"taxAmount":6,"quantity":"1","unit":"项"}]}}'
41
- ```
42
-
43
- macOS/Linux(bash/zsh):
44
-
45
- ```bash
46
- weaver-work-cli --json invoice run invoice.issuing.make.prepare --input-json '{"mode":"ledger","payload":{"invoiceType":"8","externalDocumentNo":"AI-EXAMPLE-001","purchaserName":"XX科技有限公司","purchaserTaxNo":"91310000MA1234AB56","totalAmount":100,"taxAmount":6,"totalAmountWithTax":106,"details":[{"goodsName":"信息技术咨询服务","revenueCode":"3040205","taxRate":0.06,"amount":100,"amountWithTax":106,"taxAmount":6,"quantity":"1","unit":"项"}]}}'
47
- ```
48
-
49
- 复杂 payload 建议保存为 UTF-8 JSON 文件。
50
-
51
- Windows PowerShell:
52
-
53
- ```powershell
54
- Set-Content -Encoding utf8 -LiteralPath .\issuing.json -Value @'
55
- {
56
- "mode": "issue",
57
- "payload": {
58
- "invoiceType": "8",
59
- "externalDocumentNo": "AI-EXAMPLE-001",
60
- "purchaserName": "XX科技有限公司",
61
- "purchaserTaxNo": "91310000MA1234AB56",
62
- "totalAmount": 100,
63
- "taxAmount": 6,
64
- "totalAmountWithTax": 106,
65
- "details": [{"goodsName":"信息技术咨询服务","taxRate":0.06,"amount":100,"amountWithTax":106,"taxAmount":6,"quantity":"1","unit":"项"}]
66
- }
67
- }
68
- '@
69
- weaver-work-cli --json invoice run invoice.issuing.make.prepare --input .\issuing.json
70
- ```
71
-
72
- macOS/Linux(bash/zsh):
73
-
74
- ```bash
75
- cat > ./issuing.json <<'JSON'
76
- {
77
- "mode": "issue",
78
- "payload": {
79
- "invoiceType": "8",
80
- "externalDocumentNo": "AI-EXAMPLE-001",
81
- "purchaserName": "XX科技有限公司",
82
- "purchaserTaxNo": "91310000MA1234AB56",
83
- "totalAmount": 100,
84
- "taxAmount": 6,
85
- "totalAmountWithTax": 106,
86
- "details": [{"goodsName":"信息技术咨询服务","taxRate":0.06,"amount":100,"amountWithTax":106,"taxAmount":6,"quantity":"1","unit":"项"}]
87
- }
88
- }
89
- JSON
90
- weaver-work-cli --json invoice run invoice.issuing.make.prepare --input ./issuing.json
91
- ```
92
-
93
- ## 确认链
94
-
95
- `.prepare` 返回 `preview`、`normalizedPayload`、`continuation` 和 `workflow.state="AWAITING_CONFIRMATION"`。向用户展示发票类型、购方名称、税号、外部单号、明细数量、合计不含税、税额和价税合计;用户明确确认开票或存台账后,再用相同 payload、continuation 和 `confirm=true` 调用 `.apply`。
96
-
97
- ## 输出处理
98
-
99
- `.apply` 成功返回 `mode`、`serialNo`、`orderNo`、`ledgerOnly` 和原始响应。正式开票时说明申请已提交;存台账时说明已保存为待开台账。接口失败时展示业务错误原因,不自动重试。
100
-
101
- ## 注意
102
-
103
- 正式开票是高风险且不可逆的业务写入。同一 continuation 只服务一次确认场景;如果用户修改购方、金额、税率或明细,必须重新 prepare。
104
-
105
- 字段提取、税率推断和金额计算由 Agent 在调用 CLI 前完成。原始税号、金额、名称、编码等值必须逐字符保留;不要为了“补齐位数”或“格式化”改写用户或接口给出的 ID、日期和金额。
106
-
107
- 如果用户提供 Excel、Word、TXT、图片或截图来提取开票字段,解析前必须先提醒用户:文件内容可能进入当前大模型上下文,并可能发送到解析服务;必须等待明确确认。