diff --git a/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java b/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java index 18d16e2..3054177 100644 --- a/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java +++ b/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java @@ -284,4 +284,17 @@ public class RkInfoController extends BaseController return toAjax(rkInfoService.updateBillInfo(rkInfo)); } + /** + * 相同入库单据号追加入库 + * @param dto + * @return + */ + @PostMapping("/append") + @PreAuthorize("@ss.hasPermi('wisdom:stock:add')") + @Log(title = "追加入库", businessType = BusinessType.INSERT) + public AjaxResult append(@RequestBody PcRkInfoBatchDTO dto) { + rkInfoService.appendToExistingBill(dto); + return AjaxResult.success("追加入库成功"); + } + } diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java index 4f603c2..9bcad5c 100644 --- a/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java +++ b/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java @@ -11,6 +11,9 @@ import java.util.List; @Data public class PcRkInfoBatchDTO { + /** 要追加到的入库单据号(必填) */ + private String billNo; + /** 审核人用户ID */ private String approverId; diff --git a/src/main/java/com/zg/project/wisdom/mapper/RkInfoMapper.java b/src/main/java/com/zg/project/wisdom/mapper/RkInfoMapper.java index 2fccbd7..95e981c 100644 --- a/src/main/java/com/zg/project/wisdom/mapper/RkInfoMapper.java +++ b/src/main/java/com/zg/project/wisdom/mapper/RkInfoMapper.java @@ -239,4 +239,5 @@ public interface RkInfoMapper Long selectPcde(RkInfo query); int updateBillInfo(RkInfo query); + } diff --git a/src/main/java/com/zg/project/wisdom/service/IRkInfoService.java b/src/main/java/com/zg/project/wisdom/service/IRkInfoService.java index eb1b193..af4326a 100644 --- a/src/main/java/com/zg/project/wisdom/service/IRkInfoService.java +++ b/src/main/java/com/zg/project/wisdom/service/IRkInfoService.java @@ -173,4 +173,10 @@ public interface IRkInfoService Long selectPcde(RkInfo query); public int updateBillInfo(RkInfo rkInfo); + + /** + * 追加入库 + * @param dto + */ + void appendToExistingBill(PcRkInfoBatchDTO dto); } diff --git a/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java b/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java index 8574e8c..73c3abd 100644 --- a/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java +++ b/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java @@ -23,7 +23,6 @@ import com.zg.project.system.service.ISysConfigService; import com.zg.project.wisdom.domain.AuditSignature; import com.zg.project.wisdom.domain.GysJh; import com.zg.project.wisdom.domain.dto.*; -import com.zg.project.wisdom.domain.vo.PcodeQtyVO; import com.zg.project.wisdom.mapper.AuditSignatureMapper; import com.zg.project.wisdom.mapper.GysJhMapper; import com.zg.project.wisdom.utils.BillNoUtil; @@ -36,6 +35,8 @@ import com.zg.project.wisdom.domain.RkInfo; import com.zg.project.wisdom.service.IRkInfoService; import org.springframework.transaction.annotation.Transactional; +import static com.zg.common.utils.SecurityUtils.getUsername; + /** * 库存单据主Service业务层处理 * @@ -259,7 +260,7 @@ public class RkInfoServiceImpl implements IRkInfoService RkInfo update = new RkInfo(); update.setId(id); update.setIsChuku("4"); // 4 = 已撤销 - update.setUpdateBy(SecurityUtils.getUsername()); + update.setUpdateBy(getUsername()); update.setUpdateTime(DateUtils.getNowDate()); return rkInfoMapper.updateRkInfo(update); @@ -927,7 +928,7 @@ public class RkInfoServiceImpl implements IRkInfoService update.setId(originalId); update.setIsBorrowed("2"); update.setReturnTime(DateUtils.getNowDate()); - update.setUpdateBy(SecurityUtils.getUsername()); + update.setUpdateBy(getUsername()); update.setUpdateTime(DateUtils.getNowDate()); rkInfoMapper.updateById(update); @@ -940,7 +941,7 @@ public class RkInfoServiceImpl implements IRkInfoService RkInfo update = new RkInfo(); update.setId(id); update.setIsChuku("5"); - update.setUpdateBy(SecurityUtils.getUsername()); + update.setUpdateBy(getUsername()); update.setUpdateTime(DateUtils.getNowDate()); // 执行更新 @@ -1019,8 +1020,118 @@ public class RkInfoServiceImpl implements IRkInfoService return rkInfoMapper.updateBillInfo(query); } + @Override + @Transactional(rollbackFor = Exception.class) + public void appendToExistingBill(PcRkInfoBatchDTO dto) { + // ========== 参数校验 ========== + if (StringUtils.isEmpty(dto.getBillNo())) { + throw new ServiceException("入库单号 billNo 不能为空"); + } + if (dto.getRkList() == null || dto.getRkList().isEmpty()) { + throw new ServiceException("追加明细不能为空"); + } + // ========== 1. 校验原单据是否存在 ========== + List exists = rkInfoMapper.selectRkInfoListByBillNo(dto.getBillNo()); + if (exists == null || exists.isEmpty()) { + throw new ServiceException("目标入库单不存在:" + dto.getBillNo()); + } + Date now = DateUtils.getNowDate(); + String user = getUsername(); + // ========== 2. 组装并插入追加的入库明细(无审批:直接入库) ========== + List toSave = new ArrayList<>(dto.getRkList().size()); + Date rkTime = dto.getRkTime() != null ? dto.getRkTime() : now; + for (PcRkInfoItemDTO item : dto.getRkList()) { + RkInfo e = new RkInfo(); + BeanUtils.copyProperties(item, e); // 拷贝 DTO 相同字段 + + // 公共字段 + e.setBillNo(dto.getBillNo()); + e.setRkType(dto.getRkType()); + e.setWlType(dto.getWlType()); + e.setCangku(dto.getCangku()); + e.setLihuoY(dto.getLihuoY()); + e.setRkTime(rkTime); + + // 入库状态(未启用审批) + e.setIsChuku("0"); // 已入库 + e.setStatus("1"); // 正常 + e.setIsDelete("0"); + + e.setCreateBy(user); + e.setCreateTime(now); + e.setUpdateBy(user); + e.setUpdateTime(now); + + toSave.add(e); + } + rkInfoMapper.batchInsertRkInfo(toSave); + + // ========== 3. 更新供应计划(关键改动):只在“部分入库”时扣减 ========== + for (PcRkInfoItemDTO item : dto.getRkList()) { + Long jhId = item.getGysJhId(); + BigDecimal realQty = item.getRealQty(); + if (jhId == null || realQty == null) continue; + + // 查当前计划行 + GysJh plan = gysJhMapper.selectGysJhById(jhId); + if (plan == null) continue; + + // 已经标记为全部入库的行,直接跳过(既不扣减也不改) + if ("1".equals(plan.getStatus())) { + continue; + } + + // 计划剩余(表里 jh_qty 列) + BigDecimal remain = plan.getJhQty() == null + ? BigDecimal.ZERO + : BigDecimal.valueOf(plan.getJhQty()); + + // ① 全额入库:realQty >= remain -> 直接置 1,不做扣减 + if (remain.compareTo(BigDecimal.ZERO) <= 0 || realQty.compareTo(remain) >= 0) { + gysJhMapper.updateStatusById(jhId, "1"); // 全部入库 + // 不调用 decreaseJhQtyById,避免出现负数 + continue; + } + + // ② 部分入库:realQty < remain -> 先扣减,再把该行置 2 + gysJhMapper.decreaseJhQtyById(jhId, realQty); // jh_qty = jh_qty - realQty + gysJhMapper.updateStatusById(jhId, "2"); // 部分入库 + } + + // ========== 4. 按 sapNo 再做一轮收尾(把 <=0 的行批量收敛到 1,其余置 2)========== + // 说明:上面已经对每个行做了状态落地;此处是“兜底收敛”,确保同一 sapNo 下的行一致 + Set sapNos = dto.getRkList().stream() + .map(PcRkInfoItemDTO::getSapNo) + .filter(StringUtils::isNotEmpty) + .collect(Collectors.toSet()); + + for (String sapNo : sapNos) { + // 仅返回 status != '1' 的行(未完全入库的) + List rows = gysJhMapper.getBySapNo(sapNo); + if (rows == null || rows.isEmpty()) continue; + + List toAll = new ArrayList<>(); + List toPartial = new ArrayList<>(); + + for (GysJh r : rows) { + long remain = r.getJhQty() == null ? 0L : r.getJhQty(); + if (remain <= 0L) { + toAll.add(r.getId()); // 已经无剩余 -> 置 1 + } else { + toPartial.add(r.getId()); // 仍有剩余 -> 置 2 + } + } + + for (Long id : toAll) { + gysJhMapper.updateStatusById(id, "1"); // 全部入库 + } + if (!toPartial.isEmpty()) { + gysJhMapper.batchUpdateStatusByIds(new HashSet<>(toPartial)); // 部分入库 + } + } + } }