出入库逻辑修改

This commit is contained in:
2025-07-25 17:04:11 +08:00
parent 428787f83f
commit 0696040874
9 changed files with 303 additions and 99 deletions

View File

@@ -38,8 +38,8 @@ public class RkInfoController extends BaseController
* 查询库存单据主列表
*/
@PreAuthorize("@ss.hasPermi('wisdom:stock:list')")
@GetMapping("/list")
public TableDataInfo list(RkInfo rkInfo)
@PostMapping("/list")
public TableDataInfo list(@RequestBody RkInfo rkInfo)
{
startPage();
List<RkInfo> list = rkInfoService.selectRkInfoList(rkInfo);

View File

@@ -83,6 +83,14 @@ public class GysJh extends BaseEntity
@Excel(name = "0未到货1已入库")
private String status;
/** 身份码 */
@Excel(name = "身份码")
private String entityId;
/** 备注 */
@Excel(name = "备注")
private String remark;
/** 是否删除0正常 1删除 */
@Excel(name = "是否删除", readConverterExp = "0=正常,1=删除")
private String isDelete;
@@ -257,6 +265,26 @@ public class GysJh extends BaseEntity
return status;
}
public void setEntityId(String entityId)
{
this.entityId = entityId;
}
public String getEntityId()
{
return entityId;
}
public void setRemark(String remark)
{
this.remark = remark;
}
public String getRemark()
{
return remark;
}
public void setIsDelete(String isDelete)
{
this.isDelete = isDelete;
@@ -287,6 +315,7 @@ public class GysJh extends BaseEntity
.append("htQty", getHtQty())
.append("dw", getDw())
.append("status", getStatus())
.append("entityId", getEntityId())
.append("remark", getRemark())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())

View File

@@ -34,6 +34,10 @@ public class RkInfo extends BaseEntity
@Excel(name = "供应计划ID")
private Long gysJhId;
/** 审批人ID非数据库字段 */
@TableField(exist = false)
private String approverId;
/** 库龄 */
private Long stockAge;
@@ -249,6 +253,14 @@ public class RkInfo extends BaseEntity
public void setGysJhId(Long gysJhId) {
this.gysJhId = gysJhId;
}
public String getApproverId() {
return approverId;
}
public void setApproverId(String approverId) {
this.approverId = approverId;
}
public Long getStockAge() { return stockAge; }
public void setStockAge(Long stockAge) { this.stockAge = stockAge; }
public String getRkType() { return rkType; }
@@ -424,6 +436,7 @@ public class RkInfo extends BaseEntity
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("gysJhId", getGysJhId())
.append("approverId", getApproverId())
.append("rkType", getRkType())
.append("wlType", getWlType())
.append("cangku", getCangku())

View File

