From 8c7cce90ba0ce34f11ce5fedcbe6dea4f4784bf1 Mon Sep 17 00:00:00 2001 From: wangyu <823267011@qq.com> Date: Mon, 29 Jun 2026 10:18:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=87=87=E8=B4=AD=E5=92=8C?= =?UTF-8?q?=E9=9B=86=E6=88=90=E9=85=B8=E8=BD=A7=E7=BB=86=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/purchase-plan-ddl.sql | 31 ++- .../controller/ErpPurchasePlanController.java | 17 +- .../com/klp/erp/domain/ErpPurchasePlan.java | 8 +- .../erp/domain/ErpPurchasePlanDelivery.java | 5 +- .../klp/erp/domain/ErpPurchasePlanItem.java | 6 + .../erp/domain/bo/ErpPurchasePlanItemBo.java | 6 + .../domain/vo/ErpPurchasePlanDeliveryVo.java | 3 + .../erp/domain/vo/ErpPurchasePlanItemVo.java | 6 + .../klp/erp/domain/vo/ErpPurchasePlanVo.java | 13 +- .../klp/erp/mapper/ErpPurchasePlanMapper.java | 10 + .../erp/service/IErpPurchasePlanService.java | 12 +- .../impl/ErpPurchasePlanServiceImpl.java | 151 ++++-------- .../mapper/erp/ErpPurchasePlanMapper.xml | 25 ++ klp-ui/src/api/erp/purchasePlan.js | 17 +- klp-ui/src/views/erp/purchaseAudit/index.vue | 28 +-- .../src/views/erp/purchaseDelivery/index.vue | 178 +++++--------- klp-ui/src/views/erp/purchasePlan/index.vue | 232 +++++------------- .../acid/components/QualityReportDialog.vue | 60 ++--- 18 files changed, 326 insertions(+), 482 deletions(-) diff --git a/docs/purchase-plan-ddl.sql b/docs/purchase-plan-ddl.sql index 8303a3db3..dcbd345a4 100644 --- a/docs/purchase-plan-ddl.sql +++ b/docs/purchase-plan-ddl.sql @@ -148,6 +148,27 @@ SET @c := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = SET @s := IF(@c = 0, 'ALTER TABLE erp_purchase_plan ADD COLUMN arrived_count INT NOT NULL DEFAULT 0 COMMENT ''已到货卷数'' AFTER plan_qty', 'SELECT 1'); PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; +-- 2026-06-29 大改:采购计划→采购合同;要求改为 规格+总重量+厂商;到货区分已到/在途 +SET @c := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'erp_purchase_plan_item' AND COLUMN_NAME = 'spec'); +SET @s := IF(@c = 0, 'ALTER TABLE erp_purchase_plan_item ADD COLUMN spec VARCHAR(128) DEFAULT NULL COMMENT ''规格'' AFTER plan_id', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @c := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'erp_purchase_plan_item' AND COLUMN_NAME = 'manufacturer'); +SET @s := IF(@c = 0, 'ALTER TABLE erp_purchase_plan_item ADD COLUMN manufacturer VARCHAR(128) DEFAULT NULL COMMENT ''厂商(手填,历史记忆)'' AFTER spec', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @c := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'erp_purchase_plan_delivery' AND COLUMN_NAME = 'in_transit'); +SET @s := IF(@c = 0, 'ALTER TABLE erp_purchase_plan_delivery ADD COLUMN in_transit TINYINT NOT NULL DEFAULT 0 COMMENT ''是否在途:1是0否(钢卷表存在且data_type=10)'' AFTER arrived', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @c := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'erp_purchase_plan' AND COLUMN_NAME = 'in_transit_count'); +SET @s := IF(@c = 0, 'ALTER TABLE erp_purchase_plan ADD COLUMN in_transit_count INT NOT NULL DEFAULT 0 COMMENT ''在途卷数'' AFTER arrived_count', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @c := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'erp_purchase_plan' AND COLUMN_NAME = 'in_transit_weight'); +SET @s := IF(@c = 0, 'ALTER TABLE erp_purchase_plan ADD COLUMN in_transit_weight DECIMAL(14,3) NOT NULL DEFAULT 0 COMMENT ''在途重量(T)'' AFTER in_transit_count', 'SELECT 1'); +PREPARE stmt FROM @s; EXECUTE stmt; DEALLOCATE PREPARE stmt; + -- ============ 菜单 ============ -- 采购目录挂在「生产辅助」(path=helper) 下;父 id 按 path 动态解析,兼容不同环境的不同 menu_id。 @@ -170,11 +191,11 @@ SET @purchase_id = (SELECT menu_id FROM (SELECT menu_id FROM sys_menu WHERE path -- 5) 采购计划 + 按钮(REPLACE 可重复执行) REPLACE INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query_param, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark) VALUES -(2100000000000000001, '采购计划', @purchase_id, 2, 'purchasePlan', 'erp/purchasePlan/index', '', 1, 0, 'C', '0', '0', 'erp:purchasePlan:list', 'form', 'admin', sysdate(), '采购计划菜单'), -(2100000000000000002, '采购计划查询', 2100000000000000001, 1, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:query', '#', 'admin', sysdate(), ''), -(2100000000000000003, '采购计划新增', 2100000000000000001, 2, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:add', '#', 'admin', sysdate(), ''), -(2100000000000000004, '采购计划修改', 2100000000000000001, 3, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:edit', '#', 'admin', sysdate(), ''), -(2100000000000000005, '采购计划删除', 2100000000000000001, 4, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:remove', '#', 'admin', sysdate(), ''), +(2100000000000000001, '采购合同', @purchase_id, 2, 'purchasePlan', 'erp/purchasePlan/index', '', 1, 0, 'C', '0', '0', 'erp:purchasePlan:list', 'form', 'admin', sysdate(), '采购合同菜单'), +(2100000000000000002, '采购合同查询', 2100000000000000001, 1, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:query', '#', 'admin', sysdate(), ''), +(2100000000000000003, '采购合同新增', 2100000000000000001, 2, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:add', '#', 'admin', sysdate(), ''), +(2100000000000000004, '采购合同修改', 2100000000000000001, 3, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:edit', '#', 'admin', sysdate(), ''), +(2100000000000000005, '采购合同删除', 2100000000000000001, 4, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:remove', '#', 'admin', sysdate(), ''), (2100000000000000006, '到货导入', 2100000000000000001, 5, '', '', '', 1, 0, 'F', '0', '0', 'erp:purchasePlan:import', '#', 'admin', sysdate(), ''); -- 6) 采购审核 + 按钮(REPLACE 可重复执行) diff --git a/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchasePlanController.java b/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchasePlanController.java index 5d5d80000..2f8b82cce 100644 --- a/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchasePlanController.java +++ b/klp-erp/src/main/java/com/klp/erp/controller/ErpPurchasePlanController.java @@ -13,7 +13,6 @@ import com.klp.common.utils.poi.ExcelUtil; import com.klp.erp.domain.bo.ErpPurchasePlanAuditBo; import com.klp.erp.domain.bo.ErpPurchasePlanBo; import com.klp.erp.domain.vo.ErpContractOptionVo; -import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryBatchVo; import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryVo; import com.klp.erp.domain.vo.ErpPurchasePlanItemVo; import com.klp.erp.domain.vo.ErpPurchasePlanVo; @@ -149,19 +148,13 @@ public class ErpPurchasePlanController extends BaseController { return R.ok(); } - /** 某计划的到货上传批次(每次上传一条,可回看) */ - @GetMapping("/{planId}/deliveryBatches") - public R> deliveryBatches(@PathVariable Long planId) { - return R.ok(iErpPurchasePlanService.queryDeliveryBatches(planId)); + /** 厂商历史记忆(手填自动补全) */ + @GetMapping("/manufacturers") + public R> manufacturers(@RequestParam(value = "keyword", required = false) String keyword) { + return R.ok(iErpPurchasePlanService.queryManufacturers(keyword)); } - /** 某批次的到货明细 */ - @GetMapping("/deliveryBatch/{batchId}") - public R> deliveryByBatch(@PathVariable Long batchId) { - return R.ok(iErpPurchasePlanService.queryDeliveryListByBatch(batchId)); - } - - /** 到货记录页左侧:审核通过的计划分页 */ + /** 到货记录页左侧:审核通过的合同分页 */ @GetMapping("/deliveryPlans") public TableDataInfo deliveryPlans(@RequestParam(value = "keyword", required = false) String keyword, PageQuery pageQuery) { diff --git a/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlan.java b/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlan.java index 066002d47..2dfd0dffe 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlan.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlan.java @@ -57,12 +57,18 @@ public class ErpPurchasePlan extends BaseEntity { /** 已到货重量(T) = Σ到货卷(WMS已确认)单卷重量 */ private BigDecimal arrivedWeight; - /** 计划要求总数量(卷/件) = Σ明细数量 */ + /** 要求项数 = 明细行数 */ private Integer planQty; /** 已到货卷数 = WMS确认到货的上传卷数 */ private Integer arrivedCount; + /** 在途卷数 = 钢卷表存在但 data_type=10 的上传卷数 */ + private Integer inTransitCount; + + /** 在途重量(T) */ + private BigDecimal inTransitWeight; + /** 删除标志 */ @TableLogic private String delFlag; diff --git a/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlanDelivery.java b/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlanDelivery.java index 54e304fc3..5c1a20952 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlanDelivery.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlanDelivery.java @@ -33,9 +33,12 @@ public class ErpPurchasePlanDelivery extends BaseEntity { /** 关联上传批次ID */ private Long batchId; - /** 是否WMS已确认到货: 1-是 0-否(卷号在钢卷表查不到或为占位类型) */ + /** 是否WMS已确认到货: 1-是 0-否(卷号在钢卷表存在且 data_type<>10) */ private Integer arrived; + /** 是否在途: 1-是(卷号在钢卷表存在但 data_type=10) 0-否 */ + private Integer inTransit; + /** 日期 */ private Date arrivalDate; diff --git a/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlanItem.java b/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlanItem.java index bcbf950cc..bbb874d4b 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlanItem.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/ErpPurchasePlanItem.java @@ -29,6 +29,12 @@ public class ErpPurchasePlanItem extends BaseEntity { /** 关联计划ID */ private Long planId; + /** 规格 */ + private String spec; + + /** 厂商(手填,带历史记忆) */ + private String manufacturer; + /** 产品(如热轧卷板) */ private String productType; diff --git a/klp-erp/src/main/java/com/klp/erp/domain/bo/ErpPurchasePlanItemBo.java b/klp-erp/src/main/java/com/klp/erp/domain/bo/ErpPurchasePlanItemBo.java index 22715a09b..e7657448b 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/bo/ErpPurchasePlanItemBo.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/bo/ErpPurchasePlanItemBo.java @@ -22,6 +22,12 @@ public class ErpPurchasePlanItemBo extends BaseEntity { /** 关联计划ID */ private Long planId; + /** 规格 */ + private String spec; + + /** 厂商(手填,带历史记忆) */ + private String manufacturer; + /** 产品(如热轧卷板) */ private String productType; diff --git a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanDeliveryVo.java b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanDeliveryVo.java index 2e0d3e459..5c801eefb 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanDeliveryVo.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanDeliveryVo.java @@ -31,6 +31,9 @@ public class ErpPurchasePlanDeliveryVo implements Serializable { /** 是否WMS已确认到货: 1-是 0-否 */ private Integer arrived; + /** 是否在途: 1-是 0-否 */ + private Integer inTransit; + @ExcelProperty(value = "日期") @JsonFormat(pattern = "yyyy-MM-dd") private Date arrivalDate; diff --git a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanItemVo.java b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanItemVo.java index c692cb030..94aab1b80 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanItemVo.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanItemVo.java @@ -24,6 +24,12 @@ public class ErpPurchasePlanItemVo implements Serializable { private Long planId; + @ExcelProperty(value = "规格") + private String spec; + + @ExcelProperty(value = "厂商") + private String manufacturer; + @ExcelProperty(value = "产品") private String productType; diff --git a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanVo.java b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanVo.java index c9ef4f786..3700fb25e 100644 --- a/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanVo.java +++ b/klp-erp/src/main/java/com/klp/erp/domain/vo/ErpPurchasePlanVo.java @@ -59,21 +59,24 @@ public class ErpPurchasePlanVo implements Serializable { @ExcelProperty(value = "已到货重量(T)") private BigDecimal arrivedWeight; - /** 计划要求总数量(卷/件) */ + /** 要求项数(明细行数) */ private Integer planQty; /** 已到货卷数 */ private Integer arrivedCount; + /** 在途卷数 */ + private Integer inTransitCount; + + /** 在途重量(T) */ + private BigDecimal inTransitWeight; + @ExcelProperty(value = "备注") private String remark; - /** 到货进度-按重量(0-100) = 已到货重量/计划要求总重量 */ + /** 到货进度-按重量(0-100) = 已到货重量/要求总重量 */ private BigDecimal progress; - /** 到货进度-按卷数(0-100) = 已到货卷数/计划要求总数量 */ - private BigDecimal progressQty; - /** 明细行 */ private List items; diff --git a/klp-erp/src/main/java/com/klp/erp/mapper/ErpPurchasePlanMapper.java b/klp-erp/src/main/java/com/klp/erp/mapper/ErpPurchasePlanMapper.java index a556fcc7b..00c2cb581 100644 --- a/klp-erp/src/main/java/com/klp/erp/mapper/ErpPurchasePlanMapper.java +++ b/klp-erp/src/main/java/com/klp/erp/mapper/ErpPurchasePlanMapper.java @@ -51,4 +51,14 @@ public interface ErpPurchasePlanMapper extends BaseMapperPlus selectExistingSupplierCoilNos(@Param("coilNos") Collection coilNos); + + /** + * 在途卷号:WMS 钢卷表中存在但 data_type=10(在途)的厂家卷号集合。 + */ + List selectInTransitSupplierCoilNos(@Param("coilNos") Collection coilNos); + + /** + * 厂商历史记忆:已保存过的厂商去重(可按关键字过滤),用于手填自动补全。 + */ + List selectDistinctManufacturers(@Param("kw") String kw); } diff --git a/klp-erp/src/main/java/com/klp/erp/service/IErpPurchasePlanService.java b/klp-erp/src/main/java/com/klp/erp/service/IErpPurchasePlanService.java index f40d531ce..1c21f6229 100644 --- a/klp-erp/src/main/java/com/klp/erp/service/IErpPurchasePlanService.java +++ b/klp-erp/src/main/java/com/klp/erp/service/IErpPurchasePlanService.java @@ -6,7 +6,6 @@ import com.klp.erp.domain.bo.ErpPurchasePlanAuditBo; import com.klp.erp.domain.bo.ErpPurchasePlanBo; import com.klp.erp.domain.vo.ErpContractOptionVo; import com.klp.erp.domain.vo.ErpPurchasePlanAuditLogVo; -import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryBatchVo; import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryVo; import com.klp.erp.domain.vo.ErpPurchasePlanItemVo; import com.klp.erp.domain.vo.ErpPurchasePlanVo; @@ -66,16 +65,13 @@ public interface IErpPurchasePlanService { */ Map importDelivery(Long planId, InputStream inputStream, String fileName, String operator); - /** 查询某计划的到货明细(matched 标记是否与明细卷号匹配) */ + /** 查询某计划的到货明细(仅最新一次上传,含到货/在途标记) */ List queryDeliveryList(Long planId); - /** 某计划下指定批次的到货明细 */ - List queryDeliveryListByBatch(Long batchId); + /** 厂商历史记忆(去重,可按关键字过滤),用于手填自动补全 */ + List queryManufacturers(String keyword); - /** 某计划的到货上传批次(最新在前) */ - List queryDeliveryBatches(Long planId); - - /** 到货记录页左侧:审核通过的计划分页(含合同号、明细数、进度) */ + /** 到货记录页左侧:审核通过的合同分页(含合同号、出卖方、进度) */ TableDataInfo queryDeliveryPlanPage(String keyword, PageQuery pageQuery); /** 删除到货明细,并刷新进度 */ diff --git a/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchasePlanServiceImpl.java b/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchasePlanServiceImpl.java index 483f4162a..6f7e5d341 100644 --- a/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchasePlanServiceImpl.java +++ b/klp-erp/src/main/java/com/klp/erp/service/impl/ErpPurchasePlanServiceImpl.java @@ -13,7 +13,6 @@ import com.klp.common.utils.StringUtils; import com.klp.erp.domain.ErpPurchasePlan; import com.klp.erp.domain.ErpPurchasePlanContractRel; import com.klp.erp.domain.ErpPurchasePlanDelivery; -import com.klp.erp.domain.ErpPurchasePlanDeliveryBatch; import com.klp.erp.domain.ErpPurchasePlanItem; import com.klp.erp.domain.ErpPurchasePlanAuditLog; import com.klp.erp.domain.bo.ErpPurchasePlanAuditBo; @@ -21,13 +20,11 @@ import com.klp.erp.domain.bo.ErpPurchasePlanBo; import com.klp.erp.domain.bo.ErpPurchasePlanItemBo; import com.klp.erp.domain.vo.ErpContractOptionVo; import com.klp.erp.domain.vo.ErpPurchasePlanAuditLogVo; -import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryBatchVo; import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryImportVo; import com.klp.erp.domain.vo.ErpPurchasePlanDeliveryVo; import com.klp.erp.domain.vo.ErpPurchasePlanItemVo; import com.klp.erp.domain.vo.ErpPurchasePlanVo; import com.klp.erp.mapper.ErpPurchasePlanContractRelMapper; -import com.klp.erp.mapper.ErpPurchasePlanDeliveryBatchMapper; import com.klp.erp.mapper.ErpPurchasePlanDeliveryMapper; import com.klp.erp.mapper.ErpPurchasePlanItemMapper; import com.klp.erp.mapper.ErpPurchasePlanAuditLogMapper; @@ -46,7 +43,6 @@ import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -73,7 +69,6 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { private final ErpPurchasePlanItemMapper itemMapper; private final ErpPurchasePlanContractRelMapper relMapper; private final ErpPurchasePlanDeliveryMapper deliveryMapper; - private final ErpPurchasePlanDeliveryBatchMapper deliveryBatchMapper; private final ErpPurchasePlanAuditLogMapper auditLogMapper; @Override @@ -167,7 +162,7 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { add.setAuditStatus(AUDIT_DRAFT); // 新建为「待送审」,需手动送审后才进入审核池 add.setArrivedWeight(BigDecimal.ZERO); add.setPlanWeight(sumItemWeight(bo.getItems())); - add.setPlanQty(sumItemQty(bo.getItems())); + add.setPlanQty(bo.getItems() == null ? 0 : bo.getItems().size()); add.setArrivedCount(0); if (baseMapper.insert(add) <= 0) { return false; @@ -192,7 +187,7 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { update.setPlanNo(bo.getPlanNo()); } update.setPlanWeight(sumItemWeight(bo.getItems())); - update.setPlanQty(sumItemQty(bo.getItems())); + update.setPlanQty(bo.getItems() == null ? 0 : bo.getItems().size()); baseMapper.updateById(update); // 覆盖式重写明细与合同关联 itemMapper.delete(Wrappers.lambdaQuery(ErpPurchasePlanItem.class) @@ -242,13 +237,6 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { .reduce(BigDecimal.ZERO, BigDecimal::add); } - private int sumItemQty(List items) { - if (items == null) { - return 0; - } - return items.stream().mapToInt(i -> i.getQuantity() == null ? 0 : i.getQuantity()).sum(); - } - @Override @Transactional(rollbackFor = Exception.class) public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { @@ -341,31 +329,7 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { if (valid.isEmpty()) { throw new ServiceException("未解析到有效到货数据,请检查文件内容或列名是否与模板一致"); } - // 2) 牌号校验:到货表里的牌号必须都在本计划「采购要求」的牌号范围内 - List planItems = itemMapper.selectList(Wrappers.lambdaQuery(ErpPurchasePlanItem.class) - .eq(ErpPurchasePlanItem::getPlanId, planId)); - Set reqGrades = planItems.stream() - .map(it -> normCoil(it.getGrade())) - .filter(StringUtils::isNotBlank) - .collect(Collectors.toSet()); - if (!reqGrades.isEmpty()) { - Set badGrades = new LinkedHashSet<>(); - for (ErpPurchasePlanDeliveryImportVo r : valid) { - String g = normCoil(r.getGrade()); - if (StringUtils.isBlank(g)) { - badGrades.add("(空牌号)"); - } else if (!reqGrades.contains(g)) { - badGrades.add(r.getGrade().trim()); - } - } - if (!badGrades.isEmpty()) { - String allow = planItems.stream().map(ErpPurchasePlanItem::getGrade) - .filter(StringUtils::isNotBlank).map(String::trim).distinct().collect(Collectors.joining("、")); - throw new ServiceException("到货表中的牌号 [" + String.join("、", badGrades) - + "] 不在本计划采购要求的牌号范围内(仅允许:" + allow + "),请核对后重新上传"); - } - } - // 3) kg→t 单位判定(文件级:单卷重量最大值超阈值视为 kg) + // 2) kg→t 单位判定(文件级:单卷重量最大值超阈值视为 kg) BigDecimal maxCoil = valid.stream() .map(ErpPurchasePlanDeliveryImportVo::getCoilWeight) .filter(w -> w != null) @@ -373,29 +337,26 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { .orElse(BigDecimal.ZERO); boolean kgConverted = maxCoil.compareTo(KG_THRESHOLD) > 0; - // 4) 卷号去 WMS 钢卷表校验:存在且 data_type<>10 即视为已实际到货入库 + // 3) 卷号去 WMS 钢卷表分类:存在且 data_type<>10=已到货;data_type=10=在途;查不到=未到 List uploadCoilNos = valid.stream() .map(ErpPurchasePlanDeliveryImportVo::getCoilNo) - .filter(StringUtils::isNotBlank) - .map(String::trim) + .filter(StringUtils::isNotBlank).map(String::trim) .collect(Collectors.toList()); - Set wmsArrivedSet = uploadCoilNos.isEmpty() ? new HashSet<>() - : baseMapper.selectExistingSupplierCoilNos(uploadCoilNos).stream() - .map(this::normCoil).collect(Collectors.toSet()); + Set arrivedSet = uploadCoilNos.isEmpty() ? new HashSet<>() + : baseMapper.selectExistingSupplierCoilNos(uploadCoilNos).stream().map(this::normCoil).collect(Collectors.toSet()); + Set inTransitSet = uploadCoilNos.isEmpty() ? new HashSet<>() + : baseMapper.selectInTransitSupplierCoilNos(uploadCoilNos).stream().map(this::normCoil).collect(Collectors.toSet()); - // 5) 先建批次(每次上传存档,可随时回看) - ErpPurchasePlanDeliveryBatch batch = new ErpPurchasePlanDeliveryBatch(); - batch.setPlanId(planId); - batch.setFileName(StringUtils.isNotBlank(fileName) ? fileName : "到货表"); - deliveryBatchMapper.insert(batch); + // 4) 覆盖式:每次上传只用最新文件,先清掉该计划旧到货记录 + deliveryMapper.delete(Wrappers.lambdaQuery(ErpPurchasePlanDelivery.class).eq(ErpPurchasePlanDelivery::getPlanId, planId)); - // 6) 落库 + 单位换算 + WMS到货标记 + // 5) 落库 + 单位换算 + 到货/在途标记 // 合并单元格:车号(F)几卷共用一车 → 向下填充让每卷都带车号; - // 数量(G=整车总重)/件数(H=整车件数) 是「整车合计」,只记在该车首行(其余行留空), - // 避免按行重复计数(用户:一共3件,不是每行3件)。 + // 数量(G=整车总重)/件数(H=整车件数) 是整车合计,只记在该车首行,不向下填充。 String lastTruckNo = null; int count = 0; - int matched = 0; + int arrivedNum = 0; + int transitNum = 0; for (ErpPurchasePlanDeliveryImportVo row : rows) { if (StringUtils.isNotBlank(row.getTruckNo())) { lastTruckNo = row.getTruckNo(); @@ -403,20 +364,19 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { if (StringUtils.isBlank(row.getCoilNo()) && row.getCoilWeight() == null) { continue; } - boolean arrived = StringUtils.isNotBlank(row.getCoilNo()) && wmsArrivedSet.contains(normCoil(row.getCoilNo())); + String coil = normCoil(row.getCoilNo()); + boolean arrived = !coil.isEmpty() && arrivedSet.contains(coil); + boolean transit = !arrived && !coil.isEmpty() && inTransitSet.contains(coil); ErpPurchasePlanDelivery d = new ErpPurchasePlanDelivery(); d.setPlanId(planId); - d.setBatchId(batch.getBatchId()); d.setArrived(arrived ? 1 : 0); + d.setInTransit(transit ? 1 : 0); d.setArrivalDate(parseDate(row.getArrivalDate())); d.setGrade(row.getGrade()); d.setSpec(row.getSpec()); d.setCoilNo(row.getCoilNo()); d.setCoilWeight(convertWeight(row.getCoilWeight(), kgConverted)); - // 车号:每卷归属的车(向下填充) d.setTruckNo(StringUtils.isNotBlank(row.getTruckNo()) ? row.getTruckNo() : lastTruckNo); - // 整车总重 / 件数:整车合计,仅该车首行有值,不向下填充 - // 数量/件数 作为 String 读取以兼容合并单元格的空白/点号等占位符,在此 parse d.setTruckWeight(convertWeight(parseDecimal(row.getTruckWeight()), kgConverted)); d.setPieceCount(parseInteger(row.getPieceCount())); d.setSalesCode(row.getSalesCode()); @@ -424,20 +384,16 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { deliveryMapper.insert(d); count++; if (arrived) { - matched++; + arrivedNum++; + } else if (transit) { + transitNum++; } } - // 7) 汇总刷新进度 + // 6) 汇总刷新进度 refreshProgress(planId); - // 8) 回填批次统计(行数、WMS确认到货卷数、上传后进度快照) - ErpPurchasePlan after = baseMapper.selectById(planId); - batch.setRowCount(count); - batch.setMatchedCount(matched); - batch.setArrivedPercent(calcPct(after.getArrivedWeight(), after.getPlanWeight())); - deliveryBatchMapper.updateById(batch); - - StringBuilder msg = new StringBuilder("成功导入 " + count + " 条到货记录,其中 " + matched + " 卷在钢卷表确认到货"); + int notArrived = count - arrivedNum - transitNum; + StringBuilder msg = new StringBuilder("导入 " + count + " 条:已到 " + arrivedNum + " 卷,在途 " + transitNum + " 卷,未到 " + notArrived + " 卷"); if (kgConverted) { msg.append(";检测到重量疑似按 kg 录入(最大单卷 ") .append(maxCoil.stripTrailingZeros().toPlainString()) @@ -445,7 +401,8 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { } Map result = new HashMap<>(6); result.put("count", count); - result.put("matched", matched); + result.put("arrived", arrivedNum); + result.put("inTransit", transitNum); result.put("kgConverted", kgConverted); result.put("message", msg.toString()); return result; @@ -508,17 +465,8 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { } @Override - public List queryDeliveryListByBatch(Long batchId) { - return deliveryMapper.selectVoList(Wrappers.lambdaQuery(ErpPurchasePlanDelivery.class) - .eq(ErpPurchasePlanDelivery::getBatchId, batchId) - .orderByDesc(ErpPurchasePlanDelivery::getDeliveryId)); - } - - @Override - public List queryDeliveryBatches(Long planId) { - return deliveryBatchMapper.selectVoList(Wrappers.lambdaQuery(ErpPurchasePlanDeliveryBatch.class) - .eq(ErpPurchasePlanDeliveryBatch::getPlanId, planId) - .orderByDesc(ErpPurchasePlanDeliveryBatch::getBatchId)); + public List queryManufacturers(String keyword) { + return baseMapper.selectDistinctManufacturers(keyword); } @Override @@ -568,27 +516,39 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { .filter(StringUtils::isNotBlank) .map(String::trim) .collect(Collectors.toList()); - Set wmsArrivedSet = coilNos.isEmpty() ? new HashSet<>() - : baseMapper.selectExistingSupplierCoilNos(coilNos).stream() - .map(this::normCoil).collect(Collectors.toSet()); + Set arrivedSet = coilNos.isEmpty() ? new HashSet<>() + : baseMapper.selectExistingSupplierCoilNos(coilNos).stream().map(this::normCoil).collect(Collectors.toSet()); + Set inTransitSet = coilNos.isEmpty() ? new HashSet<>() + : baseMapper.selectInTransitSupplierCoilNos(coilNos).stream().map(this::normCoil).collect(Collectors.toSet()); int arrivedCount = 0; + int transitCount = 0; BigDecimal arrivedWeight = BigDecimal.ZERO; + BigDecimal transitWeight = BigDecimal.ZERO; for (ErpPurchasePlanDelivery d : deliveries) { - int nowArrived = StringUtils.isNotBlank(d.getCoilNo()) && wmsArrivedSet.contains(normCoil(d.getCoilNo())) ? 1 : 0; - // 状态有变化才回写,减少无谓更新 - if (d.getArrived() == null || d.getArrived() != nowArrived) { + String coil = normCoil(d.getCoilNo()); + int nowArrived = !coil.isEmpty() && arrivedSet.contains(coil) ? 1 : 0; + int nowTransit = nowArrived == 0 && !coil.isEmpty() && inTransitSet.contains(coil) ? 1 : 0; + if (d.getArrived() == null || d.getArrived() != nowArrived + || d.getInTransit() == null || d.getInTransit() != nowTransit) { d.setArrived(nowArrived); + d.setInTransit(nowTransit); deliveryMapper.updateById(d); } + BigDecimal w = d.getCoilWeight() == null ? BigDecimal.ZERO : d.getCoilWeight(); if (nowArrived == 1) { arrivedCount++; - arrivedWeight = arrivedWeight.add(d.getCoilWeight() == null ? BigDecimal.ZERO : d.getCoilWeight()); + arrivedWeight = arrivedWeight.add(w); + } else if (nowTransit == 1) { + transitCount++; + transitWeight = transitWeight.add(w); } } plan.setArrivedCount(arrivedCount); plan.setArrivedWeight(arrivedWeight); - // 到货重量达到计划要求总重量 → 自动归档 + plan.setInTransitCount(transitCount); + plan.setInTransitWeight(transitWeight); + // 到货重量达到要求总重量 → 自动归档 BigDecimal planWeight = plan.getPlanWeight() == null ? BigDecimal.ZERO : plan.getPlanWeight(); boolean done = planWeight.compareTo(BigDecimal.ZERO) > 0 && arrivedWeight.compareTo(planWeight) >= 0; plan.setPlanStatus(done ? PLAN_STATUS_ARCHIVED : PLAN_STATUS_ONGOING); @@ -612,12 +572,9 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { return map; } - /** 同时填充按重量、按卷数两个到货百分比 */ + /** 到货百分比按重量 = 已到货重量 / 要求总重量 */ private void fillProgress(ErpPurchasePlanVo v) { v.setProgress(calcPct(v.getArrivedWeight(), v.getPlanWeight())); - v.setProgressQty(calcPct( - v.getArrivedCount() == null ? null : BigDecimal.valueOf(v.getArrivedCount()), - v.getPlanQty() == null ? null : BigDecimal.valueOf(v.getPlanQty()))); } /** 百分比(0-100,保留2位) = num/den,封顶100 */ @@ -630,13 +587,13 @@ public class ErpPurchasePlanServiceImpl implements IErpPurchasePlanService { return pct.min(BigDecimal.valueOf(100)); } - /** 自动生成计划号:CG + yyyyMMdd + 4位流水 */ + /** 自动生成合同号:yyyyMMdd-当日序号(如 20260629-1) */ private String generatePlanNo() { - String prefix = "CG" + DateUtil.format(new Date(), "yyyyMMdd"); + String prefix = DateUtil.format(new Date(), "yyyyMMdd"); Long todayCount = baseMapper.selectCount(Wrappers.lambdaQuery(ErpPurchasePlan.class) - .likeRight(ErpPurchasePlan::getPlanNo, prefix)); + .likeRight(ErpPurchasePlan::getPlanNo, prefix + "-")); long seq = (todayCount == null ? 0L : todayCount) + 1L; - return prefix + String.format("%04d", seq); + return prefix + "-" + seq; } private Date parseDate(String text) { diff --git a/klp-erp/src/main/resources/mapper/erp/ErpPurchasePlanMapper.xml b/klp-erp/src/main/resources/mapper/erp/ErpPurchasePlanMapper.xml index 2fbeaed64..9bc505264 100644 --- a/klp-erp/src/main/resources/mapper/erp/ErpPurchasePlanMapper.xml +++ b/klp-erp/src/main/resources/mapper/erp/ErpPurchasePlanMapper.xml @@ -77,6 +77,31 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + + +