@chenchaolong/plugin-trade-compliance-workbench 1.0.11 → 1.0.12
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.
- package/README.md +10 -0
- package/dist/lib/catalog-import/catalog-document.parser.d.ts +18 -0
- package/dist/lib/catalog-import/catalog-document.parser.d.ts.map +1 -0
- package/dist/lib/catalog-import/catalog-document.parser.js +36 -0
- package/dist/lib/catalog-import/catalog-document.parser.js.map +1 -0
- package/dist/lib/catalog-import/catalog-import.pipeline.d.ts +30 -0
- package/dist/lib/catalog-import/catalog-import.pipeline.d.ts.map +1 -0
- package/dist/lib/catalog-import/catalog-import.pipeline.js +54 -0
- package/dist/lib/catalog-import/catalog-import.pipeline.js.map +1 -0
- package/dist/lib/catalog-import/confidence.d.ts +3 -0
- package/dist/lib/catalog-import/confidence.d.ts.map +1 -0
- package/dist/lib/catalog-import/confidence.js +52 -0
- package/dist/lib/catalog-import/confidence.js.map +1 -0
- package/dist/lib/catalog-import/contracts.d.ts +50 -0
- package/dist/lib/catalog-import/contracts.d.ts.map +1 -0
- package/dist/lib/catalog-import/contracts.js +2 -0
- package/dist/lib/catalog-import/contracts.js.map +1 -0
- package/dist/lib/catalog-import/docx.parser.d.ts +6 -0
- package/dist/lib/catalog-import/docx.parser.d.ts.map +1 -0
- package/dist/lib/catalog-import/docx.parser.js +130 -0
- package/dist/lib/catalog-import/docx.parser.js.map +1 -0
- package/dist/lib/catalog-import/header-mapping.d.ts +4 -0
- package/dist/lib/catalog-import/header-mapping.d.ts.map +1 -0
- package/dist/lib/catalog-import/header-mapping.js +34 -0
- package/dist/lib/catalog-import/header-mapping.js.map +1 -0
- package/dist/lib/catalog-import/pdf-layout.parser.d.ts +15 -0
- package/dist/lib/catalog-import/pdf-layout.parser.d.ts.map +1 -0
- package/dist/lib/catalog-import/pdf-layout.parser.js +133 -0
- package/dist/lib/catalog-import/pdf-layout.parser.js.map +1 -0
- package/dist/lib/catalog-import/pdf-table.normalizer.d.ts +4 -0
- package/dist/lib/catalog-import/pdf-table.normalizer.d.ts.map +1 -0
- package/dist/lib/catalog-import/pdf-table.normalizer.js +22 -0
- package/dist/lib/catalog-import/pdf-table.normalizer.js.map +1 -0
- package/dist/lib/catalog-import/spreadsheet.parser.d.ts +7 -0
- package/dist/lib/catalog-import/spreadsheet.parser.d.ts.map +1 -0
- package/dist/lib/catalog-import/spreadsheet.parser.js +118 -0
- package/dist/lib/catalog-import/spreadsheet.parser.js.map +1 -0
- package/dist/lib/constants.d.ts +3 -0
- package/dist/lib/constants.d.ts.map +1 -1
- package/dist/lib/constants.js +3 -0
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/entities/catalog.entity.d.ts +25 -1
- package/dist/lib/entities/catalog.entity.d.ts.map +1 -1
- package/dist/lib/entities/catalog.entity.js +94 -0
- package/dist/lib/entities/catalog.entity.js.map +1 -1
- package/dist/lib/entities/index.d.ts +2 -2
- package/dist/lib/entities/index.d.ts.map +1 -1
- package/dist/lib/entities/index.js +3 -2
- package/dist/lib/entities/index.js.map +1 -1
- package/dist/lib/entities/shared.entity.d.ts +3 -1
- package/dist/lib/entities/shared.entity.d.ts.map +1 -1
- package/dist/lib/entities/shared.entity.js +8 -0
- package/dist/lib/entities/shared.entity.js.map +1 -1
- package/dist/lib/import-jobs/import-command.builder.d.ts +4 -0
- package/dist/lib/import-jobs/import-command.builder.d.ts.map +1 -1
- package/dist/lib/import-jobs/import-command.builder.js +11 -0
- package/dist/lib/import-jobs/import-command.builder.js.map +1 -1
- package/dist/lib/import-jobs/import-job-callback.processor.d.ts.map +1 -1
- package/dist/lib/import-jobs/import-job-callback.processor.js +22 -0
- package/dist/lib/import-jobs/import-job-callback.processor.js.map +1 -1
- package/dist/lib/import-jobs/import-job.processor.d.ts.map +1 -1
- package/dist/lib/import-jobs/import-job.processor.js +32 -1
- package/dist/lib/import-jobs/import-job.processor.js.map +1 -1
- package/dist/lib/public-dto.d.ts +1 -1
- package/dist/lib/public-dto.d.ts.map +1 -1
- package/dist/lib/public-dto.js +2 -0
- package/dist/lib/public-dto.js.map +1 -1
- package/dist/lib/remote-components/trade-compliance-workbench/app.js +5 -5
- package/dist/lib/remote-ui/app-source.js +12 -0
- package/dist/lib/remote-ui/app-source.js.map +1 -1
- package/dist/lib/remote-ui/contracts.d.ts +9 -0
- package/dist/lib/remote-ui/contracts.d.ts.map +1 -1
- package/dist/lib/runtime-validation.d.ts +1 -1
- package/dist/lib/types.d.ts +26 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +3 -0
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/workbench-view.provider.d.ts +7 -0
- package/dist/lib/workbench-view.provider.d.ts.map +1 -1
- package/dist/lib/workbench-view.provider.js +1 -0
- package/dist/lib/workbench-view.provider.js.map +1 -1
- package/dist/lib/workbench.middleware.d.ts +89 -6
- package/dist/lib/workbench.middleware.d.ts.map +1 -1
- package/dist/lib/workbench.middleware.js +3 -0
- package/dist/lib/workbench.middleware.js.map +1 -1
- package/dist/lib/workbench.service.d.ts +56 -1
- package/dist/lib/workbench.service.d.ts.map +1 -1
- package/dist/lib/workbench.service.js +463 -7
- package/dist/lib/workbench.service.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -45,6 +45,16 @@ pnpm visual:check
|
|
|
45
45
|
|
|
46
46
|
该命令生成 38 张原型映射截图、9 张窄屏截图和 3 张布局契约截图,共 50 张,写入 `artifacts/visual-check/`。检查覆盖 route、页面标题、dialog、关键字段、操作列策略、184/56px 侧栏、内部滚动、首页八步四列流程、按钮图标,以及页面和控件的溢出、重叠问题。
|
|
47
47
|
|
|
48
|
+
### 目录解析样本验证
|
|
49
|
+
|
|
50
|
+
混合目录管线对 XLS/XLSX、结构化 DOCX 和带文本表格层的 PDF 使用代码解析;无法验证的局部来源块进入 ChatKit/人工复核,旧 DOC、图片和扫描 PDF 回退兼容模式。可使用明确提供的样本路径运行只读验证:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pnpm verify:catalog-samples -- "/path/to/controlled-catalog.pdf" "/path/to/sanction-catalog.docx"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
命令会先构建插件,再输出 PDF schema、自动接受数、复核原因、DOCX 实体/自然人数和别名统计;不会写入数据库。
|
|
57
|
+
|
|
48
58
|
## 演示数据初始化
|
|
49
59
|
|
|
50
60
|
> 警告:以下命令会向 `XPERT_ORG_ID` 指定的真实组织写入演示业务数据和演示 XLSX 文件。请先确认目标组织,生产组织不要执行。
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { SourceFileFormat } from '../types.js';
|
|
2
|
+
import type { CatalogCandidateKind, CatalogParseResult } from './contracts.js';
|
|
3
|
+
import { type PdfCatalogParseResult } from './pdf-layout.parser.js';
|
|
4
|
+
export type ParseCatalogDocumentInput = {
|
|
5
|
+
format: SourceFileFormat;
|
|
6
|
+
kind: CatalogCandidateKind;
|
|
7
|
+
buffer: Buffer | Uint8Array;
|
|
8
|
+
};
|
|
9
|
+
export type CatalogCompatibilityResult = {
|
|
10
|
+
mode: 'COMPATIBILITY_AGENT';
|
|
11
|
+
accepted: [];
|
|
12
|
+
reviewBlocks: [];
|
|
13
|
+
skipped: [];
|
|
14
|
+
reason: 'FORMAT_REQUIRES_AGENT' | 'PDF_STRUCTURE_UNAVAILABLE' | 'DOCX_STRUCTURE_UNAVAILABLE';
|
|
15
|
+
};
|
|
16
|
+
export type CatalogDocumentParseResult = CatalogParseResult | PdfCatalogParseResult | CatalogCompatibilityResult;
|
|
17
|
+
export declare function parseCatalogDocument(input: ParseCatalogDocumentInput): Promise<CatalogDocumentParseResult>;
|
|
18
|
+
//# sourceMappingURL=catalog-document.parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-document.parser.d.ts","sourceRoot":"","sources":["../../../src/lib/catalog-import/catalog-document.parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AACnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAE9E,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAA;AAGpF,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,gBAAgB,CAAA;IACxB,IAAI,EAAE,oBAAoB,CAAA;IAC1B,MAAM,EAAE,MAAM,GAAG,UAAU,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,qBAAqB,CAAA;IAC3B,QAAQ,EAAE,EAAE,CAAA;IACZ,YAAY,EAAE,EAAE,CAAA;IAChB,OAAO,EAAE,EAAE,CAAA;IACX,MAAM,EAAE,uBAAuB,GAAG,2BAA2B,GAAG,4BAA4B,CAAA;CAC7F,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG,kBAAkB,GAAG,qBAAqB,GAAG,0BAA0B,CAAA;AAMhH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAwBhH"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { parseDocxCatalog } from './docx.parser.js';
|
|
2
|
+
import { parsePdfCatalog } from './pdf-layout.parser.js';
|
|
3
|
+
import { parseSpreadsheetCatalog } from './spreadsheet.parser.js';
|
|
4
|
+
function compatibility(reason) {
|
|
5
|
+
return { mode: 'COMPATIBILITY_AGENT', accepted: [], reviewBlocks: [], skipped: [], reason };
|
|
6
|
+
}
|
|
7
|
+
export async function parseCatalogDocument(input) {
|
|
8
|
+
if (input.format === 'XLS' || input.format === 'XLSX') {
|
|
9
|
+
return parseSpreadsheetCatalog(input);
|
|
10
|
+
}
|
|
11
|
+
if (input.format === 'DOCX') {
|
|
12
|
+
if (input.kind !== 'SANCTION')
|
|
13
|
+
return compatibility('FORMAT_REQUIRES_AGENT');
|
|
14
|
+
try {
|
|
15
|
+
return await parseDocxCatalog(input);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return compatibility('DOCX_STRUCTURE_UNAVAILABLE');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (input.format === 'PDF') {
|
|
22
|
+
if (input.kind !== 'CONTROLLED')
|
|
23
|
+
return compatibility('FORMAT_REQUIRES_AGENT');
|
|
24
|
+
try {
|
|
25
|
+
const result = await parsePdfCatalog(input.buffer);
|
|
26
|
+
return result.accepted.length > 0 || result.reviewBlocks.length > 0
|
|
27
|
+
? result
|
|
28
|
+
: compatibility('PDF_STRUCTURE_UNAVAILABLE');
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return compatibility('PDF_STRUCTURE_UNAVAILABLE');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return compatibility('FORMAT_REQUIRES_AGENT');
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=catalog-document.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-document.parser.js","sourceRoot":"","sources":["../../../src/lib/catalog-import/catalog-document.parser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,eAAe,EAA8B,MAAM,wBAAwB,CAAA;AACpF,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAA;AAkBjE,SAAS,aAAa,CAAC,MAA4C;IACjE,OAAO,EAAE,IAAI,EAAE,qBAAqB,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,CAAA;AAC7F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAgC;IACzE,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACtD,OAAO,uBAAuB,CAAC,KAAK,CAAC,CAAA;IACvC,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,OAAO,aAAa,CAAC,uBAAuB,CAAC,CAAA;QAC5E,IAAI,CAAC;YACH,OAAO,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAA;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,aAAa,CAAC,4BAA4B,CAAC,CAAA;QACpD,CAAC;IACH,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;YAAE,OAAO,aAAa,CAAC,uBAAuB,CAAC,CAAA;QAC9E,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;YAClD,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC;gBACjE,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,aAAa,CAAC,2BAA2B,CAAC,CAAA;QAChD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,aAAa,CAAC,2BAA2B,CAAC,CAAA;QACnD,CAAC;IACH,CAAC;IACD,OAAO,aAAa,CAAC,uBAAuB,CAAC,CAAA;AAC/C,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { ImportTask } from '../entities/index.js';
|
|
2
|
+
import type { RequestScope } from '../types.js';
|
|
3
|
+
import type { TradeComplianceFileStorage } from '../adapters/file-storage.js';
|
|
4
|
+
import type { TradeComplianceWorkbenchService } from '../workbench.service.js';
|
|
5
|
+
import { type CatalogDocumentParseResult, type ParseCatalogDocumentInput } from './catalog-document.parser.js';
|
|
6
|
+
type FastCatalogTask = Pick<ImportTask, 'id' | 'documentType' | 'sourceFileId' | 'sourceFileName' | 'sourceFileFormat' | 'executionInput'>;
|
|
7
|
+
type CatalogParser = (input: ParseCatalogDocumentInput) => Promise<CatalogDocumentParseResult>;
|
|
8
|
+
type FastReadyObserver = (summary: {
|
|
9
|
+
taskId: string;
|
|
10
|
+
totalCandidates: number;
|
|
11
|
+
reviewCount: number;
|
|
12
|
+
}) => Promise<void>;
|
|
13
|
+
type FastCatalogService = Pick<TradeComplianceWorkbenchService, 'beginFastCatalogImport' | 'appendFastCatalogBatch' | 'finalizeFastCatalogImport'>;
|
|
14
|
+
export declare class CatalogImportPipeline {
|
|
15
|
+
private readonly service;
|
|
16
|
+
private readonly storage;
|
|
17
|
+
private readonly parser;
|
|
18
|
+
private readonly onFastReady?;
|
|
19
|
+
constructor(service: FastCatalogService, storage: Pick<TradeComplianceFileStorage, 'read'>, parser?: CatalogParser, onFastReady?: FastReadyObserver | undefined);
|
|
20
|
+
process(scope: RequestScope, task: FastCatalogTask): Promise<{
|
|
21
|
+
kind: "COMPATIBILITY_AGENT";
|
|
22
|
+
reason: "FORMAT_REQUIRES_AGENT" | "PDF_STRUCTURE_UNAVAILABLE" | "DOCX_STRUCTURE_UNAVAILABLE";
|
|
23
|
+
} | {
|
|
24
|
+
kind: "COMPLETED";
|
|
25
|
+
reason?: undefined;
|
|
26
|
+
}>;
|
|
27
|
+
private appendBatch;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=catalog-import.pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-import.pipeline.d.ts","sourceRoot":"","sources":["../../../src/lib/catalog-import/catalog-import.pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,yBAAyB,CAAA;AAC9E,OAAO,EAAwB,KAAK,0BAA0B,EAAE,KAAK,yBAAyB,EAAE,MAAM,8BAA8B,CAAA;AAKpI,KAAK,eAAe,GAAG,IAAI,CACzB,UAAU,EACV,IAAI,GAAG,cAAc,GAAG,cAAc,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,gBAAgB,CAClG,CAAA;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,yBAAyB,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAA;AAC9F,KAAK,iBAAiB,GAAG,CAAC,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAErH,KAAK,kBAAkB,GAAG,IAAI,CAC5B,+BAA+B,EAC/B,wBAAwB,GAAG,wBAAwB,GAAG,2BAA2B,CAClF,CAAA;AAED,qBAAa,qBAAqB;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;gBAHZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,EAAE,IAAI,CAAC,0BAA0B,EAAE,MAAM,CAAC,EACjD,MAAM,GAAE,aAAoC,EAC5C,WAAW,CAAC,EAAE,iBAAiB,YAAA;IAG5C,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe;;;;;;;YA0C1C,WAAW;CAkB1B"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { parseCatalogDocument } from './catalog-document.parser.js';
|
|
2
|
+
const FAST_BATCH_SIZE = 100;
|
|
3
|
+
export class CatalogImportPipeline {
|
|
4
|
+
constructor(service, storage, parser = parseCatalogDocument, onFastReady) {
|
|
5
|
+
this.service = service;
|
|
6
|
+
this.storage = storage;
|
|
7
|
+
this.parser = parser;
|
|
8
|
+
this.onFastReady = onFastReady;
|
|
9
|
+
}
|
|
10
|
+
async process(scope, task) {
|
|
11
|
+
const kind = task.documentType === 'CONTROLLED_CATALOG' ? 'CONTROLLED' : 'SANCTION';
|
|
12
|
+
const buffer = await this.storage.read(task.sourceFileId);
|
|
13
|
+
const parsed = await this.parser({ format: task.sourceFileFormat, kind, buffer });
|
|
14
|
+
if (parsed.mode === 'COMPATIBILITY_AGENT') {
|
|
15
|
+
return { kind: 'COMPATIBILITY_AGENT', reason: parsed.reason };
|
|
16
|
+
}
|
|
17
|
+
const state = await this.service.beginFastCatalogImport(scope, {
|
|
18
|
+
taskId: task.id,
|
|
19
|
+
catalogType: task.executionInput?.catalogType,
|
|
20
|
+
replaceBatchId: task.executionInput?.replaceBatchId,
|
|
21
|
+
totalCandidates: parsed.accepted.length + parsed.reviewBlocks.length + parsed.skipped.length
|
|
22
|
+
});
|
|
23
|
+
await this.onFastReady?.({
|
|
24
|
+
taskId: task.id,
|
|
25
|
+
totalCandidates: parsed.accepted.length + parsed.reviewBlocks.length + parsed.skipped.length,
|
|
26
|
+
reviewCount: parsed.reviewBlocks.length
|
|
27
|
+
});
|
|
28
|
+
let cursor = Math.min(state.committedCursor, parsed.accepted.length);
|
|
29
|
+
if (parsed.accepted.length === 0) {
|
|
30
|
+
await this.appendBatch(scope, task.id, [], parsed.reviewBlocks, parsed.skipped, 0, 0);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
while (cursor < parsed.accepted.length) {
|
|
34
|
+
const endCursor = Math.min(cursor + FAST_BATCH_SIZE, parsed.accepted.length);
|
|
35
|
+
const finalBatch = endCursor === parsed.accepted.length;
|
|
36
|
+
await this.appendBatch(scope, task.id, parsed.accepted.slice(cursor, endCursor), finalBatch ? parsed.reviewBlocks : [], finalBatch ? parsed.skipped : [], cursor, endCursor);
|
|
37
|
+
cursor = endCursor;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
await this.service.finalizeFastCatalogImport(scope, task.id);
|
|
41
|
+
return { kind: 'COMPLETED' };
|
|
42
|
+
}
|
|
43
|
+
async appendBatch(scope, taskId, candidates, reviewBlocks, skipped, startCursor, endCursor) {
|
|
44
|
+
return this.service.appendFastCatalogBatch(scope, {
|
|
45
|
+
taskId,
|
|
46
|
+
candidates,
|
|
47
|
+
reviewBlocks,
|
|
48
|
+
skipped,
|
|
49
|
+
startCursor,
|
|
50
|
+
endCursor
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=catalog-import.pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog-import.pipeline.js","sourceRoot":"","sources":["../../../src/lib/catalog-import/catalog-import.pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence.d.ts","sourceRoot":"","sources":["../../../src/lib/catalog-import/confidence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,yBAAyB,EAG1B,MAAM,gBAAgB,CAAA;AAsCvB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,GAAG,yBAAyB,CAmBxF"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const HS_CODE_PATTERN = /^\d{8,10}$/;
|
|
2
|
+
const EFFECTIVE_DATE_PATTERN = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
|
|
3
|
+
const CONTROL_CODE_PATTERN = /^\d[A-Z]\d{3}(?:\.[a-z0-9]+)*$/;
|
|
4
|
+
const REVIEW_SIGNALS = new Set([
|
|
5
|
+
'CROSS_PAGE_UNCERTAIN',
|
|
6
|
+
'COLUMN_LAYOUT_DRIFT',
|
|
7
|
+
'FIELD_CONFLICT'
|
|
8
|
+
]);
|
|
9
|
+
function isBlank(value) {
|
|
10
|
+
return typeof value !== 'string' || value.trim().length === 0;
|
|
11
|
+
}
|
|
12
|
+
function hardFailure(candidate) {
|
|
13
|
+
if (candidate.evidence.length === 0 || candidate.evidence.some(item => isBlank(item.sourceLocation) || isBlank(item.sourceContent))) {
|
|
14
|
+
return 'SOURCE_EVIDENCE_MISSING';
|
|
15
|
+
}
|
|
16
|
+
if (candidate.kind === 'CONTROLLED' && isBlank(candidate.values.productName)) {
|
|
17
|
+
return 'PRODUCT_NAME_MISSING';
|
|
18
|
+
}
|
|
19
|
+
if (candidate.kind === 'SANCTION' && isBlank(candidate.values.companyName)) {
|
|
20
|
+
return 'COMPANY_NAME_MISSING';
|
|
21
|
+
}
|
|
22
|
+
if (candidate.values.hsCodes?.some(code => !HS_CODE_PATTERN.test(code))) {
|
|
23
|
+
return 'HS_CODE_INVALID';
|
|
24
|
+
}
|
|
25
|
+
if (candidate.values.effectiveDate !== undefined && !EFFECTIVE_DATE_PATTERN.test(candidate.values.effectiveDate)) {
|
|
26
|
+
return 'EFFECTIVE_DATE_INVALID';
|
|
27
|
+
}
|
|
28
|
+
if (candidate.values.controlCode !== undefined && !CONTROL_CODE_PATTERN.test(candidate.values.controlCode)) {
|
|
29
|
+
return 'CONTROL_CODE_INVALID';
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
export function classifyCandidate(candidate) {
|
|
34
|
+
const failure = hardFailure(candidate);
|
|
35
|
+
if (failure) {
|
|
36
|
+
return { confidence: 'LOW', autoPersist: false, reasons: [failure] };
|
|
37
|
+
}
|
|
38
|
+
const reviewReasons = candidate.signals.filter(signal => REVIEW_SIGNALS.has(signal));
|
|
39
|
+
if (reviewReasons.length > 0) {
|
|
40
|
+
return { confidence: 'MEDIUM', autoPersist: false, reasons: reviewReasons };
|
|
41
|
+
}
|
|
42
|
+
const unverifiableReasons = [];
|
|
43
|
+
if (!candidate.signals.includes('RECORD_START_EXPLICIT'))
|
|
44
|
+
unverifiableReasons.push('RECORD_START_UNVERIFIED');
|
|
45
|
+
if (!candidate.signals.includes('COLUMN_LAYOUT_STABLE'))
|
|
46
|
+
unverifiableReasons.push('COLUMN_LAYOUT_UNVERIFIED');
|
|
47
|
+
if (unverifiableReasons.length > 0) {
|
|
48
|
+
return { confidence: 'MEDIUM', autoPersist: false, reasons: unverifiableReasons };
|
|
49
|
+
}
|
|
50
|
+
return { confidence: 'HIGH', autoPersist: true, reasons: ['VERIFIABLE_STRUCTURE'] };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=confidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confidence.js","sourceRoot":"","sources":["../../../src/lib/catalog-import/confidence.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { CatalogConfidence } from '../types.js';
|
|
2
|
+
export type CatalogCandidateKind = 'CONTROLLED' | 'SANCTION';
|
|
3
|
+
export type CatalogEvidence = {
|
|
4
|
+
sourceLocation: string;
|
|
5
|
+
sourceContent: string;
|
|
6
|
+
};
|
|
7
|
+
export type CatalogSignal = 'STRUCTURED_SOURCE' | 'HEADER_MAPPED' | 'RECORD_START_EXPLICIT' | 'COLUMN_LAYOUT_STABLE' | 'CROSS_PAGE_UNCERTAIN' | 'COLUMN_LAYOUT_DRIFT' | 'FIELD_CONFLICT';
|
|
8
|
+
export type CatalogCandidateValues = {
|
|
9
|
+
productName?: string;
|
|
10
|
+
companyName?: string;
|
|
11
|
+
hsCodes?: string[];
|
|
12
|
+
effectiveDate?: string;
|
|
13
|
+
controlCode?: string;
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
};
|
|
16
|
+
export type CatalogCandidate = {
|
|
17
|
+
kind: CatalogCandidateKind;
|
|
18
|
+
ordinal: number;
|
|
19
|
+
values: CatalogCandidateValues;
|
|
20
|
+
evidence: CatalogEvidence[];
|
|
21
|
+
signals: CatalogSignal[];
|
|
22
|
+
warnings: string[];
|
|
23
|
+
};
|
|
24
|
+
export type CatalogConfidenceReason = 'SOURCE_EVIDENCE_MISSING' | 'PRODUCT_NAME_MISSING' | 'COMPANY_NAME_MISSING' | 'HS_CODE_INVALID' | 'EFFECTIVE_DATE_INVALID' | 'CONTROL_CODE_INVALID' | 'CROSS_PAGE_UNCERTAIN' | 'COLUMN_LAYOUT_DRIFT' | 'FIELD_CONFLICT' | 'RECORD_START_UNVERIFIED' | 'COLUMN_LAYOUT_UNVERIFIED' | 'VERIFIABLE_STRUCTURE';
|
|
25
|
+
export type CatalogConfidenceDecision = {
|
|
26
|
+
confidence: CatalogConfidence;
|
|
27
|
+
autoPersist: boolean;
|
|
28
|
+
reasons: CatalogConfidenceReason[];
|
|
29
|
+
};
|
|
30
|
+
export type CatalogReviewDraft = {
|
|
31
|
+
ordinal: number;
|
|
32
|
+
kind: CatalogCandidateKind;
|
|
33
|
+
confidence: CatalogConfidence;
|
|
34
|
+
sourceLocation: string;
|
|
35
|
+
sourceContent: string;
|
|
36
|
+
payload: CatalogCandidateValues;
|
|
37
|
+
reasons: string[];
|
|
38
|
+
};
|
|
39
|
+
export type CatalogSkippedSource = {
|
|
40
|
+
sourceLocation: string;
|
|
41
|
+
sourceContent: string;
|
|
42
|
+
reason: string;
|
|
43
|
+
};
|
|
44
|
+
export type CatalogParseResult = {
|
|
45
|
+
mode: 'FAST_PIPELINE';
|
|
46
|
+
accepted: CatalogCandidate[];
|
|
47
|
+
reviewBlocks: CatalogReviewDraft[];
|
|
48
|
+
skipped: CatalogSkippedSource[];
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../src/lib/catalog-import/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,UAAU,CAAA;AAE5D,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,aAAa,GACrB,mBAAmB,GACnB,eAAe,GACf,uBAAuB,GACvB,sBAAsB,GACtB,sBAAsB,GACtB,qBAAqB,GACrB,gBAAgB,CAAA;AAEpB,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,oBAAoB,CAAA;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,sBAAsB,CAAA;IAC9B,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAC/B,yBAAyB,GACzB,sBAAsB,GACtB,sBAAsB,GACtB,iBAAiB,GACjB,wBAAwB,GACxB,sBAAsB,GACtB,sBAAsB,GACtB,qBAAqB,GACrB,gBAAgB,GAChB,yBAAyB,GACzB,0BAA0B,GAC1B,sBAAsB,CAAA;AAE1B,MAAM,MAAM,yBAAyB,GAAG;IACtC,UAAU,EAAE,iBAAiB,CAAA;IAC7B,WAAW,EAAE,OAAO,CAAA;IACpB,OAAO,EAAE,uBAAuB,EAAE,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,oBAAoB,CAAA;IAC1B,UAAU,EAAE,iBAAiB,CAAA;IAC7B,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,sBAAsB,CAAA;IAC/B,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,eAAe,CAAA;IACrB,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,YAAY,EAAE,kBAAkB,EAAE,CAAA;IAClC,OAAO,EAAE,oBAAoB,EAAE,CAAA;CAChC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../../src/lib/catalog-import/contracts.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CatalogParseResult } from './contracts.js';
|
|
2
|
+
export type ParseDocxCatalogInput = {
|
|
3
|
+
buffer: Buffer | Uint8Array;
|
|
4
|
+
};
|
|
5
|
+
export declare function parseDocxCatalog(input: ParseDocxCatalogInput): Promise<CatalogParseResult>;
|
|
6
|
+
//# sourceMappingURL=docx.parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docx.parser.d.ts","sourceRoot":"","sources":["../../../src/lib/catalog-import/docx.parser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAoB,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAG1E,MAAM,MAAM,qBAAqB,GAAG;IAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,CAAA;AAmDnE,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAqEhG"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { load } from 'cheerio';
|
|
2
|
+
import JSZip from 'jszip';
|
|
3
|
+
import { classifyCandidate } from './confidence.js';
|
|
4
|
+
import { mapCatalogHeaders } from './header-mapping.js';
|
|
5
|
+
function normalizedText(value) {
|
|
6
|
+
return value.replace(/\u00a0/g, ' ').replace(/[ \t]+/g, ' ').replace(/\n\s*/g, '\n').trim();
|
|
7
|
+
}
|
|
8
|
+
function paragraphText($, paragraph) {
|
|
9
|
+
const parts = [];
|
|
10
|
+
$(paragraph).find('*').each((_, node) => {
|
|
11
|
+
if (node.type !== 'tag')
|
|
12
|
+
return;
|
|
13
|
+
if (node.name === 'w:t')
|
|
14
|
+
parts.push($(node).text());
|
|
15
|
+
if (node.name === 'w:br' || node.name === 'w:tab')
|
|
16
|
+
parts.push('\n');
|
|
17
|
+
});
|
|
18
|
+
return normalizedText(parts.join(''));
|
|
19
|
+
}
|
|
20
|
+
function cellText($, cell) {
|
|
21
|
+
return normalizedText($(cell).children('w\\:p').toArray().map(node => paragraphText($, node)).filter(Boolean).join('\n'));
|
|
22
|
+
}
|
|
23
|
+
function value(mapping, cells, field) {
|
|
24
|
+
const index = mapping.get(field);
|
|
25
|
+
return index === undefined ? '' : (cells[index] ?? '').trim();
|
|
26
|
+
}
|
|
27
|
+
function normalizeListingDate(input) {
|
|
28
|
+
const raw = input.trim();
|
|
29
|
+
if (/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/.test(raw))
|
|
30
|
+
return raw;
|
|
31
|
+
const match = /^(\d{1,2})[./-](\d{1,2})[./-](\d{4})$/.exec(raw);
|
|
32
|
+
if (!match)
|
|
33
|
+
return undefined;
|
|
34
|
+
const [, day, month, year] = match;
|
|
35
|
+
return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;
|
|
36
|
+
}
|
|
37
|
+
function parseNames(raw) {
|
|
38
|
+
const lines = raw.split(/\n+/).map(item => item.trim()).filter(Boolean);
|
|
39
|
+
const companyName = lines.shift() ?? '';
|
|
40
|
+
const aliases = [];
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
const aka = /^(?:also known as|a\.?k\.?a\.?|aka)\s*:?\s*(.+)$/i.exec(line);
|
|
43
|
+
if (aka) {
|
|
44
|
+
for (const alias of aka[1].split(/\s*;\s*/).filter(Boolean))
|
|
45
|
+
aliases.push({ alias, aliasType: 'AKA' });
|
|
46
|
+
}
|
|
47
|
+
else if (/\p{Script=Cyrillic}/u.test(line)) {
|
|
48
|
+
aliases.push({ alias: line, aliasType: 'LOCAL_LANGUAGE' });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return { companyName, aliases };
|
|
52
|
+
}
|
|
53
|
+
export async function parseDocxCatalog(input) {
|
|
54
|
+
const zip = await JSZip.loadAsync(input.buffer);
|
|
55
|
+
const documentFile = zip.file('word/document.xml');
|
|
56
|
+
if (!documentFile)
|
|
57
|
+
throw new Error('DOCX_DOCUMENT_XML_MISSING');
|
|
58
|
+
const xml = await documentFile.async('string');
|
|
59
|
+
const $ = load(xml, { xmlMode: true });
|
|
60
|
+
const result = { mode: 'FAST_PIPELINE', accepted: [], reviewBlocks: [], skipped: [] };
|
|
61
|
+
let section;
|
|
62
|
+
let tableNumber = 0;
|
|
63
|
+
$('w\\:body').first().children().each((_, node) => {
|
|
64
|
+
if (node.type !== 'tag')
|
|
65
|
+
return;
|
|
66
|
+
if (node.name === 'w:p') {
|
|
67
|
+
const heading = paragraphText($, node);
|
|
68
|
+
if (/^persons$/i.test(heading))
|
|
69
|
+
section = 'Persons';
|
|
70
|
+
if (/^entities$/i.test(heading))
|
|
71
|
+
section = 'Entities';
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (node.name !== 'w:tbl')
|
|
75
|
+
return;
|
|
76
|
+
tableNumber += 1;
|
|
77
|
+
const rows = $(node).children('w\\:tr').toArray().map((row, rowIndex) => ({
|
|
78
|
+
rowNumber: rowIndex + 1,
|
|
79
|
+
cells: $(row).children('w\\:tc').toArray().map(cell => cellText($, cell))
|
|
80
|
+
}));
|
|
81
|
+
if (rows.length === 0)
|
|
82
|
+
return;
|
|
83
|
+
const mapping = mapCatalogHeaders(rows[0].cells);
|
|
84
|
+
const tableSection = section;
|
|
85
|
+
for (const row of rows.slice(1)) {
|
|
86
|
+
const sourceLocation = `${tableSection ?? 'Unknown'} table ${tableNumber} row ${row.rowNumber}`;
|
|
87
|
+
const sourceContent = row.cells.join(' | ');
|
|
88
|
+
if (tableSection === 'Persons') {
|
|
89
|
+
result.skipped.push({ sourceLocation, sourceContent, reason: 'SANCTION_PERSON_OUT_OF_SCOPE' });
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const rawName = value(mapping, row.cells, 'companyName');
|
|
93
|
+
const names = parseNames(rawName);
|
|
94
|
+
const rawDate = value(mapping, row.cells, 'effectiveDate');
|
|
95
|
+
const normalizedDate = normalizeListingDate(rawDate);
|
|
96
|
+
const parsedOrdinal = Number.parseInt(value(mapping, row.cells, 'ordinal'), 10);
|
|
97
|
+
const candidate = {
|
|
98
|
+
kind: 'SANCTION',
|
|
99
|
+
ordinal: Number.isFinite(parsedOrdinal) ? parsedOrdinal : row.rowNumber - 1,
|
|
100
|
+
values: {
|
|
101
|
+
companyName: names.companyName,
|
|
102
|
+
aliases: names.aliases,
|
|
103
|
+
countryOrRegion: value(mapping, row.cells, 'countryOrRegion') || undefined,
|
|
104
|
+
sanctionReason: value(mapping, row.cells, 'sanctionReason') || undefined,
|
|
105
|
+
effectiveDate: normalizedDate ?? (rawDate || undefined)
|
|
106
|
+
},
|
|
107
|
+
evidence: [{ sourceLocation, sourceContent }],
|
|
108
|
+
signals: tableSection === 'Entities' && mapping.has('companyName')
|
|
109
|
+
? ['STRUCTURED_SOURCE', 'HEADER_MAPPED', 'RECORD_START_EXPLICIT', 'COLUMN_LAYOUT_STABLE']
|
|
110
|
+
: ['STRUCTURED_SOURCE'],
|
|
111
|
+
warnings: []
|
|
112
|
+
};
|
|
113
|
+
const decision = classifyCandidate(candidate);
|
|
114
|
+
if (decision.autoPersist)
|
|
115
|
+
result.accepted.push(candidate);
|
|
116
|
+
else
|
|
117
|
+
result.reviewBlocks.push({
|
|
118
|
+
ordinal: candidate.ordinal,
|
|
119
|
+
kind: candidate.kind,
|
|
120
|
+
confidence: decision.confidence,
|
|
121
|
+
sourceLocation,
|
|
122
|
+
sourceContent,
|
|
123
|
+
payload: candidate.values,
|
|
124
|
+
reasons: decision.reasons
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=docx.parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docx.parser.js","sourceRoot":"","sources":["../../../src/lib/catalog-import/docx.parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type CatalogField = 'ordinal' | 'productName' | 'referenceProductName' | 'hsCodes' | 'controlCode' | 'controlDescription' | 'companyName' | 'countryOrRegion' | 'sanctionReason' | 'effectiveDate';
|
|
2
|
+
export declare function normalizeHeader(value: unknown): string;
|
|
3
|
+
export declare function mapCatalogHeaders(cells: unknown[]): Map<CatalogField, number>;
|
|
4
|
+
//# sourceMappingURL=header-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header-mapping.d.ts","sourceRoot":"","sources":["../../../src/lib/catalog-import/header-mapping.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,aAAa,GACb,sBAAsB,GACtB,SAAS,GACT,aAAa,GACb,oBAAoB,GACpB,aAAa,GACb,iBAAiB,GACjB,gBAAgB,GAChB,eAAe,CAAA;AAenB,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAKtD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAa7E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const HEADER_ALIASES = {
|
|
2
|
+
ordinal: ['序号', '编号', 'no', 'number'],
|
|
3
|
+
productName: ['商品名称', '物项名称', '物项名称及描述', '产品名称', '品名', 'descriptionofgoods'],
|
|
4
|
+
referenceProductName: ['参考商品名称', '参考品名', 'referenceproductname'],
|
|
5
|
+
hsCodes: ['海关商品编号', '海关编码', '商品编码', 'hscode', 'commoditycode'],
|
|
6
|
+
controlCode: ['管制编码', '出口管制编码', 'controlcode', 'eccn'],
|
|
7
|
+
controlDescription: ['管制说明', '商品描述', '技术说明', 'description', '备注'],
|
|
8
|
+
companyName: ['企业名称', '公司名称', '实体名称', 'name'],
|
|
9
|
+
countryOrRegion: ['国家或地区', '国家地区', 'countryorregion', 'identifyinginformation'],
|
|
10
|
+
sanctionReason: ['制裁原因', '列名原因', 'reasons', 'reason'],
|
|
11
|
+
effectiveDate: ['生效日期', '列名日期', 'dateoflisting', 'effectivedate']
|
|
12
|
+
};
|
|
13
|
+
export function normalizeHeader(value) {
|
|
14
|
+
return String(value ?? '')
|
|
15
|
+
.normalize('NFKC')
|
|
16
|
+
.toLowerCase()
|
|
17
|
+
.replace(/[\s\p{P}\p{S}]+/gu, '');
|
|
18
|
+
}
|
|
19
|
+
export function mapCatalogHeaders(cells) {
|
|
20
|
+
const mapping = new Map();
|
|
21
|
+
cells.forEach((cell, index) => {
|
|
22
|
+
const normalized = normalizeHeader(cell);
|
|
23
|
+
if (!normalized)
|
|
24
|
+
return;
|
|
25
|
+
for (const [field, aliases] of Object.entries(HEADER_ALIASES)) {
|
|
26
|
+
if (!mapping.has(field) && aliases.some(alias => normalized === normalizeHeader(alias))) {
|
|
27
|
+
mapping.set(field, index);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return mapping;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=header-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header-mapping.js","sourceRoot":"","sources":["../../../src/lib/catalog-import/header-mapping.ts"],"names":[],"mappings":"AAYA,MAAM,cAAc,GAAmC;IACrD,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC;IACrC,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,CAAC;IAC5E,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,sBAAsB,CAAC;IAChE,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,CAAC;IAC9D,WAAW,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC;IACtD,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC;IACjE,WAAW,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;IAC7C,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,wBAAwB,CAAC;IAC/E,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC;IACrD,aAAa,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,eAAe,CAAC;CAClE,CAAA;AAED,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SACvB,SAAS,CAAC,MAAM,CAAC;SACjB,WAAW,EAAE;SACb,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAgB;IAChD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAA;IAC/C,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;QACxC,IAAI,CAAC,UAAU;YAAE,OAAM;QACvB,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAA+B,EAAE,CAAC;YAC5F,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,KAAK,eAAe,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBACxF,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;gBACzB,MAAK;YACP,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IACF,OAAO,OAAO,CAAA;AAChB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CatalogParseResult } from './contracts.js';
|
|
2
|
+
import { type PdfCatalogSchema } from './pdf-table.normalizer.js';
|
|
3
|
+
export type PdfCatalogSection = 'IMPORT' | 'EXPORT';
|
|
4
|
+
export type PdfLayoutPage = {
|
|
5
|
+
pageNumber: number;
|
|
6
|
+
section?: PdfCatalogSection;
|
|
7
|
+
text?: string;
|
|
8
|
+
tables: string[][][];
|
|
9
|
+
};
|
|
10
|
+
export type PdfCatalogParseResult = CatalogParseResult & {
|
|
11
|
+
schemas: PdfCatalogSchema[];
|
|
12
|
+
};
|
|
13
|
+
export declare function parsePdfLayoutPages(pages: PdfLayoutPage[]): PdfCatalogParseResult;
|
|
14
|
+
export declare function parsePdfCatalog(buffer: Buffer | Uint8Array): Promise<PdfCatalogParseResult>;
|
|
15
|
+
//# sourceMappingURL=pdf-layout.parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdf-layout.parser.d.ts","sourceRoot":"","sources":["../../../src/lib/catalog-import/pdf-layout.parser.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAoB,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AAE1E,OAAO,EAAyC,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAExG,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAEnD,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,iBAAiB,CAAA;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,GAAG;IACvD,OAAO,EAAE,gBAAgB,EAAE,CAAA;CAC5B,CAAA;AAiCD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,qBAAqB,CA0EjF;AAQD,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAgBjG"}
|