功能重构开发
This commit is contained in:
@@ -3,6 +3,7 @@ package com.zg.project.wisdom.controller;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.zg.project.wisdom.domain.dto.BorrowReturnDTO;
|
||||
import com.zg.project.wisdom.domain.dto.RkBillCreateDTO;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -125,10 +126,10 @@ public class RkBillController extends BaseController
|
||||
* 还料入库
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('wisdom:bill:return:add')")
|
||||
@Log(title = "还料入库", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/return/add")
|
||||
public AjaxResult returnIn(@RequestBody RkBillCreateDTO dto) {
|
||||
return toAjax(rkBillService.insertReturnBillAndDetail(dto));
|
||||
@Log(title = "还料", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/borrow/return")
|
||||
public AjaxResult returnBorrow(@RequestBody BorrowReturnDTO dto) {
|
||||
return toAjax(rkBillService.returnBorrow(dto));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.zg.project.wisdom.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.zg.project.wisdom.domain.vo.StockStatisticVO;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -101,4 +103,13 @@ public class RkInfoController extends BaseController
|
||||
{
|
||||
return toAjax(rkInfoService.deleteRkInfoByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 库存统计(随查询条件动态变化)
|
||||
*/
|
||||
@PostMapping("/statistic")
|
||||
public AjaxResult statistic(@RequestBody RkInfo query) {
|
||||
return AjaxResult.success(rkInfoService.getStockStatistic(query));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -162,4 +162,12 @@ public class RkRecordController extends BaseController
|
||||
return toAjax(rkRecordService.deletePreOutRecords(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 出入库统计(同时返回)
|
||||
*/
|
||||
@PostMapping("/statistic")
|
||||
public AjaxResult statistic(@RequestBody RkRecord query) {
|
||||
return AjaxResult.success(rkRecordService.getRecordStatistic(query));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ public class RkRecord extends BaseEntity
|
||||
@Excel(name = "施工队")
|
||||
private String teamCode;
|
||||
|
||||
/** 施工队名称(联表) */
|
||||
@Excel(name = "施工队名称")
|
||||
private String teamName;
|
||||
|
||||
/** 执行状态(0预入/预出,1已完成) */
|
||||
@Excel(name = "执行状态", readConverterExp = "0=预操作,1=已完成")
|
||||
private String execStatus;
|
||||
@@ -222,7 +226,7 @@ public class RkRecord extends BaseEntity
|
||||
private Long sid;
|
||||
|
||||
/** 是否需要配送(0否,1是,2配送中,3配送完成) */
|
||||
// @Excel(name = "是否需要配送(0否,1是,2配送中,3配送完成)")
|
||||
@Excel(name = "是否需要配送(0否,1是,2配送中,3配送完成)")
|
||||
private String isDelivery;
|
||||
|
||||
/** 封样编号1 */
|
||||
@@ -645,6 +649,14 @@ public class RkRecord extends BaseEntity
|
||||
return teamCode;
|
||||
}
|
||||
|
||||
public String getTeamName() {
|
||||
return teamName;
|
||||
}
|
||||
|
||||
public void setTeamName(String teamName) {
|
||||
this.teamName = teamName;
|
||||
}
|
||||
|
||||
public void setBorrowTime(Date borrowTime)
|
||||
{
|
||||
this.borrowTime = borrowTime;
|
||||
@@ -850,6 +862,7 @@ public class RkRecord extends BaseEntity
|
||||
.append("trayCode", getTrayCode())
|
||||
.append("entityId", getEntityId())
|
||||
.append("teamCode", getTeamCode())
|
||||
.append("teamName", teamName)
|
||||
.append("borrowTime", getBorrowTime())
|
||||
.append("returnTime", getReturnTime())
|
||||
.append("hasMoved", getHasMoved())
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.zg.project.wisdom.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class BorrowReturnDTO {
|
||||
|
||||
/** 原借料出库单据号 */
|
||||
private String borrowBillNo;
|
||||
|
||||
/** 还料单据号(可不传,后端生成) */
|
||||
private String returnBillNo;
|
||||
|
||||
/** 操作人 */
|
||||
private Long operator;
|
||||
|
||||
/** 还料时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date returnTime;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
|
||||
/** 明细列表 */
|
||||
private List<BorrowReturnItemDTO> items;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.zg.project.wisdom.domain.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class BorrowReturnItemDTO {
|
||||
|
||||
/** 🔑 原借料出库记录 rk_record.id(必须) */
|
||||
private Long recordId;
|
||||
|
||||
/** 原 rk_info.id */
|
||||
private Long rkInfoId;
|
||||
|
||||
/** 还料数量 */
|
||||
private BigDecimal returnQty;
|
||||
|
||||
/** 库位 */
|
||||
private String pcode;
|
||||
|
||||
/** 托盘 */
|
||||
private String trayCode;
|
||||
|
||||
/** 实物ID */
|
||||
private String entityId;
|
||||
|
||||
/** 借料时间(前端如果传) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date borrowTime;
|
||||
|
||||
/** 还料时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
private Date returnTime;
|
||||
|
||||
/** 备注 */
|
||||
private String remark;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.zg.project.wisdom.domain.vo;// package com.zg.project.wisdom.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
public class BillGroupVO {
|
||||
/** 分组主键:统一用入库单号 bill_no(若为空会用 bill_no_ck 兜底) */
|
||||
private String billNo;
|
||||
|
||||
/** 出库单号(出库单据时有值,前端可展示/操作) */
|
||||
private String billNoCk;
|
||||
|
||||
/** 单据类型:IN / OUT */
|
||||
private String billType;
|
||||
|
||||
/** 单据时间:IN 取最早 rk_time;OUT 取最早 ly_time */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date billTime;
|
||||
|
||||
// ——主数据常用抬头字段(从首条提取即可)——
|
||||
private String xj;
|
||||
private String xmNo;
|
||||
private String xmMs;
|
||||
private String rkType; private String rkTypeName;
|
||||
private String ckType; private String ckTypeName;
|
||||
private String teamCode; private String teamName;
|
||||
private String cangkuName;
|
||||
private String lihuoYName;
|
||||
private String remark;
|
||||
|
||||
// ——聚合指标——
|
||||
private Integer itemCount; // 明细条数
|
||||
private BigDecimal sumQty; // 数量合计(sum real_qty)
|
||||
private BigDecimal sumAmount; // 金额合计(sum ht_dj * real_qty)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.zg.project.wisdom.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RecordStatisticVO {
|
||||
|
||||
/** 入库统计 */
|
||||
private StockStatisticVO inStatistic;
|
||||
|
||||
/** 出库统计 */
|
||||
private StockStatisticVO outStatistic;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.zg.project.wisdom.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class StockStatisticVO {
|
||||
|
||||
/** 库存总金额 */
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
/** 使用库位数量 */
|
||||
private Integer locationCount;
|
||||
|
||||
/** 货物总数量 */
|
||||
private BigDecimal totalQuantity;
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import com.zg.project.wisdom.domain.RkInfo;
|
||||
import com.zg.project.wisdom.domain.vo.StockStatisticVO;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
|
||||
/**
|
||||
@@ -102,4 +103,9 @@ public interface RkInfoMapper
|
||||
@Param("returnTime") Date returnTime);
|
||||
|
||||
List<RkInfo> selectRkInfoByIds(@Param("rkInfoIds") List<Long> rkInfoIds);
|
||||
/**
|
||||
* 库存统计(金额 / 库位数 / 数量)
|
||||
*/
|
||||
StockStatisticVO selectStockStatisticByCondition(RkInfo query);
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import com.zg.project.wisdom.domain.RkInfo;
|
||||
import com.zg.project.wisdom.domain.RkRecord;
|
||||
import com.zg.project.wisdom.domain.vo.StockStatisticVO;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
|
||||
/**
|
||||
@@ -121,4 +122,28 @@ public interface RkRecordMapper
|
||||
* @return 记录
|
||||
*/
|
||||
RkRecord selectRkRecordByRkInfoId(@Param("rkInfoId") Long rkInfoId);
|
||||
|
||||
/**
|
||||
* 入库统计
|
||||
*/
|
||||
StockStatisticVO selectInRecordStatistic(RkRecord query);
|
||||
|
||||
/**
|
||||
* 出库统计
|
||||
*/
|
||||
StockStatisticVO selectOutRecordStatistic(RkRecord query);
|
||||
|
||||
/**
|
||||
* 借出入库
|
||||
*/
|
||||
int updateBorrowReturnRecordById(@Param("id") Long id,
|
||||
@Param("isBorrowed") String isBorrowed,
|
||||
@Param("returnTime") Date returnTime,
|
||||
@Param("updateBy") String updateBy,
|
||||
@Param("updateTime") Date updateTime);
|
||||
|
||||
/**
|
||||
* 查询某个单据下仍为预入库状态的记录数量
|
||||
*/
|
||||
int countPreInRecordByBillNo(@Param("billNo") String billNo);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.zg.project.wisdom.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.zg.project.wisdom.domain.RkBill;
|
||||
import com.zg.project.wisdom.domain.dto.BorrowReturnDTO;
|
||||
import com.zg.project.wisdom.domain.dto.RkBillCreateDTO;
|
||||
|
||||
/**
|
||||
@@ -75,5 +76,5 @@ public interface IRkBillService
|
||||
/**
|
||||
* 还料入库
|
||||
*/
|
||||
int insertReturnBillAndDetail(RkBillCreateDTO dto);
|
||||
int returnBorrow(BorrowReturnDTO dto);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.zg.project.wisdom.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.zg.project.wisdom.domain.RkInfo;
|
||||
import com.zg.project.wisdom.domain.vo.StockStatisticVO;
|
||||
|
||||
/**
|
||||
* 库存单据明细Service接口
|
||||
@@ -58,4 +59,12 @@ public interface IRkInfoService
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRkInfoById(Long id);
|
||||
|
||||
/**
|
||||
* 查询库存统计信息
|
||||
*/
|
||||
|
||||
StockStatisticVO getStockStatistic(RkInfo query);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.zg.project.wisdom.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.zg.project.wisdom.domain.RkRecord;
|
||||
import com.zg.project.wisdom.domain.vo.RecordStatisticVO;
|
||||
|
||||
/**
|
||||
* 出入库记录Service接口
|
||||
@@ -90,4 +91,7 @@ public interface IRkRecordService
|
||||
* 删除预出库记录(仅限 exec_status = 0)
|
||||
*/
|
||||
int deletePreOutRecords(Long[] ids);
|
||||
|
||||
|
||||
RecordStatisticVO getRecordStatistic(RkRecord query);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.zg.common.exception.ServiceException;
|
||||
import com.zg.common.utils.DateUtils;
|
||||
@@ -14,6 +15,8 @@ import com.zg.project.information.mapper.PcdeDetailMapper;
|
||||
import com.zg.project.wisdom.domain.GysJh;
|
||||
import com.zg.project.wisdom.domain.RkInfo;
|
||||
import com.zg.project.wisdom.domain.RkRecord;
|
||||
import com.zg.project.wisdom.domain.dto.BorrowReturnDTO;
|
||||
import com.zg.project.wisdom.domain.dto.BorrowReturnItemDTO;
|
||||
import com.zg.project.wisdom.domain.dto.RkBillCreateDTO;
|
||||
import com.zg.project.wisdom.mapper.GysJhMapper;
|
||||
import com.zg.project.wisdom.mapper.RkInfoMapper;
|
||||
@@ -101,7 +104,12 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
Date now = DateUtils.getNowDate();
|
||||
String userId = String.valueOf(SecurityUtils.getUserId());
|
||||
|
||||
/* ================== 1. 主单 rk_bill ================== */
|
||||
List<RkInfo> rkInfoList = dto.getRkInfoList();
|
||||
|
||||
/* ================== 0️⃣ 入库前:供应计划【批量】校验 ================== */
|
||||
checkGysJhQtyBeforeInStockBatch(rkInfoList);
|
||||
|
||||
/* ================== 1️⃣ 主单 rk_bill ================== */
|
||||
RkBill bill = new RkBill();
|
||||
if (dto.getRkBill() != null) {
|
||||
BeanUtils.copyProperties(dto.getRkBill(), bill);
|
||||
@@ -109,41 +117,33 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
|
||||
bill.setBillNo(billNo);
|
||||
bill.setBizType("0"); // 入库
|
||||
bill.setExecStatus(bill.getExecStatus());
|
||||
bill.setOperationTime(dto.getRkBill().getOperationTime());
|
||||
bill.setCreateTime(now);
|
||||
bill.setCreateBy(userId);
|
||||
bill.setIsDelete("0");
|
||||
|
||||
// operator:默认当前登录人
|
||||
if (bill.getOperator() == null) {
|
||||
bill.setOperator(Integer.valueOf(userId));
|
||||
}
|
||||
|
||||
// execStatus:默认已完成(预入库 / 直接入库统一处理)
|
||||
if (StringUtils.isBlank(bill.getExecStatus())) {
|
||||
bill.setExecStatus("1");
|
||||
}
|
||||
|
||||
rkBillMapper.insertRkBill(bill);
|
||||
|
||||
/* ================== 2. 明细 + 事件 + 供应计划 ================== */
|
||||
for (RkInfo info : dto.getRkInfoList()) {
|
||||
/* ================== 2️⃣ 明细 & 事件 ================== */
|
||||
for (RkInfo info : rkInfoList) {
|
||||
|
||||
/* ====== ★ 0. 入库前:供应计划数量校验(核心新增) ====== */
|
||||
checkGysJhQtyBeforeInStock(info);
|
||||
info.setExecStatus(bill.getExecStatus());
|
||||
|
||||
/* ====== ① 根据 pcode 查询 pcde_detail,获取 encoded_id ====== */
|
||||
// 库位编码
|
||||
if (StringUtils.isNotBlank(info.getPcode())) {
|
||||
|
||||
PcdeDetail pcde = pcdeDetailMapper.selectByPcode(info.getPcode());
|
||||
if (pcde == null) {
|
||||
throw new RuntimeException("库位不存在:" + info.getPcode());
|
||||
}
|
||||
|
||||
info.setPcodeId(pcde.getEncodedId());
|
||||
}
|
||||
|
||||
/* ---------- rk_info ---------- */
|
||||
// rk_info
|
||||
info.setBillNo(billNo);
|
||||
info.setBizType(bill.getBizType());
|
||||
info.setOperationType(bill.getOperationType());
|
||||
@@ -155,104 +155,75 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
info.setIsChuku("0");
|
||||
info.setHasMoved("0");
|
||||
info.setIsBorrowed("0");
|
||||
info.setExecStatus(bill.getExecStatus());
|
||||
info.setIsDelete("0");
|
||||
|
||||
info.setCreateTime(now);
|
||||
info.setCreateBy(userId);
|
||||
info.setIsDelete("0");
|
||||
|
||||
rkInfoMapper.insertRkInfo(info);
|
||||
|
||||
/* ---------- rk_record ---------- */
|
||||
// rk_record
|
||||
RkRecord record = buildInRkRecord(bill, info, now);
|
||||
record.setExecStatus(bill.getExecStatus());
|
||||
record.setPcodeId(info.getPcodeId());
|
||||
|
||||
rkRecordMapper.insertRkRecord(record);
|
||||
|
||||
/* ---------- 供应计划 ---------- */
|
||||
handleGysJhAfterInStock(info);
|
||||
}
|
||||
|
||||
/* ================== 3️⃣ 入库后:供应计划【批量】更新 ================== */
|
||||
handleGysJhAfterInStockBatch(rkInfoList);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库前校验:入库数量不能超过供应计划数量
|
||||
* 入库前校验(按供应计划ID聚合)
|
||||
* 规则:已入库数量 + 本次单据入库合计 ≤ 计划数量
|
||||
*/
|
||||
private void checkGysJhQtyBeforeInStock(RkInfo info) {
|
||||
private void checkGysJhQtyBeforeInStockBatch(List<RkInfo> rkInfoList) {
|
||||
|
||||
if (info.getGysJhId() == null || info.getRealQty() == null) {
|
||||
return;
|
||||
}
|
||||
Map<Long, BigDecimal> qtyMap = rkInfoList.stream()
|
||||
.filter(i -> i.getGysJhId() != null && i.getRealQty() != null)
|
||||
.collect(Collectors.groupingBy(
|
||||
RkInfo::getGysJhId,
|
||||
Collectors.mapping(
|
||||
RkInfo::getRealQty,
|
||||
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)
|
||||
)
|
||||
));
|
||||
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(info.getGysJhId());
|
||||
if (gysJh == null) {
|
||||
throw new RuntimeException("供应计划不存在,ID:" + info.getGysJhId());
|
||||
}
|
||||
for (Map.Entry<Long, BigDecimal> entry : qtyMap.entrySet()) {
|
||||
|
||||
BigDecimal planQty = gysJh.getJhQty();
|
||||
if (planQty == null) {
|
||||
return;
|
||||
}
|
||||
Long gysJhId = entry.getKey();
|
||||
BigDecimal currentInQty = entry.getValue();
|
||||
|
||||
BigDecimal alreadyInQty = gysJh.getRealQty();
|
||||
if (alreadyInQty == null) {
|
||||
alreadyInQty = BigDecimal.ZERO;
|
||||
}
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
|
||||
if (gysJh == null) {
|
||||
throw new RuntimeException("供应计划不存在,ID:" + gysJhId);
|
||||
}
|
||||
|
||||
BigDecimal afterQty = alreadyInQty.add(info.getRealQty());
|
||||
BigDecimal planQty = gysJh.getJhQty();
|
||||
if (planQty == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (afterQty.compareTo(planQty) > 0) {
|
||||
throw new RuntimeException(
|
||||
"入库数量超出供应计划数量,物料号:" + info.getWlNo()
|
||||
+ ",计划数量:" + planQty
|
||||
+ ",已入库:" + alreadyInQty
|
||||
+ ",本次入库:" + info.getRealQty()
|
||||
);
|
||||
BigDecimal alreadyInQty = gysJh.getRealQty();
|
||||
if (alreadyInQty == null) {
|
||||
alreadyInQty = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
BigDecimal afterQty = alreadyInQty.add(currentInQty);
|
||||
|
||||
if (afterQty.compareTo(planQty) > 0) {
|
||||
throw new RuntimeException(
|
||||
"入库数量超出供应计划数量,物料号:" + gysJh.getWlNo()
|
||||
+ ",计划数量:" + planQty
|
||||
+ ",已入库:" + alreadyInQty
|
||||
+ ",本次入库:" + currentInQty
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGysJhAfterInStock(RkInfo info) {
|
||||
|
||||
// 1. 未关联供应计划或无实际入库数量,直接跳过
|
||||
if (info.getGysJhId() == null || info.getRealQty() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 累加 实际入库数量(real_qty = real_qty + 本次入库数量)
|
||||
gysJhMapper.increaseRealQtyById(
|
||||
info.getRealQty(),
|
||||
info.getGysJhId()
|
||||
);
|
||||
|
||||
// 3. 查询最新供应计划数据
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(info.getGysJhId());
|
||||
if (gysJh == null) {
|
||||
throw new RuntimeException("供应计划不存在,ID:" + info.getGysJhId());
|
||||
}
|
||||
|
||||
BigDecimal planQty = gysJh.getJhQty(); // 计划交货数量
|
||||
BigDecimal realQty = gysJh.getRealQty(); // 实际入库数量
|
||||
|
||||
if (realQty == null) {
|
||||
realQty = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
// 4. 状态判定
|
||||
String status;
|
||||
if (realQty.compareTo(BigDecimal.ZERO) == 0) {
|
||||
status = "0"; // 未到货
|
||||
} else if (planQty != null && realQty.compareTo(planQty) >= 0) {
|
||||
status = "1"; // 已入库
|
||||
} else {
|
||||
status = "2"; // 部分入库
|
||||
}
|
||||
|
||||
// 5. 更新供应计划状态
|
||||
gysJhMapper.updateStatusById(gysJh.getId(), status);
|
||||
}
|
||||
|
||||
private RkRecord buildInRkRecord(RkBill bill, RkInfo info, Date now) {
|
||||
|
||||
RkRecord record = new RkRecord();
|
||||
@@ -286,6 +257,55 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
|
||||
return record;
|
||||
}
|
||||
/**
|
||||
* 入库完成后:按供应计划ID汇总本次入库数量,统一更新 real_qty 与 status
|
||||
*/
|
||||
private void handleGysJhAfterInStockBatch(List<RkInfo> rkInfoList) {
|
||||
|
||||
// 1️⃣ 按 gysJhId 分组并汇总 realQty
|
||||
Map<Long, BigDecimal> qtyMap = rkInfoList.stream()
|
||||
.filter(i -> i.getGysJhId() != null && i.getRealQty() != null)
|
||||
.collect(Collectors.groupingBy(
|
||||
RkInfo::getGysJhId,
|
||||
Collectors.mapping(
|
||||
RkInfo::getRealQty,
|
||||
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)
|
||||
)
|
||||
));
|
||||
|
||||
// 2️⃣ 逐个供应计划更新
|
||||
for (Map.Entry<Long, BigDecimal> entry : qtyMap.entrySet()) {
|
||||
|
||||
Long gysJhId = entry.getKey();
|
||||
BigDecimal totalInQty = entry.getValue();
|
||||
|
||||
// 累加入库数量
|
||||
gysJhMapper.increaseRealQtyById(totalInQty, gysJhId);
|
||||
|
||||
// 查询最新状态
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
|
||||
if (gysJh == null) {
|
||||
throw new RuntimeException("供应计划不存在,ID:" + gysJhId);
|
||||
}
|
||||
|
||||
BigDecimal planQty = gysJh.getJhQty();
|
||||
BigDecimal realQty = gysJh.getRealQty();
|
||||
if (realQty == null) {
|
||||
realQty = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -293,95 +313,97 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
|
||||
if (dto == null || dto.getRkBill() == null
|
||||
|| StringUtils.isBlank(dto.getRkBill().getBillNo())) {
|
||||
throw new RuntimeException("单据号不能为空");
|
||||
throw new ServiceException("单据号不能为空");
|
||||
}
|
||||
|
||||
if (dto.getRkInfoList() == null || dto.getRkInfoList().isEmpty()) {
|
||||
throw new RuntimeException("入库明细不能为空");
|
||||
throw new ServiceException("入库明细不能为空");
|
||||
}
|
||||
|
||||
String billNo = dto.getRkBill().getBillNo();
|
||||
Date now = DateUtils.getNowDate();
|
||||
|
||||
// ================== 1. 查主单 ==================
|
||||
/* ================== 1️⃣ 查询主单 ================== */
|
||||
RkBill bill = rkBillMapper.selectByBillNo(billNo);
|
||||
if (bill == null) {
|
||||
throw new RuntimeException("单据不存在:" + billNo);
|
||||
throw new ServiceException("单据不存在:" + billNo);
|
||||
}
|
||||
|
||||
// ================== 2. execStatus 规则 ==================
|
||||
/* ================== 2️⃣ 执行状态规则 ================== */
|
||||
String execStatus = dto.getRkBill().getExecStatus();
|
||||
if (StringUtils.isBlank(execStatus)) {
|
||||
execStatus = bill.getExecStatus();
|
||||
}
|
||||
|
||||
// ================== 3. 追加明细 ==================
|
||||
for (RkInfo info : dto.getRkInfoList()) {
|
||||
// 🚩 标记:本次是否包含预入库
|
||||
boolean hasPreIn = false;
|
||||
|
||||
// ===== ① 根据 pcode 查询 pcde_detail → encoded_id(关键新增) =====
|
||||
List<RkInfo> rkInfoList = dto.getRkInfoList();
|
||||
|
||||
/* ================== 3️⃣ 追加前:供应计划【批量】校验 ================== */
|
||||
checkGysJhQtyBeforeInStockBatch(rkInfoList);
|
||||
|
||||
/* ================== 4️⃣ 插入明细 & 事件 ================== */
|
||||
for (RkInfo info : rkInfoList) {
|
||||
|
||||
/* ===== 4.1 库位校验 ===== */
|
||||
if (StringUtils.isNotBlank(info.getPcode())) {
|
||||
|
||||
PcdeDetail pcde = pcdeDetailMapper.selectByPcode(info.getPcode());
|
||||
if (pcde == null) {
|
||||
throw new RuntimeException("库位不存在:" + info.getPcode());
|
||||
throw new ServiceException("库位不存在:" + info.getPcode());
|
||||
}
|
||||
|
||||
info.setPcodeId(pcde.getEncodedId());
|
||||
}
|
||||
|
||||
// ---------- 基础关联 ----------
|
||||
/* ===== 4.2 继承主单字段 ===== */
|
||||
info.setBillNo(bill.getBillNo());
|
||||
|
||||
// ---------- 类型信息(来源于主单,不信前端) ----------
|
||||
info.setOperationType(bill.getOperationType());
|
||||
info.setBizType(bill.getBizType());
|
||||
info.setWlType(bill.getWlType());
|
||||
|
||||
// ---------- 仓库 ----------
|
||||
info.setCangku(bill.getCangku());
|
||||
|
||||
// ---------- 操作信息 ----------
|
||||
info.setOperationTime(info.getOperationTime());
|
||||
info.setOperator(info.getOperator());
|
||||
|
||||
// ---------- 执行状态 ----------
|
||||
info.setOperationTime(now);
|
||||
info.setOperator(bill.getOperator());
|
||||
info.setExecStatus(execStatus);
|
||||
|
||||
// ---------- 库存状态 ----------
|
||||
if ("0".equals(execStatus)) {
|
||||
hasPreIn = true;
|
||||
}
|
||||
|
||||
info.setIsChuku("0");
|
||||
info.setHasMoved("0");
|
||||
info.setIsBorrowed("0");
|
||||
|
||||
// ---------- 备注 ----------
|
||||
String finalRemark = info.getRemark();
|
||||
if (StringUtils.isBlank(finalRemark)) {
|
||||
finalRemark = bill.getRemark();
|
||||
}
|
||||
/* ===== 4.3 备注兜底 ===== */
|
||||
String finalRemark = StringUtils.isNotBlank(info.getRemark())
|
||||
? info.getRemark()
|
||||
: bill.getRemark();
|
||||
info.setRemark(finalRemark);
|
||||
|
||||
// ---------- 审计字段 ----------
|
||||
/* ===== 4.4 审计字段 ===== */
|
||||
info.setCreateTime(now);
|
||||
info.setCreateBy(bill.getCreateBy());
|
||||
info.setIsDelete("0");
|
||||
|
||||
// ---------- 插入 rk_info ----------
|
||||
/* ===== 4.5 插入 rk_info ===== */
|
||||
rkInfoMapper.insertRkInfo(info);
|
||||
|
||||
// ---------- rk_record ----------
|
||||
/* ===== 4.6 插入 rk_record ===== */
|
||||
RkRecord record = buildInRkRecord(bill, info, now);
|
||||
record.setExecStatus(execStatus);
|
||||
record.setRkInfoId(info.getId());
|
||||
|
||||
// ⭐ encoded_id 同步
|
||||
record.setPcodeId(info.getPcodeId());
|
||||
|
||||
// ⭐ 备注同步
|
||||
record.setRemark(finalRemark);
|
||||
|
||||
rkRecordMapper.insertRkRecord(record);
|
||||
}
|
||||
|
||||
// ---------- 供应计划 ----------
|
||||
handleGysJhAfterInStock(info);
|
||||
/* ================== 5️⃣ 追加后:供应计划【批量】更新 ================== */
|
||||
handleGysJhAfterInStockBatch(rkInfoList);
|
||||
|
||||
/* ================== 6️⃣ 同步回退主单状态 ================== */
|
||||
if (hasPreIn && !"0".equals(bill.getExecStatus())) {
|
||||
rkBillMapper.updateExecStatusByBillNo(billNo, "0");
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -575,8 +597,8 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
record.setOperationType(bill.getOperationType());
|
||||
record.setOperationTime(bill.getOperationTime());
|
||||
record.setOperator(bill.getOperator());
|
||||
record.setCangku(dbInfo.getCangku());
|
||||
record.setTeamCode(dbInfo.getTeamCode());
|
||||
record.setCangku(bill.getCangku());
|
||||
record.setTeamCode(bill.getTeamCode());
|
||||
|
||||
// ===== ★ 关键:备注来自【出库明细 outInfo】=====
|
||||
record.setRemark(outInfo.getRemark());
|
||||
@@ -611,136 +633,64 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int insertReturnBillAndDetail(RkBillCreateDTO dto) {
|
||||
public int returnBorrow(BorrowReturnDTO dto) {
|
||||
|
||||
if (dto == null || dto.getRkInfoList() == null || dto.getRkInfoList().isEmpty()) {
|
||||
if (dto == null || dto.getItems() == null || dto.getItems().isEmpty()) {
|
||||
throw new RuntimeException("还料明细不能为空");
|
||||
}
|
||||
|
||||
String billNo = BillNoUtil.generateTodayBillNo("HL", null);
|
||||
Date now = DateUtils.getNowDate();
|
||||
String userId = String.valueOf(SecurityUtils.getUserId());
|
||||
|
||||
/* ================== 1. 主单 rk_bill ================== */
|
||||
RkBill bill = new RkBill();
|
||||
if (dto.getRkBill() != null) {
|
||||
BeanUtils.copyProperties(dto.getRkBill(), bill);
|
||||
}
|
||||
for (BorrowReturnItemDTO item : dto.getItems()) {
|
||||
|
||||
bill.setBillNo(billNo);
|
||||
bill.setBizType("3"); // 3 = 还料入库
|
||||
bill.setOperationTime(now);
|
||||
bill.setCreateTime(now);
|
||||
bill.setCreateBy(userId);
|
||||
bill.setIsDelete("0");
|
||||
|
||||
if (bill.getOperator() == null) {
|
||||
bill.setOperator(Integer.valueOf(userId));
|
||||
}
|
||||
|
||||
// 还料入库默认已完成
|
||||
if (StringUtils.isBlank(bill.getExecStatus())) {
|
||||
bill.setExecStatus("1");
|
||||
}
|
||||
|
||||
rkBillMapper.insertRkBill(bill);
|
||||
|
||||
/* ================== 2. 明细 + 事件 ================== */
|
||||
for (RkInfo info : dto.getRkInfoList()) {
|
||||
|
||||
// ===== ① 基础校验 =====
|
||||
if (info.getRealQty() == null || info.getRealQty().compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new RuntimeException("还料数量必须大于 0");
|
||||
/* ================== 1. 参数校验 ================== */
|
||||
if (item.getRecordId() == null) {
|
||||
throw new RuntimeException("借料记录ID(recordId)不能为空");
|
||||
}
|
||||
if (item.getReturnTime() == null) {
|
||||
throw new RuntimeException("归还时间不能为空");
|
||||
}
|
||||
|
||||
// 必须关联原借料出库库存
|
||||
if (info.getRdid() == null) {
|
||||
throw new RuntimeException("还料必须指定原借料库存ID(rdid)");
|
||||
/* ================== 2. 查询借料 record(主驱动) ================== */
|
||||
RkRecord record = rkRecordMapper.selectRkRecordById(item.getRecordId());
|
||||
if (record == null) {
|
||||
throw new RuntimeException("借料记录不存在,recordId=" + item.getRecordId());
|
||||
}
|
||||
|
||||
RkInfo borrowInfo = rkInfoMapper.selectRkInfoById(info.getRdid());
|
||||
if (borrowInfo == null) {
|
||||
throw new RuntimeException("原借料库存不存在,ID:" + info.getRdid());
|
||||
// 必须是借料出库记录
|
||||
if (!"2".equals(record.getBizType())) {
|
||||
throw new RuntimeException("该记录不是借料出库记录,禁止还料");
|
||||
}
|
||||
|
||||
/* ---------- rk_info(新增库存) ---------- */
|
||||
info.setId(null);
|
||||
info.setBillNo(billNo);
|
||||
info.setBizType("3"); // 还料入库
|
||||
info.setOperationType(bill.getOperationType());
|
||||
info.setOperationTime(bill.getOperationTime());
|
||||
info.setOperator(bill.getOperator());
|
||||
// 防止重复还料
|
||||
if ("2".equals(record.getIsBorrowed())) {
|
||||
throw new RuntimeException("该借料记录已归还,禁止重复操作");
|
||||
}
|
||||
|
||||
// 关键:库存是“新增”,不是回补原库存
|
||||
info.setIsChuku("0");
|
||||
info.setIsBorrowed("0");
|
||||
info.setHasMoved("0");
|
||||
info.setExecStatus(bill.getExecStatus());
|
||||
Long rkInfoId = record.getRkInfoId();
|
||||
if (rkInfoId == null) {
|
||||
throw new RuntimeException("借料记录未关联库存(rkInfoId)");
|
||||
}
|
||||
|
||||
// 仓库 / 物料 / 项目信息,默认继承原借料库存
|
||||
info.setCangku(borrowInfo.getCangku());
|
||||
info.setWlType(borrowInfo.getWlType());
|
||||
info.setXmNo(borrowInfo.getXmNo());
|
||||
info.setXmMs(borrowInfo.getXmMs());
|
||||
info.setWlNo(borrowInfo.getWlNo());
|
||||
info.setWlMs(borrowInfo.getWlMs());
|
||||
info.setGysNo(borrowInfo.getGysNo());
|
||||
info.setGysMc(borrowInfo.getGysMc());
|
||||
info.setDw(borrowInfo.getDw());
|
||||
|
||||
info.setCreateTime(now);
|
||||
info.setCreateBy(userId);
|
||||
info.setIsDelete("0");
|
||||
|
||||
rkInfoMapper.insertRkInfo(info);
|
||||
|
||||
/* ---------- rk_record(还料入库事件) ---------- */
|
||||
RkRecord record = buildReturnRkRecord(bill, info, now);
|
||||
rkRecordMapper.insertRkRecord(record);
|
||||
|
||||
/* ---------- 原借料记录标记“已归还” ---------- */
|
||||
/* ================== 3. 更新 rk_info(库存闭环) ================== */
|
||||
rkInfoMapper.updateBorrowReturn(
|
||||
borrowInfo.getId(),
|
||||
"2", // is_borrowed = 2 已归还
|
||||
rkInfoId,
|
||||
"2", // is_borrowed = 已归还
|
||||
item.getReturnTime()
|
||||
);
|
||||
|
||||
/* ================== 4. 更新 rk_record(状态闭环,按主键) ================== */
|
||||
rkRecordMapper.updateBorrowReturnRecordById(
|
||||
record.getId(),
|
||||
"2", // is_borrowed = 已归还
|
||||
item.getReturnTime(),
|
||||
userId,
|
||||
now
|
||||
);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
private RkRecord buildReturnRkRecord(RkBill bill, RkInfo info, Date now) {
|
||||
|
||||
RkRecord record = new RkRecord();
|
||||
|
||||
// ① 明细快照
|
||||
BeanUtils.copyProperties(info, record);
|
||||
record.setId(null);
|
||||
|
||||
// ② 主单上下文
|
||||
record.setBillNo(bill.getBillNo());
|
||||
record.setBizType("3"); // 还料入库
|
||||
record.setOperationType(bill.getOperationType());
|
||||
record.setOperationTime(bill.getOperationTime());
|
||||
record.setOperator(bill.getOperator());
|
||||
record.setCangku(info.getCangku());
|
||||
record.setTeamCode(info.getTeamCode());
|
||||
|
||||
// ③ 状态
|
||||
record.setIsChuku("0");
|
||||
record.setIsBorrowed("2"); // 已归还
|
||||
record.setHasMoved("0");
|
||||
record.setExecStatus(bill.getExecStatus());
|
||||
record.setIsDelete("0");
|
||||
|
||||
// ④ 审计
|
||||
record.setCreateTime(now);
|
||||
record.setCreateBy(bill.getCreateBy());
|
||||
|
||||
// ⑤ 关联
|
||||
record.setRkInfoId(info.getId());
|
||||
record.setRdid(info.getRdid()); // 指向原借料库存
|
||||
|
||||
return record;
|
||||
return dto.getItems().size();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.zg.project.wisdom.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import com.zg.common.utils.DateUtils;
|
||||
import com.zg.project.wisdom.domain.vo.StockStatisticVO;
|
||||
import com.zg.project.wisdom.mapper.RkRecordMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -105,4 +106,10 @@ public class RkInfoServiceImpl implements IRkInfoService
|
||||
{
|
||||
return rkInfoMapper.deleteRkInfoById(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public StockStatisticVO getStockStatistic(RkInfo query) {
|
||||
return rkInfoMapper.selectStockStatisticByCondition(query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.zg.common.utils.DateUtils;
|
||||
import com.zg.common.utils.StringUtils;
|
||||
import com.zg.project.wisdom.domain.GysJh;
|
||||
import com.zg.project.wisdom.domain.RkInfo;
|
||||
import com.zg.project.wisdom.domain.vo.RecordStatisticVO;
|
||||
import com.zg.project.wisdom.mapper.GysJhMapper;
|
||||
import com.zg.project.wisdom.mapper.RkBillMapper;
|
||||
import com.zg.project.wisdom.mapper.RkInfoMapper;
|
||||
@@ -206,6 +207,8 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
info.setGysMc(rkRecord.getGysMc());
|
||||
info.setDw(rkRecord.getDw());
|
||||
info.setHtDj(rkRecord.getHtDj());
|
||||
info.setCangku(rkRecord.getCangku());
|
||||
info.setPcode(rkRecord.getPcode());
|
||||
info.setIsChuku("0");
|
||||
}
|
||||
|
||||
@@ -240,6 +243,8 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
info.setGysMc(rkRecord.getGysMc());
|
||||
info.setDw(rkRecord.getDw());
|
||||
info.setHtDj(rkRecord.getHtDj());
|
||||
info.setCangku(rkRecord.getCangku());
|
||||
info.setPcode(rkRecord.getPcode());
|
||||
}
|
||||
|
||||
/* ====================== 4. 更新库存表 ====================== */
|
||||
@@ -431,14 +436,12 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
}
|
||||
|
||||
/* ================== 1. 查询 rk_record ================== */
|
||||
List<RkRecord> recordList =
|
||||
rkRecordMapper.selectRkRecordByIds(recordIds);
|
||||
|
||||
List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
|
||||
if (recordList == null || recordList.isEmpty()) {
|
||||
throw new ServiceException("入库记录不存在");
|
||||
}
|
||||
|
||||
/* ================== 2. 只处理「预入库」记录 ================== */
|
||||
/* ================== 2. 仅处理「预入库」记录 ================== */
|
||||
List<RkRecord> preRecordList = recordList.stream()
|
||||
.filter(r -> "0".equals(r.getExecStatus())) // 预入库
|
||||
.collect(Collectors.toList());
|
||||
@@ -447,16 +450,13 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
throw new ServiceException("所选入库记录均已完成,无需重复入库");
|
||||
}
|
||||
|
||||
/* ================== 3. ★ 校验:一键入库数量 ≤ 计划交货数量 ================== */
|
||||
// 按供应计划ID聚合「本次完成入库数量」
|
||||
/* ================== 3. 校验:完成入库数量 ≤ 计划交货数量 ================== */
|
||||
Map<Long, BigDecimal> finishQtyMap = new HashMap<>();
|
||||
|
||||
for (RkRecord record : preRecordList) {
|
||||
|
||||
if (record.getGysJhId() == null || record.getRealQty() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
finishQtyMap.merge(
|
||||
record.getGysJhId(),
|
||||
record.getRealQty(),
|
||||
@@ -464,7 +464,6 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
);
|
||||
}
|
||||
|
||||
// 只和「计划交货数量」做校验
|
||||
for (Map.Entry<Long, BigDecimal> entry : finishQtyMap.entrySet()) {
|
||||
|
||||
Long gysJhId = entry.getKey();
|
||||
@@ -494,7 +493,7 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
|
||||
rkRecordMapper.updateExecStatusByIds(preRecordIds, "1");
|
||||
|
||||
// ② rk_info.exec_status = 1
|
||||
// ② rk_info.exec_status = 1(只推进本次涉及的库存)
|
||||
List<Long> rkInfoIds = preRecordList.stream()
|
||||
.map(RkRecord::getRkInfoId)
|
||||
.filter(Objects::nonNull)
|
||||
@@ -505,27 +504,33 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1");
|
||||
}
|
||||
|
||||
// ③ rk_bill.exec_status = 1
|
||||
List<String> billNos = preRecordList.stream()
|
||||
// ③ rk_bill.exec_status = 1(✅ 只有当 bill 下所有 record 均完成)
|
||||
Set<String> billNoSet = preRecordList.stream()
|
||||
.map(RkRecord::getBillNo)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (String billNo : billNos) {
|
||||
rkBillMapper.updateExecStatusByBillNo(billNo, "1");
|
||||
for (String billNo : billNoSet) {
|
||||
|
||||
// 查询该 bill 下是否仍存在 预入库 record
|
||||
int unFinishedCount = rkRecordMapper.countPreInRecordByBillNo(billNo);
|
||||
|
||||
// 只有当不存在任何预入库 record 时,才推进 bill 状态
|
||||
if (unFinishedCount == 0) {
|
||||
rkBillMapper.updateExecStatusByBillNo(billNo, "1");
|
||||
}
|
||||
}
|
||||
|
||||
/* ================== 5. ★ 同步修正供应计划(以完成结果为准) ================== */
|
||||
/* ================== 5. 同步修正供应计划 ================== */
|
||||
for (Map.Entry<Long, BigDecimal> entry : finishQtyMap.entrySet()) {
|
||||
|
||||
Long gysJhId = entry.getKey();
|
||||
BigDecimal finishQty = entry.getValue();
|
||||
|
||||
// ① 直接修正 real_qty(以一键入库结果为准)
|
||||
// ① 修正实收数量
|
||||
gysJhMapper.updateRealQtyById(gysJhId, finishQty);
|
||||
|
||||
// ② 重新判定状态
|
||||
// ② 修正状态
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
|
||||
if (gysJh == null) {
|
||||
continue;
|
||||
@@ -546,6 +551,7 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
return preRecordIds.size();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int rollbackOut(List<Long> recordIds) {
|
||||
@@ -752,6 +758,12 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
|
||||
return deleteCount;
|
||||
}
|
||||
@Override
|
||||
public RecordStatisticVO getRecordStatistic(RkRecord query) {
|
||||
|
||||
|
||||
RecordStatisticVO vo = new RecordStatisticVO();
|
||||
vo.setInStatistic(rkRecordMapper.selectInRecordStatistic(query));
|
||||
vo.setOutStatistic(rkRecordMapper.selectOutRecordStatistic(query));
|
||||
return vo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,6 +189,65 @@
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<select id="selectStockStatisticByCondition"
|
||||
parameterType="com.zg.project.wisdom.domain.RkInfo"
|
||||
resultType="com.zg.project.wisdom.domain.vo.StockStatisticVO">
|
||||
|
||||
SELECT
|
||||
IFNULL(SUM(ri.real_qty * ri.ht_dj), 0) AS total_amount,
|
||||
COUNT(DISTINCT ri.pcode) AS location_count,
|
||||
IFNULL(SUM(ri.real_qty), 0) AS total_quantity
|
||||
FROM rk_info ri
|
||||
<where>
|
||||
ri.exec_status = 1
|
||||
AND ri.is_chuku = 0
|
||||
AND ri.is_delete = 0
|
||||
|
||||
<if test="operationType != null and operationType != ''">
|
||||
AND ri.operation_type LIKE CONCAT('%', #{operationType}, '%')
|
||||
</if>
|
||||
<if test="sapNo != null and sapNo != ''">
|
||||
AND ri.sap_no LIKE CONCAT('%', #{sapNo}, '%')
|
||||
</if>
|
||||
<if test="xmNo != null and xmNo != ''">
|
||||
AND ri.xm_no LIKE CONCAT('%', #{xmNo}, '%')
|
||||
</if>
|
||||
<if test="xmMs != null and xmMs != ''">
|
||||
AND ri.xm_ms LIKE CONCAT('%', #{xmMs}, '%')
|
||||
</if>
|
||||
<if test="wlNo != null and wlNo != ''">
|
||||
AND ri.wl_no LIKE CONCAT('%', #{wlNo}, '%')
|
||||
</if>
|
||||
<if test="wlMs != null and wlMs != ''">
|
||||
AND ri.wl_ms LIKE CONCAT('%', #{wlMs}, '%')
|
||||
</if>
|
||||
<if test="gysMc != null and gysMc != ''">
|
||||
AND ri.gys_mc LIKE CONCAT('%', #{gysMc}, '%')
|
||||
</if>
|
||||
<if test="pcode != null and pcode != ''">
|
||||
AND ri.pcode LIKE CONCAT('%', #{pcode}, '%')
|
||||
</if>
|
||||
<if test="bizType != null and bizType != ''">
|
||||
AND ri.biz_type LIKE CONCAT('%', #{bizType}, '%')
|
||||
</if>
|
||||
<if test="wlType != null and wlType != ''">
|
||||
AND ri.wl_type LIKE CONCAT('%', #{wlType}, '%')
|
||||
</if>
|
||||
<if test="cangku != null and cangku != ''">
|
||||
AND ri.cangku LIKE CONCAT('%', #{cangku}, '%')
|
||||
</if>
|
||||
<if test="billNo != null and billNo != ''">
|
||||
AND ri.bill_no LIKE CONCAT('%', #{billNo}, '%')
|
||||
</if>
|
||||
<if test="startDate != null">
|
||||
AND ri.operation_time >= #{startDate}
|
||||
</if>
|
||||
<if test="endDate != null">
|
||||
AND ri.operation_time <= #{endDate}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<!-- ========================= 删除 ========================= -->
|
||||
<delete id="deleteRkInfoById" parameterType="Long">
|
||||
DELETE FROM rk_info WHERE id = #{id}
|
||||
@@ -327,6 +386,7 @@
|
||||
return_time = #{returnTime},
|
||||
update_time = NOW()
|
||||
WHERE id = #{id}
|
||||
AND is_delete = '0'
|
||||
</update>
|
||||
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
<result property="trayCode" column="tray_code"/>
|
||||
<result property="entityId" column="entity_id"/>
|
||||
<result property="teamCode" column="team_code"/>
|
||||
<result property="teamName" column="team_name"/>
|
||||
|
||||
<result property="borrowTime" column="borrow_time"/>
|
||||
<result property="returnTime" column="return_time"/>
|
||||
@@ -101,7 +102,8 @@
|
||||
/* 仓库信息:小仓/大仓 */
|
||||
wh.warehouse_name,
|
||||
wh.parent_warehouse_code,
|
||||
wh.parent_warehouse_name
|
||||
wh.parent_warehouse_name,
|
||||
ct.team_name AS team_name
|
||||
FROM rk_record rr
|
||||
LEFT JOIN sys_user su
|
||||
ON rr.operator = su.user_id
|
||||
@@ -113,6 +115,9 @@
|
||||
ON rr.operation_type = sot.type_code
|
||||
LEFT JOIN warehouse_info wh
|
||||
ON rr.cangku = wh.warehouse_code
|
||||
LEFT JOIN construction_team ct
|
||||
ON rr.team_code = ct.team_code
|
||||
AND ct.is_delete = '0'
|
||||
</sql>
|
||||
|
||||
<!-- ===================== 查询列表 ===================== -->
|
||||
@@ -193,7 +198,10 @@
|
||||
<if test="wlMs != null and wlMs != ''">
|
||||
AND rr.wl_ms LIKE concat('%', #{wlMs}, '%')
|
||||
</if>
|
||||
|
||||
<!-- 是否借料 -->
|
||||
<if test="isBorrowed != null and isBorrowed != ''">
|
||||
AND rr.is_borrowed = #{isBorrowed}
|
||||
</if>
|
||||
<!-- 默认不查删除 -->
|
||||
<if test="isDelete == null">
|
||||
AND (rr.is_delete = '0' OR rr.is_delete = 0 OR rr.is_delete IS NULL)
|
||||
@@ -528,4 +536,102 @@
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
|
||||
<!-- 入库统计 -->
|
||||
<select id="selectInRecordStatistic"
|
||||
parameterType="com.zg.project.wisdom.domain.RkRecord"
|
||||
resultType="com.zg.project.wisdom.domain.vo.StockStatisticVO">
|
||||
|
||||
SELECT
|
||||
IFNULL(SUM(rr.real_qty * rr.ht_dj), 0) AS total_amount,
|
||||
COUNT(DISTINCT rr.pcode) AS location_count,
|
||||
IFNULL(SUM(rr.real_qty), 0) AS total_quantity
|
||||
FROM rk_record rr
|
||||
<where>
|
||||
rr.is_delete = 0
|
||||
AND rr.exec_status = 1
|
||||
AND rr.biz_type = 0 <!-- 入库 -->
|
||||
|
||||
<if test="operationType != null and operationType != ''">
|
||||
AND rr.operation_type LIKE CONCAT('%', #{operationType}, '%')
|
||||
</if>
|
||||
<if test="xmNo != null and xmNo != ''">
|
||||
AND rr.xm_no LIKE CONCAT('%', #{xmNo}, '%')
|
||||
</if>
|
||||
<if test="wlNo != null and wlNo != ''">
|
||||
AND rr.wl_no LIKE CONCAT('%', #{wlNo}, '%')
|
||||
</if>
|
||||
<if test="pcode != null and pcode != ''">
|
||||
AND rr.pcode LIKE CONCAT('%', #{pcode}, '%')
|
||||
</if>
|
||||
<if test="cangku != null and cangku != ''">
|
||||
AND rr.cangku LIKE CONCAT('%', #{cangku}, '%')
|
||||
</if>
|
||||
<if test="startDate != null">
|
||||
AND rr.operation_time >= #{startDate}
|
||||
</if>
|
||||
<if test="endDate != null">
|
||||
AND rr.operation_time <= #{endDate}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<!-- 出库统计 -->
|
||||
<select id="selectOutRecordStatistic"
|
||||
parameterType="com.zg.project.wisdom.domain.RkRecord"
|
||||
resultType="com.zg.project.wisdom.domain.vo.StockStatisticVO">
|
||||
|
||||
SELECT
|
||||
IFNULL(SUM(rr.real_qty * rr.ht_dj), 0) AS total_amount,
|
||||
COUNT(DISTINCT rr.pcode) AS location_count,
|
||||
IFNULL(SUM(rr.real_qty), 0) AS total_quantity
|
||||
FROM rk_record rr
|
||||
<where>
|
||||
rr.is_delete = 0
|
||||
AND rr.exec_status = 1
|
||||
AND rr.biz_type = 1 <!-- 出库 -->
|
||||
|
||||
<if test="operationType != null and operationType != ''">
|
||||
AND rr.operation_type LIKE CONCAT('%', #{operationType}, '%')
|
||||
</if>
|
||||
<if test="xmNo != null and xmNo != ''">
|
||||
AND rr.xm_no LIKE CONCAT('%', #{xmNo}, '%')
|
||||
</if>
|
||||
<if test="wlNo != null and wlNo != ''">
|
||||
AND rr.wl_no LIKE CONCAT('%', #{wlNo}, '%')
|
||||
</if>
|
||||
<if test="pcode != null and pcode != ''">
|
||||
AND rr.pcode LIKE CONCAT('%', #{pcode}, '%')
|
||||
</if>
|
||||
<if test="cangku != null and cangku != ''">
|
||||
AND rr.cangku LIKE CONCAT('%', #{cangku}, '%')
|
||||
</if>
|
||||
<if test="startDate != null">
|
||||
AND rr.operation_time >= #{startDate}
|
||||
</if>
|
||||
<if test="endDate != null">
|
||||
AND rr.operation_time <= #{endDate}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="countPreInRecordByBillNo" resultType="int">
|
||||
SELECT COUNT(1)
|
||||
FROM rk_record
|
||||
WHERE bill_no = #{billNo}
|
||||
AND exec_status = '0'
|
||||
AND is_delete = '0'
|
||||
</select>
|
||||
|
||||
<update id="updateBorrowReturnRecordById">
|
||||
UPDATE rk_record
|
||||
SET
|
||||
is_borrowed = #{isBorrowed},
|
||||
return_time = #{returnTime},
|
||||
update_by = #{updateBy},
|
||||
update_time = #{updateTime}
|
||||
WHERE id = #{id}
|
||||
AND is_delete = '0'
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user