@chenchaolong/plugin-trade-compliance-workbench 1.0.91 → 1.0.93

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.
@@ -88,6 +88,15 @@ function controlledGoodsDto(item) {
88
88
  delete dto.sourceContent;
89
89
  return dto;
90
90
  }
91
+ function duplicateTargetFromRecord(record) {
92
+ const name = record.productName?.trim() || record.companyName?.trim() || '历史记录';
93
+ const sequence = typeof record.sourceSequence === 'number' ? `第 ${record.sourceSequence} 条` : '历史记录';
94
+ return [name, sequence, record.sourceLocation].filter(Boolean).join(' · ');
95
+ }
96
+ function normalizedIssuePayload(row) {
97
+ const { duplicateTargetName: _duplicateTargetName, duplicateTargetSourceSequence: _duplicateTargetSourceSequence, duplicateTargetSourceLocation: _duplicateTargetSourceLocation, ...payload } = row;
98
+ return payload;
99
+ }
91
100
  function sanctionedCompanyDto(item) {
92
101
  const dto = { ...item };
93
102
  delete dto.sourceContent;
@@ -174,9 +183,6 @@ let TradeComplianceWorkbenchService = class TradeComplianceWorkbenchService {
174
183
  cancellationTarget: null
175
184
  };
176
185
  }
177
- if (!DELETABLE_IMPORT_TASK_STATUSES.includes(task.status)) {
178
- throw new DomainError(DomainErrorCodes.INVALID_INPUT, '已完成任务不允许删除');
179
- }
180
186
  const cancellationTarget = {
181
187
  importTaskId: task.id,
182
188
  claimAttemptToken: task.claimAttemptToken
@@ -547,7 +553,11 @@ let TradeComplianceWorkbenchService = class TradeComplianceWorkbenchService {
547
553
  changed = true;
548
554
  batch.invalidCount += 1;
549
555
  batch.totalCount += 1;
550
- await issueRepo.save(issueRepo.create({ ...createdScope(scope), batchId: batch.id, issueType: 'INVALID', sourceSequence: batch.totalCount, sourceLocation: row.sourceLocation ?? null, sourceContent: row.sourceContent ?? null, parsedPayload: row, message: localized.error }));
556
+ await issueRepo.save(issueRepo.create({
557
+ ...createdScope(scope), batchId: batch.id, issueType: 'INVALID', sourceSequence: batch.totalCount,
558
+ sourceLocation: row.sourceLocation ?? null, sourceContent: row.sourceContent ?? null,
559
+ parsedPayload: row, message: localized.error
560
+ }));
551
561
  continue;
552
562
  }
553
563
  const duplicate = await recordRepo.findOne({ where: [
@@ -561,7 +571,13 @@ let TradeComplianceWorkbenchService = class TradeComplianceWorkbenchService {
561
571
  batch.totalCount += 1;
562
572
  if (duplicate) {
563
573
  batch.duplicateCount += 1;
564
- await issueRepo.save(issueRepo.create({ ...createdScope(scope), batchId: batch.id, issueType: 'DUPLICATE', sourceSequence: batch.totalCount, sourceLocation: row.sourceLocation ?? null, sourceContent: row.sourceContent ?? null, parsedPayload: row, message: '目录中已存在相同商品名称和海关编码' }));
574
+ const duplicateTarget = duplicateTargetFromRecord(duplicate);
575
+ await issueRepo.save(issueRepo.create({
576
+ ...createdScope(scope), batchId: batch.id, issueType: 'DUPLICATE', sourceSequence: batch.totalCount,
577
+ sourceLocation: row.sourceLocation ?? null, sourceContent: row.sourceContent ?? null,
578
+ parsedPayload: { ...row, duplicateTargetName: duplicateTarget },
579
+ message: '目录中已存在相同商品名称和海关编码'
580
+ }));
565
581
  continue;
566
582
  }
567
583
  await recordRepo.save(recordRepo.create({ ...auditScope(scope), batchId: batch.id, lifecycleStatus: batch.lifecycleStatus, reviewStatus: 'PENDING', sourceType: 'FILE_IMPORT', catalogType: batch.catalogType, productName, normalizedProductName: productName, hsCode: row.hsCode ?? null, normalizedHsCode, controlDescription: localized.controlDescription, originalProductName: localized.originalProductName, originalControlDescription: localized.originalControlDescription, translationSource: localized.translationSource, controlCode: row.controlCode ?? null, sourceSection: row.sourceSection ?? null, sourceOrdinal: row.sourceOrdinal ?? null, sourceLocation: row.sourceLocation ?? null, sourceContent: row.sourceContent ?? null }));
@@ -571,8 +587,14 @@ let TradeComplianceWorkbenchService = class TradeComplianceWorkbenchService {
571
587
  return changed;
572
588
  }
573
589
  async catalogIssueExists(repository, scope, batchId, issueType, row) {
590
+ const payload = normalizedIssuePayload(row);
591
+ const find = repository.find?.bind(repository);
592
+ if (find) {
593
+ const issues = await find({ where: { ...activeScope(scope), batchId, issueType } });
594
+ return issues.some(issue => canonicalJson(normalizedIssuePayload((issue.parsedPayload ?? {}))) === canonicalJson(payload));
595
+ }
574
596
  const where = {
575
- ...activeScope(scope), batchId, issueType, parsedPayload: row
597
+ ...activeScope(scope), batchId, issueType, parsedPayload: payload
576
598
  };
577
599
  return Boolean(await repository.findOne({ where }));
578
600
  }
@@ -1769,12 +1791,13 @@ let TradeComplianceWorkbenchService = class TradeComplianceWorkbenchService {
1769
1791
  continue;
1770
1792
  batch.successCount = Math.max(0, batch.successCount - 1);
1771
1793
  batch.duplicateCount += 1;
1794
+ const duplicateTarget = duplicateTargetFromRecord(conflict);
1772
1795
  await issueRepo.save(issueRepo.create({
1773
1796
  ...createdScope(scope), batchId: batch.id, issueType: 'DUPLICATE',
1774
1797
  sourceSequence: Math.max(1, batch.totalCount - batch.successCount),
1775
1798
  sourceLocation: record.sourceLocation, sourceContent: record.sourceContent,
1776
1799
  parsedPayload: {
1777
- catalogType: record.catalogType, productName: record.productName, hsCode: record.hsCode
1800
+ catalogType: record.catalogType, productName: record.productName, hsCode: record.hsCode, duplicateTargetName: duplicateTarget
1778
1801
  },
1779
1802
  message: '发布前检测到相同商品名称和海关编码的活动记录'
1780
1803
  }));
@@ -1803,12 +1826,13 @@ let TradeComplianceWorkbenchService = class TradeComplianceWorkbenchService {
1803
1826
  continue;
1804
1827
  batch.successCount = Math.max(0, batch.successCount - 1);
1805
1828
  batch.duplicateCount += 1;
1829
+ const duplicateTarget = duplicateTargetFromRecord(conflict);
1806
1830
  await issueRepo.save(issueRepo.create({
1807
1831
  ...createdScope(scope), batchId: batch.id, issueType: 'DUPLICATE',
1808
1832
  sourceSequence: Math.max(1, batch.totalCount - batch.successCount),
1809
1833
  sourceLocation: record.sourceLocation, sourceContent: record.sourceContent,
1810
1834
  parsedPayload: {
1811
- companyName: record.companyName, sanctionListSource: record.sanctionListSource
1835
+ companyName: record.companyName, sanctionListSource: record.sanctionListSource, duplicateTargetName: duplicateTarget
1812
1836
  },
1813
1837
  message: '发布前检测到相同公司和名单来源的活动记录'
1814
1838
  }));