diff --git a/src/main/java/com/zg/project/wisdom/controller/DdTaskController.java b/src/main/java/com/zg/project/wisdom/controller/DdTaskController.java index 20087ad..82dfe1f 100644 --- a/src/main/java/com/zg/project/wisdom/controller/DdTaskController.java +++ b/src/main/java/com/zg/project/wisdom/controller/DdTaskController.java @@ -22,7 +22,7 @@ import org.springframework.security.access.prepost.PreAuthorize; * @author zg */ @RestController -@RequestMapping("/wisdom/task") +@RequestMapping("/wisdom/dispatch") public class DdTaskController extends BaseController { @Autowired 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 e19f367..a59a9e6 100644 --- a/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java +++ b/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java @@ -146,7 +146,7 @@ public class RkInfoController extends BaseController */ @PreAuthorize("@ss.hasPermi('wisdom:stock:edit')") @Log(title = "库存单据主", businessType = BusinessType.UPDATE) - @PutMapping("/update") + @PostMapping("/update") public AjaxResult edit(@RequestBody RkInfo rkInfo) { return toAjax(rkInfoService.updateRkInfo(rkInfo)); diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/StockOutItemDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/StockOutItemDTO.java index 6734873..4166de0 100644 --- a/src/main/java/com/zg/project/wisdom/domain/dto/StockOutItemDTO.java +++ b/src/main/java/com/zg/project/wisdom/domain/dto/StockOutItemDTO.java @@ -1,7 +1,10 @@ package com.zg.project.wisdom.domain.dto; +import com.zg.framework.aspectj.lang.annotation.Excel; import lombok.Data; +import java.math.BigDecimal; + /** * 出库明细 DTO */ @@ -20,6 +23,9 @@ public class StockOutItemDTO { /** 托盘码 */ private String trayCode; + /** 实际数量 */ + private BigDecimal realQty; + /** 现场照片(单张) */ private String photoUrl; // ✅ 一物一图绑定 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 5cd7a83..7c2d56c 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 @@ -348,6 +348,11 @@ public class RkInfoServiceImpl implements IRkInfoService } + /** + * 新增入库单据 + * @param dto + * @return + */ /** * 新增入库单据 * @param dto @@ -366,27 +371,30 @@ public class RkInfoServiceImpl implements IRkInfoService String userId = SecurityUtils.getUserId().toString(); Date now = DateUtils.getNowDate(); - // 🚩 0. 校验库位是否属于当前小仓 - validateWarehouseAndPcode(dto); + // ✅ 0. 只有前端传了库位编码,才做“库位属于当前小仓”的校验(否则不传库位会被拦截) + boolean hasPcode = list != null && list.stream() + .anyMatch(x -> StringUtils.isNotBlank(x.getPcode())); + if (hasPcode) { + validateWarehouseAndPcode(dto); + } - // ✅ 1. 供应计划扣减映射 + // ✅ 1. 供应计划扣减映射(同一个 gysJhId 多条明细时,realQty 累加) Map realQtyMap = list.stream() .filter(item -> item.getGysJhId() != null && item.getRealQty() != null) .collect(Collectors.toMap( PcRkInfoItemDTO::getGysJhId, PcRkInfoItemDTO::getRealQty, - (a, b) -> b + (a, b) -> a.add(b) )); - // ✅ 2-4. 供应计划扣减&状态更新 + // ✅ 2-4. 供应计划扣减&状态更新(保持你原逻辑) if (!realQtyMap.isEmpty()) { List jhList = gysJhMapper.selectByIds(new ArrayList<>(realQtyMap.keySet())); Set idsToUpdateStatus = new HashSet<>(); for (GysJh jh : jhList) { Long jhId = jh.getId(); - BigDecimal planQty = - jh.getJhQty() == null ? BigDecimal.ZERO : jh.getJhQty(); + BigDecimal planQty = jh.getJhQty() == null ? BigDecimal.ZERO : jh.getJhQty(); BigDecimal realQty = realQtyMap.get(jhId); if (realQty == null) { continue; @@ -395,13 +403,11 @@ public class RkInfoServiceImpl implements IRkInfoService boolean isEqual = realQty.compareTo(planQty) == 0; if (!isEqual) { - // 部分入库:扣减计划数量 gysJhMapper.decreaseJhQtyById(jhId, realQty); if (!needAudit) { gysJhMapper.updateStatusById(jhId, "2"); // 2 = 部分入库 } } else { - // 全部入库:状态=1 if (!needAudit) { gysJhMapper.updateStatusById(jhId, "1"); // 1 = 全部入库 } @@ -413,27 +419,18 @@ public class RkInfoServiceImpl implements IRkInfoService } } - // ✅ 5. 构建 RkInfo 入库记录(注意:小仓 = dto.getWarehouseCode()) + // ✅ 5. 构建 RkInfo 入库记录(库位字段按“前端是否传 pcode”决定是否设置) for (PcRkInfoItemDTO item : list) { RkInfo rk = new RkInfo(); - // 物料、项目、供应商、xj(县局)、数量等等从 item 拷贝 BeanUtils.copyProperties(item, rk); rk.setBillNo(billNo); rk.setRkType(dto.getRkType()); rk.setWlType(dto.getWlType()); rk.setLihuoY(dto.getLihuoY()); - - // 🚩 所属小仓:页面选的小仓编码 rk.setCangku(dto.getWarehouseCode()); - - // 🚩 入库时间:页面传,若为空则使用当前时间 rk.setRkTime(dto.getRkTime() != null ? dto.getRkTime() : DateUtils.getNowDate()); - // 库位 encodedId - String encodedId = pcdeDetailMapper.selectEncodedIdByPcode(item.getPcode()); - rk.setPcodeId(encodedId); - rk.setCreateBy(userId); rk.setCreateTime(now); rk.setIsDelete("0"); @@ -442,6 +439,35 @@ public class RkInfoServiceImpl implements IRkInfoService rk.setFycde1(item.getFycde1()); rk.setFycde2(item.getFycde2()); + // 库位编码前端不传,就不设置库位相关字段(并且不查 encodedId) + if (StringUtils.isNotBlank(item.getPcode())) { + // pcode 有值:允许设置/绑定库位 + rk.setPcode(item.getPcode()); + + // 只有有 pcode 才查 pcodeId + String encodedId = pcdeDetailMapper.selectEncodedIdByPcode(item.getPcode()); + rk.setPcodeId(encodedId); + + // 这些字段如果前端没传,保持 null;如果传了就写入 + if (StringUtils.isNotBlank(item.getTrayCode())) { + rk.setTrayCode(item.getTrayCode()); + } else { + rk.setTrayCode(null); + } + + if (StringUtils.isNotBlank(item.getEntityId())) { + rk.setEntityId(item.getEntityId()); + } else { + rk.setEntityId(null); + } + } else { + // pcode 不传:明确不设置库位信息 + rk.setPcode(null); + rk.setPcodeId(null); + rk.setTrayCode(null); + rk.setEntityId(null); + } + if (needAudit) { rk.setStatus("0"); // 待审核 rk.setIsChuku("2"); // 待入库(审核中) @@ -449,6 +475,7 @@ public class RkInfoServiceImpl implements IRkInfoService rk.setStatus("1"); // 审核通过 rk.setIsChuku("0"); // 已入库 } + rkInfos.add(rk); } @@ -465,15 +492,18 @@ public class RkInfoServiceImpl implements IRkInfoService AuditSignature photo = new AuditSignature(); photo.setRkId(rk.getId()); photo.setBillNo(billNo); - photo.setBillType("0"); // 入库 - photo.setAuditResult("2"); // 待审核 + photo.setBillType("0"); + photo.setAuditResult("2"); photo.setSignerId(userId); - photo.setSignerRole("2"); // 现场照片 - photo.setImageType("1"); // photo + photo.setSignerRole("2"); + photo.setImageType("1"); photo.setSignUrl(item.getPhotoUrl()); photo.setSignTime(now); - photo.setPcode(item.getPcode()); - photo.setTrayCode(item.getTrayCode()); + + // 这里照旧:有库位就写库位/托盘;没库位就是 null + photo.setPcode(rk.getPcode()); + photo.setTrayCode(rk.getTrayCode()); + photo.setApproverId(dto.getApproverId()); photo.setIsCurrent("1"); photo.setIsDelete("0"); @@ -493,15 +523,15 @@ public class RkInfoServiceImpl implements IRkInfoService AuditSignature mainSign = new AuditSignature(); mainSign.setBillNo(billNo); - mainSign.setBillType("0"); // 入库 + mainSign.setBillType("0"); mainSign.setSignerId(userId); - mainSign.setSignerRole("0"); // 发起人 + mainSign.setSignerRole("0"); mainSign.setApproverId(dto.getApproverId()); mainSign.setSignUrl(dto.getSignatureUrl()); - mainSign.setImageType("0"); // sign + mainSign.setImageType("0"); mainSign.setSignTime(now); mainSign.setIsCurrent("1"); - mainSign.setAuditResult("2"); // 待审核 + mainSign.setAuditResult("2"); mainSign.setIsDelete("0"); mainSign.setCreateBy(userId); mainSign.setCreateTime(now); @@ -871,42 +901,133 @@ public class RkInfoServiceImpl implements IRkInfoService boolean needAudit = "1".equals(configService.selectConfigByKey("rk.audit.enabled")); // Step 2: 生成出库单据号 - String billNo = BillNoUtil.generateTodayBillNo("RK", rkInfoMapper); + String billNo = BillNoUtil.generateTodayBillNo("CK", rkInfoMapper); - // Step 3: 批量更新 rk_info 出库字段 + // 记录:原记录id -> 出库记录id(部分出库时,照片要绑定到新插入的出库记录) + Map outRkIdMap = new HashMap<>(); + + // Step 3: 出库处理(支持部分出库) for (StockOutItemDTO item : dto.getCkList()) { - RkInfo update = new RkInfo(); - update.setId(item.getId()); - update.setBillNoCk(billNo); - update.setIsDelivery(dto.getIsDelivery()); - update.setCkType(dto.getCkType()); - update.setTeamCode(dto.getTeamCode()); - update.setLyTime(now); - update.setCkLihuoY(dto.getCkLihuoY()); - update.setCkRemark(item.getCkRemark()); - update.setXmNoCk(dto.getXmNoCk()); - update.setXmMsCk(dto.getXmMsCk()); - update.setUpdateBy(userId); - update.setUpdateTime(now); - if ("JLCK".equals(dto.getCkType())) { - update.setIsBorrowed("1"); - update.setBorrowTime(dto.getBorrowTime()); - update.setReturnTime(dto.getReturnTime()); + if (item.getId() == null) { + throw new ServiceException("出库记录ID不能为空"); + } + if (item.getRealQty() == null || item.getRealQty().compareTo(BigDecimal.ZERO) <= 0) { + throw new ServiceException("出库数量必须大于0,id=" + item.getId()); } - if (needAudit) { - update.setStatus("3"); // 出库待审核 - update.setIsChuku("JLCK".equals(dto.getCkType()) ? "3" : "2"); + // 3.1 查询原库存记录 + RkInfo db = rkInfoMapper.selectRkInfoById(item.getId()); + if (db == null) { + throw new ServiceException("库存记录不存在,id=" + item.getId()); + } + + BigDecimal oldQty = db.getRealQty() == null ? BigDecimal.ZERO : db.getRealQty(); + BigDecimal outQty = item.getRealQty(); + + // 3.2 校验不能超出库存 + BigDecimal newQty = oldQty.subtract(outQty); + if (newQty.compareTo(BigDecimal.ZERO) < 0) { + throw new ServiceException("出库数量不能大于库存数量,id=" + item.getId() + + ",库存=" + oldQty + ",出库=" + outQty); + } + + boolean partialOut = newQty.compareTo(BigDecimal.ZERO) > 0; + + if (partialOut) { + // ✅ 部分出库:原记录只扣减 real_qty + RkInfo reduce = new RkInfo(); + reduce.setId(db.getId()); + reduce.setRealQty(newQty); + reduce.setUpdateBy(userId); + reduce.setUpdateTime(now); + rkInfoMapper.updateById(reduce); + + // ✅ 插入一条新的“出库记录”:复制原记录 + 覆盖本次出库字段 + RkInfo outRow = new RkInfo(); + BeanUtils.copyProperties(db, outRow); + outRow.setId(null); + + // —— 出库这次操作字段 + outRow.setBillNoCk(billNo); + outRow.setIsDelivery(dto.getIsDelivery()); + outRow.setCkType(dto.getCkType()); + outRow.setTeamCode(dto.getTeamCode()); + outRow.setLyTime(now); + outRow.setCkLihuoY(dto.getCkLihuoY()); + outRow.setCkRemark(item.getCkRemark()); + outRow.setXmNoCk(dto.getXmNoCk()); + outRow.setXmMsCk(dto.getXmMsCk()); + + // 新出库记录数量=本次出库数量 + outRow.setRealQty(outQty); + + // 借料字段(仅 JLCK 才写) + if ("JLCK".equals(dto.getCkType())) { + outRow.setIsBorrowed("1"); + outRow.setBorrowTime(dto.getBorrowTime()); + outRow.setReturnTime(dto.getReturnTime()); + } + + // 审核状态 + is_chuku(部分出库:新出库记录按正常出库逻辑走) + if (needAudit) { + outRow.setStatus("3"); // 出库待审核 + outRow.setIsChuku("JLCK".equals(dto.getCkType()) ? "3" : "2"); + } else { + outRow.setStatus("1"); // 审核通过 + outRow.setIsChuku("JLCK".equals(dto.getCkType()) ? "3" : "1"); + } + + // 通用字段 + outRow.setIsDelete("0"); + outRow.setCreateBy(userId); + outRow.setCreateTime(now); + outRow.setUpdateBy(userId); + outRow.setUpdateTime(now); + + rkInfoMapper.insertRkInfo(outRow); + + // 记录映射:照片绑定新出库记录 + outRkIdMap.put(db.getId(), outRow.getId()); + } else { - update.setStatus("1"); // 审核通过 - update.setIsChuku("JLCK".equals(dto.getCkType()) ? "3" : "1"); - } + // ✅ 全部出库:不扣减 real_qty,直接改状态 + RkInfo update = new RkInfo(); + update.setId(item.getId()); + update.setBillNoCk(billNo); + update.setIsDelivery(dto.getIsDelivery()); + update.setCkType(dto.getCkType()); + update.setTeamCode(dto.getTeamCode()); + update.setLyTime(now); + update.setCkLihuoY(dto.getCkLihuoY()); + update.setCkRemark(item.getCkRemark()); + update.setXmNoCk(dto.getXmNoCk()); + update.setXmMsCk(dto.getXmMsCk()); + update.setUpdateBy(userId); + update.setUpdateTime(now); - rkInfoMapper.updateById(update); + if ("JLCK".equals(dto.getCkType())) { + update.setIsBorrowed("1"); + update.setBorrowTime(dto.getBorrowTime()); + update.setReturnTime(dto.getReturnTime()); + } + + if (needAudit) { + update.setStatus("3"); // 出库待审核 + update.setIsChuku("JLCK".equals(dto.getCkType()) ? "3" : "2"); + } else { + update.setStatus("1"); // 审核通过 + update.setIsChuku("JLCK".equals(dto.getCkType()) ? "3" : "1"); + } + + rkInfoMapper.updateById(update); + + // 全出库:照片绑定原记录 + outRkIdMap.put(item.getId(), item.getId()); + } } - // Step 4: 如果启用审核,写入签字记录 + // Step 4: 如果启用审核,写入签字记录(部分出库:照片绑定新出库记录ID) if (needAudit) { List recordList = new ArrayList<>(); @@ -934,6 +1055,8 @@ public class RkInfoServiceImpl implements IRkInfoService for (StockOutItemDTO item : dto.getCkList()) { if (StringUtils.isBlank(item.getPhotoUrl())) continue; + Long rkIdForPhoto = outRkIdMap.getOrDefault(item.getId(), item.getId()); + AuditSignature photo = new AuditSignature(); photo.setBillNo(billNo); photo.setBillType("1"); @@ -948,9 +1071,12 @@ public class RkInfoServiceImpl implements IRkInfoService photo.setIsDelete("0"); photo.setCreateBy(userId); photo.setCreateTime(now); - photo.setRkId(item.getId()); + + // ✅ 关键:部分出库绑定“新出库记录”的 rk_id + photo.setRkId(rkIdForPhoto); photo.setPcode(item.getPcode()); photo.setTrayCode(item.getTrayCode()); + recordList.add(photo); } @@ -962,6 +1088,7 @@ public class RkInfoServiceImpl implements IRkInfoService return dto.getCkList().size(); } + @Override @Transactional(rollbackFor = Exception.class) // 开启事务,异常时回滚 public void matchWithStatus(QueryDTO dto) { @@ -1256,7 +1383,7 @@ public class RkInfoServiceImpl implements IRkInfoService e.setBillNo(dto.getBillNo()); e.setRkType(dto.getRkType()); e.setWlType(dto.getWlType()); - e.setWarehouseCode(dto.getWarehouseCode()); + e.setCangku(dto.getWarehouseCode()); e.setLihuoY(dto.getLihuoY()); e.setRkTime(rkTime); diff --git a/src/main/resources/application-druid.yml b/src/main/resources/application-druid.yml index 3cde3ee..9111b2c 100644 --- a/src/main/resources/application-druid.yml +++ b/src/main/resources/application-druid.yml @@ -7,9 +7,9 @@ spring: # 主库数据源 master: # url: jdbc:mysql://101.132.133.142:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 -# url: jdbc:mysql://192.168.1.28:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 + url: jdbc:mysql://192.168.1.28:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # url: jdbc:mysql://192.168.1.192:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 - url: jdbc:mysql://192.168.1.251:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 +# url: jdbc:mysql://192.168.1.251:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 # url: jdbc:mysql://localhost:3306/wisdom?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: shzg diff --git a/src/main/resources/mybatis/wisdom/RkInfoMapper.xml b/src/main/resources/mybatis/wisdom/RkInfoMapper.xml index bf28bd0..2a8e3d6 100644 --- a/src/main/resources/mybatis/wisdom/RkInfoMapper.xml +++ b/src/main/resources/mybatis/wisdom/RkInfoMapper.xml @@ -183,6 +183,7 @@ ck_lihuo_y, ck_type, team_code, ck_remark, ly_time, bill_no_ck, has_moved, gys_jh_id, + status, create_by, create_time, update_by, update_time, is_delete ) VALUES ( #{rkType}, #{wlType}, #{cangku}, #{rkTime}, #{lihuoY}, @@ -193,6 +194,7 @@ #{ckLihuoY}, #{ckType}, #{teamCode}, #{ckRemark}, #{lyTime}, #{billNoCk}, #{hasMoved}, #{gysJhId}, + #{status}, #{createBy}, #{createTime}, #{updateBy}, #{updateTime}, #{isDelete} ) @@ -393,8 +395,9 @@ AND ri.is_delete = 0 - AND ri.is_chuku = '0' - + + AND ri.is_chuku = #{isChuku} + @@ -453,27 +456,20 @@ a.ck_lihuo_y, u.user_name AS ck_lihuo_y_name, ru.user_name AS lihuo_y_name, - a.is_delivery AS is_delivery + a.is_delivery AS is_delivery, + a.team_code, + ct.team_name AS team_name FROM ( SELECT MIN(t.id) AS id, - - /* ✅ 单据号:出库/借料出库 -> CK;其它 -> RK(用于页面展示) */ t.show_bill_no AS bill_no, - - /* 保留 bill_no_ck 字段(出库态有值) */ MIN(t.bill_no_ck) AS bill_no_ck, - MIN(t.rk_type) AS rk_type, MIN(t.wl_type) AS wl_type, MIN(t.cangku) AS cangku, - - /* 时间:你要更合理也可以改成 MAX(COALESCE(ly_time,rk_time)) */ MIN(t.rk_time) AS rk_time, - MIN(t.lihuo_y) AS lihuo_y, MAX(t.is_chuku) AS is_chuku, - MIN(t.xj) AS xj, MIN(t.xm_no) AS xm_no, MIN(t.xm_ms) AS xm_ms, @@ -484,14 +480,13 @@ MIN(t.wl_ms) AS wl_ms, MIN(t.gys_no) AS gys_no, MIN(t.sap_no) AS sap_no, - MIN(t.ck_type) AS ck_type, MAX(t.ly_time) AS ly_time, MIN(t.ck_lihuo_y) AS ck_lihuo_y, MIN(t.is_delivery) AS is_delivery, - - /* ✅ 用于 needAudit 子查询判断:本组是 RK 组还是 CK 组 */ - MIN(t.show_bill_type) AS show_bill_type + MIN(t.team_code) AS team_code, + MIN(t.show_bill_type) AS show_bill_type, + MAX(t.create_time) AS create_time FROM ( SELECT @@ -520,6 +515,8 @@ ri.pcode, ri.is_delete, ri.is_delivery, + ri.team_code, + ri.create_time, CASE WHEN ri.is_chuku IN ('1','3') @@ -528,7 +525,6 @@ THEN ri.bill_no_ck ELSE ri.bill_no END AS show_bill_no, - CASE WHEN ri.is_chuku IN ('1','3') AND ri.bill_no_ck IS NOT NULL @@ -536,162 +532,61 @@ THEN 'CK' ELSE 'RK' END AS show_bill_type - FROM rk_info ri - ) t - - - - - AND t.is_delete = #{q.isDelete} - - - AND t.is_delete = 0 - - + AND ri.is_delete = 0 - - - - AND t.is_chuku IN - - #{val} - - - - AND t.is_chuku = #{q.isChuku} - - - - - - = #{q.startTime} ]]> - - - + + + AND ri.is_chuku IN + + #{s} + - - - = #{q.lyStartTime} ]]> - - - + + + AND ri.is_chuku = #{q.isChuku} - - - AND t.rk_type LIKE concat('%', #{q.rkType}, '%') - - - AND t.wl_type LIKE concat('%', #{q.wlType}, '%') - - - AND t.cangku LIKE concat('%', #{q.cangku}, '%') - - - - AND t.lihuo_y LIKE concat('%', #{q.lihuoY}, '%') - - - AND t.xj LIKE concat('%', #{q.xj}, '%') - - - - - AND t.show_bill_no LIKE concat('%', #{q.billNo}, '%') - - - - - AND t.bill_no_ck LIKE concat('%', #{q.billNoCk}, '%') - - - - - AND t.xm_no LIKE concat('%', #{q.xmNo}, '%') - - - AND t.xm_ms LIKE concat('%', #{q.xmMs}, '%') - - - AND t.wl_no LIKE concat('%', #{q.wlNo}, '%') - - - AND t.wl_ms LIKE concat('%', #{q.wlMs}, '%') - - - AND t.gys_no LIKE concat('%', #{q.gysNo}, '%') - - - AND t.gys_mc LIKE concat('%', #{q.gysMc}, '%') - - - AND t.sap_no LIKE concat('%', #{q.sapNo}, '%') - - - AND t.pcode LIKE concat('%', #{q.pcode}, '%') - - - AND t.ck_type LIKE concat('%', #{q.ckType}, '%') - - - - AND t.is_delivery = #{q.isDelivery} - - - AND ( - t.xm_no LIKE concat('%', #{q.keyword}, '%') - OR t.xm_ms LIKE concat('%', #{q.keyword}, '%') - OR t.wl_no LIKE concat('%', #{q.keyword}, '%') - OR t.wl_ms LIKE concat('%', #{q.keyword}, '%') - OR t.gys_no LIKE concat('%', #{q.keyword}, '%') - OR t.gys_mc LIKE concat('%', #{q.keyword}, '%') - OR t.sap_no LIKE concat('%', #{q.keyword}, '%') - OR t.bill_no LIKE concat('%', #{q.keyword}, '%') - OR t.bill_no_ck LIKE concat('%', #{q.keyword}, '%') - OR t.show_bill_no LIKE concat('%', #{q.keyword}, '%') - OR t.ck_type LIKE concat('%', #{q.keyword}, '%') - OR t.pcode LIKE concat('%', #{q.keyword}, '%') + ri.bill_no LIKE concat('%', #{q.keyword}, '%') + OR ri.bill_no_ck LIKE concat('%', #{q.keyword}, '%') + OR ri.xm_no LIKE concat('%', #{q.keyword}, '%') + OR ri.xm_ms LIKE concat('%', #{q.keyword}, '%') + OR ri.wl_no LIKE concat('%', #{q.keyword}, '%') + OR ri.wl_ms LIKE concat('%', #{q.keyword}, '%') + OR ri.sap_no LIKE concat('%', #{q.keyword}, '%') + OR ri.gys_mc LIKE concat('%', #{q.keyword}, '%') ) - - - AND NOT EXISTS ( - SELECT 1 - FROM rk_info r2 - JOIN audit_signature asg - ON asg.rk_id = r2.id - AND asg.approver_id IS NOT NULL - AND (asg.audit_result IS NOT NULL AND asg.audit_result != '1') - WHERE r2.is_delete = 0 - AND ( - (t.show_bill_type = 'RK' AND r2.bill_no = t.show_bill_no) - OR (t.show_bill_type = 'CK' AND r2.bill_no_ck = t.show_bill_no) - ) - ) + + AND ri.cangku = #{q.cangku} + + + AND ri.rk_time >= #{q.startTime} + + AND ri.rk_time <= #{q.endTime} + - - /* ✅ 关键:按 show_bill_no 分组(出库合并 CK,在库保留 RK) */ + ) t GROUP BY t.show_bill_no - ) a - LEFT JOIN stock_in_type si ON a.rk_type = si.type_code - LEFT JOIN stock_out_type so ON a.ck_type = so.type_code - LEFT JOIN sys_user u ON a.ck_lihuo_y = u.user_id - LEFT JOIN material_type mt ON a.wl_type = mt.type_code - LEFT JOIN sys_user ru ON a.lihuo_y = ru.user_id - ORDER BY a.rk_time DESC + LEFT JOIN stock_in_type si ON a.rk_type = si.type_code + LEFT JOIN stock_out_type so ON a.ck_type = so.type_code + LEFT JOIN sys_user u ON a.ck_lihuo_y = u.user_id + LEFT JOIN material_type mt ON a.wl_type = mt.type_code + LEFT JOIN sys_user ru ON a.lihuo_y = ru.user_id + LEFT JOIN construction_team ct ON a.team_code = ct.team_code + + ORDER BY a.create_time DESC -