diff --git a/src/main/java/com/gaotao/modules/check/controller/PhysicalInventoryController.java b/src/main/java/com/gaotao/modules/check/controller/PhysicalInventoryController.java index 727460f2..e48e979c 100644 --- a/src/main/java/com/gaotao/modules/check/controller/PhysicalInventoryController.java +++ b/src/main/java/com/gaotao/modules/check/controller/PhysicalInventoryController.java @@ -494,6 +494,15 @@ public class PhysicalInventoryController { physicalInventoryService.updateSysIfCount(site, value); return R.ok(); } + + /** + * @Description 生成年度盘点报告(年中/年末),在盘点模式下按在库标签生成已完成单 - rqrq + * @author rqrq + */ + @PostMapping("/generateYearInventoryReport") + public R generateYearInventoryReport(@RequestBody java.util.Map query) { + return physicalInventoryService.generateYearInventoryReport(query); + } // ==================== 自动盘盈盘亏处理 ==================== - rqrq diff --git a/src/main/java/com/gaotao/modules/check/entity/CountHeader.java b/src/main/java/com/gaotao/modules/check/entity/CountHeader.java index 17891bc0..fc606feb 100644 --- a/src/main/java/com/gaotao/modules/check/entity/CountHeader.java +++ b/src/main/java/com/gaotao/modules/check/entity/CountHeader.java @@ -22,7 +22,7 @@ import java.util.Date; *

核心字段说明:

* @@ -73,6 +73,9 @@ public class CountHeader { * */ @TableField("count_type") @@ -174,6 +177,10 @@ public class CountHeader { public static final String COUNT_TYPE_MANUAL = "MANUAL"; /** 盘点类型:日常盘点(WCS日常RFID盘点)- rqrq */ public static final String COUNT_TYPE_DAILY = "DAILY"; + /** 盘点类型:年中盘点(年度盘点报告,写入 count_header.count_type)- rqrq */ + public static final String COUNT_TYPE_MID_YEAR = "MID_YEAR"; + /** 盘点类型:年末盘点(年度盘点报告,写入 count_header.count_type)- rqrq */ + public static final String COUNT_TYPE_YEAR_END = "YEAR_END"; /** 状态:草稿 */ public static final String STATUS_DRAFT = "DRAFT"; diff --git a/src/main/java/com/gaotao/modules/check/mapper/PhysicalInventoryMapper.java b/src/main/java/com/gaotao/modules/check/mapper/PhysicalInventoryMapper.java index f17a71cb..25287232 100644 --- a/src/main/java/com/gaotao/modules/check/mapper/PhysicalInventoryMapper.java +++ b/src/main/java/com/gaotao/modules/check/mapper/PhysicalInventoryMapper.java @@ -478,6 +478,31 @@ public interface PhysicalInventoryMapper extends BaseMapper { * @author rqrq */ int insertCountHeader(@Param("header") CountHeader header); + + /** + * @Description 在库且未盘点标签数量(年度盘点报告校验)- rqrq + */ + int countInStockUncountedLabels(@Param("site") String site); + + /** + * @Description 在库且未盘点标签号前 20 条 - rqrq + */ + List listInStockUncountedUnitIdsTop(@Param("site") String site); + + /** + * @Description 在库且已盘点标签数(in_stock_flag=Y 且 count_flag=Y),年度报告准入 - rqrq + */ + int countHandlingUnitInStock(@Param("site") String site); + + /** + * @Description 年度盘点报告:符合条件标签批量插入 count_label - rqrq + */ + int insertYearReportCountLabelFromHandlingUnit(@Param("site") String site, @Param("countNo") String countNo, @Param("username") String username); + + /** + * @Description 年度盘点报告:符合条件标签批量插入 count_result - rqrq + */ + int insertYearReportCountResultFromHandlingUnit(@Param("site") String site, @Param("countNo") String countNo, @Param("username") String username); /** * @Description 删除盘点主表 - rqrq diff --git a/src/main/java/com/gaotao/modules/check/service/PhysicalInventoryService.java b/src/main/java/com/gaotao/modules/check/service/PhysicalInventoryService.java index 35eb0d73..46fbec12 100644 --- a/src/main/java/com/gaotao/modules/check/service/PhysicalInventoryService.java +++ b/src/main/java/com/gaotao/modules/check/service/PhysicalInventoryService.java @@ -1,6 +1,7 @@ package com.gaotao.modules.check.service; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.gaotao.common.utils.R; import com.gaotao.modules.automatedWarehouse.entity.WmsOrderTaskData; import com.gaotao.modules.automatedWarehouse.entity.WmsOrderTaskDetailData; import com.gaotao.modules.check.entity.*; @@ -407,5 +408,12 @@ public interface PhysicalInventoryService { */ void updateSysIfCount(String site, String value); + /** + * @Description 年度盘点报告:校验盘点模式与未盘点标签,生成已完成盘点单及 count_label/count_result(不写 count_pallet)- rqrq + * @param query site、username、countType(MID_YEAR/YEAR_END)、remark、forceContinue(可选二次提交) + * @return R 成功 put row(countNo/labelCount/resultCount);未盘点拦截 code=460 + * @author rqrq + */ + R generateYearInventoryReport(java.util.Map query); } diff --git a/src/main/java/com/gaotao/modules/check/service/impl/PhysicalInventoryServiceImpl.java b/src/main/java/com/gaotao/modules/check/service/impl/PhysicalInventoryServiceImpl.java index 978bd3fc..b7259ea1 100644 --- a/src/main/java/com/gaotao/modules/check/service/impl/PhysicalInventoryServiceImpl.java +++ b/src/main/java/com/gaotao/modules/check/service/impl/PhysicalInventoryServiceImpl.java @@ -11,6 +11,7 @@ import com.gaotao.modules.automatedWarehouse.mapper.WcsIntegrationMapper; import com.gaotao.modules.check.entity.*; import com.gaotao.modules.check.mapper.PhysicalInventoryMapper; import com.gaotao.modules.check.service.PhysicalInventoryService; +import com.gaotao.common.utils.R; import com.gaotao.modules.trans.entity.TransNoControl; import com.gaotao.modules.trans.service.TransNoControlService; import com.gaotao.modules.api.entity.NotifyDataToWcs; @@ -2721,4 +2722,72 @@ public class PhysicalInventoryServiceImpl extends ServiceImpl query) { + String site = query.get("site") != null ? String.valueOf(query.get("site")).trim() : ""; + String username = query.get("username") != null ? String.valueOf(query.get("username")).trim() : ""; + String countType = query.get("countType") != null ? String.valueOf(query.get("countType")).trim() : ""; + String remark = query.get("remark") != null ? String.valueOf(query.get("remark")).trim() : ""; + Object fc = query.get("forceContinue"); + boolean forceContinue = Boolean.TRUE.equals(fc) + || "true".equalsIgnoreCase(String.valueOf(fc)); + + if (!StringUtils.hasText(site)) { + return R.error("工厂编码不能为空"); + } + if (!StringUtils.hasText(username)) { + return R.error("操作用户不能为空"); + } + if (!CountHeader.COUNT_TYPE_MID_YEAR.equals(countType) && !CountHeader.COUNT_TYPE_YEAR_END.equals(countType)) { + return R.error("盘点报告类型无效,请选择年中盘点或年末盘点"); + } + if (!"Y".equals(baseMapper.getSysIfCount(site))) { + return R.error("当前未开启盘点模式,无法生成年度盘点报告"); + } + + int inStockCnt = baseMapper.countHandlingUnitInStock(site); + if (inStockCnt <= 0) { + return R.error("没有在库且已盘点(in_stock_flag=Y 且 count_flag=Y)的标签,无法生成年度盘点报告"); // 业务口径 - rqrq + } + + int uncounted = baseMapper.countInStockUncountedLabels(site); + if (uncounted > 0 && !forceContinue) { + List ids = baseMapper.listInStockUncountedUnitIdsTop(site); + String sample = ids.isEmpty() ? "" : String.join("、", ids); + String msg = String.format("存在未盘点在库标签共 %d 条,前 20 个标签号:%s。是否仍要继续生成?", uncounted, sample); + return R.error(460, msg).put("uncountedTotal", uncounted).put("uncountedUnitIds", ids); + } + + TransNoControl transData = transNoService.getTransNo(site, "PD", 10); + String countNo = transData.getNewTransNo(); + + CountHeader header = new CountHeader(); + header.setSite(site); + header.setCountNo(countNo); + header.setCountType(countType); + header.setStatus(CountHeader.STATUS_COMPLETED); + header.setCountPercent(null); + header.setApplyUser(username); + header.setReleaseUser(username); + header.setCompleteUser(username); + header.setRemark(StringUtils.hasText(remark) ? remark : "年度盘点报告"); + header.setCreatedBy(username); + baseMapper.insertCountHeader(header); + + int labelRows = baseMapper.insertYearReportCountLabelFromHandlingUnit(site, countNo, username); + int resultRows = baseMapper.insertYearReportCountResultFromHandlingUnit(site, countNo, username); + + Map row = new HashMap<>(); + row.put("countNo", countNo); + row.put("labelCount", labelRows); + row.put("resultCount", resultRows); + log.info("年度盘点报告生成完成 - rqrq,site={},countNo={},labelCount={},resultCount={}", site, countNo, labelRows, resultRows); + return R.ok().put("row", row); + } } diff --git a/src/main/resources/mapper/check/PhysicalInventoryMapper.xml b/src/main/resources/mapper/check/PhysicalInventoryMapper.xml index 6becc5dc..9756d88c 100644 --- a/src/main/resources/mapper/check/PhysicalInventoryMapper.xml +++ b/src/main/resources/mapper/check/PhysicalInventoryMapper.xml @@ -26,6 +26,8 @@ WHEN 'CYCLE' THEN '循环盘点' WHEN 'MANUAL' THEN '手工盘点' WHEN 'DAILY' THEN '日常盘点' + WHEN 'MID_YEAR' THEN '年中盘点' + WHEN 'YEAR_END' THEN '年末盘点' ELSE h.count_type END AS countTypeDesc, CASE h.status @@ -118,7 +120,7 @@ h.remark, h.created_by AS createdBy, h.created_date AS createdDate, - CASE h.count_type WHEN 'CYCLE' THEN '循环盘点' WHEN 'MANUAL' THEN '手工盘点' WHEN 'DAILY' THEN '日常盘点' ELSE h.count_type END AS countTypeDesc, + CASE h.count_type WHEN 'CYCLE' THEN '循环盘点' WHEN 'MANUAL' THEN '手工盘点' WHEN 'DAILY' THEN '日常盘点' WHEN 'MID_YEAR' THEN '年中盘点' WHEN 'YEAR_END' THEN '年末盘点' ELSE h.count_type END AS countTypeDesc, CASE h.status WHEN 'DRAFT' THEN '草稿' WHEN 'RELEASED' THEN '已下达' WHEN 'CHECKING' THEN '盘点中' WHEN 'APPROVED' THEN '已审批' WHEN 'COMPLETED' THEN '已完成' WHEN 'CANCELLED' THEN '已取消' ELSE h.status END AS statusDesc, (SELECT COUNT(1) FROM count_label WHERE site = h.site AND count_no = h.count_no) AS totalLabelCount, (SELECT COUNT(1) FROM count_label WHERE site = h.site AND count_no = h.count_no AND count_flag = 'Y') AS checkedLabelCount, @@ -878,11 +880,119 @@ WHERE site = #{header.site} AND count_no = #{header.countNo} - + - INSERT INTO count_header (site, count_no, count_type, status, count_percent, apply_user, apply_date, remark, created_by, created_date) + INSERT INTO count_header (site, count_no, count_type, status, count_percent, apply_user, apply_date, remark, created_by, created_date + + , release_user, release_date + + + , complete_user, complete_date + + ) VALUES (#{header.site}, #{header.countNo}, #{header.countType}, #{header.status}, #{header.countPercent}, - #{header.applyUser}, GETDATE(), #{header.remark}, #{header.createdBy}, GETDATE()) + #{header.applyUser}, GETDATE(), #{header.remark}, #{header.createdBy}, GETDATE() + + , #{header.releaseUser}, GETDATE() + + + , #{header.completeUser}, GETDATE() + + ) + + + + + + + + + + + + + + INSERT INTO count_label ( + site, count_no, unit_id, part_no, qty, + batch_no, location_id, warehouse_id, wdr, pallet_id, + label_type, count_flag, count_date, count_user, + created_by, created_date + ) + SELECT + h.site, + #{countNo}, + h.unit_id, + h.part_no, + h.qty, + h.batch_no, + h.location_id, + h.warehouse_id, + h.wdr, + '*', + 'ASSIGNED', + 'Y', + COALESCE(h.last_count_date, h.modified_date, h.created_date, GETDATE()), + 'SYSTEM', + #{username}, + GETDATE() + FROM handling_unit h WITH (NOLOCK) + WHERE h.site = #{site} + AND h.in_stock_flag = 'Y' + AND h.count_flag = 'Y' + + + + + INSERT INTO count_result ( + site, count_no, unit_id, part_no, qty, + batch_no, location_id, warehouse_id, wdr, pallet_id, + count_date, count_user, count_result, diff_qty, + handle_flag, handle_type, remark, + created_by, created_date + ) + SELECT + h.site, + #{countNo}, + h.unit_id, + h.part_no, + h.qty, + h.batch_no, + h.location_id, + h.warehouse_id, + h.wdr, + '*', + COALESCE(h.last_count_date, h.modified_date, h.created_date, GETDATE()), + 'SYSTEM', + 'OK', + 0, + 'Y', + '', + N'年度盘点报告(无差异)', + #{username}, + GETDATE() + FROM handling_unit h WITH (NOLOCK) + WHERE h.site = #{site} + AND h.in_stock_flag = 'Y' + AND h.count_flag = 'Y'