From 405c05236f1de40af6434b42a869b43b6c370cca Mon Sep 17 00:00:00 2001 From: "han\\hanst" Date: Mon, 17 Aug 2026 15:54:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A6=82=E6=9E=9CNPI=E9=87=8C=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E4=BA=86Sample=20Tracking=E4=B8=8B=E7=9A=84=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E4=BF=A1=E6=81=AF=E5=92=8C=E7=89=A9=E6=96=99=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=EF=BC=8C=E5=90=8C=E6=AD=A5=E6=97=B6=E8=A6=81=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E6=9B=B4=E6=94=B9=EF=BC=8C=E4=B8=8D=E8=83=BD=E8=A6=86?= =?UTF-8?q?=E7=9B=96=E6=88=96=E6=96=B0=E5=A2=9E=20=E5=A6=82=E6=9E=9CNPI?= =?UTF-8?q?=E9=87=8C=E5=AD=98=E5=9C=A8=E4=BA=86Sample=20Tracking=E4=B8=8B?= =?UTF-8?q?=E7=9A=84=E9=A1=B9=E7=9B=AE=E4=BF=A1=E6=81=AF=EF=BC=8C=E4=BD=86?= =?UTF-8?q?=E7=89=A9=E6=96=99=E4=BF=A1=E6=81=AF=E4=B8=8D=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=EF=BC=8C=E5=90=8C=E6=AD=A5=E6=97=B6=E8=A6=81=E5=9C=A8=E5=B7=B2?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E7=9A=84=E9=A1=B9=E7=9B=AE=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E4=B8=8B=E6=96=B0=E5=A2=9E=E7=89=A9=E6=96=99=20=E5=A6=82?= =?UTF-8?q?=E6=9E=9CNPI=E9=87=8C=E9=83=BD=E4=B8=8D=E5=AD=98=E5=9C=A8Sample?= =?UTF-8?q?=20Tracking=E4=B8=8B=E7=9A=84=E9=A1=B9=E7=9B=AE=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=92=8C=E7=89=A9=E6=96=99=E4=BF=A1=E6=81=AF=EF=BC=8C?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=97=B6=E6=AD=A3=E5=B8=B8=E6=96=B0=E5=A2=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/SampleTrackingMapper.java | 4 +- .../impl/SampleTrackingServiceImpl.java | 48 +++++++++++++++---- .../sampletracking/SampleTrackingMapper.xml | 3 +- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/xujie/sys/modules/sampletracking/mapper/SampleTrackingMapper.java b/src/main/java/com/xujie/sys/modules/sampletracking/mapper/SampleTrackingMapper.java index 313d5898..e100906a 100644 --- a/src/main/java/com/xujie/sys/modules/sampletracking/mapper/SampleTrackingMapper.java +++ b/src/main/java/com/xujie/sys/modules/sampletracking/mapper/SampleTrackingMapper.java @@ -49,7 +49,9 @@ public interface SampleTrackingMapper { ProjectInfoTrackingData selectProjectInfoTrackingById(@Param("projectId") Integer projectId); - Integer selectNpiProjectIdBySiteAndProjectNo(@Param("site") String site, @Param("projectNo") String projectNo); + Integer selectNpiProjectIdBySiteBuNoAndProjectNo(@Param("site") String site, + @Param("buNo") String buNo, + @Param("projectNo") String projectNo); void updateNpiProjectFromTracking(ProjectInfoTrackingData data); diff --git a/src/main/java/com/xujie/sys/modules/sampletracking/service/impl/SampleTrackingServiceImpl.java b/src/main/java/com/xujie/sys/modules/sampletracking/service/impl/SampleTrackingServiceImpl.java index edde99a3..bff0508f 100644 --- a/src/main/java/com/xujie/sys/modules/sampletracking/service/impl/SampleTrackingServiceImpl.java +++ b/src/main/java/com/xujie/sys/modules/sampletracking/service/impl/SampleTrackingServiceImpl.java @@ -298,10 +298,9 @@ public class SampleTrackingServiceImpl implements SampleTrackingService { if (!missingFields.isEmpty()) { throw new RuntimeException("项目追踪记录缺少以下必填项,无法同步: " + String.join("、", missingFields)); } - // 优先按“trackingId == npiId”的目标查 NPI: - // 若已存在则更新,不存在则插入,后续再统一做 tracking ID 对齐。 - Project existedNpiProject = projectMapper.selectById(trackingProjectId); - Integer npiProjectId = existedNpiProject == null ? null : existedNpiProject.getProjectId(); + // 同步判定优先使用业务键(site + buNo + projectNo),这样可以避免“同项目不同ID”重复插入。 + // 若业务键未命中,再回退到 trackingId == npiId 的历史兼容策略。 + Integer npiProjectId = resolveMatchedNpiProjectId(trackingProjectId, trackingProject); if (npiProjectId == null) { Project insertProject = buildProjectForInsert(trackingProject, operator); int insertRows = projectMapper.insert(insertProject); @@ -345,8 +344,9 @@ public class SampleTrackingServiceImpl implements SampleTrackingService { throw new RuntimeException("项目物料追踪记录缺少以下必填项,无法同步: " + String.join("、", latestPartMissingFields)); } latestPart.setProjectId(npiProjectId); - ProjectPart existedNpiPart = projectPartMapper.selectById(trackingProjectPartId); - Integer npiProjectPartId = existedNpiPart == null ? null : existedNpiPart.getId(); + // 物料同步同样优先按业务键(site + projectId + testPartNo)定位,命中后执行更新。 + // 仅在业务键未命中时,才按 trackingId == npiId 兼容旧数据。 + Integer npiProjectPartId = resolveMatchedNpiProjectPartId(trackingProjectPartId, npiProjectId, latestPart); if (npiProjectPartId == null) { ProjectPart insertPart = buildProjectPartForInsert(latestPart, operator); int insertRows = projectPartMapper.insert(insertPart); @@ -525,9 +525,9 @@ public class SampleTrackingServiceImpl implements SampleTrackingService { throw new RuntimeException("请先同步项目物料后再同步打样单"); } // 若业务键可用,则进一步校验 tracking 与 NPI 指向同一业务记录,避免ID偶合误判 - if (!isBlank(trackingProject.getSite()) && !isBlank(trackingProject.getProjectNo())) { - Integer matchedProjectId = sampleTrackingMapper.selectNpiProjectIdBySiteAndProjectNo( - trackingProject.getSite(), trackingProject.getProjectNo()); + if (!isBlank(trackingProject.getSite()) && !isBlank(trackingProject.getBuNo()) && !isBlank(trackingProject.getProjectNo())) { + Integer matchedProjectId = sampleTrackingMapper.selectNpiProjectIdBySiteBuNoAndProjectNo( + trackingProject.getSite(), trackingProject.getBuNo(), trackingProject.getProjectNo()); if (matchedProjectId != null && !Objects.equals(matchedProjectId, trackingProjectId)) { throw new RuntimeException("请先同步项目后再同步打样单"); } @@ -861,6 +861,36 @@ public class SampleTrackingServiceImpl implements SampleTrackingService { return missingFields; } + private Integer resolveMatchedNpiProjectId(Integer trackingProjectId, ProjectInfoTrackingData trackingProject) { + if (trackingProject != null + && !isBlank(trackingProject.getSite()) + && !isBlank(trackingProject.getBuNo()) + && !isBlank(trackingProject.getProjectNo())) { + Integer matchedByBusinessKey = sampleTrackingMapper.selectNpiProjectIdBySiteBuNoAndProjectNo( + trackingProject.getSite().trim(), trackingProject.getBuNo().trim(), trackingProject.getProjectNo().trim()); + if (matchedByBusinessKey != null) { + return matchedByBusinessKey; + } + } + Project existedByTrackingId = projectMapper.selectById(trackingProjectId); + return existedByTrackingId == null ? null : existedByTrackingId.getProjectId(); + } + + private Integer resolveMatchedNpiProjectPartId(Integer trackingProjectPartId, + Integer npiProjectId, + ProjectPartTrackingData trackingPart) { + if (trackingPart != null && npiProjectId != null + && !isBlank(trackingPart.getSite()) && !isBlank(trackingPart.getTestPartNo())) { + Integer matchedByBusinessKey = sampleTrackingMapper.selectNpiProjectPartIdBySiteProjectAndPartNo( + trackingPart.getSite().trim(), npiProjectId, trackingPart.getTestPartNo().trim()); + if (matchedByBusinessKey != null) { + return matchedByBusinessKey; + } + } + ProjectPart existedByTrackingId = projectPartMapper.selectById(trackingProjectPartId); + return existedByTrackingId == null ? null : existedByTrackingId.getId(); + } + private Project buildProjectForInsert(ProjectInfoTrackingData trackingProject, String operator) { Project project = new Project(); BeanUtils.copyProperties(trackingProject, project); diff --git a/src/main/resources/mapper/sampletracking/SampleTrackingMapper.xml b/src/main/resources/mapper/sampletracking/SampleTrackingMapper.xml index 16cac21b..928ef3fe 100644 --- a/src/main/resources/mapper/sampletracking/SampleTrackingMapper.xml +++ b/src/main/resources/mapper/sampletracking/SampleTrackingMapper.xml @@ -361,10 +361,11 @@ WHERE a.id = #{projectId} - SELECT TOP 1 id FROM plm_project_info WHERE site = #{site} + AND bu_no = #{buNo} AND project_no = #{projectNo} ORDER BY id DESC