@@ -6,9 +6,6 @@ import java.util.List;
@Data
public class RkInfoBatchDTO {
/** 供应商计划ID */
private Long gysJhId;
/** 审核人用户ID */
private String approverId;

View File

@@ -11,9 +11,6 @@ import java.util.List;
@Data
public class RkInfoItemDTO {
/** 供应计划主键ID */
private Long gysJhId;
/** SAP物料号数据库字段 wl_no */
private String wlNo;

View File

@@ -1,5 +1,7 @@
package com.zg.project.wisdom.mapper;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -96,6 +98,19 @@ public interface GysJhMapper
* 批量修改状态
* @param
*/
void batchUpdateStatusByIds(@Param("idSet") Set<Long> idSet);
void batchUpdateStatusByIds(@Param("ids") Set<Long> ids);
/**
* 根据id批量查询
* @param
* @return
*/
List<GysJh> selectByIds(@Param("ids") List<Long> ids);
/**
* 根据id修改
* @param
* @param realQty
*/
void decreaseJhQtyById(@Param("id") Long id, @Param("realQty") BigDecimal realQty);
}

View File

@@ -1,5 +1,6 @@
package com.zg.project.wisdom.service.impl;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
@@ -19,6 +20,7 @@ import com.zg.project.Inventory.domain.vo.ChartDataVO;
import com.zg.project.Inventory.domain.vo.PcdeCntVO;
import com.zg.project.system.service.ISysConfigService;
import com.zg.project.wisdom.domain.AuditSignature;
import com.zg.project.wisdom.domain.GysJh;
import com.zg.project.wisdom.domain.dto.*;
import com.zg.project.wisdom.mapper.AuditSignatureMapper;
import com.zg.project.wisdom.mapper.GysJhMapper;
@@ -95,27 +97,33 @@ public class RkInfoServiceImpl implements IRkInfoService
info.setStockAge(days);
}
// 查询现场图片 + 审核结果image_type = '1'
// 查询现场图片 + 审核结果
AuditSignature signature = auditSignatureMapper.selectPhotoUrlByRkId(info.getId());
if (signature != null) {
info.setScenePhotoUrl(signature.getSignUrl());
info.setAuditResult(signature.getAuditResult());
info.setApproverId(signature.getApproverId());
} else {
info.setScenePhotoUrl(null);
info.setAuditResult(null);
info.setApproverId(null);
}
}
// 审核开启,过滤掉未通过的(只有 auditResult = '1' 保留
// 审核开启,过滤掉审核结果不是“通过” 且 审核人不为空(说明是审核失败
if (needAudit) {
list = list.stream()
.filter(info -> "1".equals(info.getAuditResult()))
.filter(info ->
// ① 未审核过approverId 为空)或
info.getApproverId() == null ||
// ② 审核通过
"1".equals(info.getAuditResult())
)
.collect(Collectors.toList());
}
return list;
}
/**
* 修改库存单据主
*
@@ -126,6 +134,7 @@ public class RkInfoServiceImpl implements IRkInfoService
public int updateRkInfo(RkInfo rkInfo)
{
rkInfo.setUpdateTime(DateUtils.getNowDate());
rkInfo.setUpdateBy(SecurityUtils.getUserId().toString());
return rkInfoMapper.updateRkInfo(rkInfo);
}
@@ -164,14 +173,50 @@ public class RkInfoServiceImpl implements IRkInfoService
String billNo = BillNoUtil.generateTodayBillNo("RK");
List<PcRkInfoItemDTO> list = dto.getRkList();
List<RkInfo> rkInfos = new ArrayList<>();
List<AuditSignature> records = new ArrayList<>();
boolean needAudit = "1".equals(configService.selectConfigByKey("rk.audit.enabled"));
String userId = SecurityUtils.getUserId().toString();
Date now = DateUtils.getNowDate();
List<AuditSignature> records = new ArrayList<>();
// ✅ 第1步构建 gysJhId -> realQty 映射
Map<Long, BigDecimal> realQtyMap = list.stream()
.filter(item -> item.getGysJhId() != null && item.getRealQty() != null)
.collect(Collectors.toMap(
PcRkInfoItemDTO::getGysJhId,
PcRkInfoItemDTO::getRealQty,
(a, b) -> b
));
// ✅ 第步:构造 RkInfo 列表(包含 gysJhId
// ✅ 第2步:查询对应供应计划
List<GysJh> jhList = gysJhMapper.selectByIds(new ArrayList<>(realQtyMap.keySet()));
Set<Long> idsToUpdateStatus = new HashSet<>();
// ✅ 第3步更新 jh_qty 和 status根据是否开启审核判断逻辑
for (GysJh jh : jhList) {
Long jhId = jh.getId();
BigDecimal planQty = BigDecimal.valueOf(jh.getJhQty());
BigDecimal realQty = realQtyMap.get(jhId);
if (realQty == null) continue;
boolean isEqual = realQty.compareTo(planQty) == 0;
if (!isEqual) {
gysJhMapper.decreaseJhQtyById(jhId, realQty);
idsToUpdateStatus.add(jhId);
} else {
if (!needAudit) {
idsToUpdateStatus.add(jhId);
}
}
}
// ✅ 第4步批量更新 status = 2
if (!idsToUpdateStatus.isEmpty()) {
gysJhMapper.batchUpdateStatusByIds(idsToUpdateStatus);
}
// ✅ 第5步构建 RkInfo 入库记录
for (PcRkInfoItemDTO item : list) {
RkInfo rk = new RkInfo();
BeanUtils.copyProperties(item, rk);
@@ -184,12 +229,11 @@ public class RkInfoServiceImpl implements IRkInfoService
rk.setCreateBy(userId);
rk.setCreateTime(now);
rk.setIsDelete("0");
rk.setGysJhId(item.getGysJhId()); // ✅ 正确设置 gysJhId
rk.setGysJhId(item.getGysJhId());
if (needAudit) {
rk.setStatus("0"); // 待审核
rk.setIsChuku("2"); // 待入库(审核中)
rk.setIsChuku("2"); // 待入库
} else {
rk.setStatus("1"); // 审核通过
rk.setIsChuku("0"); // 已入库
@@ -198,10 +242,10 @@ public class RkInfoServiceImpl implements IRkInfoService
rkInfos.add(rk);
}
// ✅ 第步:批量保存入库记录
// ✅ 第6步:保存入库记录
rkInfoMapper.batchInsertRkInfo(rkInfos);
// ✅ 第步:构造照片记录(审核开启时)
// ✅ 第7步:照片记录(审核开启时)
for (int i = 0; i < rkInfos.size(); i++) {
RkInfo rk = rkInfos.get(i);
PcRkInfoItemDTO item = list.get(i);
@@ -214,7 +258,7 @@ public class RkInfoServiceImpl implements IRkInfoService
photo.setAuditResult("2");
photo.setSignerId(userId);
photo.setSignerRole("2");
photo.setImageType("1"); // 现场图
photo.setImageType("1");
photo.setSignUrl(item.getPhotoUrl());
photo.setSignTime(now);
photo.setPcode(item.getPcode());
@@ -228,7 +272,7 @@ public class RkInfoServiceImpl implements IRkInfoService
}
}
// ✅ 第步:审核开启时添加发起人签字记录
// ✅ 第8步:发起人签字记录(审核开启时)
if (needAudit) {
boolean hasOldSign = auditSignatureMapper.existsCurrentSigner(billNo, "0");
if (hasOldSign) {
@@ -239,10 +283,10 @@ public class RkInfoServiceImpl implements IRkInfoService
mainSign.setBillNo(billNo);
mainSign.setBillType("0");
mainSign.setSignerId(userId);
mainSign.setSignerRole("0"); // 发起人
mainSign.setSignerRole("0");
mainSign.setApproverId(dto.getApproverId());
mainSign.setSignUrl(dto.getSignatureUrl());
mainSign.setImageType("0"); // 签字图
mainSign.setImageType("0");
mainSign.setSignTime(now);
mainSign.setIsCurrent("1");
mainSign.setAuditResult("2");
@@ -251,21 +295,7 @@ public class RkInfoServiceImpl implements IRkInfoService
mainSign.setCreateTime(now);
records.add(mainSign);
if (!records.isEmpty()) {
auditSignatureMapper.batchInsert(records);
}
}
// ✅ 第五步:如果审核关闭,立即批量更新供应计划状态
if (!needAudit) {
Set<Long> jhIdSet = list.stream()
.map(PcRkInfoItemDTO::getGysJhId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
if (!jhIdSet.isEmpty()) {
gysJhMapper.batchUpdateStatusByIds(jhIdSet);
}
auditSignatureMapper.batchInsert(records);
}
}
@@ -288,12 +318,55 @@ public class RkInfoServiceImpl implements IRkInfoService
boolean needAudit = "1".equals(configService.selectConfigByKey("rk.audit.enabled"));
String billNo = BillNoUtil.generateTodayBillNo("RK");
// ✅ 第步:构造入库数据列表
// ✅ 第1步:构造 gysJhId → realQty 的映射(从 scanList 中提取)
Map<Long, BigDecimal> realQtyMap = new HashMap<>();
for (RkInfoItemDTO item : dto.getRkList()) {
List<RkInfoScanDTO> scanList = item.getScanList();
if (scanList == null || scanList.isEmpty()) continue;
if (item.getScanList() == null) continue;
for (RkInfoScanDTO scan : item.getScanList()) {
Long jhId = scan.getGysJhId();
BigDecimal realQty = scan.getRealQty();
if (jhId != null && realQty != null) {
realQtyMap.put(jhId, realQty); // ✅ 一物一图场景,每个 jhId 只有一条 scan 数据
}
}
}
for (RkInfoScanDTO scan : scanList) {
// ✅ 第2步更新 gys_jh 的 jh_qty 与 status
Set<Long> idsToUpdateStatus = new HashSet<>();
List<Long> allJhIds = new ArrayList<>(realQtyMap.keySet());
if (!allJhIds.isEmpty()) {
List<GysJh> jhList = gysJhMapper.selectByIds(allJhIds);
for (GysJh jh : jhList) {
Long jhId = jh.getId();
BigDecimal planQty = BigDecimal.valueOf(jh.getJhQty());
BigDecimal realQty = realQtyMap.get(jhId);
if (realQty == null) continue;
boolean isEqual = realQty.compareTo(planQty) == 0;
if (!isEqual) {
// 数量不相等,减数量 + 状态设为 2
gysJhMapper.decreaseJhQtyById(jhId, realQty);
idsToUpdateStatus.add(jhId);
} else {
if (!needAudit) {
// 审核关闭且数量相等,仅更新状态
idsToUpdateStatus.add(jhId);
}
}
}
}
if (!idsToUpdateStatus.isEmpty()) {
gysJhMapper.batchUpdateStatusByIds(idsToUpdateStatus);
}
// ✅ 第3步构建 RkInfo 入库实体
for (RkInfoItemDTO item : dto.getRkList()) {
if (item.getScanList() == null) continue;
for (RkInfoScanDTO scan : item.getScanList()) {
RkInfo entity = new RkInfo();
entity.setRkType(dto.getRkType());
entity.setWlType(dto.getWlType());
@@ -307,7 +380,6 @@ public class RkInfoServiceImpl implements IRkInfoService
entity.setJhQty(item.getJhQty());
entity.setHtQty(item.getHtQty());
entity.setJhAmt(item.getJhAmt());
entity.setGysJhId(item.getGysJhId());
entity.setHtDj(item.getHtDj());
entity.setDw(item.getDw());
entity.setWlNo(item.getWlNo());
@@ -320,6 +392,7 @@ public class RkInfoServiceImpl implements IRkInfoService
entity.setRealQty(scan.getRealQty());
entity.setEntityId(scan.getEntityId());
entity.setRemark(scan.getRemark());
entity.setGysJhId(scan.getGysJhId());
entity.setIsDelete("0");
entity.setRkTime(now);
entity.setCreateBy(userId);
@@ -327,7 +400,7 @@ public class RkInfoServiceImpl implements IRkInfoService
if (needAudit) {
entity.setStatus("0"); // 待审核
entity.setIsChuku("2"); // 待入库(审核中)
entity.setIsChuku("2"); // 待入库
} else {
entity.setStatus("1"); // 审核通过
entity.setIsChuku("0"); // 已入库
@@ -335,37 +408,31 @@ public class RkInfoServiceImpl implements IRkInfoService
saveList.add(entity);
}
if (!needAudit && item.getGysJhId() != null) {
gysJhMapper.updateStatusById(item.getGysJhId());
}
}
if (saveList.isEmpty()) {
throw new ServiceException("未提取到任何可保存的数据");
}
// ✅ 第步:批量插入入库数据回填主键ID
// ✅ 第4步:批量插入入库记录
rkInfoMapper.batchInsertRkInfo(saveList);
// ✅ 第步:处理签字与照片记录(仅启用审核时)
// ✅ 第5步:若开启审核,写入签字与照片信息
if (needAudit) {
List<AuditSignature> recordList = new ArrayList<>();
// 检查是否重新提交,旧记录置为非当前
boolean isResubmit = auditSignatureMapper.existsCurrentSigner(billNo, "0");
if (isResubmit) {
auditSignatureMapper.updateIsCurrentToZero(billNo, "0");
}
// ✅ 1. 添加发起人签字记录
// 发起人签字记录
AuditSignature mainSign = new AuditSignature();
mainSign.setBillNo(billNo);
mainSign.setBillType("0");
mainSign.setSignerId(userId);
mainSign.setSignerRole("0"); // 发起人
mainSign.setSignerRole("0");
mainSign.setSignUrl(dto.getSignatureUrl());
mainSign.setImageType("0"); // 签字图
mainSign.setImageType("0");
mainSign.setSignTime(now);
mainSign.setApproverId(dto.getApproverId());
mainSign.setAuditResult("2");
@@ -375,24 +442,21 @@ public class RkInfoServiceImpl implements IRkInfoService
mainSign.setCreateTime(now);
recordList.add(mainSign);
// ✅ 2. 绑定每条 rkInfo 与对应 scanList 的 photoUrl
// 现场照片记录
int index = 0;
for (RkInfoItemDTO item : dto.getRkList()) {
List<RkInfoScanDTO> scanList = item.getScanList();
if (scanList == null || scanList.isEmpty()) continue;
for (RkInfoScanDTO scan : scanList) {
if (item.getScanList() == null) continue;
for (RkInfoScanDTO scan : item.getScanList()) {
RkInfo rk = saveList.get(index++);
if (StringUtils.isNotBlank(scan.getPhotoUrl())) {
AuditSignature photo = new AuditSignature();
photo.setBillNo(billNo);
photo.setBillType("0");
photo.setRkId(rk.getId());
photo.setSignerId(userId);
photo.setSignerRole("2"); // 拍照人
photo.setSignerRole("2");
photo.setSignUrl(scan.getPhotoUrl());
photo.setImageType("1"); // 现场图
photo.setImageType("1");
photo.setSignTime(now);
photo.setApproverId(dto.getApproverId());
photo.setIsCurrent("1");
@@ -407,7 +471,6 @@ public class RkInfoServiceImpl implements IRkInfoService
}
}
// ✅ 3. 批量写入 audit_signature
if (!recordList.isEmpty()) {
auditSignatureMapper.batchInsert(recordList);
}
@@ -500,10 +563,18 @@ public class RkInfoServiceImpl implements IRkInfoService
if (needAudit) {
update.setStatus("3"); // 出库待审核
update.setIsChuku("2");
if ("JLCK".equals(dto.getCkType())) {
update.setIsChuku("3"); // 借料出库(待审核)
} else {
update.setIsChuku("2"); // 普通出库待审核
}
} else {
update.setIsChuku("1");
update.setStatus("1"); // 审核通过
if ("JLCK".equals(dto.getCkType())) {
update.setIsChuku("3"); // 借料出库(已审核)
} else {
update.setIsChuku("1"); // 普通出库已审核
}
}
rkInfoMapper.updateById(update);