Compare commits

...

2 Commits

Author SHA1 Message Date
86ecbf0e78 功能重构开发0130 2026-01-30 10:20:32 +08:00
e5926e82fd 功能重构开发 2026-01-26 17:01:42 +08:00
12 changed files with 347 additions and 402 deletions

View File

@@ -3,6 +3,7 @@ package com.zg.project.wisdom.controller;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import com.github.pagehelper.PageHelper;
import com.zg.project.wisdom.domain.dto.BorrowReturnDTO; import com.zg.project.wisdom.domain.dto.BorrowReturnDTO;
import com.zg.project.wisdom.domain.dto.RkBillCreateDTO; import com.zg.project.wisdom.domain.dto.RkBillCreateDTO;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -42,8 +43,11 @@ public class RkBillController extends BaseController
@PreAuthorize("@ss.hasPermi('wisdom:bill:list')") @PreAuthorize("@ss.hasPermi('wisdom:bill:list')")
@PostMapping("/list") @PostMapping("/list")
public TableDataInfo list(@RequestBody RkBill rkBill) { public TableDataInfo list(@RequestBody RkBill rkBill) {
startPage();
PageHelper.startPage(rkBill.getPageNum(), rkBill.getPageSize());
List<RkBill> list = rkBillService.selectRkBillList(rkBill); List<RkBill> list = rkBillService.selectRkBillList(rkBill);
return getDataTable(list); return getDataTable(list);
} }

View File

@@ -109,7 +109,8 @@ public class RkInfoController extends BaseController
*/ */
@PostMapping("/statistic") @PostMapping("/statistic")
public AjaxResult statistic(@RequestBody RkInfo query) { public AjaxResult statistic(@RequestBody RkInfo query) {
return AjaxResult.success(rkInfoService.getStockStatistic(query)); StockStatisticVO stockStatistic = rkInfoService.getStockStatistic(query);
return AjaxResult.success(stockStatistic);
} }
} }

View File

@@ -22,6 +22,12 @@ public class RkBill extends BaseEntity {
/** 主键ID */ /** 主键ID */
private Long id; private Long id;
/** 当前页 */
private Integer pageNum;
/** 每页条数 */
private Integer pageSize;
/** 物资类型 */ /** 物资类型 */
@Excel(name = "物资类型") @Excel(name = "物资类型")
private String wlType; private String wlType;
@@ -46,7 +52,7 @@ public class RkBill extends BaseEntity {
@Excel(name = "单据号") @Excel(name = "单据号")
private String billNo; private String billNo;
/** 原字段:出入库类型 */ /** 出入库类型 */
@Excel(name = "出入库类型") @Excel(name = "出入库类型")
private String operationType; private String operationType;
@@ -103,29 +109,14 @@ public class RkBill extends BaseEntity {
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date returnTime; private Date returnTime;
/** 借用方项目号(借用方项目) */ /** 借用方项目号 */
@Excel(name = "借用方项目号") @Excel(name = "借用方项目号")
private String xmNoCk; private String xmNoCk;
/** 借用方项目描述(借用方项目描述) */ /** 借用方项目描述 */
@Excel(name = "借用方项目描述") @Excel(name = "借用方项目描述")
private String xmMsCk; private String xmMsCk;
/** 创建人 */
private String createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/** 更新人 */
private String updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
/** 是否删除0正常1删除 */ /** 是否删除0正常1删除 */
private String isDelete; private String isDelete;
@@ -143,256 +134,96 @@ public class RkBill extends BaseEntity {
// ================= getter / setter ================= // ================= getter / setter =================
public Long getId() { public Long getId() { return id; }
return id; public void setId(Long id) { this.id = id; }
}
public void setId(Long id) { public Integer getPageNum() { return pageNum; }
this.id = id; public void setPageNum(Integer pageNum) { this.pageNum = pageNum; }
}
public String getWlType() { public Integer getPageSize() { return pageSize; }
return wlType; public void setPageSize(Integer pageSize) { this.pageSize = pageSize; }
}
public void setWlType(String wlType) { public String getWlType() { return wlType; }
this.wlType = wlType; public void setWlType(String wlType) { this.wlType = wlType; }
}
public String getWlTypeName() { public String getWlTypeName() { return wlTypeName; }
return wlTypeName; public void setWlTypeName(String wlTypeName) { this.wlTypeName = wlTypeName; }
}
public void setWlTypeName(String wlTypeName) { public String getCangku() { return cangku; }
this.wlTypeName = wlTypeName; public void setCangku(String cangku) { this.cangku = cangku; }
}
public String getCangku() { public String getWarehouseName() { return warehouseName; }
return cangku; public void setWarehouseName(String warehouseName) { this.warehouseName = warehouseName; }
}
public void setCangku(String cangku) { public String getParentWarehouseName() { return parentWarehouseName; }
this.cangku = cangku; public void setParentWarehouseName(String parentWarehouseName) { this.parentWarehouseName = parentWarehouseName; }
}
public String getWarehouseName() { public String getBillNo() { return billNo; }
return warehouseName; public void setBillNo(String billNo) { this.billNo = billNo; }
}
public void setWarehouseName(String warehouseName) { public String getOperationType() { return operationType; }
this.warehouseName = warehouseName; public void setOperationType(String operationType) { this.operationType = operationType; }
}
public String getParentWarehouseName() { public String getOperationTypeName() { return operationTypeName; }
return parentWarehouseName; public void setOperationTypeName(String operationTypeName) { this.operationTypeName = operationTypeName; }
}
public void setParentWarehouseName(String parentWarehouseName) { public String getBizType() { return bizType; }
this.parentWarehouseName = parentWarehouseName; public void setBizType(String bizType) { this.bizType = bizType; }
}
public String getBillNo() { public List<String> getBizTypeList() { return bizTypeList; }
return billNo; public void setBizTypeList(List<String> bizTypeList) { this.bizTypeList = bizTypeList; }
}
public void setBillNo(String billNo) { public Date getOperationTime() { return operationTime; }
this.billNo = billNo; public void setOperationTime(Date operationTime) { this.operationTime = operationTime; }
}
public String getOperationType() { public String getExecStatus() { return execStatus; }
return operationType; public void setExecStatus(String execStatus) { this.execStatus = execStatus; }
}
public void setOperationType(String operationType) { public Integer getOperator() { return operator; }
this.operationType = operationType; public void setOperator(Integer operator) { this.operator = operator; }
}
public String getOperationTypeName() { public String getOperatorName() { return operatorName; }
return operationTypeName; public void setOperatorName(String operatorName) { this.operatorName = operatorName; }
}
public void setOperationTypeName(String operationTypeName) { public String getTeamCode() { return teamCode; }
this.operationTypeName = operationTypeName; public void setTeamCode(String teamCode) { this.teamCode = teamCode; }
}
public String getBizType() { public String getTeamName() { return teamName; }
return bizType; public void setTeamName(String teamName) { this.teamName = teamName; }
}
public void setBizType(String bizType) { public String getIsDelivery() { return isDelivery; }
this.bizType = bizType; public void setIsDelivery(String isDelivery) { this.isDelivery = isDelivery; }
}
public List<String> getBizTypeList() { public Date getBorrowTime() { return borrowTime; }
return bizTypeList; public void setBorrowTime(Date borrowTime) { this.borrowTime = borrowTime; }
}
public void setBizTypeList(List<String> bizTypeList) { public Date getReturnTime() { return returnTime; }
this.bizTypeList = bizTypeList; public void setReturnTime(Date returnTime) { this.returnTime = returnTime; }
}
public Date getOperationTime() { public String getXmNoCk() { return xmNoCk; }
return operationTime; public void setXmNoCk(String xmNoCk) { this.xmNoCk = xmNoCk; }
}
public void setOperationTime(Date operationTime) { public String getXmMsCk() { return xmMsCk; }
this.operationTime = operationTime; public void setXmMsCk(String xmMsCk) { this.xmMsCk = xmMsCk; }
}
public String getExecStatus() { public String getIsDelete() { return isDelete; }
return execStatus; public void setIsDelete(String isDelete) { this.isDelete = isDelete; }
}
public void setExecStatus(String execStatus) { public Date getStartDate() { return startDate; }
this.execStatus = execStatus; public void setStartDate(Date startDate) { this.startDate = startDate; }
}
public Integer getOperator() { public Date getEndDate() { return endDate; }
return operator; public void setEndDate(Date endDate) { this.endDate = endDate; }
}
public void setOperator(Integer operator) { public String getRemark() { return remark; }
this.operator = operator; public void setRemark(String remark) { this.remark = remark; }
}
public String getOperatorName() {
return operatorName;
}
public void setOperatorName(String operatorName) {
this.operatorName = operatorName;
}
public String getTeamCode() {
return teamCode;
}
public void setTeamCode(String teamCode) {
this.teamCode = teamCode;
}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
public String getIsDelivery() {
return isDelivery;
}
public void setIsDelivery(String isDelivery) {
this.isDelivery = isDelivery;
}
public Date getBorrowTime() {
return borrowTime;
}
public void setBorrowTime(Date borrowTime) {
this.borrowTime = borrowTime;
}
public Date getReturnTime() {
return returnTime;
}
public void setReturnTime(Date returnTime) {
this.returnTime = returnTime;
}
public void setXmNoCk(String xmNoCk)
{
this.xmNoCk = xmNoCk;
}
public String getXmNoCk()
{
return xmNoCk;
}
public void setXmMsCk(String xmMsCk)
{
this.xmMsCk = xmMsCk;
}
public String getXmMsCk()
{
return xmMsCk;
}
public String getCreateBy() {
return createBy;
}
public void setCreateBy(String createBy) {
this.createBy = createBy;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getUpdateBy() {
return updateBy;
}
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getIsDelete() {
return isDelete;
}
public void setIsDelete(String isDelete) {
this.isDelete = isDelete;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
// ================= toString =================
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", id) .append("id", id)
.append("pageNum", pageNum)
.append("pageSize", pageSize)
.append("wlType", wlType) .append("wlType", wlType)
.append("wlTypeName", wlTypeName) .append("wlTypeName", wlTypeName)
.append("cangku", cangku) .append("cangku", cangku)
@@ -411,16 +242,11 @@ public class RkBill extends BaseEntity {
.append("isDelivery", isDelivery) .append("isDelivery", isDelivery)
.append("borrowTime", borrowTime) .append("borrowTime", borrowTime)
.append("returnTime", returnTime) .append("returnTime", returnTime)
.append("xmNoCk", getXmNoCk()) .append("xmNoCk", xmNoCk)
.append("xmMsCk", getXmMsCk()) .append("xmMsCk", xmMsCk)
.append("createBy", createBy)
.append("createTime", createTime)
.append("updateBy", updateBy)
.append("updateTime", updateTime)
.append("isDelete", isDelete)
.append("remark", remark)
.append("startDate", startDate) .append("startDate", startDate)
.append("endDate", endDate) .append("endDate", endDate)
.append("remark", remark)
.toString(); .toString();
} }
} }

View File

@@ -213,6 +213,7 @@ public class RkInfo extends BaseEntity
private Long sid; private Long sid;
/** 是否需要配送(0否,1是,2配送中,3配送完成) */ /** 是否需要配送(0否,1是,2配送中,3配送完成) */
@Excel(name = "是否需要配送", readConverterExp = "0否,1是,2配送中,3配送完成")
private String isDelivery; private String isDelivery;
/** 封样编号1 */ /** 封样编号1 */

View File

@@ -188,12 +188,12 @@ public class RkRecord extends BaseEntity
private String entityId; private String entityId;
/** 借用时间 */ /** 借用时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
// @Excel(name = "借用时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") // @Excel(name = "借用时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date borrowTime; private Date borrowTime;
/** 归还时间 */ /** 归还时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
// @Excel(name = "归还时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") // @Excel(name = "归还时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date returnTime; private Date returnTime;

View File

@@ -169,4 +169,14 @@ public interface GysJhMapper
*/ */
int updateRealQtyById(@Param("gysJhId") Long gysJhId, int updateRealQtyById(@Param("gysJhId") Long gysJhId,
@Param("realQty") BigDecimal realQty); @Param("realQty") BigDecimal realQty);
/**
* 回退实际入库数量(累减)
*
* @param rollbackQty 回退数量
* @param gysJhId 供应计划ID
* @return 影响行数
*/
int decreaseRealQtyById(@Param("rollbackQty") BigDecimal rollbackQty,
@Param("gysJhId") Long gysJhId);
} }

View File

@@ -146,4 +146,7 @@ public interface RkRecordMapper
* 查询某个单据下仍为预入库状态的记录数量 * 查询某个单据下仍为预入库状态的记录数量
*/ */
int countPreInRecordByBillNo(@Param("billNo") String billNo); int countPreInRecordByBillNo(@Param("billNo") String billNo);
int countPreOutRecordByBillNo(@Param("billNo") String billNo);
} }

View File

@@ -106,7 +106,7 @@ public class RkBillServiceImpl implements IRkBillService
List<RkInfo> rkInfoList = dto.getRkInfoList(); List<RkInfo> rkInfoList = dto.getRkInfoList();
/* ================== 0⃣ 入库前:供应计划【批量】校验 ================== */ /* ================== 0⃣ 入库前:供应计划【批量】校验(预入库也要校验) ================== */
checkGysJhQtyBeforeInStockBatch(rkInfoList); checkGysJhQtyBeforeInStockBatch(rkInfoList);
/* ================== 1⃣ 主单 rk_bill ================== */ /* ================== 1⃣ 主单 rk_bill ================== */
@@ -117,8 +117,6 @@ public class RkBillServiceImpl implements IRkBillService
bill.setBillNo(billNo); bill.setBillNo(billNo);
bill.setBizType("0"); // 入库 bill.setBizType("0"); // 入库
bill.setExecStatus(bill.getExecStatus());
bill.setOperationTime(dto.getRkBill().getOperationTime());
bill.setCreateTime(now); bill.setCreateTime(now);
bill.setCreateBy(userId); bill.setCreateBy(userId);
bill.setIsDelete("0"); bill.setIsDelete("0");
@@ -129,12 +127,12 @@ public class RkBillServiceImpl implements IRkBillService
rkBillMapper.insertRkBill(bill); rkBillMapper.insertRkBill(bill);
/* ================== 2⃣ 明细 & 事件 ================== */ /* ================== 2⃣ 明细 & 入库记录 ================== */
for (RkInfo info : rkInfoList) { for (RkInfo info : rkInfoList) {
info.setExecStatus(bill.getExecStatus()); info.setExecStatus(bill.getExecStatus());
// 库位编码 // 库位校验
if (StringUtils.isNotBlank(info.getPcode())) { if (StringUtils.isNotBlank(info.getPcode())) {
PcdeDetail pcde = pcdeDetailMapper.selectByPcode(info.getPcode()); PcdeDetail pcde = pcdeDetailMapper.selectByPcode(info.getPcode());
if (pcde == null) { if (pcde == null) {
@@ -170,8 +168,10 @@ public class RkBillServiceImpl implements IRkBillService
rkRecordMapper.insertRkRecord(record); rkRecordMapper.insertRkRecord(record);
} }
/* ================== 3⃣ 入库后:供应计划【批量】更新 ================== */ /* ================== 3⃣ 入库完成后:更新供应计划(❗仅完成入库) ================== */
handleGysJhAfterInStockBatch(rkInfoList); if ("1".equals(bill.getExecStatus())) {
handleGysJhAfterInStockBatch(rkInfoList);
}
return 1; return 1;
} }
@@ -335,7 +335,7 @@ public class RkBillServiceImpl implements IRkBillService
execStatus = bill.getExecStatus(); execStatus = bill.getExecStatus();
} }
// 🚩 标记:本次是否包含预入库 // 标记:本次是否包含预入库
boolean hasPreIn = false; boolean hasPreIn = false;
List<RkInfo> rkInfoList = dto.getRkInfoList(); List<RkInfo> rkInfoList = dto.getRkInfoList();
@@ -346,7 +346,7 @@ public class RkBillServiceImpl implements IRkBillService
/* ================== 4⃣ 插入明细 & 事件 ================== */ /* ================== 4⃣ 插入明细 & 事件 ================== */
for (RkInfo info : rkInfoList) { for (RkInfo info : rkInfoList) {
/* ===== 4.1 库位校验 ===== */ /* 4.1 库位校验 */
if (StringUtils.isNotBlank(info.getPcode())) { if (StringUtils.isNotBlank(info.getPcode())) {
PcdeDetail pcde = pcdeDetailMapper.selectByPcode(info.getPcode()); PcdeDetail pcde = pcdeDetailMapper.selectByPcode(info.getPcode());
if (pcde == null) { if (pcde == null) {
@@ -355,7 +355,7 @@ public class RkBillServiceImpl implements IRkBillService
info.setPcodeId(pcde.getEncodedId()); info.setPcodeId(pcde.getEncodedId());
} }
/* ===== 4.2 继承主单字段 ===== */ /* 4.2 继承主单字段 */
info.setBillNo(bill.getBillNo()); info.setBillNo(bill.getBillNo());
info.setOperationType(bill.getOperationType()); info.setOperationType(bill.getOperationType());
info.setBizType(bill.getBizType()); info.setBizType(bill.getBizType());
@@ -374,21 +374,21 @@ public class RkBillServiceImpl implements IRkBillService
info.setHasMoved("0"); info.setHasMoved("0");
info.setIsBorrowed("0"); info.setIsBorrowed("0");
/* ===== 4.3 备注兜底 ===== */ /* 4.3 备注兜底 */
String finalRemark = StringUtils.isNotBlank(info.getRemark()) String finalRemark = StringUtils.isNotBlank(info.getRemark())
? info.getRemark() ? info.getRemark()
: bill.getRemark(); : bill.getRemark();
info.setRemark(finalRemark); info.setRemark(finalRemark);
/* ===== 4.4 审计字段 ===== */ /* 4.4 审计字段 */
info.setCreateTime(now); info.setCreateTime(now);
info.setCreateBy(bill.getCreateBy()); info.setCreateBy(bill.getCreateBy());
info.setIsDelete("0"); info.setIsDelete("0");
/* ===== 4.5 插入 rk_info ===== */ /* 4.5 插入 rk_info */
rkInfoMapper.insertRkInfo(info); rkInfoMapper.insertRkInfo(info);
/* ===== 4.6 插入 rk_record ===== */ /* 4.6 插入 rk_record */
RkRecord record = buildInRkRecord(bill, info, now); RkRecord record = buildInRkRecord(bill, info, now);
record.setExecStatus(execStatus); record.setExecStatus(execStatus);
record.setRkInfoId(info.getId()); record.setRkInfoId(info.getId());
@@ -398,8 +398,10 @@ public class RkBillServiceImpl implements IRkBillService
rkRecordMapper.insertRkRecord(record); rkRecordMapper.insertRkRecord(record);
} }
/* ================== 5⃣ 追加后:供应计划【批量】更新 ================== */ /* ================== 5⃣ 追加后:供应计划【仅完成入库】 ================== */
handleGysJhAfterInStockBatch(rkInfoList); if ("1".equals(execStatus)) {
handleGysJhAfterInStockBatch(rkInfoList);
}
/* ================== 6⃣ 同步回退主单状态 ================== */ /* ================== 6⃣ 同步回退主单状态 ================== */
if (hasPreIn && !"0".equals(bill.getExecStatus())) { if (hasPreIn && !"0".equals(bill.getExecStatus())) {

View File

@@ -263,13 +263,6 @@ public class RkRecordServiceImpl implements IRkRecordService
return rows; return rows;
} }
/**
* 批量删除出入库记录
*
* @param ids 需要删除的出入库记录主键
* @return 结果
*/
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public int deleteRkRecordByIds(Long[] ids) { public int deleteRkRecordByIds(Long[] ids) {
@@ -278,55 +271,27 @@ public class RkRecordServiceImpl implements IRkRecordService
return 0; return 0;
} }
// ================== 1. 查询 record ================== /* ================== 1️⃣ 查询 record ================== */
List<RkRecord> records = rkRecordMapper.selectRkRecordByIds(Arrays.asList(ids)); List<RkRecord> records = rkRecordMapper.selectRkRecordByIds(Arrays.asList(ids));
if (records == null || records.isEmpty()) { if (records == null || records.isEmpty()) {
return 0; return 0;
} }
// ================== 2. 校验 record 必须全部是预入库 ================== /* ================== 2️⃣ 校验必须全部是预入库 / 预出库】 ================== */
boolean hasFinishedRecord = records.stream() boolean hasFinishedRecord = records.stream()
.anyMatch(r -> r.getExecStatus() == null || !"0".equals(r.getExecStatus())); .anyMatch(r -> r.getExecStatus() == null || !"0".equals(r.getExecStatus()));
if (hasFinishedRecord) { if (hasFinishedRecord) {
throw new ServiceException("仅允许删除预入库/预出库的出入库记录"); throw new ServiceException("仅允许删除预入库/预出库的出入库记录");
} }
// ================== 3. 回滚供应计划已入库数量 + 状态 ================== /* ================== 3️⃣ 收集 rkInfoId ================== */
Map<Long, BigDecimal> rollbackMap = records.stream()
.filter(r -> r.getGysJhId() != null && r.getRealQty() != null)
.collect(Collectors.groupingBy(
RkRecord::getGysJhId,
Collectors.mapping(
RkRecord::getRealQty,
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)
)
));
for (Map.Entry<Long, BigDecimal> entry : rollbackMap.entrySet()) {
Long jhId = entry.getKey();
BigDecimal rollbackQty = entry.getValue();
// 1⃣ 回滚数量
gysJhMapper.rollbackInQty(jhId, rollbackQty);
// 2⃣ 判断回滚后数量是否为 0
BigDecimal remainQty = gysJhMapper.selectRealQtyById(jhId);
if (remainQty == null || remainQty.compareTo(BigDecimal.ZERO) == 0) {
// 3⃣ 已入库数量为 0回退状态
gysJhMapper.updateStatus(jhId, "0"); // 0=未入库
}
}
// ================== 4. 收集 rkInfoId ==================
List<Long> rkInfoIds = records.stream() List<Long> rkInfoIds = records.stream()
.map(RkRecord::getRkInfoId) .map(RkRecord::getRkInfoId)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
// ================== 5. 校验 info 也必须是预入库 ================== /* ================== 4 校验 info 也必须是预入库 ================== */
if (!rkInfoIds.isEmpty()) { if (!rkInfoIds.isEmpty()) {
int invalidCount = rkInfoMapper.countNotPreByIds(rkInfoIds); int invalidCount = rkInfoMapper.countNotPreByIds(rkInfoIds);
if (invalidCount > 0) { if (invalidCount > 0) {
@@ -337,10 +302,10 @@ public class RkRecordServiceImpl implements IRkRecordService
rkInfoMapper.deleteRkInfoByIds(rkInfoIds.toArray(new Long[0])); rkInfoMapper.deleteRkInfoByIds(rkInfoIds.toArray(new Long[0]));
} }
// ================== 6. 删除 record ================== /* ================== 5 删除 record ================== */
int deleteCount = rkRecordMapper.deleteRkRecordByIds(ids); int deleteCount = rkRecordMapper.deleteRkRecordByIds(ids);
// ================== 7. 判断是否需要更新 bill 状态 ================== /* ================== 6 判断是否需要更新 bill 状态 ================== */
Set<String> billNos = records.stream() Set<String> billNos = records.stream()
.map(RkRecord::getBillNo) .map(RkRecord::getBillNo)
.filter(StringUtils::isNotBlank) .filter(StringUtils::isNotBlank)
@@ -383,8 +348,17 @@ public class RkRecordServiceImpl implements IRkRecordService
throw new ServiceException("入库记录不存在"); throw new ServiceException("入库记录不存在");
} }
/* ====================== 2校验是否发生过移库 ====================== */ /* ====================== 2仅处理【已完成入库】记录 ====================== */
List<Long> rkInfoIds = recordList.stream() List<RkRecord> finishedList = recordList.stream()
.filter(r -> "1".equals(r.getExecStatus()))
.collect(Collectors.toList());
if (finishedList.isEmpty()) {
throw new ServiceException("所选记录均为预入库状态,无需撤销");
}
/* ====================== 3⃣ 校验是否发生过移库 ====================== */
List<Long> rkInfoIds = finishedList.stream()
.map(RkRecord::getRkInfoId) .map(RkRecord::getRkInfoId)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.distinct() .distinct()
@@ -392,10 +366,8 @@ public class RkRecordServiceImpl implements IRkRecordService
if (!rkInfoIds.isEmpty()) { if (!rkInfoIds.isEmpty()) {
// 查询对应库存
List<RkInfo> infoList = rkInfoMapper.selectRkInfoByIds(rkInfoIds); List<RkInfo> infoList = rkInfoMapper.selectRkInfoByIds(rkInfoIds);
// 只要有一条 has_moved = 1直接禁止撤销
boolean hasMoved = infoList.stream() boolean hasMoved = infoList.stream()
.anyMatch(info -> "1".equals(info.getHasMoved())); .anyMatch(info -> "1".equals(info.getHasMoved()));
@@ -404,26 +376,74 @@ public class RkRecordServiceImpl implements IRkRecordService
} }
} }
/* ====================== 3️⃣ rk_record 回退为预入库 ====================== */ /* ====================== 4️⃣ 汇总需回退的供应计划数量 ====================== */
rkRecordMapper.updateExecStatusByIds(recordIds, "0"); Map<Long, BigDecimal> rollbackQtyMap = finishedList.stream()
.filter(r -> r.getGysJhId() != null && r.getRealQty() != null)
.collect(Collectors.groupingBy(
RkRecord::getGysJhId,
Collectors.mapping(
RkRecord::getRealQty,
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)
)
));
/* ====================== 4️⃣ rk_info 回退为预入库 ====================== */ /* ====================== 5️⃣ 状态回退 ====================== */
// ① rk_record.exec_status = 0
List<Long> finishedRecordIds = finishedList.stream()
.map(RkRecord::getId)
.collect(Collectors.toList());
rkRecordMapper.updateExecStatusByIds(finishedRecordIds, "0");
// ② rk_info.exec_status = 0
if (!rkInfoIds.isEmpty()) { if (!rkInfoIds.isEmpty()) {
rkInfoMapper.updateExecStatusByIds(rkInfoIds, "0"); rkInfoMapper.updateExecStatusByIds(rkInfoIds, "0");
} }
/* ====================== 5⃣ rk_bill 回退为预入库 ====================== */ // ③ rk_bill.exec_status = 0
List<String> billNos = recordList.stream() Set<String> billNoSet = finishedList.stream()
.map(RkRecord::getBillNo) .map(RkRecord::getBillNo)
.filter(StringUtils::isNotBlank) .filter(StringUtils::isNotBlank)
.distinct() .collect(Collectors.toSet());
.collect(Collectors.toList());
for (String billNo : billNos) { for (String billNo : billNoSet) {
rkBillMapper.updateExecStatusByBillNo(billNo, "0"); rkBillMapper.updateExecStatusByBillNo(billNo, "0");
} }
return recordIds.size(); /* ====================== 6⃣ 回退供应计划(关键补充) ====================== */
for (Map.Entry<Long, BigDecimal> entry : rollbackQtyMap.entrySet()) {
Long gysJhId = entry.getKey();
BigDecimal rollbackQty = entry.getValue();
// ① 实际入库数量回退(累减)
gysJhMapper.decreaseRealQtyById(rollbackQty, gysJhId);
// ② 重算状态
GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
if (gysJh == null) {
continue;
}
BigDecimal planQty = gysJh.getJhQty();
BigDecimal realQty = gysJh.getRealQty() == null
? BigDecimal.ZERO
: gysJh.getRealQty();
String status;
if (realQty.compareTo(BigDecimal.ZERO) == 0) {
status = "0"; // 未到货
} else if (planQty != null && realQty.compareTo(planQty) >= 0) {
status = "1"; // 已入库
} else {
status = "2"; // 部分入库
}
gysJhMapper.updateStatusById(gysJhId, status);
}
return finishedRecordIds.size();
} }
@@ -435,22 +455,22 @@ public class RkRecordServiceImpl implements IRkRecordService
throw new ServiceException("入库记录ID不能为空"); throw new ServiceException("入库记录ID不能为空");
} }
/* ================== 1. 查询 rk_record ================== */ /* ================== 1️⃣ 查询 rk_record ================== */
List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds); List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
if (recordList == null || recordList.isEmpty()) { if (recordList == null || recordList.isEmpty()) {
throw new ServiceException("入库记录不存在"); throw new ServiceException("入库记录不存在");
} }
/* ================== 2. 仅处理预入库记录 ================== */ /* ================== 2️⃣ 仅处理预入库记录 ================== */
List<RkRecord> preRecordList = recordList.stream() List<RkRecord> preRecordList = recordList.stream()
.filter(r -> "0".equals(r.getExecStatus())) // 预入库 .filter(r -> "0".equals(r.getExecStatus())) // 0 = 预入库
.collect(Collectors.toList()); .collect(Collectors.toList());
if (preRecordList.isEmpty()) { if (preRecordList.isEmpty()) {
throw new ServiceException("所选入库记录均已完成,无需重复入库"); throw new ServiceException("所选入库记录均已完成,无需重复入库");
} }
/* ================== 3. 校验:完成入库数量 ≤ 计划交货数量 ================== */ /* ================== 3️⃣ 校验:已入库 + 本次完成 ≤ 计划数量 ================== */
Map<Long, BigDecimal> finishQtyMap = new HashMap<>(); Map<Long, BigDecimal> finishQtyMap = new HashMap<>();
for (RkRecord record : preRecordList) { for (RkRecord record : preRecordList) {
@@ -475,16 +495,21 @@ public class RkRecordServiceImpl implements IRkRecordService
} }
BigDecimal planQty = gysJh.getJhQty(); BigDecimal planQty = gysJh.getJhQty();
if (planQty != null && finishQty.compareTo(planQty) > 0) { BigDecimal alreadyQty = gysJh.getRealQty() == null
? BigDecimal.ZERO
: gysJh.getRealQty();
if (planQty != null && alreadyQty.add(finishQty).compareTo(planQty) > 0) {
throw new ServiceException( throw new ServiceException(
"一键入库数量超出供应计划数量,物料号:" + gysJh.getWlNo() "一键入库数量超出供应计划数量,物料号:" + gysJh.getWlNo()
+ ",计划数量:" + planQty + ",计划数量:" + planQty
+ "本次完成入库:" + finishQty + "入库:" + alreadyQty
+ ",本次完成:" + finishQty
); );
} }
} }
/* ================== 4. 状态推进 ================== */ /* ================== 4️⃣ 状态推进 ================== */
// ① rk_record.exec_status = 1 // ① rk_record.exec_status = 1
List<Long> preRecordIds = preRecordList.stream() List<Long> preRecordIds = preRecordList.stream()
@@ -493,7 +518,7 @@ public class RkRecordServiceImpl implements IRkRecordService
rkRecordMapper.updateExecStatusByIds(preRecordIds, "1"); rkRecordMapper.updateExecStatusByIds(preRecordIds, "1");
// ② rk_info.exec_status = 1只推进本次涉及的库存) // ② rk_info.exec_status = 1本次涉及的库存)
List<Long> rkInfoIds = preRecordList.stream() List<Long> rkInfoIds = preRecordList.stream()
.map(RkRecord::getRkInfoId) .map(RkRecord::getRkInfoId)
.filter(Objects::nonNull) .filter(Objects::nonNull)
@@ -504,54 +529,56 @@ public class RkRecordServiceImpl implements IRkRecordService
rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1"); rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1");
} }
// ③ rk_bill.exec_status = 1只有 bill 下所有 record 均完成) // ③ rk_bill.exec_status = 1只有 bill 下所有 record 均完成)
Set<String> billNoSet = preRecordList.stream() Set<String> billNoSet = preRecordList.stream()
.map(RkRecord::getBillNo) .map(RkRecord::getBillNo)
.filter(StringUtils::isNotBlank) .filter(StringUtils::isNotBlank)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
for (String billNo : billNoSet) { for (String billNo : billNoSet) {
// 查询该 bill 下是否仍存在 预入库 record
int unFinishedCount = rkRecordMapper.countPreInRecordByBillNo(billNo); int unFinishedCount = rkRecordMapper.countPreInRecordByBillNo(billNo);
// 只有当不存在任何预入库 record 时,才推进 bill 状态
if (unFinishedCount == 0) { if (unFinishedCount == 0) {
rkBillMapper.updateExecStatusByBillNo(billNo, "1"); rkBillMapper.updateExecStatusByBillNo(billNo, "1");
} }
} }
/* ================== 5. 同步修正供应计划 ================== */ /* ================== 5️⃣ 累加更新供应计划(关键修复点) ================== */
for (Map.Entry<Long, BigDecimal> entry : finishQtyMap.entrySet()) { for (Map.Entry<Long, BigDecimal> entry : finishQtyMap.entrySet()) {
Long gysJhId = entry.getKey(); Long gysJhId = entry.getKey();
BigDecimal finishQty = entry.getValue(); BigDecimal finishQty = entry.getValue();
// ① 修正实收数量 // ✅ 改为【累加】而不是覆盖
gysJhMapper.updateRealQtyById(gysJhId, finishQty); gysJhMapper.increaseRealQtyById(finishQty, gysJhId);
// ② 修正状态 // 重新计算状态
GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId); GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
if (gysJh == null) { if (gysJh == null) {
continue; continue;
} }
BigDecimal planQty = gysJh.getJhQty(); BigDecimal planQty = gysJh.getJhQty();
BigDecimal realQty = gysJh.getRealQty(); BigDecimal realQty = gysJh.getRealQty() == null
? BigDecimal.ZERO
: gysJh.getRealQty();
if (realQty == null || realQty.compareTo(BigDecimal.ZERO) == 0) { String status;
gysJhMapper.updateStatusById(gysJhId, "0"); // 未到货 if (realQty.compareTo(BigDecimal.ZERO) == 0) {
status = "0"; // 未到货
} else if (planQty != null && realQty.compareTo(planQty) >= 0) { } else if (planQty != null && realQty.compareTo(planQty) >= 0) {
gysJhMapper.updateStatusById(gysJhId, "1"); // 已入库 status = "1"; // 已入库
} else { } else {
gysJhMapper.updateStatusById(gysJhId, "2"); // 部分入库 status = "2"; // 部分入库
} }
gysJhMapper.updateStatusById(gysJhId, status);
} }
return preRecordIds.size(); return preRecordIds.size();
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public int rollbackOut(List<Long> recordIds) { public int rollbackOut(List<Long> recordIds) {
@@ -628,23 +655,23 @@ public class RkRecordServiceImpl implements IRkRecordService
throw new ServiceException("出库记录ID不能为空"); throw new ServiceException("出库记录ID不能为空");
} }
// ================== 1. 查询 rk_record ================== /* ================== 1️⃣ 查询 rk_record ================== */
List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds); List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
if (recordList == null || recordList.isEmpty()) { if (recordList == null || recordList.isEmpty()) {
throw new ServiceException("出库记录不存在"); throw new ServiceException("出库记录不存在");
} }
// ================== 2. 只保留预出库记录 ================== /* ================== 2️⃣ 仅保留预出库记录 ================== */
List<RkRecord> preOutList = recordList.stream() List<RkRecord> preOutList = recordList.stream()
.filter(r -> "1".equals(r.getBizType())) // 出库 .filter(r -> "1".equals(r.getBizType())) // 出库
.filter(r -> "0".equals(r.getExecStatus())) // 预出库 .filter(r -> "0".equals(r.getExecStatus())) // 预出库
.collect(Collectors.toList()); .collect(Collectors.toList());
if (preOutList.isEmpty()) { if (preOutList.isEmpty()) {
throw new ServiceException("所选出库记录均已完成出库"); throw new ServiceException("所选出库记录均已完成出库");
} }
// ================== 3. 库存校验 + 扣减 ================== /* ================== 3️⃣ 库存校验 + 扣减 ================== */
for (RkRecord record : preOutList) { for (RkRecord record : preOutList) {
Long rkInfoId = record.getRkInfoId(); Long rkInfoId = record.getRkInfoId();
@@ -670,24 +697,24 @@ public class RkRecordServiceImpl implements IRkRecordService
BigDecimal newQty = remainQty.subtract(outQty); BigDecimal newQty = remainQty.subtract(outQty);
// 扣库存 // 扣库存数量
rkInfoMapper.updateRealQtyById(rkInfoId, newQty); rkInfoMapper.updateRealQtyById(rkInfoId, newQty);
// 同步出库状态 // ② 若扣完,同步库存出库状态
if (newQty.compareTo(BigDecimal.ZERO) == 0) { if (newQty.compareTo(BigDecimal.ZERO) == 0) {
rkInfoMapper.updateIsChukuById(rkInfoId, "1"); rkInfoMapper.updateIsChukuById(rkInfoId, "1");
} }
} }
// ================== 4. 推进状态 ================== /* ================== 4️⃣ 状态推进 ================== */
// ① rk_record.exec_status = 1 // ① rk_record.exec_status = 1(仅本次完成的)
List<Long> preOutIds = preOutList.stream() List<Long> finishedRecordIds = preOutList.stream()
.map(RkRecord::getId) .map(RkRecord::getId)
.collect(Collectors.toList()); .collect(Collectors.toList());
rkRecordMapper.updateExecStatusByIds(preOutIds, "1"); rkRecordMapper.updateExecStatusByIds(finishedRecordIds, "1");
// ② rk_info.exec_status = 1 // ② rk_info.exec_status = 1(涉及到的库存)
List<Long> rkInfoIds = preOutList.stream() List<Long> rkInfoIds = preOutList.stream()
.map(RkRecord::getRkInfoId) .map(RkRecord::getRkInfoId)
.filter(Objects::nonNull) .filter(Objects::nonNull)
@@ -697,17 +724,26 @@ public class RkRecordServiceImpl implements IRkRecordService
rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1"); rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1");
} }
// ③ rk_bill.exec_status = 1 // 只有当【该单据下不存在任何预出库记录】才允许完成
List<String> billNos = preOutList.stream() List<String> billNos = preOutList.stream()
.map(RkRecord::getBillNo) .map(RkRecord::getBillNo)
.filter(StringUtils::isNotBlank) .filter(StringUtils::isNotBlank)
.distinct() .distinct()
.collect(Collectors.toList()); .collect(Collectors.toList());
for (String billNo : billNos) { for (String billNo : billNos) {
// 判断该出库单下是否还存在预出库记录
int preOutCount = rkRecordMapper.countPreOutRecordByBillNo(billNo);
if (preOutCount > 0) {
// 只要还有一条预出库,整单不能完成
continue;
}
rkBillMapper.updateExecStatusByBillNo(billNo, "1"); rkBillMapper.updateExecStatusByBillNo(billNo, "1");
} }
return preOutIds.size(); return finishedRecordIds.size();
} }
@Override @Override

View File

@@ -311,4 +311,11 @@
WHERE id = #{gysJhId} WHERE id = #{gysJhId}
</update> </update>
<update id="decreaseRealQtyById">
UPDATE gys_jh
SET real_qty = IFNULL(real_qty, 0) - #{rollbackQty}
WHERE id = #{gysJhId}
AND IFNULL(real_qty, 0) >= #{rollbackQty}
</update>
</mapper> </mapper>

View File

@@ -194,9 +194,9 @@
resultType="com.zg.project.wisdom.domain.vo.StockStatisticVO"> resultType="com.zg.project.wisdom.domain.vo.StockStatisticVO">
SELECT SELECT
IFNULL(SUM(ri.real_qty * ri.ht_dj), 0) AS total_amount, IFNULL(SUM(ri.real_qty * ri.ht_dj), 0) AS totalAmount,
COUNT(DISTINCT ri.pcode) AS location_count, COUNT(DISTINCT ri.pcode) AS locationCount,
IFNULL(SUM(ri.real_qty), 0) AS total_quantity IFNULL(SUM(ri.real_qty), 0) AS totalQuantity
FROM rk_info ri FROM rk_info ri
<where> <where>
ri.exec_status = 1 ri.exec_status = 1

View File

@@ -5,20 +5,18 @@
<mapper namespace="com.zg.project.wisdom.mapper.RkRecordMapper"> <mapper namespace="com.zg.project.wisdom.mapper.RkRecordMapper">
<!-- ===================== resultMap ===================== --> <!-- ===================== resultMap ===================== -->
<resultMap type="RkRecord" id="RkRecordResult"> <resultMap id="RkRecordResult" type="com.zg.project.wisdom.domain.RkRecord">
<result property="id" column="id"/> <result property="id" column="id"/>
<!-- ✅ 新增:关联 rk_info 主键 -->
<result property="rkInfoId" column="rk_info_id"/> <result property="rkInfoId" column="rk_info_id"/>
<result property="bizType" column="biz_type"/>
<result property="operationType" column="operation_type"/> <result property="operationType" column="operation_type"/>
<result property="operationTypeName" column="operation_type_name"/> <result property="operationTypeName" column="operation_type_name"/>
<result property="bizType" column="biz_type"/>
<result property="wlType" column="wl_type"/> <result property="wlType" column="wl_type"/>
<result property="wlTypeName" column="wl_type_name"/> <result property="wlTypeName" column="wl_type_name"/>
<!-- 仓库层级 -->
<result property="cangku" column="cangku"/> <result property="cangku" column="cangku"/>
<result property="warehouseName" column="warehouse_name"/> <result property="warehouseName" column="warehouse_name"/>
<result property="parentWarehouseCode" column="parent_warehouse_code"/> <result property="parentWarehouseCode" column="parent_warehouse_code"/>
@@ -60,6 +58,7 @@
<result property="pcodeId" column="pcode_id"/> <result property="pcodeId" column="pcode_id"/>
<result property="trayCode" column="tray_code"/> <result property="trayCode" column="tray_code"/>
<result property="entityId" column="entity_id"/> <result property="entityId" column="entity_id"/>
<result property="teamCode" column="team_code"/> <result property="teamCode" column="team_code"/>
<result property="teamName" column="team_name"/> <result property="teamName" column="team_name"/>
@@ -85,52 +84,54 @@
<result property="isDelete" column="is_delete"/> <result property="isDelete" column="is_delete"/>
</resultMap> </resultMap>
<!-- ===================== 查询字段(连表补齐 ===================== --> <!-- ===================== 查询字段(统一视图 ===================== -->
<sql id="selectRkRecordVo"> <sql id="selectRkRecordVo">
SELECT SELECT
rr.*, rr.*,
/* 理货员姓名 */
su.nick_name AS operator_name, su.nick_name AS operator_name,
/* 物资类型名称 */
mt.type_name AS wl_type_name, mt.type_name AS wl_type_name,
/* 出入库类型名称:入库 / 出库 二选一 */
COALESCE(sit.type_name, sot.type_name) AS operation_type_name, COALESCE(sit.type_name, sot.type_name) AS operation_type_name,
/* 仓库信息:小仓/大仓 */ -- 小仓
wh.warehouse_name, wh.warehouse_name AS warehouse_name,
wh.parent_warehouse_code,
wh.parent_warehouse_name, -- ✅ 大仓(直接取小仓行里的父仓字段)
wh.parent_warehouse_code AS parent_warehouse_code,
wh.parent_warehouse_name AS parent_warehouse_name,
ct.team_name AS team_name ct.team_name AS team_name
FROM rk_record rr FROM rk_record rr
LEFT JOIN sys_user su LEFT JOIN sys_user su ON rr.operator = su.user_id
ON rr.operator = su.user_id LEFT JOIN material_type mt ON rr.wl_type = mt.type_code
LEFT JOIN material_type mt LEFT JOIN stock_in_type sit ON rr.operation_type = sit.type_code
ON rr.wl_type = mt.type_code LEFT JOIN stock_out_type sot ON rr.operation_type = sot.type_code
LEFT JOIN stock_in_type sit
ON rr.operation_type = sit.type_code LEFT JOIN warehouse_info wh ON rr.cangku = wh.warehouse_code
LEFT JOIN stock_out_type sot
ON rr.operation_type = sot.type_code
LEFT JOIN warehouse_info wh
ON rr.cangku = wh.warehouse_code
LEFT JOIN construction_team ct LEFT JOIN construction_team ct
ON rr.team_code = ct.team_code ON rr.team_code = ct.team_code
AND ct.is_delete = '0' AND ct.is_delete = '0'
</sql> </sql>
<!-- ===================== 查询列表 ===================== --> <!-- ===================== 查询列表 ===================== -->
<select id="selectRkRecordList" parameterType="RkRecord" resultMap="RkRecordResult"> <select id="selectRkRecordList"
parameterType="RkRecord"
resultMap="RkRecordResult">
<include refid="selectRkRecordVo"/> <include refid="selectRkRecordVo"/>
<where> <where>
AND rr.exec_status = '1' AND rr.exec_status = '1'
<if test="operationType != null and operationType != ''"> <if test="operationType != null and operationType != ''">
AND rr.operation_type = #{operationType} AND rr.operation_type = #{operationType}
</if> </if>
<!-- 多 bizType --> <!-- 多 bizType -->
<if test="bizTypeList != null and bizTypeList.size > 0"> <if test="bizTypeList != null and bizTypeList.size > 0">
AND rb.biz_type IN AND rr.biz_type IN
<foreach collection="bizTypeList" <foreach collection="bizTypeList"
item="bt" item="bt"
open="(" open="("
@@ -139,37 +140,48 @@
#{bt} #{bt}
</foreach> </foreach>
</if> </if>
<if test="bizType != null and bizType != ''"> <if test="bizType != null and bizType != ''">
AND rr.biz_type = #{bizType} AND rr.biz_type = #{bizType}
</if> </if>
<if test="pcode != null and pcode != ''"> <if test="pcode != null and pcode != ''">
AND rr.pcode = #{pcode} AND rr.pcode = #{pcode}
</if> </if>
<if test="wlType != null and wlType != ''"> <if test="wlType != null and wlType != ''">
AND rr.wl_type = #{wlType} AND rr.wl_type = #{wlType}
</if> </if>
<if test="cangku != null and cangku != ''"> <if test="cangku != null and cangku != ''">
AND rr.cangku = #{cangku} AND rr.cangku = #{cangku}
</if> </if>
<if test="operator != null and operator != ''"> <if test="operator != null and operator != ''">
AND rr.operator = #{operator} AND rr.operator = #{operator}
</if> </if>
<if test="isChuku != null and isChuku != ''"> <if test="isChuku != null and isChuku != ''">
AND rr.is_chuku = #{isChuku} AND rr.is_chuku = #{isChuku}
</if> </if>
<if test="status != null and status != ''"> <if test="status != null and status != ''">
AND rr.status = #{status} AND rr.status = #{status}
</if> </if>
<if test="execStatus != null and execStatus != ''"> <if test="execStatus != null and execStatus != ''">
AND rr.exec_status = #{execStatus} AND rr.exec_status = #{execStatus}
</if> </if>
<if test="billNo != null and billNo != ''"> <if test="billNo != null and billNo != ''">
AND rr.bill_no = #{billNo} AND rr.bill_no = #{billNo}
</if> </if>
<if test="isDelivery != null and isDelivery != ''"> <if test="isDelivery != null and isDelivery != ''">
AND rr.is_delivery = #{isDelivery} AND rr.is_delivery = #{isDelivery}
</if> </if>
<!-- 项目号 -->
<!-- 项目 -->
<if test="xmNo != null and xmNo != ''"> <if test="xmNo != null and xmNo != ''">
AND rr.xm_no LIKE concat('%', #{xmNo}, '%') AND rr.xm_no LIKE concat('%', #{xmNo}, '%')
</if> </if>
@@ -177,50 +189,81 @@
AND rr.xm_ms LIKE concat('%', #{xmMs}, '%') AND rr.xm_ms LIKE concat('%', #{xmMs}, '%')
</if> </if>
<!-- 订单编号 --> <!-- 订单 -->
<if test="sapNo != null and sapNo != ''"> <if test="sapNo != null and sapNo != ''">
AND rr.sap_no LIKE concat('%', #{sapNo}, '%') AND rr.sap_no LIKE concat('%', #{sapNo}, '%')
</if> </if>
<!-- 供应商名称 --> <!-- 供应商 -->
<if test="gysMc != null and gysMc != ''"> <if test="gysMc != null and gysMc != ''">
AND rr.gys_mc LIKE concat('%', #{gysMc}, '%') AND rr.gys_mc LIKE concat('%', #{gysMc}, '%')
</if> </if>
<!-- 所属小仓warehouseCode 实际就是 cangku -->
<if test="cangku != null and cangku != ''">
AND rr.cangku = #{cangku}
</if>
<if test="wlNo != null and wlNo != ''"> <if test="wlNo != null and wlNo != ''">
AND rr.wl_no LIKE concat('%', #{wlNo}, '%') AND rr.wl_no LIKE concat('%', #{wlNo}, '%')
</if> </if>
<!-- 物料描述 -->
<if test="wlMs != null and wlMs != ''"> <if test="wlMs != null and wlMs != ''">
AND rr.wl_ms LIKE concat('%', #{wlMs}, '%') AND rr.wl_ms LIKE concat('%', #{wlMs}, '%')
</if> </if>
<!-- 是否借料 --> <!-- 是否借料 -->
<if test="isBorrowed != null and isBorrowed != ''"> <if test="isBorrowed != null and isBorrowed != ''">
AND rr.is_borrowed = #{isBorrowed} AND rr.is_borrowed = #{isBorrowed}
</if> </if>
<!-- 默认不查删除 -->
<!-- 删除标识 -->
<if test="isDelete == null"> <if test="isDelete == null">
AND (rr.is_delete = '0' OR rr.is_delete = 0 OR rr.is_delete IS NULL) AND (rr.is_delete = '0' OR rr.is_delete = 0 OR rr.is_delete IS NULL)
</if> </if>
<!-- 如果前端明确传 isDelete则按传入的精确过滤 -->
<if test="isDelete != null and isDelete != ''"> <if test="isDelete != null and isDelete != ''">
AND rr.is_delete = #{isDelete} AND rr.is_delete = #{isDelete}
</if> </if>
<!-- 出入库时间范围 -->
<if test="startDate != null"> <!-- ================= 时间条件(最终正确版) ================= -->
AND rr.operation_time &gt;= #{startDate} <if test="startDate != null or endDate != null">
</if> AND (
<if test="endDate != null"> <!-- 普通入库 / 出库:精确到时分秒 -->
AND rr.operation_time &lt;= #{endDate} (
rr.biz_type IN ('0','1')
<if test="startDate != null">
AND rr.operation_time &gt;= #{startDate}
</if>
<if test="endDate != null">
AND rr.operation_time &lt;= #{endDate}
</if>
)
OR
<!-- 借料出库:按 borrow_time按天 -->
(
rr.biz_type = '2'
<if test="startDate != null">
AND rr.borrow_time &gt;= DATE(#{startDate})
</if>
<if test="endDate != null">
AND rr.borrow_time &lt; DATE_ADD(DATE(#{endDate}), INTERVAL 1 DAY)
</if>
)
OR
<!-- 还料入库:按 return_time按天 -->
(
rr.biz_type = '3'
<if test="startDate != null">
AND rr.return_time &gt;= DATE(#{startDate})
</if>
<if test="endDate != null">
AND rr.return_time &lt; DATE_ADD(DATE(#{endDate}), INTERVAL 1 DAY)
</if>
)
)
</if> </if>
</where> </where>
ORDER BY rr.exec_status = '0' DESC, rr.operation_time DESC
ORDER BY rr.exec_status = '0' DESC,
rr.operation_time DESC
</select> </select>
<!-- ===================== 按 ID 查询 ===================== --> <!-- ===================== 按 ID 查询 ===================== -->
<select id="selectRkRecordById" parameterType="Long" resultMap="RkRecordResult"> <select id="selectRkRecordById" parameterType="Long" resultMap="RkRecordResult">
<include refid="selectRkRecordVo"/> <include refid="selectRkRecordVo"/>
@@ -623,12 +666,24 @@
AND is_delete = '0' AND is_delete = '0'
</select> </select>
<select id="countPreOutRecordByBillNo"
parameterType="java.lang.String"
resultType="java.lang.Integer">
SELECT COUNT(1)
FROM rk_record
WHERE bill_no = #{billNo}
AND biz_type = '1' <!-- 仅统计出库记录 -->
AND exec_status = '0' <!-- 预出库 -->
AND is_delete = '0'
</select>
<update id="updateBorrowReturnRecordById"> <update id="updateBorrowReturnRecordById">
UPDATE rk_record UPDATE rk_record
SET SET
biz_type = '3',
is_borrowed = #{isBorrowed}, is_borrowed = #{isBorrowed},
return_time = #{returnTime}, return_time = #{returnTime},
update_by = #{updateBy}, update_by = #{updateBy},
update_time = #{updateTime} update_time = #{updateTime}
WHERE id = #{id} WHERE id = #{id}
AND is_delete = '0' AND is_delete = '0'