库存模块功能开发
This commit is contained in:
@@ -42,6 +42,17 @@ public class MoveRecordController extends BaseController
|
||||
return AjaxResult.success("移库成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销移库
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('wisdom:stock:move:rollback')")
|
||||
@Log(title = "撤销移库", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/rollback/{id}")
|
||||
public AjaxResult rollbackMove(@PathVariable("id") Long moveRecordId) {
|
||||
moveRecordService.rollbackMove(moveRecordId);
|
||||
return AjaxResult.success("撤销移库成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询移库记录列表
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@@ -90,7 +89,6 @@ public class RkBillController extends BaseController
|
||||
return toAjax(rkBillService.appendRkBillDetail(dto));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改库存单据
|
||||
*/
|
||||
@@ -107,9 +105,30 @@ public class RkBillController extends BaseController
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('wisdom:bill:remove')")
|
||||
@Log(title = "库存单据", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
@DeleteMapping("/delete")
|
||||
public AjaxResult remove(@RequestBody Long[] ids)
|
||||
{
|
||||
return toAjax(rkBillService.deleteRkBillByIds(ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增出库单据
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('wisdom:bill:out:add')")
|
||||
@Log(title = "出库单据", businessType = BusinessType.INSERT)
|
||||
@PostMapping("/out/add")
|
||||
public AjaxResult addOut(@RequestBody RkBillCreateDTO dto) {
|
||||
return toAjax(rkBillService.insertOutBillAndDetail(dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 还料入库
|
||||
*/
|
||||
@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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -102,12 +102,12 @@ public class RkRecordController extends BaseController
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除出入库记录
|
||||
* 删除入库记录
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('wisdom:record:remove')")
|
||||
@Log(title = "出入库记录", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{ids}")
|
||||
public AjaxResult remove(@PathVariable Long[] ids)
|
||||
@Log(title = "入库记录", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/delete")
|
||||
public AjaxResult remove(@RequestBody Long[] ids)
|
||||
{
|
||||
return toAjax(rkRecordService.deleteRkRecordByIds(ids));
|
||||
}
|
||||
@@ -132,4 +132,34 @@ public class RkRecordController extends BaseController
|
||||
return toAjax(rkRecordService.finishIn(record.getIds()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销出库
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('wisdom:bill:out:rollback')")
|
||||
@Log(title = "撤销出库", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/out/rollback")
|
||||
public AjaxResult rollbackOut(@RequestBody RkRecord record) {
|
||||
return toAjax(rkRecordService.rollbackOut(record.getIds()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 一键出库(批量完成出库)
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('wisdom:record:out:finish')")
|
||||
@Log(title = "一键出库", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/out/finish")
|
||||
public AjaxResult finishOut(@RequestBody RkRecord record) {
|
||||
return toAjax(rkRecordService.finishOut(record.getIds()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除预出库记录
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('wisdom:record:out:remove')")
|
||||
@Log(title = "预出库记录删除", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/out/delete")
|
||||
public AjaxResult deletePreOut(@RequestBody Long[] ids) {
|
||||
return toAjax(rkRecordService.deletePreOutRecords(ids));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,12 @@ import com.zg.framework.web.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 供应计划对象 gys_jh
|
||||
*
|
||||
*
|
||||
* 说明:
|
||||
* - jhQty :计划交货数量
|
||||
* - realQty :累计已入库数量(落库)
|
||||
* - waitQty :待入库数量 = jhQty - realQty(仅用于反显,不落库)
|
||||
*
|
||||
* @author zg
|
||||
* @date 2025-05-28
|
||||
*/
|
||||
@@ -78,12 +83,28 @@ public class GysJh extends BaseEntity
|
||||
@Excel(name = "计划交货数量")
|
||||
private BigDecimal jhQty;
|
||||
|
||||
/** 已入库数量(累计) */
|
||||
@Excel(name = "已入库数量")
|
||||
private BigDecimal realQty;
|
||||
|
||||
/**
|
||||
* 待入库数量(反显字段,不落库)
|
||||
*
|
||||
* 计算规则:
|
||||
* waitQty = jhQty - realQty
|
||||
*/
|
||||
private BigDecimal waitQty;
|
||||
|
||||
/** 计量单位 */
|
||||
@Excel(name = "计量单位")
|
||||
private String dw;
|
||||
|
||||
/** 0:未到货,1:已入库,2部分入库 */
|
||||
// @Excel(name = "0:未到货,1:已入库,2部分入库")
|
||||
/**
|
||||
* 状态
|
||||
* 0:未到货
|
||||
* 1:部分入库
|
||||
* 2:已入库
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/** 身份码 */
|
||||
@@ -95,7 +116,6 @@ public class GysJh extends BaseEntity
|
||||
private String remark;
|
||||
|
||||
/** 是否删除(0正常 1删除) */
|
||||
// @Excel(name = "是否删除", readConverterExp = "0=正常,1=删除")
|
||||
private String isDelete;
|
||||
|
||||
/** 查询开始时间(yyyy-MM-dd HH:mm:ss) */
|
||||
@@ -106,236 +126,120 @@ public class GysJh extends BaseEntity
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date endTime;
|
||||
|
||||
public void setId(Long id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
// ======================= getter / setter =======================
|
||||
|
||||
public Long getId()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
|
||||
public void setIndexNo(Long indexNo)
|
||||
{
|
||||
this.indexNo = indexNo;
|
||||
}
|
||||
public String getXh() { return xh; }
|
||||
public void setXh(String xh) { this.xh = xh; }
|
||||
|
||||
public Long getIndexNo()
|
||||
{
|
||||
return indexNo;
|
||||
}
|
||||
public Long getIndexNo() { return indexNo; }
|
||||
public void setIndexNo(Long indexNo) { this.indexNo = indexNo; }
|
||||
|
||||
public void setXj(String xj)
|
||||
{
|
||||
this.xj = xj;
|
||||
}
|
||||
public String getXj() { return xj; }
|
||||
public void setXj(String xj) { this.xj = xj; }
|
||||
|
||||
public String getXj()
|
||||
{
|
||||
return xj;
|
||||
}
|
||||
public String getXmNo() { return xmNo; }
|
||||
public void setXmNo(String xmNo) { this.xmNo = xmNo; }
|
||||
|
||||
public void setXmNo(String xmNo)
|
||||
{
|
||||
this.xmNo = xmNo;
|
||||
}
|
||||
public String getXmMs() { return xmMs; }
|
||||
public void setXmMs(String xmMs) { this.xmMs = xmMs; }
|
||||
|
||||
public String getXmNo()
|
||||
{
|
||||
return xmNo;
|
||||
}
|
||||
public String getWlNo() { return wlNo; }
|
||||
public void setWlNo(String wlNo) { this.wlNo = wlNo; }
|
||||
|
||||
public void setXmMs(String xmMs)
|
||||
{
|
||||
this.xmMs = xmMs;
|
||||
}
|
||||
public String getWlMs() { return wlMs; }
|
||||
public void setWlMs(String wlMs) { this.wlMs = wlMs; }
|
||||
|
||||
public String getXmMs()
|
||||
{
|
||||
return xmMs;
|
||||
}
|
||||
public String getGysNo() { return gysNo; }
|
||||
public void setGysNo(String gysNo) { this.gysNo = gysNo; }
|
||||
|
||||
public void setWlNo(String wlNo)
|
||||
{
|
||||
this.wlNo = wlNo;
|
||||
}
|
||||
public String getGysMc() { return gysMc; }
|
||||
public void setGysMc(String gysMc) { this.gysMc = gysMc; }
|
||||
|
||||
public String getWlNo()
|
||||
{
|
||||
return wlNo;
|
||||
}
|
||||
public BigDecimal getJhAmt() { return jhAmt; }
|
||||
public void setJhAmt(BigDecimal jhAmt) { this.jhAmt = jhAmt; }
|
||||
|
||||
public void setWlMs(String wlMs)
|
||||
{
|
||||
this.wlMs = wlMs;
|
||||
}
|
||||
public BigDecimal getHtDj() { return htDj; }
|
||||
public void setHtDj(BigDecimal htDj) { this.htDj = htDj; }
|
||||
|
||||
public String getWlMs()
|
||||
{
|
||||
return wlMs;
|
||||
}
|
||||
|
||||
public void setGysNo(String gysNo)
|
||||
{
|
||||
this.gysNo = gysNo;
|
||||
}
|
||||
|
||||
public String getGysNo()
|
||||
{
|
||||
return gysNo;
|
||||
}
|
||||
|
||||
public void setGysMc(String gysMc)
|
||||
{
|
||||
this.gysMc = gysMc;
|
||||
}
|
||||
|
||||
public String getGysMc()
|
||||
{
|
||||
return gysMc;
|
||||
}
|
||||
|
||||
public void setJhAmt(BigDecimal jhAmt)
|
||||
{
|
||||
this.jhAmt = jhAmt;
|
||||
}
|
||||
|
||||
public BigDecimal getJhAmt()
|
||||
{
|
||||
return jhAmt;
|
||||
}
|
||||
|
||||
public void setHtDj(BigDecimal htDj)
|
||||
{
|
||||
this.htDj = htDj;
|
||||
}
|
||||
|
||||
public BigDecimal getHtDj()
|
||||
{
|
||||
return htDj;
|
||||
}
|
||||
|
||||
public void setSapNo(String sapNo)
|
||||
{
|
||||
this.sapNo = sapNo;
|
||||
}
|
||||
|
||||
public String getSapNo()
|
||||
{
|
||||
return sapNo;
|
||||
}
|
||||
|
||||
public void setXh(String xh)
|
||||
{
|
||||
this.xh = xh;
|
||||
}
|
||||
|
||||
public String getXh()
|
||||
{
|
||||
return xh;
|
||||
}
|
||||
|
||||
public void setJhQty(BigDecimal jhQty) { this.jhQty = jhQty; }
|
||||
public BigDecimal getJhQty() { return jhQty; }
|
||||
|
||||
public void setHtQty(BigDecimal htQty) { this.htQty = htQty; }
|
||||
public BigDecimal getHtQty() { return htQty; }
|
||||
public void setHtQty(BigDecimal htQty) { this.htQty = htQty; }
|
||||
|
||||
public void setDw(String dw)
|
||||
{
|
||||
this.dw = dw;
|
||||
public String getSapNo() { return sapNo; }
|
||||
public void setSapNo(String sapNo) { this.sapNo = sapNo; }
|
||||
|
||||
public BigDecimal getJhQty() { return jhQty; }
|
||||
public void setJhQty(BigDecimal jhQty) { this.jhQty = jhQty; }
|
||||
|
||||
public BigDecimal getRealQty() { return realQty; }
|
||||
public void setRealQty(BigDecimal realQty) { this.realQty = realQty; }
|
||||
|
||||
/**
|
||||
* 待入库数量(不落库,动态计算)
|
||||
*/
|
||||
public BigDecimal getWaitQty() {
|
||||
if (jhQty == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
BigDecimal inQty = realQty == null ? BigDecimal.ZERO : realQty;
|
||||
return jhQty.subtract(inQty);
|
||||
}
|
||||
public void setWaitQty(BigDecimal waitQty) {
|
||||
this.waitQty = waitQty;
|
||||
}
|
||||
|
||||
public String getDw()
|
||||
{
|
||||
return dw;
|
||||
}
|
||||
public String getDw() { return dw; }
|
||||
public void setDw(String dw) { this.dw = dw; }
|
||||
|
||||
public void setStatus(String status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
|
||||
public String getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
public String getEntityId() { return entityId; }
|
||||
public void setEntityId(String entityId) { this.entityId = entityId; }
|
||||
|
||||
public void setEntityId(String entityId)
|
||||
{
|
||||
this.entityId = entityId;
|
||||
}
|
||||
public String getRemark() { return remark; }
|
||||
public void setRemark(String remark) { this.remark = remark; }
|
||||
|
||||
public String getEntityId()
|
||||
{
|
||||
return entityId;
|
||||
}
|
||||
public String getIsDelete() { return isDelete; }
|
||||
public void setIsDelete(String isDelete) { this.isDelete = isDelete; }
|
||||
|
||||
public void setRemark(String remark)
|
||||
{
|
||||
this.remark = remark;
|
||||
}
|
||||
public Date getBeginTime() { return beginTime; }
|
||||
public void setBeginTime(Date beginTime) { this.beginTime = beginTime; }
|
||||
|
||||
public String getRemark()
|
||||
{
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setIsDelete(String isDelete)
|
||||
{
|
||||
this.isDelete = isDelete;
|
||||
}
|
||||
|
||||
public String getIsDelete()
|
||||
{
|
||||
return isDelete;
|
||||
}
|
||||
|
||||
|
||||
public Date getBeginTime() {
|
||||
return beginTime;
|
||||
}
|
||||
|
||||
public void setBeginTime(Date beginTime) {
|
||||
this.beginTime = beginTime;
|
||||
}
|
||||
|
||||
public Date getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public void setEndTime(Date endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
public Date getEndTime() { return endTime; }
|
||||
public void setEndTime(Date endTime) { this.endTime = endTime; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("indexNo", getIndexNo())
|
||||
.append("xj", getXj())
|
||||
.append("xmNo", getXmNo())
|
||||
.append("xmMs", getXmMs())
|
||||
.append("wlNo", getWlNo())
|
||||
.append("wlMs", getWlMs())
|
||||
.append("gysNo", getGysNo())
|
||||
.append("gysMc", getGysMc())
|
||||
.append("jhAmt", getJhAmt())
|
||||
.append("htDj", getHtDj())
|
||||
.append("sapNo", getSapNo())
|
||||
.append("xh", getXh())
|
||||
.append("jhQty", getJhQty())
|
||||
.append("htQty", getHtQty())
|
||||
.append("dw", getDw())
|
||||
.append("status", getStatus())
|
||||
.append("entityId", getEntityId())
|
||||
.append("remark", getRemark())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("isDelete", getIsDelete())
|
||||
.toString();
|
||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("indexNo", getIndexNo())
|
||||
.append("xj", getXj())
|
||||
.append("xmNo", getXmNo())
|
||||
.append("xmMs", getXmMs())
|
||||
.append("wlNo", getWlNo())
|
||||
.append("wlMs", getWlMs())
|
||||
.append("gysNo", getGysNo())
|
||||
.append("gysMc", getGysMc())
|
||||
.append("jhAmt", getJhAmt())
|
||||
.append("htDj", getHtDj())
|
||||
.append("sapNo", getSapNo())
|
||||
.append("xh", getXh())
|
||||
.append("jhQty", getJhQty())
|
||||
.append("realQty", getRealQty())
|
||||
.append("waitQty", getWaitQty())
|
||||
.append("htQty", getHtQty())
|
||||
.append("dw", getDw())
|
||||
.append("status", getStatus())
|
||||
.append("entityId", getEntityId())
|
||||
.append("remark", getRemark())
|
||||
.append("createBy", getCreateBy())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateBy", getUpdateBy())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.append("isDelete", getIsDelete())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.zg.framework.aspectj.lang.annotation.Excel;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@@ -20,13 +21,20 @@ public class MoveRecord extends BaseEntity {
|
||||
/** 主键ID */
|
||||
private Long id;
|
||||
|
||||
/** 关联库存表ID(rk_info.id) */
|
||||
/** 原库存ID(rk_info.id) */
|
||||
private Long rkInfoId;
|
||||
|
||||
/** 移库生成的新库存ID(rk_info.id,用于撤销移库) */
|
||||
private Long newRkInfoId;
|
||||
|
||||
/** 实物ID */
|
||||
@Excel(name = "实物ID")
|
||||
private String entityId;
|
||||
|
||||
/** 实际移库数量 */
|
||||
@Excel(name = "移库数量")
|
||||
private BigDecimal realQty;
|
||||
|
||||
/** 原仓库 */
|
||||
@Excel(name = "原仓库")
|
||||
private String fromCangku;
|
||||
@@ -112,6 +120,14 @@ public class MoveRecord extends BaseEntity {
|
||||
this.rkInfoId = rkInfoId;
|
||||
}
|
||||
|
||||
public Long getNewRkInfoId() {
|
||||
return newRkInfoId;
|
||||
}
|
||||
|
||||
public void setNewRkInfoId(Long newRkInfoId) {
|
||||
this.newRkInfoId = newRkInfoId;
|
||||
}
|
||||
|
||||
public String getEntityId() {
|
||||
return entityId;
|
||||
}
|
||||
@@ -120,6 +136,14 @@ public class MoveRecord extends BaseEntity {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
public BigDecimal getRealQty() {
|
||||
return realQty;
|
||||
}
|
||||
|
||||
public void setRealQty(BigDecimal realQty) {
|
||||
this.realQty = realQty;
|
||||
}
|
||||
|
||||
public String getFromCangku() {
|
||||
return fromCangku;
|
||||
}
|
||||
@@ -261,7 +285,9 @@ public class MoveRecord extends BaseEntity {
|
||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("id", getId())
|
||||
.append("rkInfoId", getRkInfoId())
|
||||
.append("newRkInfoId", getNewRkInfoId())
|
||||
.append("entityId", getEntityId())
|
||||
.append("realQty", getRealQty())
|
||||
.append("fromCangku", getFromCangku())
|
||||
.append("fromPcode", getFromPcode())
|
||||
.append("fromTrayCode", getFromTrayCode())
|
||||
|
||||
@@ -77,7 +77,6 @@ public class RkBill extends BaseEntity {
|
||||
private String execStatus;
|
||||
|
||||
/** 理货员(用户ID) */
|
||||
// @Excel(name = "理货员")
|
||||
private Integer operator;
|
||||
|
||||
/** 理货员名称(联表) */
|
||||
@@ -88,10 +87,31 @@ public class RkBill extends BaseEntity {
|
||||
@Excel(name = "施工队编码")
|
||||
private String teamCode;
|
||||
|
||||
/** 施工队名称(联表) */
|
||||
@Excel(name = "施工队名称")
|
||||
private String teamName;
|
||||
|
||||
/** 是否需要配送(0否,1是,2配送中,3配送完成) */
|
||||
@Excel(name = "是否需要配送", readConverterExp = "0=否,1=是,2=配送中,3=配送完成")
|
||||
private String isDelivery;
|
||||
|
||||
/** 借用时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date borrowTime;
|
||||
|
||||
/** 归还时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||
private Date returnTime;
|
||||
|
||||
/** 借用方项目号(借用方项目) */
|
||||
@Excel(name = "借用方项目号")
|
||||
private String xmNoCk;
|
||||
|
||||
/** 借用方项目描述(借用方项目描述) */
|
||||
@Excel(name = "借用方项目描述")
|
||||
private String xmMsCk;
|
||||
|
||||
|
||||
/** 创建人 */
|
||||
private String createBy;
|
||||
|
||||
@@ -251,6 +271,14 @@ public class RkBill extends BaseEntity {
|
||||
this.teamCode = teamCode;
|
||||
}
|
||||
|
||||
public String getTeamName() {
|
||||
return teamName;
|
||||
}
|
||||
|
||||
public void setTeamName(String teamName) {
|
||||
this.teamName = teamName;
|
||||
}
|
||||
|
||||
public String getIsDelivery() {
|
||||
return isDelivery;
|
||||
}
|
||||
@@ -259,6 +287,42 @@ public class RkBill extends BaseEntity {
|
||||
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;
|
||||
}
|
||||
@@ -343,13 +407,18 @@ public class RkBill extends BaseEntity {
|
||||
.append("operator", operator)
|
||||
.append("operatorName", operatorName)
|
||||
.append("teamCode", teamCode)
|
||||
.append("teamName", teamName)
|
||||
.append("isDelivery", isDelivery)
|
||||
.append("borrowTime", borrowTime)
|
||||
.append("returnTime", returnTime)
|
||||
.append("xmNoCk", getXmNoCk())
|
||||
.append("xmMsCk", getXmMsCk())
|
||||
.append("createBy", createBy)
|
||||
.append("createTime", createTime)
|
||||
.append("updateBy", updateBy)
|
||||
.append("updateTime", updateTime)
|
||||
.append("isDelete", isDelete)
|
||||
.append("remark", getRemark())
|
||||
.append("remark", remark)
|
||||
.append("startDate", startDate)
|
||||
.append("endDate", endDate)
|
||||
.toString();
|
||||
|
||||
@@ -102,11 +102,11 @@ public class RkInfo extends BaseEntity
|
||||
private String xmMs;
|
||||
|
||||
/** 出库项目号(借用方项目) */
|
||||
@Excel(name = "出库项目号")
|
||||
@Excel(name = "借用方项目号")
|
||||
private String xmNoCk;
|
||||
|
||||
/** 出库项目描述(借用方项目描述) */
|
||||
@Excel(name = "出库项目描述")
|
||||
@Excel(name = "借用方项目描述")
|
||||
private String xmMsCk;
|
||||
|
||||
/** 物料号 */
|
||||
@@ -178,13 +178,13 @@ public class RkInfo extends BaseEntity
|
||||
private String teamCode;
|
||||
|
||||
/** 借用时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "借用时间", width = 20, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
// @Excel(name = "借用时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date borrowTime;
|
||||
|
||||
/** 归还时间 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Excel(name = "归还时间", width = 20, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
// @Excel(name = "归还时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date returnTime;
|
||||
|
||||
/** 是否移库过(0否 1是) */
|
||||
|
||||
@@ -29,6 +29,8 @@ public class RkRecord extends BaseEntity
|
||||
/** 业务类型 */
|
||||
@Excel(name = "业务类型", readConverterExp = "0=入库,1=出库,2=借料出库,3=还料入库")
|
||||
private String bizType;
|
||||
/** 业务类型列表(查询用) */
|
||||
private List<String> bizTypeList;
|
||||
/** 出入库类型 */
|
||||
// @Excel(name = "出入库类型")
|
||||
private String operationType;
|
||||
@@ -275,7 +277,13 @@ public class RkRecord extends BaseEntity
|
||||
public String getBizType() {
|
||||
return bizType;
|
||||
}
|
||||
public List<String> getBizTypeList() {
|
||||
return bizTypeList;
|
||||
}
|
||||
|
||||
public void setBizTypeList(List<String> bizTypeList) {
|
||||
this.bizTypeList = bizTypeList;
|
||||
}
|
||||
public void setOperationType(String operationType)
|
||||
{
|
||||
this.operationType = operationType;
|
||||
|
||||
@@ -132,4 +132,41 @@ public interface GysJhMapper
|
||||
@Param("dw") String dw);
|
||||
|
||||
|
||||
/**
|
||||
* 根据供应计划ID,累加实际入库数量
|
||||
*/
|
||||
void increaseRealQtyById(
|
||||
@Param("realQty") BigDecimal realQty,
|
||||
@Param("gysJhId") Long gysJhId
|
||||
);
|
||||
|
||||
|
||||
void rollbackInQty(
|
||||
@Param("jhId") Long jhId,
|
||||
@Param("rollbackQty") BigDecimal rollbackQty
|
||||
);
|
||||
|
||||
/**
|
||||
* 根据id查询实收数量
|
||||
*/
|
||||
BigDecimal selectRealQtyById(@Param("jhId") Long jhId);
|
||||
|
||||
/**
|
||||
* 根据id修改状态
|
||||
*/
|
||||
|
||||
void updateStatus(
|
||||
@Param("jhId") Long jhId,
|
||||
@Param("status") String status
|
||||
);
|
||||
|
||||
/**
|
||||
* 根据供应计划ID,直接更新已入库数量(real_qty)
|
||||
*
|
||||
* @param gysJhId 供应计划ID
|
||||
* @param realQty 已入库数量(以一键入库结果为准)
|
||||
* @return 影响行数
|
||||
*/
|
||||
int updateRealQtyById(@Param("gysJhId") Long gysJhId,
|
||||
@Param("realQty") BigDecimal realQty);
|
||||
}
|
||||
|
||||
@@ -78,4 +78,12 @@ public interface RkBillMapper
|
||||
@Param("execStatus") String execStatus
|
||||
);
|
||||
|
||||
/**
|
||||
* 修改执行状态
|
||||
* @param billNo
|
||||
* @param execStatus
|
||||
* @return
|
||||
*/
|
||||
int updateExecStatus(@Param("billNo") String billNo,
|
||||
@Param("execStatus") String execStatus);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.zg.project.wisdom.mapper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import com.zg.project.wisdom.domain.RkInfo;
|
||||
import io.lettuce.core.dynamic.annotation.Param;
|
||||
@@ -58,11 +60,46 @@ public interface RkInfoMapper
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRkInfoByIds(Long[] ids);
|
||||
int deleteRkInfoByIds(@Param("ids") Long[] ids);
|
||||
|
||||
/**
|
||||
* 修改库存明细执行状态
|
||||
*/
|
||||
int updateExecStatusByIds(@Param("ids") List<Long> ids,
|
||||
@Param("execStatus") String execStatus);
|
||||
|
||||
/**
|
||||
* 根据单据编号查询库存明细数量
|
||||
*/
|
||||
int countByBillNo(String billNo);
|
||||
|
||||
/**
|
||||
* 根据入库明细ID查询非预入库数量
|
||||
*/
|
||||
int countNotPreByIds(@Param("rkInfoIds") List<Long> rkInfoIds);
|
||||
|
||||
/**
|
||||
* 根据入库明细ID更新实收数量
|
||||
*/
|
||||
void updateRealQtyById(
|
||||
@Param("id") Long id,
|
||||
@Param("realQty") BigDecimal realQty
|
||||
);
|
||||
|
||||
/**
|
||||
* 根据入库明细ID更新出库状态
|
||||
*/
|
||||
void updateIsChukuById(
|
||||
@Param("id") Long id,
|
||||
@Param("isChuku") String isChuku
|
||||
);
|
||||
|
||||
/**
|
||||
* 标记借料已归还
|
||||
*/
|
||||
int updateBorrowReturn(@Param("id") Long id,
|
||||
@Param("isBorrowed") String isBorrowed,
|
||||
@Param("returnTime") Date returnTime);
|
||||
|
||||
List<RkInfo> selectRkInfoByIds(@Param("rkInfoIds") List<Long> rkInfoIds);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public interface RkRecordMapper
|
||||
* @param ids 需要删除的数据主键集合
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRkRecordByIds(Long[] ids);
|
||||
int deleteRkRecordByIds(@Param("ids") Long[] ids);
|
||||
|
||||
/**
|
||||
* 修改执行状态
|
||||
@@ -95,4 +95,30 @@ public interface RkRecordMapper
|
||||
* @param rkInfo 单据信息
|
||||
*/
|
||||
void updateByRkInfo(RkInfo rkInfo);
|
||||
|
||||
/**
|
||||
* 根据单据号查询记录数量
|
||||
*
|
||||
* @param billNo 单据号
|
||||
* @return 记录数量
|
||||
*/
|
||||
int countByBillNo(String billNo);
|
||||
|
||||
/**
|
||||
* 根据单据号查询预入库记录数量
|
||||
*
|
||||
* @param billNo 单据号
|
||||
* @return 记录数量
|
||||
*/
|
||||
int countPreByBillNo(@Param("billNo") String billNo);
|
||||
|
||||
int countPreOutByBillNo(@Param("billNo") String billNo);
|
||||
|
||||
/**
|
||||
* 根据单据ID查询记录
|
||||
*
|
||||
* @param rkInfoId 单据ID
|
||||
* @return 记录
|
||||
*/
|
||||
RkRecord selectRkRecordByRkInfoId(@Param("rkInfoId") Long rkInfoId);
|
||||
}
|
||||
|
||||
@@ -60,4 +60,11 @@ public interface IMoveRecordService
|
||||
* @param dto
|
||||
*/
|
||||
void processMove(MoveRequestDTO dto);
|
||||
|
||||
/**
|
||||
* 撤销移库
|
||||
*
|
||||
* @param moveRecordId 移库记录ID
|
||||
*/
|
||||
void rollbackMove(Long moveRecordId);
|
||||
}
|
||||
|
||||
@@ -66,4 +66,14 @@ public interface IRkBillService
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteRkBillById(Long id);
|
||||
|
||||
/**
|
||||
* 新增出库
|
||||
*/
|
||||
int insertOutBillAndDetail(RkBillCreateDTO dto);
|
||||
|
||||
/**
|
||||
* 还料入库
|
||||
*/
|
||||
int insertReturnBillAndDetail(RkBillCreateDTO dto);
|
||||
}
|
||||
|
||||
@@ -76,4 +76,18 @@ public interface IRkRecordService
|
||||
* 批量将指定入库记录完成入库
|
||||
*/
|
||||
int finishIn(List<Long> ids);
|
||||
/**
|
||||
* 撤销出库(已出库 → 预出库)
|
||||
*/
|
||||
int rollbackOut(List<Long> recordIds);
|
||||
|
||||
/**
|
||||
* 批量完成预出库 → 已出库
|
||||
*/
|
||||
int finishOut(List<Long> recordIds);
|
||||
|
||||
/**
|
||||
* 删除预出库记录(仅限 exec_status = 0)
|
||||
*/
|
||||
int deletePreOutRecords(Long[] ids);
|
||||
}
|
||||
|
||||
@@ -167,13 +167,12 @@ public class GysJhServiceImpl implements IGysJhService
|
||||
|
||||
List<GysJh> list = gysJhMapper.getBySapNo(sapNo);
|
||||
|
||||
AjaxResult result = AjaxResult.success(list);
|
||||
|
||||
if (list == null || list.isEmpty()) {
|
||||
return result;
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
// 找出已入库(status=1)的物料号,去重、过滤空值
|
||||
AjaxResult result = AjaxResult.success(list);
|
||||
|
||||
List<String> inStockWlNos = list.stream()
|
||||
.filter(x -> x != null && "1".equals(String.valueOf(x.getStatus()).trim()))
|
||||
.map(GysJh::getWlNo)
|
||||
@@ -185,18 +184,14 @@ public class GysJhServiceImpl implements IGysJhService
|
||||
if (!inStockWlNos.isEmpty()) {
|
||||
result.put("warn", true);
|
||||
result.put("inStockWlNos", inStockWlNos);
|
||||
|
||||
// 组装提示文案(可根据前端展示需要调整长度)
|
||||
String msg = "该 SAP 订单号下,以下物料号已入库过,请注意:"
|
||||
+ String.join("、", inStockWlNos);
|
||||
result.put("msg", msg);
|
||||
result.put("msg", "该 SAP 订单号下,以下物料号已全部入库,请注意:"
|
||||
+ String.join("、", inStockWlNos));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int importByMapping(MultipartFile file, List<ExcelFieldMapping> mapping) throws Exception {
|
||||
|
||||
@@ -114,18 +114,13 @@ public class MoveRecordServiceImpl implements IMoveRecordService
|
||||
/**
|
||||
* 处理库存移库操作
|
||||
*
|
||||
* @param dto 移库请求参数(包含原库存ID、移库目标列表等)
|
||||
*/
|
||||
/**
|
||||
* 处理库存移库操作
|
||||
*
|
||||
* @param dto 移库请求参数(包含原库存ID、移库目标列表等)
|
||||
* @param dto 移库请求参数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void processMove(MoveRequestDTO dto) {
|
||||
|
||||
// ========= 0. 基本校验 =========
|
||||
/* ====================== 0. 基础校验 ====================== */
|
||||
if (dto == null || dto.getFromRkId() == null) {
|
||||
throw new ServiceException("原库存ID不能为空");
|
||||
}
|
||||
@@ -133,18 +128,18 @@ public class MoveRecordServiceImpl implements IMoveRecordService
|
||||
throw new ServiceException("目标位置列表不能为空");
|
||||
}
|
||||
|
||||
// ========= 1. 查询原库存 =========
|
||||
/* ====================== 1. 查询原库存 ====================== */
|
||||
RkInfo original = rkInfoMapper.selectRkInfoById(dto.getFromRkId());
|
||||
if (original == null || "1".equals(original.getIsDelete())) {
|
||||
throw new ServiceException("原库存不存在或已删除");
|
||||
}
|
||||
|
||||
BigDecimal originQty = original.getRealQty();
|
||||
if (originQty == null) {
|
||||
throw new ServiceException("原库存数量为空");
|
||||
if (originQty == null || originQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new ServiceException("原库存数量异常");
|
||||
}
|
||||
|
||||
// ========= 2. 计算移库总量 =========
|
||||
/* ====================== 2. 计算移库总量 ====================== */
|
||||
BigDecimal moveTotalQty = dto.getTargets().stream()
|
||||
.map(MoveTargetItem::getRealQty)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
@@ -153,146 +148,189 @@ public class MoveRecordServiceImpl implements IMoveRecordService
|
||||
throw new ServiceException("移库数量不能大于原库存数量");
|
||||
}
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
String username = userId.toString();
|
||||
String userId = String.valueOf(SecurityUtils.getUserId());
|
||||
Date now = DateUtils.getNowDate();
|
||||
|
||||
// ========= 3. 快照(只用于拷贝字段) =========
|
||||
/* ====================== 3. 原库存快照 ====================== */
|
||||
RkInfo snapshot = new RkInfo();
|
||||
BeanUtils.copyProperties(original, snapshot);
|
||||
|
||||
// ========= 4. 查询原 rk_record(用于同步更新) =========
|
||||
RkRecord originRecord = rkRecordMapper.selectRkRecordById(original.getId());
|
||||
if (originRecord == null) {
|
||||
throw new ServiceException("未找到对应的出入库记录");
|
||||
}
|
||||
|
||||
// ================== 一、全量移库 ==================
|
||||
/* ====================== 4. 全量移库(不拆分) ====================== */
|
||||
if (dto.getTargets().size() == 1 && moveTotalQty.compareTo(originQty) == 0) {
|
||||
|
||||
MoveTargetItem target = dto.getTargets().get(0);
|
||||
|
||||
// 1️⃣ rk_info:更新库位
|
||||
// 4.1 更新原库存(仅换库位)
|
||||
original.setCangku(target.getToCangku());
|
||||
original.setPcode(target.getToPcode());
|
||||
original.setTrayCode(target.getToTrayCode());
|
||||
original.setHasMoved("1");
|
||||
original.setUpdateBy(username);
|
||||
original.setUpdateBy(userId);
|
||||
original.setUpdateTime(now);
|
||||
rkInfoMapper.updateRkInfo(original);
|
||||
|
||||
// 2️⃣ rk_record:同步更新库位
|
||||
originRecord.setCangku(target.getToCangku());
|
||||
originRecord.setPcode(target.getToPcode());
|
||||
originRecord.setTrayCode(target.getToTrayCode());
|
||||
originRecord.setHasMoved("1");
|
||||
originRecord.setUpdateBy(username);
|
||||
originRecord.setUpdateTime(now);
|
||||
rkRecordMapper.updateRkRecord(originRecord);
|
||||
// 4.2 移库流水(全量移库,无新库存)
|
||||
MoveRecord record = new MoveRecord();
|
||||
record.setRkInfoId(snapshot.getId());
|
||||
record.setNewRkInfoId(null); // ✅ 关键:全量移库没有新库存
|
||||
record.setEntityId(snapshot.getEntityId());
|
||||
record.setRealQty(originQty);
|
||||
|
||||
// 3️⃣ move_record:记录移库流水(绑定原 rk_info.id)
|
||||
moveRecordMapper.insertMoveRecord(
|
||||
createMoveRecord(original, target, dto)
|
||||
);
|
||||
record.setFromCangku(snapshot.getCangku());
|
||||
record.setFromPcode(snapshot.getPcode());
|
||||
record.setFromTrayCode(snapshot.getTrayCode());
|
||||
|
||||
record.setToCangku(target.getToCangku());
|
||||
record.setToPcode(target.getToPcode());
|
||||
record.setToTrayCode(target.getToTrayCode());
|
||||
|
||||
record.setMoveReason(dto.getMoveReason());
|
||||
record.setMovedBy(userId);
|
||||
record.setMovedAt(now);
|
||||
|
||||
record.setCreateBy(userId);
|
||||
record.setCreateTime(now);
|
||||
record.setUpdateBy(userId);
|
||||
record.setUpdateTime(now);
|
||||
record.setIsDelete("0");
|
||||
|
||||
moveRecordMapper.insertMoveRecord(record);
|
||||
return;
|
||||
}
|
||||
|
||||
// ================== 二、部分移库 ==================
|
||||
/* ====================== 5. 部分移库(拆分库存) ====================== */
|
||||
|
||||
// 1️⃣ 原 rk_info 扣减数量
|
||||
// 5.1 原库存扣减数量
|
||||
original.setRealQty(originQty.subtract(moveTotalQty));
|
||||
original.setHasMoved("1");
|
||||
original.setUpdateBy(username);
|
||||
original.setUpdateBy(userId);
|
||||
original.setUpdateTime(now);
|
||||
rkInfoMapper.updateRkInfo(original);
|
||||
|
||||
// 2️⃣ 原 rk_record 扣减数量
|
||||
originRecord.setRealQty(
|
||||
originRecord.getRealQty().subtract(moveTotalQty)
|
||||
);
|
||||
originRecord.setHasMoved("1");
|
||||
originRecord.setUpdateBy(username);
|
||||
originRecord.setUpdateTime(now);
|
||||
rkRecordMapper.updateRkRecord(originRecord);
|
||||
|
||||
// 3️⃣ 新增目标库存 + 新增目标记录
|
||||
// 5.2 生成新库存 + 移库流水
|
||||
for (MoveTargetItem target : dto.getTargets()) {
|
||||
|
||||
// —— 新 rk_info
|
||||
/* ---------- 新库存 ---------- */
|
||||
RkInfo newInfo = new RkInfo();
|
||||
BeanUtils.copyProperties(snapshot, newInfo, "id");
|
||||
|
||||
newInfo.setCangku(target.getToCangku());
|
||||
newInfo.setPcode(target.getToPcode());
|
||||
newInfo.setTrayCode(target.getToTrayCode());
|
||||
newInfo.setRealQty(target.getRealQty());
|
||||
newInfo.setHasMoved("1");
|
||||
newInfo.setCreateBy(username);
|
||||
|
||||
newInfo.setCreateBy(userId);
|
||||
newInfo.setCreateTime(now);
|
||||
newInfo.setUpdateBy(username);
|
||||
newInfo.setUpdateBy(userId);
|
||||
newInfo.setUpdateTime(now);
|
||||
|
||||
rkInfoMapper.insertRkInfo(newInfo);
|
||||
|
||||
// —— 新 rk_record
|
||||
RkRecord newRecord = new RkRecord();
|
||||
BeanUtils.copyProperties(originRecord, newRecord, "id");
|
||||
newRecord.setCangku(target.getToCangku());
|
||||
newRecord.setPcode(target.getToPcode());
|
||||
newRecord.setTrayCode(target.getToTrayCode());
|
||||
newRecord.setRealQty(target.getRealQty());
|
||||
newRecord.setHasMoved("1");
|
||||
newRecord.setCreateBy(username);
|
||||
newRecord.setCreateTime(now);
|
||||
newRecord.setUpdateBy(username);
|
||||
newRecord.setUpdateTime(now);
|
||||
rkRecordMapper.insertRkRecord(newRecord);
|
||||
/* ---------- 移库流水(重点) ---------- */
|
||||
MoveRecord record = new MoveRecord();
|
||||
record.setRkInfoId(snapshot.getId()); // 原库存
|
||||
record.setNewRkInfoId(newInfo.getId()); // ✅ 关键:新库存ID
|
||||
record.setEntityId(snapshot.getEntityId());
|
||||
record.setRealQty(target.getRealQty());
|
||||
|
||||
// —— move_record:绑定新生成的 rk_info.id
|
||||
moveRecordMapper.insertMoveRecord(
|
||||
createMoveRecord(newInfo, target, dto)
|
||||
);
|
||||
record.setFromCangku(snapshot.getCangku());
|
||||
record.setFromPcode(snapshot.getPcode());
|
||||
record.setFromTrayCode(snapshot.getTrayCode());
|
||||
|
||||
record.setToCangku(target.getToCangku());
|
||||
record.setToPcode(target.getToPcode());
|
||||
record.setToTrayCode(target.getToTrayCode());
|
||||
|
||||
record.setMoveReason(dto.getMoveReason());
|
||||
record.setMovedBy(userId);
|
||||
record.setMovedAt(now);
|
||||
|
||||
record.setCreateBy(userId);
|
||||
record.setCreateTime(now);
|
||||
record.setUpdateBy(userId);
|
||||
record.setUpdateTime(now);
|
||||
record.setIsDelete("0");
|
||||
|
||||
moveRecordMapper.insertMoveRecord(record);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建移库记录对象
|
||||
*
|
||||
* @param info 原库存记录
|
||||
* @param target 目标位置数据
|
||||
* @param dto 请求参数
|
||||
* @return 构建后的移库记录
|
||||
* 撤销移库
|
||||
*/
|
||||
private MoveRecord createMoveRecord(RkInfo info,
|
||||
MoveTargetItem target,
|
||||
MoveRequestDTO dto) {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void rollbackMove(Long moveRecordId) {
|
||||
|
||||
Long userId = SecurityUtils.getUserId();
|
||||
if (moveRecordId == null) {
|
||||
throw new ServiceException("移库记录ID不能为空");
|
||||
}
|
||||
|
||||
/* ====================== 1. 查询移库记录 ====================== */
|
||||
MoveRecord record = moveRecordMapper.selectMoveRecordById(moveRecordId);
|
||||
if (record == null || "1".equals(record.getIsDelete())) {
|
||||
throw new ServiceException("移库记录不存在或已撤销");
|
||||
}
|
||||
|
||||
Long originRkInfoId = record.getRkInfoId();
|
||||
Long newRkInfoId = record.getNewRkInfoId();
|
||||
|
||||
/* ====================== 2. 查询原库存 ====================== */
|
||||
RkInfo origin = rkInfoMapper.selectRkInfoById(originRkInfoId);
|
||||
if (origin == null || "1".equals(origin.getIsDelete())) {
|
||||
throw new ServiceException("原库存不存在或已删除,无法撤销");
|
||||
}
|
||||
|
||||
String userId = String.valueOf(SecurityUtils.getUserId());
|
||||
Date now = DateUtils.getNowDate();
|
||||
|
||||
MoveRecord record = new MoveRecord();
|
||||
/* ====================== 3. 分情况处理 ====================== */
|
||||
|
||||
// ★ 关键:绑定 rk_info.id
|
||||
record.setRkInfoId(info.getId());
|
||||
// ---------- 情况一:全量移库 ----------
|
||||
if (newRkInfoId == null) {
|
||||
|
||||
record.setEntityId(info.getEntityId());
|
||||
record.setFromCangku(info.getCangku());
|
||||
record.setFromPcode(info.getPcode());
|
||||
record.setFromTrayCode(info.getTrayCode());
|
||||
record.setToCangku(target.getToCangku());
|
||||
record.setToPcode(target.getToPcode());
|
||||
record.setToTrayCode(target.getToTrayCode());
|
||||
record.setMoveReason(dto.getMoveReason());
|
||||
record.setMovedBy(userId.toString());
|
||||
record.setMovedAt(now);
|
||||
// 回滚库位
|
||||
origin.setCangku(record.getFromCangku());
|
||||
origin.setPcode(record.getFromPcode());
|
||||
origin.setTrayCode(record.getFromTrayCode());
|
||||
origin.setHasMoved("0");
|
||||
origin.setUpdateBy(userId);
|
||||
origin.setUpdateTime(now);
|
||||
|
||||
record.setIsDelete("0");
|
||||
record.setCreateBy(userId.toString());
|
||||
record.setCreateTime(now);
|
||||
record.setUpdateBy(userId.toString());
|
||||
rkInfoMapper.updateRkInfo(origin);
|
||||
}
|
||||
// ---------- 情况二:部分移库 ----------
|
||||
else {
|
||||
|
||||
/* 3.1 原库存回补数量 */
|
||||
BigDecimal qty = record.getRealQty();
|
||||
if (qty == null || qty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new ServiceException("移库数量异常,无法撤销");
|
||||
}
|
||||
|
||||
origin.setRealQty(origin.getRealQty().add(qty));
|
||||
origin.setHasMoved("0");
|
||||
origin.setUpdateBy(userId);
|
||||
origin.setUpdateTime(now);
|
||||
origin.setHasMoved("0");
|
||||
|
||||
rkInfoMapper.updateRkInfo(origin);
|
||||
|
||||
/* 3.2 删除移库生成的新库存 */
|
||||
RkInfo newInfo = rkInfoMapper.selectRkInfoById(newRkInfoId);
|
||||
if (newInfo != null && !"1".equals(newInfo.getIsDelete())) {
|
||||
newInfo.setIsDelete("1");
|
||||
newInfo.setUpdateBy(userId);
|
||||
newInfo.setUpdateTime(now);
|
||||
rkInfoMapper.updateRkInfo(newInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/* ====================== 4. 标记移库记录已撤销 ====================== */
|
||||
record.setIsDelete("1");
|
||||
record.setUpdateBy(userId);
|
||||
record.setUpdateTime(now);
|
||||
|
||||
return record;
|
||||
moveRecordMapper.updateMoveRecord(record);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.zg.common.exception.ServiceException;
|
||||
import com.zg.common.utils.DateUtils;
|
||||
import com.zg.common.utils.SecurityUtils;
|
||||
import com.zg.common.utils.StringUtils;
|
||||
@@ -100,7 +101,7 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
Date now = DateUtils.getNowDate();
|
||||
String userId = String.valueOf(SecurityUtils.getUserId());
|
||||
|
||||
// ================== 1. 主单 rk_bill ==================
|
||||
/* ================== 1. 主单 rk_bill ================== */
|
||||
RkBill bill = new RkBill();
|
||||
if (dto.getRkBill() != null) {
|
||||
BeanUtils.copyProperties(dto.getRkBill(), bill);
|
||||
@@ -108,7 +109,7 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
|
||||
bill.setBillNo(billNo);
|
||||
bill.setBizType("0"); // 入库
|
||||
bill.setOperationTime(now);
|
||||
bill.setOperationTime(dto.getRkBill().getOperationTime());
|
||||
bill.setCreateTime(now);
|
||||
bill.setCreateBy(userId);
|
||||
bill.setIsDelete("0");
|
||||
@@ -118,17 +119,20 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
bill.setOperator(Integer.valueOf(userId));
|
||||
}
|
||||
|
||||
// execStatus:默认已完成
|
||||
// execStatus:默认已完成(预入库 / 直接入库统一处理)
|
||||
if (StringUtils.isBlank(bill.getExecStatus())) {
|
||||
bill.setExecStatus("1");
|
||||
}
|
||||
|
||||
rkBillMapper.insertRkBill(bill);
|
||||
|
||||
// ================== 2. 明细 + 事件 + 供应计划 ==================
|
||||
/* ================== 2. 明细 + 事件 + 供应计划 ================== */
|
||||
for (RkInfo info : dto.getRkInfoList()) {
|
||||
|
||||
// ===== ① 根据 pcode 查询 pcde_detail,获取 encoded_id =====
|
||||
/* ====== ★ 0. 入库前:供应计划数量校验(核心新增) ====== */
|
||||
checkGysJhQtyBeforeInStock(info);
|
||||
|
||||
/* ====== ① 根据 pcode 查询 pcde_detail,获取 encoded_id ====== */
|
||||
if (StringUtils.isNotBlank(info.getPcode())) {
|
||||
|
||||
PcdeDetail pcde = pcdeDetailMapper.selectByPcode(info.getPcode());
|
||||
@@ -139,7 +143,7 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
info.setPcodeId(pcde.getEncodedId());
|
||||
}
|
||||
|
||||
// ---------- rk_info ----------
|
||||
/* ---------- rk_info ---------- */
|
||||
info.setBillNo(billNo);
|
||||
info.setBizType(bill.getBizType());
|
||||
info.setOperationType(bill.getOperationType());
|
||||
@@ -159,20 +163,56 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库前校验:入库数量不能超过供应计划数量
|
||||
*/
|
||||
private void checkGysJhQtyBeforeInStock(RkInfo info) {
|
||||
|
||||
if (info.getGysJhId() == null || info.getRealQty() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(info.getGysJhId());
|
||||
if (gysJh == null) {
|
||||
throw new RuntimeException("供应计划不存在,ID:" + info.getGysJhId());
|
||||
}
|
||||
|
||||
BigDecimal planQty = gysJh.getJhQty();
|
||||
if (planQty == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal alreadyInQty = gysJh.getRealQty();
|
||||
if (alreadyInQty == null) {
|
||||
alreadyInQty = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
BigDecimal afterQty = alreadyInQty.add(info.getRealQty());
|
||||
|
||||
if (afterQty.compareTo(planQty) > 0) {
|
||||
throw new RuntimeException(
|
||||
"入库数量超出供应计划数量,物料号:" + info.getWlNo()
|
||||
+ ",计划数量:" + planQty
|
||||
+ ",已入库:" + alreadyInQty
|
||||
+ ",本次入库:" + info.getRealQty()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleGysJhAfterInStock(RkInfo info) {
|
||||
|
||||
// 1. 未关联供应计划或无实际入库数量,直接跳过
|
||||
@@ -180,29 +220,36 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 扣减供应计划数量(jh_qty = jh_qty - realQty)
|
||||
gysJhMapper.decreaseJhQtyById(
|
||||
info.getGysJhId(),
|
||||
info.getRealQty()
|
||||
// 2. 累加 实际入库数量(real_qty = real_qty + 本次入库数量)
|
||||
gysJhMapper.increaseRealQtyById(
|
||||
info.getRealQty(),
|
||||
info.getGysJhId()
|
||||
);
|
||||
|
||||
// 3. 查询最新供应计划数据(用于判断剩余数量)
|
||||
// 3. 查询最新供应计划数据
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(info.getGysJhId());
|
||||
if (gysJh == null) {
|
||||
throw new RuntimeException("供应计划不存在,ID:" + info.getGysJhId());
|
||||
}
|
||||
|
||||
// 4. 根据剩余数量判断状态
|
||||
BigDecimal remainQty = gysJh.getJhQty();
|
||||
BigDecimal planQty = gysJh.getJhQty(); // 计划交货数量
|
||||
BigDecimal realQty = gysJh.getRealQty(); // 实际入库数量
|
||||
|
||||
if (realQty == null) {
|
||||
realQty = BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
// 4. 状态判定
|
||||
String status;
|
||||
if (remainQty == null || remainQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
status = "1"; // 全部入库
|
||||
if (realQty.compareTo(BigDecimal.ZERO) == 0) {
|
||||
status = "0"; // 未到货
|
||||
} else if (planQty != null && realQty.compareTo(planQty) >= 0) {
|
||||
status = "1"; // 已入库
|
||||
} else {
|
||||
status = "2"; // 部分入库
|
||||
}
|
||||
|
||||
// 5. 更新供应计划状态(⚠ 不使用 Map,直接参数)
|
||||
// 5. 更新供应计划状态
|
||||
gysJhMapper.updateStatusById(gysJh.getId(), status);
|
||||
}
|
||||
|
||||
@@ -294,8 +341,8 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
info.setCangku(bill.getCangku());
|
||||
|
||||
// ---------- 操作信息 ----------
|
||||
info.setOperationTime(now);
|
||||
info.setOperator(bill.getOperator());
|
||||
info.setOperationTime(info.getOperationTime());
|
||||
info.setOperator(info.getOperator());
|
||||
|
||||
// ---------- 执行状态 ----------
|
||||
info.setExecStatus(execStatus);
|
||||
@@ -359,11 +406,50 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteRkBillByIds(Long[] ids)
|
||||
{
|
||||
return rkBillMapper.deleteRkBillByIds(ids);
|
||||
}
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int deleteRkBillByIds(Long[] ids) {
|
||||
|
||||
if (ids == null || ids.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rows = 0;
|
||||
|
||||
for (Long id : ids) {
|
||||
|
||||
// 1. 查询单据
|
||||
RkBill bill = rkBillMapper.selectRkBillById(id);
|
||||
if (bill == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String billNo = bill.getBillNo();
|
||||
if (billNo == null || billNo.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 2. 校验 rk_record 是否存在
|
||||
int recordCount = rkRecordMapper.countByBillNo(billNo);
|
||||
if (recordCount > 0) {
|
||||
throw new ServiceException(
|
||||
"单据号【" + billNo + "】仍存在出入库记录,不允许删除"
|
||||
);
|
||||
}
|
||||
|
||||
// 3. 校验 rk_info 是否存在
|
||||
int infoCount = rkInfoMapper.countByBillNo(billNo);
|
||||
if (infoCount > 0) {
|
||||
throw new ServiceException(
|
||||
"单据号【" + billNo + "】仍存在库存明细,不允许删除"
|
||||
);
|
||||
}
|
||||
|
||||
// 4. 真正删除 rk_bill
|
||||
rows += rkBillMapper.deleteRkBillById(id);
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
/**
|
||||
* 删除库存单据信息
|
||||
*
|
||||
@@ -375,4 +461,286 @@ public class RkBillServiceImpl implements IRkBillService
|
||||
{
|
||||
return rkBillMapper.deleteRkBillById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int insertOutBillAndDetail(RkBillCreateDTO dto) {
|
||||
|
||||
if (dto == null || dto.getRkInfoList() == null || dto.getRkInfoList().isEmpty()) {
|
||||
throw new RuntimeException("出库明细不能为空");
|
||||
}
|
||||
|
||||
String billNo = BillNoUtil.generateTodayBillNo("CK", 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);
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(bill.getBizType())) {
|
||||
throw new RuntimeException("bizType 不能为空");
|
||||
}
|
||||
|
||||
bill.setBillNo(billNo);
|
||||
bill.setOperationTime(now);
|
||||
bill.setCreateTime(now);
|
||||
bill.setCreateBy(userId);
|
||||
bill.setIsDelete("0");
|
||||
|
||||
if (bill.getOperator() == null) {
|
||||
bill.setOperator(Integer.valueOf(userId));
|
||||
}
|
||||
|
||||
// exec_status:0=预出库,1=已出库
|
||||
if (StringUtils.isBlank(bill.getExecStatus())) {
|
||||
bill.setExecStatus("1");
|
||||
}
|
||||
|
||||
boolean isPreOut = "0".equals(bill.getExecStatus());
|
||||
|
||||
// ===== 借料出库字段 =====
|
||||
if ("2".equals(bill.getBizType())) {
|
||||
bill.setBorrowTime(bill.getBorrowTime() != null ? bill.getBorrowTime() : now);
|
||||
bill.setXmNoCk(bill.getXmNoCk());
|
||||
bill.setXmMsCk(bill.getXmMsCk());
|
||||
}
|
||||
|
||||
rkBillMapper.insertRkBill(bill);
|
||||
|
||||
// ================== 2. 出库处理 ==================
|
||||
for (RkInfo outInfo : dto.getRkInfoList()) {
|
||||
|
||||
if (outInfo.getId() == null) {
|
||||
throw new RuntimeException("出库必须指定库存明细ID");
|
||||
}
|
||||
if (outInfo.getRealQty() == null) {
|
||||
throw new RuntimeException("出库数量不能为空");
|
||||
}
|
||||
|
||||
RkInfo dbInfo = rkInfoMapper.selectRkInfoById(outInfo.getId());
|
||||
if (dbInfo == null) {
|
||||
throw new RuntimeException("库存不存在,ID:" + outInfo.getId());
|
||||
}
|
||||
|
||||
BigDecimal remainQty = dbInfo.getRealQty();
|
||||
BigDecimal outQty = outInfo.getRealQty();
|
||||
|
||||
if (!isPreOut && remainQty.compareTo(outQty) < 0) {
|
||||
throw new RuntimeException("出库数量不能大于库存数量,库存ID:" + dbInfo.getId());
|
||||
}
|
||||
|
||||
// ===== ① 非预出库才扣库存 =====
|
||||
if (!isPreOut) {
|
||||
BigDecimal newQty = remainQty.subtract(outQty);
|
||||
rkInfoMapper.updateRealQtyById(dbInfo.getId(), newQty);
|
||||
|
||||
rkInfoMapper.updateIsChukuById(
|
||||
dbInfo.getId(),
|
||||
newQty.compareTo(BigDecimal.ZERO) == 0 ? "1" : "0"
|
||||
);
|
||||
}
|
||||
|
||||
// ===== ② 出库记录(重点:传 outInfo)=====
|
||||
RkRecord record = buildOutRkRecord(bill, dbInfo, outInfo, outQty, now);
|
||||
record.setExecStatus(isPreOut ? "0" : "1");
|
||||
|
||||
rkRecordMapper.insertRkRecord(record);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
private RkRecord buildOutRkRecord(
|
||||
RkBill bill,
|
||||
RkInfo dbInfo,
|
||||
RkInfo outInfo,
|
||||
BigDecimal outQty,
|
||||
Date now) {
|
||||
|
||||
RkRecord record = new RkRecord();
|
||||
|
||||
// ① 库存快照
|
||||
BeanUtils.copyProperties(dbInfo, record);
|
||||
record.setId(null);
|
||||
|
||||
// ② 本次出库数量
|
||||
record.setRealQty(outQty);
|
||||
|
||||
// ③ 主单上下文
|
||||
record.setBillNo(bill.getBillNo());
|
||||
record.setBizType(bill.getBizType());
|
||||
record.setOperationType(bill.getOperationType());
|
||||
record.setOperationTime(bill.getOperationTime());
|
||||
record.setOperator(bill.getOperator());
|
||||
record.setCangku(dbInfo.getCangku());
|
||||
record.setTeamCode(dbInfo.getTeamCode());
|
||||
|
||||
// ===== ★ 关键:备注来自【出库明细 outInfo】=====
|
||||
record.setRemark(outInfo.getRemark());
|
||||
|
||||
// ④ 借料专属字段
|
||||
if ("2".equals(bill.getBizType())) {
|
||||
record.setIsBorrowed("1");
|
||||
record.setBorrowTime(bill.getBorrowTime());
|
||||
record.setReturnTime(bill.getReturnTime());
|
||||
record.setXmNoCk(bill.getXmNoCk());
|
||||
record.setXmMsCk(bill.getXmMsCk());
|
||||
} else {
|
||||
record.setIsBorrowed("0");
|
||||
}
|
||||
|
||||
// ⑤ 状态字段
|
||||
record.setIsChuku("1");
|
||||
record.setHasMoved("0");
|
||||
record.setIsDelete("0");
|
||||
record.setExecStatus(bill.getExecStatus());
|
||||
|
||||
// ⑥ 审计字段
|
||||
record.setCreateTime(now);
|
||||
record.setCreateBy(bill.getCreateBy());
|
||||
|
||||
// ⑦ 关联库存
|
||||
record.setRkInfoId(dbInfo.getId());
|
||||
record.setRdid(dbInfo.getId());
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int insertReturnBillAndDetail(RkBillCreateDTO dto) {
|
||||
|
||||
if (dto == null || dto.getRkInfoList() == null || dto.getRkInfoList().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);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
// 必须关联原借料出库库存
|
||||
if (info.getRdid() == null) {
|
||||
throw new RuntimeException("还料必须指定原借料库存ID(rdid)");
|
||||
}
|
||||
|
||||
RkInfo borrowInfo = rkInfoMapper.selectRkInfoById(info.getRdid());
|
||||
if (borrowInfo == null) {
|
||||
throw new RuntimeException("原借料库存不存在,ID:" + info.getRdid());
|
||||
}
|
||||
|
||||
/* ---------- rk_info(新增库存) ---------- */
|
||||
info.setId(null);
|
||||
info.setBillNo(billNo);
|
||||
info.setBizType("3"); // 还料入库
|
||||
info.setOperationType(bill.getOperationType());
|
||||
info.setOperationTime(bill.getOperationTime());
|
||||
info.setOperator(bill.getOperator());
|
||||
|
||||
// 关键:库存是“新增”,不是回补原库存
|
||||
info.setIsChuku("0");
|
||||
info.setIsBorrowed("0");
|
||||
info.setHasMoved("0");
|
||||
info.setExecStatus(bill.getExecStatus());
|
||||
|
||||
// 仓库 / 物料 / 项目信息,默认继承原借料库存
|
||||
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);
|
||||
|
||||
/* ---------- 原借料记录标记“已归还” ---------- */
|
||||
rkInfoMapper.updateBorrowReturn(
|
||||
borrowInfo.getId(),
|
||||
"2", // is_borrowed = 2 已归还
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package com.zg.project.wisdom.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.zg.common.exception.ServiceException;
|
||||
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.mapper.GysJhMapper;
|
||||
import com.zg.project.wisdom.mapper.RkBillMapper;
|
||||
import com.zg.project.wisdom.mapper.RkInfoMapper;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
@@ -36,6 +38,9 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
@Autowired
|
||||
private RkBillMapper rkBillMapper;
|
||||
|
||||
@Autowired
|
||||
private GysJhMapper gysJhMapper;
|
||||
|
||||
/**
|
||||
* 查询出入库记录
|
||||
*
|
||||
@@ -81,44 +86,179 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
|
||||
/**
|
||||
* 修改出入库记录
|
||||
*
|
||||
*
|
||||
* 业务约定:
|
||||
* 1. rk_record.real_qty —— 单条出入库记录的最终数量(绝对值)
|
||||
* 2. rk_info.real_qty —— 当前库存数量
|
||||
* 3. gys_jh.real_qty —— 供应计划累计已入库数量
|
||||
*
|
||||
* 入库(bizType = 0):
|
||||
* - 使用【新值 - 旧值】差量修正供应计划 real_qty
|
||||
* - 严禁累计入库数量超过计划数量 jh_qty
|
||||
* - 自动维护供应计划状态:
|
||||
* real_qty == 0 → 未到货
|
||||
* 0 < real_qty < jh_qty→ 部分到货
|
||||
* real_qty == jh_qty → 已入库
|
||||
*
|
||||
* 出库(bizType = 1):
|
||||
* - 出库数量不得超过库存
|
||||
* - 出库数量变化联动库存 real_qty
|
||||
* - 库存为 0 时 is_chuku = 1,否则 = 0
|
||||
*
|
||||
* @param rkRecord 出入库记录
|
||||
* @return 结果
|
||||
* @return 影响行数
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int updateRkRecord(RkRecord rkRecord)
|
||||
{
|
||||
// 1. 更新时间
|
||||
public int updateRkRecord(RkRecord rkRecord) {
|
||||
|
||||
/* ====================== 1. 基础校验 ====================== */
|
||||
if (rkRecord == null || rkRecord.getId() == null) {
|
||||
throw new RuntimeException("出入库记录ID不能为空");
|
||||
}
|
||||
|
||||
rkRecord.setUpdateTime(DateUtils.getNowDate());
|
||||
|
||||
// 2. 更新 rk_record
|
||||
/* ====================== 2. 查询原记录(唯一可信来源) ====================== */
|
||||
RkRecord oldRecord = rkRecordMapper.selectRkRecordById(rkRecord.getId());
|
||||
if (oldRecord == null) {
|
||||
throw new RuntimeException("原出入库记录不存在");
|
||||
}
|
||||
|
||||
/* ====================== 3. 获取并校验库存ID(必须来自 oldRecord) ====================== */
|
||||
Long rkInfoId = oldRecord.getRkInfoId();
|
||||
if (rkInfoId == null) {
|
||||
throw new RuntimeException("出入库记录未关联库存,禁止修改");
|
||||
}
|
||||
|
||||
RkInfo info = rkInfoMapper.selectRkInfoById(rkInfoId);
|
||||
if (info == null) {
|
||||
throw new RuntimeException("关联的库存记录不存在");
|
||||
}
|
||||
|
||||
String bizType = rkRecord.getBizType();
|
||||
|
||||
/* =========================================================
|
||||
* 【A】入库记录修改(bizType = 0)
|
||||
* ========================================================= */
|
||||
if ("0".equals(bizType)) {
|
||||
|
||||
BigDecimal oldInQty = oldRecord.getRealQty() == null
|
||||
? BigDecimal.ZERO
|
||||
: oldRecord.getRealQty();
|
||||
|
||||
BigDecimal newInQty = rkRecord.getRealQty() == null
|
||||
? BigDecimal.ZERO
|
||||
: rkRecord.getRealQty();
|
||||
|
||||
BigDecimal diff = newInQty.subtract(oldInQty);
|
||||
|
||||
/* ---------- 供应计划处理 ---------- */
|
||||
Long gysJhId = oldRecord.getGysJhId();
|
||||
if (gysJhId != null) {
|
||||
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
|
||||
if (gysJh == null) {
|
||||
throw new RuntimeException("关联的供应计划不存在,ID:" + gysJhId);
|
||||
}
|
||||
|
||||
BigDecimal planQty = gysJh.getJhQty();
|
||||
BigDecimal planRealQty = gysJh.getRealQty() == null
|
||||
? BigDecimal.ZERO
|
||||
: gysJh.getRealQty();
|
||||
|
||||
BigDecimal newPlanRealQty = planRealQty.add(diff);
|
||||
|
||||
if (planQty != null && newPlanRealQty.compareTo(planQty) > 0) {
|
||||
throw new RuntimeException("调整后已入库数量不能大于供应计划数量");
|
||||
}
|
||||
|
||||
gysJh.setRealQty(newPlanRealQty);
|
||||
|
||||
if (newPlanRealQty.compareTo(BigDecimal.ZERO) == 0) {
|
||||
gysJh.setStatus("0"); // 未到货
|
||||
} else if (planQty != null && newPlanRealQty.compareTo(planQty) >= 0) {
|
||||
gysJh.setStatus("1"); // 已入库
|
||||
} else {
|
||||
gysJh.setStatus("2"); // 部分入库
|
||||
}
|
||||
|
||||
gysJh.setWlNo(rkRecord.getWlNo());
|
||||
gysJh.setWlMs(rkRecord.getWlMs());
|
||||
gysJh.setXmNo(rkRecord.getXmNo());
|
||||
gysJh.setXmMs(rkRecord.getXmMs());
|
||||
gysJh.setGysNo(rkRecord.getGysNo());
|
||||
gysJh.setGysMc(rkRecord.getGysMc());
|
||||
gysJh.setDw(rkRecord.getDw());
|
||||
gysJh.setHtDj(rkRecord.getHtDj());
|
||||
gysJh.setUpdateTime(DateUtils.getNowDate());
|
||||
|
||||
gysJhMapper.updateGysJh(gysJh);
|
||||
}
|
||||
|
||||
/* ---------- 同步库存(明确字段,禁止 BeanUtils) ---------- */
|
||||
info.setRealQty(newInQty);
|
||||
info.setWlNo(rkRecord.getWlNo());
|
||||
info.setWlMs(rkRecord.getWlMs());
|
||||
info.setXmNo(rkRecord.getXmNo());
|
||||
info.setXmMs(rkRecord.getXmMs());
|
||||
info.setGysNo(rkRecord.getGysNo());
|
||||
info.setGysMc(rkRecord.getGysMc());
|
||||
info.setDw(rkRecord.getDw());
|
||||
info.setHtDj(rkRecord.getHtDj());
|
||||
info.setIsChuku("0");
|
||||
}
|
||||
|
||||
/* =========================================================
|
||||
* 【B】出库记录修改(bizType = 1)
|
||||
* ========================================================= */
|
||||
if ("1".equals(bizType)) {
|
||||
|
||||
BigDecimal oldOutQty = oldRecord.getRealQty();
|
||||
BigDecimal newOutQty = rkRecord.getRealQty();
|
||||
BigDecimal stockQty = info.getRealQty();
|
||||
|
||||
if (oldOutQty == null || newOutQty == null || stockQty == null) {
|
||||
throw new RuntimeException("数量数据异常,无法修改出库记录");
|
||||
}
|
||||
|
||||
BigDecimal diff = newOutQty.subtract(oldOutQty);
|
||||
BigDecimal newStockQty = stockQty.subtract(diff);
|
||||
|
||||
if (newStockQty.compareTo(BigDecimal.ZERO) < 0) {
|
||||
throw new RuntimeException("库存不足,无法修改出库数量");
|
||||
}
|
||||
|
||||
info.setRealQty(newStockQty);
|
||||
info.setIsChuku(newStockQty.compareTo(BigDecimal.ZERO) == 0 ? "1" : "0");
|
||||
|
||||
info.setWlNo(rkRecord.getWlNo());
|
||||
info.setWlMs(rkRecord.getWlMs());
|
||||
info.setXmNo(rkRecord.getXmNo());
|
||||
info.setXmMs(rkRecord.getXmMs());
|
||||
info.setGysNo(rkRecord.getGysNo());
|
||||
info.setGysMc(rkRecord.getGysMc());
|
||||
info.setDw(rkRecord.getDw());
|
||||
info.setHtDj(rkRecord.getHtDj());
|
||||
}
|
||||
|
||||
/* ====================== 4. 更新库存表 ====================== */
|
||||
info.setUpdateTime(DateUtils.getNowDate());
|
||||
int infoRows = rkInfoMapper.updateRkInfo(info);
|
||||
if (infoRows <= 0) {
|
||||
throw new RuntimeException("同步更新库存表失败");
|
||||
}
|
||||
|
||||
/* ====================== 5. 最后更新 rk_record ====================== */
|
||||
rkRecord.setRkInfoId(rkInfoId); // 强制回填,防止被置空
|
||||
int rows = rkRecordMapper.updateRkRecord(rkRecord);
|
||||
if (rows <= 0) {
|
||||
throw new RuntimeException("更新出入库记录失败");
|
||||
}
|
||||
|
||||
// 3. 同步更新 rk_info
|
||||
Long rkInfoId = rkRecord.getRkInfoId();
|
||||
if (rkInfoId == null) {
|
||||
throw new RuntimeException("rkInfoId 为空,无法同步更新库存表");
|
||||
}
|
||||
|
||||
// 4. 将 record 中的字段映射到 info
|
||||
RkInfo rkInfo = new RkInfo();
|
||||
BeanUtils.copyProperties(rkRecord, rkInfo);
|
||||
|
||||
// ⚠️ 关键:主键必须用 rk_info.id
|
||||
rkInfo.setId(rkInfoId);
|
||||
rkInfo.setUpdateTime(DateUtils.getNowDate());
|
||||
|
||||
int infoRows = rkInfoMapper.updateRkInfo(rkInfo);
|
||||
if (infoRows <= 0) {
|
||||
throw new RuntimeException("同步更新库存表失败");
|
||||
}
|
||||
|
||||
return rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除出入库记录
|
||||
*
|
||||
@@ -126,11 +266,92 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public int deleteRkRecordByIds(Long[] ids)
|
||||
{
|
||||
return rkRecordMapper.deleteRkRecordByIds(ids);
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int deleteRkRecordByIds(Long[] ids) {
|
||||
|
||||
if (ids == null || ids.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ================== 1. 查询 record ==================
|
||||
List<RkRecord> records = rkRecordMapper.selectRkRecordByIds(Arrays.asList(ids));
|
||||
if (records == null || records.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ================== 2. 校验 record 必须全部是预入库 ==================
|
||||
boolean hasFinishedRecord = records.stream()
|
||||
.anyMatch(r -> r.getExecStatus() == null || !"0".equals(r.getExecStatus()));
|
||||
if (hasFinishedRecord) {
|
||||
throw new ServiceException("仅允许删除预入库/预出库的出入库记录");
|
||||
}
|
||||
|
||||
// ================== 3. 回滚供应计划已入库数量 + 状态 ==================
|
||||
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()
|
||||
.map(RkRecord::getRkInfoId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// ================== 5. 校验 info 也必须是预入库 ==================
|
||||
if (!rkInfoIds.isEmpty()) {
|
||||
int invalidCount = rkInfoMapper.countNotPreByIds(rkInfoIds);
|
||||
if (invalidCount > 0) {
|
||||
throw new ServiceException("存在非预入库的库存明细,不允许删除");
|
||||
}
|
||||
|
||||
// 先删 info
|
||||
rkInfoMapper.deleteRkInfoByIds(rkInfoIds.toArray(new Long[0]));
|
||||
}
|
||||
|
||||
// ================== 6. 删除 record ==================
|
||||
int deleteCount = rkRecordMapper.deleteRkRecordByIds(ids);
|
||||
|
||||
// ================== 7. 判断是否需要更新 bill 状态 ==================
|
||||
Set<String> billNos = records.stream()
|
||||
.map(RkRecord::getBillNo)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (String billNo : billNos) {
|
||||
int remainPreCount = rkRecordMapper.countPreByBillNo(billNo);
|
||||
if (remainPreCount == 0) {
|
||||
rkBillMapper.updateExecStatus(billNo, "1");
|
||||
}
|
||||
}
|
||||
|
||||
return deleteCount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除出入库记录信息
|
||||
*
|
||||
@@ -151,26 +372,235 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
throw new ServiceException("撤销记录ID不能为空");
|
||||
}
|
||||
|
||||
// 1️⃣ 查 records
|
||||
/* ====================== 1️⃣ 查询入库记录 ====================== */
|
||||
List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
|
||||
if (recordList == null || recordList.isEmpty()) {
|
||||
throw new ServiceException("入库记录不存在");
|
||||
}
|
||||
|
||||
// 2️⃣ rk_record 批量回退 exec_status = 0
|
||||
rkRecordMapper.updateExecStatusByIds(recordIds, "0");
|
||||
|
||||
// 3️⃣ rk_info 批量回退 exec_status = 0
|
||||
/* ====================== 2️⃣ 校验是否发生过移库 ====================== */
|
||||
List<Long> rkInfoIds = recordList.stream()
|
||||
.map(RkRecord::getRkInfoId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!rkInfoIds.isEmpty()) {
|
||||
|
||||
// 查询对应库存
|
||||
List<RkInfo> infoList = rkInfoMapper.selectRkInfoByIds(rkInfoIds);
|
||||
|
||||
// 只要有一条 has_moved = 1,直接禁止撤销
|
||||
boolean hasMoved = infoList.stream()
|
||||
.anyMatch(info -> "1".equals(info.getHasMoved()));
|
||||
|
||||
if (hasMoved) {
|
||||
throw new ServiceException("存在已移库的库存数据,禁止撤销入库");
|
||||
}
|
||||
}
|
||||
|
||||
/* ====================== 3️⃣ rk_record 回退为预入库 ====================== */
|
||||
rkRecordMapper.updateExecStatusByIds(recordIds, "0");
|
||||
|
||||
/* ====================== 4️⃣ rk_info 回退为预入库 ====================== */
|
||||
if (!rkInfoIds.isEmpty()) {
|
||||
rkInfoMapper.updateExecStatusByIds(rkInfoIds, "0");
|
||||
}
|
||||
|
||||
// 4️⃣ rk_bill:保持原 Mapper 方法不变,按 billNo 去重后循环调用
|
||||
/* ====================== 5️⃣ rk_bill 回退为预入库 ====================== */
|
||||
List<String> billNos = recordList.stream()
|
||||
.map(RkRecord::getBillNo)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (String billNo : billNos) {
|
||||
rkBillMapper.updateExecStatusByBillNo(billNo, "0");
|
||||
}
|
||||
|
||||
return recordIds.size();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int finishIn(List<Long> recordIds) {
|
||||
|
||||
if (recordIds == null || recordIds.isEmpty()) {
|
||||
throw new ServiceException("入库记录ID不能为空");
|
||||
}
|
||||
|
||||
/* ================== 1. 查询 rk_record ================== */
|
||||
List<RkRecord> recordList =
|
||||
rkRecordMapper.selectRkRecordByIds(recordIds);
|
||||
|
||||
if (recordList == null || recordList.isEmpty()) {
|
||||
throw new ServiceException("入库记录不存在");
|
||||
}
|
||||
|
||||
/* ================== 2. 只处理「预入库」记录 ================== */
|
||||
List<RkRecord> preRecordList = recordList.stream()
|
||||
.filter(r -> "0".equals(r.getExecStatus())) // 预入库
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (preRecordList.isEmpty()) {
|
||||
throw new ServiceException("所选入库记录均已完成,无需重复入库");
|
||||
}
|
||||
|
||||
/* ================== 3. ★ 校验:一键入库数量 ≤ 计划交货数量 ================== */
|
||||
// 按供应计划ID聚合「本次完成入库数量」
|
||||
Map<Long, BigDecimal> finishQtyMap = new HashMap<>();
|
||||
|
||||
for (RkRecord record : preRecordList) {
|
||||
|
||||
if (record.getGysJhId() == null || record.getRealQty() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
finishQtyMap.merge(
|
||||
record.getGysJhId(),
|
||||
record.getRealQty(),
|
||||
BigDecimal::add
|
||||
);
|
||||
}
|
||||
|
||||
// 只和「计划交货数量」做校验
|
||||
for (Map.Entry<Long, BigDecimal> entry : finishQtyMap.entrySet()) {
|
||||
|
||||
Long gysJhId = entry.getKey();
|
||||
BigDecimal finishQty = entry.getValue();
|
||||
|
||||
GysJh gysJh = gysJhMapper.selectGysJhById(gysJhId);
|
||||
if (gysJh == null) {
|
||||
throw new ServiceException("供应计划不存在,ID:" + gysJhId);
|
||||
}
|
||||
|
||||
BigDecimal planQty = gysJh.getJhQty();
|
||||
if (planQty != null && finishQty.compareTo(planQty) > 0) {
|
||||
throw new ServiceException(
|
||||
"一键入库数量超出供应计划数量,物料号:" + gysJh.getWlNo()
|
||||
+ ",计划数量:" + planQty
|
||||
+ ",本次完成入库:" + finishQty
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================== 4. 状态推进 ================== */
|
||||
|
||||
// ① rk_record.exec_status = 1
|
||||
List<Long> preRecordIds = preRecordList.stream()
|
||||
.map(RkRecord::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
rkRecordMapper.updateExecStatusByIds(preRecordIds, "1");
|
||||
|
||||
// ② rk_info.exec_status = 1
|
||||
List<Long> rkInfoIds = preRecordList.stream()
|
||||
.map(RkRecord::getRkInfoId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!rkInfoIds.isEmpty()) {
|
||||
rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1");
|
||||
}
|
||||
|
||||
// ③ rk_bill.exec_status = 1
|
||||
List<String> billNos = preRecordList.stream()
|
||||
.map(RkRecord::getBillNo)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (String billNo : billNos) {
|
||||
rkBillMapper.updateExecStatusByBillNo(billNo, "1");
|
||||
}
|
||||
|
||||
/* ================== 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;
|
||||
}
|
||||
|
||||
BigDecimal planQty = gysJh.getJhQty();
|
||||
BigDecimal realQty = gysJh.getRealQty();
|
||||
|
||||
if (realQty == null || realQty.compareTo(BigDecimal.ZERO) == 0) {
|
||||
gysJhMapper.updateStatusById(gysJhId, "0"); // 未到货
|
||||
} else if (planQty != null && realQty.compareTo(planQty) >= 0) {
|
||||
gysJhMapper.updateStatusById(gysJhId, "1"); // 已入库
|
||||
} else {
|
||||
gysJhMapper.updateStatusById(gysJhId, "2"); // 部分入库
|
||||
}
|
||||
}
|
||||
|
||||
return preRecordIds.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int rollbackOut(List<Long> recordIds) {
|
||||
|
||||
if (recordIds == null || recordIds.isEmpty()) {
|
||||
throw new ServiceException("撤销出库记录ID不能为空");
|
||||
}
|
||||
|
||||
// ================== 1. 查询出库记录 ==================
|
||||
List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
|
||||
if (recordList == null || recordList.isEmpty()) {
|
||||
throw new ServiceException("出库记录不存在");
|
||||
}
|
||||
|
||||
// 只允许撤销:已出库的出库记录
|
||||
for (RkRecord record : recordList) {
|
||||
if (!"1".equals(record.getBizType())) {
|
||||
throw new ServiceException("存在非出库记录,禁止撤销");
|
||||
}
|
||||
if (!"1".equals(record.getExecStatus())) {
|
||||
throw new ServiceException("只能撤销已出库记录");
|
||||
}
|
||||
}
|
||||
|
||||
// ================== 2. 回滚库存 rk_info ==================
|
||||
for (RkRecord record : recordList) {
|
||||
|
||||
Long rkInfoId = record.getRkInfoId();
|
||||
BigDecimal outQty = record.getRealQty();
|
||||
|
||||
if (rkInfoId == null || outQty == null) {
|
||||
throw new ServiceException("出库记录数据不完整,无法撤销");
|
||||
}
|
||||
|
||||
RkInfo info = rkInfoMapper.selectRkInfoById(rkInfoId);
|
||||
if (info == null) {
|
||||
throw new ServiceException("库存不存在,ID:" + rkInfoId);
|
||||
}
|
||||
|
||||
BigDecimal oldQty = info.getRealQty();
|
||||
BigDecimal newQty = oldQty.add(outQty);
|
||||
|
||||
// ① 补回库存数量
|
||||
rkInfoMapper.updateRealQtyById(rkInfoId, newQty);
|
||||
|
||||
// ② 如果原库存为 0,说明 is_chuku=1,必须回退
|
||||
if (oldQty.compareTo(BigDecimal.ZERO) == 0) {
|
||||
rkInfoMapper.updateIsChukuById(rkInfoId, "0");
|
||||
}
|
||||
}
|
||||
|
||||
// ================== 3. 回退出库记录状态 ==================
|
||||
rkRecordMapper.updateExecStatusByIds(recordIds, "0");
|
||||
|
||||
// ================== 4. 回退主单 rk_bill ==================
|
||||
List<String> billNos = recordList.stream()
|
||||
.map(RkRecord::getBillNo)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
@@ -186,62 +616,142 @@ public class RkRecordServiceImpl implements IRkRecordService
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int finishIn(List<Long> recordIds) {
|
||||
public int finishOut(List<Long> recordIds) {
|
||||
|
||||
if (recordIds == null || recordIds.isEmpty()) {
|
||||
throw new ServiceException("入库记录ID不能为空");
|
||||
throw new ServiceException("出库记录ID不能为空");
|
||||
}
|
||||
|
||||
// 1️⃣ 查询 rk_record
|
||||
List<RkRecord> recordList =
|
||||
rkRecordMapper.selectRkRecordByIds(recordIds);
|
||||
|
||||
// ================== 1. 查询 rk_record ==================
|
||||
List<RkRecord> recordList = rkRecordMapper.selectRkRecordByIds(recordIds);
|
||||
if (recordList == null || recordList.isEmpty()) {
|
||||
throw new ServiceException("入库记录不存在");
|
||||
throw new ServiceException("出库记录不存在");
|
||||
}
|
||||
|
||||
// ================== ① 只保留「预入库」记录 ==================
|
||||
List<RkRecord> preRecordList = recordList.stream()
|
||||
.filter(r -> "0".equals(r.getExecStatus()))
|
||||
// ================== 2. 只保留「预出库」记录 ==================
|
||||
List<RkRecord> preOutList = recordList.stream()
|
||||
.filter(r -> "1".equals(r.getBizType())) // 出库
|
||||
.filter(r -> "0".equals(r.getExecStatus())) // 预出库
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// ================== ② 如果没有可完成的数据,才报错 ==================
|
||||
if (preRecordList.isEmpty()) {
|
||||
throw new ServiceException("所选入库记录均已完成,无需重复入库");
|
||||
if (preOutList.isEmpty()) {
|
||||
throw new ServiceException("所选出库记录均已完成出库");
|
||||
}
|
||||
|
||||
// ================== ③ 后续逻辑全部基于 preRecordList ==================
|
||||
// ================== 3. 库存校验 + 扣减 ==================
|
||||
for (RkRecord record : preOutList) {
|
||||
|
||||
List<Long> preRecordIds = preRecordList.stream()
|
||||
Long rkInfoId = record.getRkInfoId();
|
||||
BigDecimal outQty = record.getRealQty();
|
||||
|
||||
if (rkInfoId == null || outQty == null) {
|
||||
throw new ServiceException("出库记录数据不完整");
|
||||
}
|
||||
|
||||
RkInfo info = rkInfoMapper.selectRkInfoById(rkInfoId);
|
||||
if (info == null) {
|
||||
throw new ServiceException("库存不存在,ID:" + rkInfoId);
|
||||
}
|
||||
|
||||
BigDecimal remainQty = info.getRealQty();
|
||||
if (remainQty.compareTo(outQty) < 0) {
|
||||
throw new ServiceException(
|
||||
"库存不足,库存ID:" + rkInfoId +
|
||||
",当前库存:" + remainQty +
|
||||
",出库数量:" + outQty
|
||||
);
|
||||
}
|
||||
|
||||
BigDecimal newQty = remainQty.subtract(outQty);
|
||||
|
||||
// 扣库存
|
||||
rkInfoMapper.updateRealQtyById(rkInfoId, newQty);
|
||||
|
||||
// 同步出库状态
|
||||
if (newQty.compareTo(BigDecimal.ZERO) == 0) {
|
||||
rkInfoMapper.updateIsChukuById(rkInfoId, "1");
|
||||
}
|
||||
}
|
||||
|
||||
// ================== 4. 推进状态 ==================
|
||||
|
||||
// ① rk_record.exec_status = 1
|
||||
List<Long> preOutIds = preOutList.stream()
|
||||
.map(RkRecord::getId)
|
||||
.collect(Collectors.toList());
|
||||
rkRecordMapper.updateExecStatusByIds(preOutIds, "1");
|
||||
|
||||
// 2️⃣ rk_record.exec_status = 1
|
||||
rkRecordMapper.updateExecStatusByIds(preRecordIds, "1");
|
||||
|
||||
// 3️⃣ rk_info.exec_status = 1
|
||||
List<Long> rkInfoIds = preRecordList.stream()
|
||||
// ② rk_info.exec_status = 1
|
||||
List<Long> rkInfoIds = preOutList.stream()
|
||||
.map(RkRecord::getRkInfoId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (!rkInfoIds.isEmpty()) {
|
||||
rkInfoMapper.updateExecStatusByIds(rkInfoIds, "1");
|
||||
}
|
||||
|
||||
// 4️⃣ rk_bill.exec_status = 1
|
||||
List<String> billNos = preRecordList.stream()
|
||||
// ③ rk_bill.exec_status = 1
|
||||
List<String> billNos = preOutList.stream()
|
||||
.map(RkRecord::getBillNo)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (String billNo : billNos) {
|
||||
rkBillMapper.updateExecStatusByBillNo(billNo, "1");
|
||||
}
|
||||
|
||||
return preRecordIds.size();
|
||||
return preOutIds.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int deletePreOutRecords(Long[] ids) {
|
||||
|
||||
if (ids == null || ids.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ================== 1. 查询 record ==================
|
||||
List<RkRecord> records =
|
||||
rkRecordMapper.selectRkRecordByIds(Arrays.asList(ids));
|
||||
|
||||
if (records == null || records.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ================== 2. 严格校验:只能删「预出库」 ==================
|
||||
boolean hasInvalid = records.stream().anyMatch(r ->
|
||||
!"1".equals(r.getBizType()) // 1 = 出库
|
||||
|| !"0".equals(r.getExecStatus()) // 0 = 预出库
|
||||
);
|
||||
|
||||
if (hasInvalid) {
|
||||
throw new ServiceException("仅允许删除预出库记录");
|
||||
}
|
||||
|
||||
// ================== 3. 删除 rk_record ==================
|
||||
int deleteCount = rkRecordMapper.deleteRkRecordByIds(ids);
|
||||
|
||||
// ================== 4. 维护 bill 状态 ==================
|
||||
Set<String> billNos = records.stream()
|
||||
.map(RkRecord::getBillNo)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
for (String billNo : billNos) {
|
||||
// 该单据下是否还存在预出库记录
|
||||
int remainPreOut =
|
||||
rkRecordMapper.countPreOutByBillNo(billNo);
|
||||
|
||||
if (remainPreOut == 0) {
|
||||
// 没有任何预出库记录了,单据可视情况回退或推进
|
||||
rkBillMapper.updateExecStatusByBillNo(billNo, "1");
|
||||
}
|
||||
}
|
||||
|
||||
return deleteCount;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,38 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.zg.project.wisdom.mapper.GysJhMapper">
|
||||
|
||||
|
||||
<resultMap type="GysJh" id="GysJhResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="indexNo" column="index_no" />
|
||||
<result property="xj" column="xj" />
|
||||
<result property="xmNo" column="xm_no" />
|
||||
<result property="xmMs" column="xm_ms" />
|
||||
<result property="wlNo" column="wl_no" />
|
||||
<result property="wlMs" column="wl_ms" />
|
||||
<result property="gysNo" column="gys_no" />
|
||||
<result property="gysMc" column="gys_mc" />
|
||||
<result property="jhAmt" column="jh_amt" />
|
||||
<result property="htDj" column="ht_dj" />
|
||||
<result property="sapNo" column="sap_no" />
|
||||
<result property="xh" column="xh" />
|
||||
<result property="jhQty" column="jh_qty" />
|
||||
<result property="htQty" column="ht_qty" />
|
||||
<result property="dw" column="dw" />
|
||||
<result property="status" column="status" />
|
||||
<result property="entityId" column="entity_id" />
|
||||
<result property="remark" column="remark" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="isDelete" column="is_delete" />
|
||||
<result property="id" column="id"/>
|
||||
<result property="indexNo" column="index_no"/>
|
||||
<result property="xj" column="xj"/>
|
||||
<result property="xmNo" column="xm_no"/>
|
||||
<result property="xmMs" column="xm_ms"/>
|
||||
<result property="wlNo" column="wl_no"/>
|
||||
<result property="wlMs" column="wl_ms"/>
|
||||
<result property="gysNo" column="gys_no"/>
|
||||
<result property="gysMc" column="gys_mc"/>
|
||||
<result property="jhAmt" column="jh_amt"/>
|
||||
<result property="htDj" column="ht_dj"/>
|
||||
<result property="sapNo" column="sap_no"/>
|
||||
<result property="xh" column="xh"/>
|
||||
<result property="jhQty" column="jh_qty"/>
|
||||
<!-- 新增:已入库数量 -->
|
||||
<result property="realQty" column="real_qty"/>
|
||||
<result property="htQty" column="ht_qty"/>
|
||||
<result property="dw" column="dw"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="entityId" column="entity_id"/>
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="isDelete" column="is_delete"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectGysJhVo">
|
||||
select id, index_no, xj, xm_no, xm_ms, wl_no, wl_ms, gys_no, gys_mc, jh_amt, ht_dj, sap_no, xh, jh_qty, ht_qty, dw, status,entity_id, remark, create_by, create_time, update_by, update_time, is_delete from gys_jh
|
||||
select
|
||||
id,
|
||||
index_no,
|
||||
xj,
|
||||
xm_no,
|
||||
xm_ms,
|
||||
wl_no,
|
||||
wl_ms,
|
||||
gys_no,
|
||||
gys_mc,
|
||||
jh_amt,
|
||||
ht_dj,
|
||||
sap_no,
|
||||
xh,
|
||||
jh_qty,
|
||||
real_qty,
|
||||
ht_qty,
|
||||
dw,
|
||||
status,
|
||||
entity_id,
|
||||
remark,
|
||||
create_by,
|
||||
create_time,
|
||||
update_by,
|
||||
update_time,
|
||||
is_delete
|
||||
from gys_jh
|
||||
</sql>
|
||||
|
||||
<select id="selectGysJhList" parameterType="GysJh" resultMap="GysJhResult">
|
||||
@@ -59,11 +87,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="status != null and status != ''">
|
||||
and status = #{status}
|
||||
</if>
|
||||
<!-- and (status is null or trim(status) != '1') -->
|
||||
<if test="isDelete != null and isDelete != ''">
|
||||
and is_delete = #{isDelete}
|
||||
</if>
|
||||
<!-- 按创建时间筛选:create_time 在 [beginTime, endTime] -->
|
||||
<if test="beginTime != null">
|
||||
and create_time <![CDATA[>=]]> #{beginTime}
|
||||
</if>
|
||||
@@ -72,48 +98,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="selectGysJhById" parameterType="Long" resultMap="GysJhResult">
|
||||
<include refid="selectGysJhVo"/>
|
||||
where id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="getBySapNo" parameterType="java.lang.String" resultMap="GysJhResult">
|
||||
<select id="getBySapNo" parameterType="String" resultMap="GysJhResult">
|
||||
<include refid="selectGysJhVo"/>
|
||||
WHERE sap_no = #{sapNo}
|
||||
</select>
|
||||
|
||||
<!-- 【已注释】唯一性校验查询:基于SAP订单号、项目号、物料号判断是否已存在 -->
|
||||
<!-- <select id="existsByUniqueKeys" resultType="boolean">
|
||||
SELECT COUNT(1)
|
||||
FROM gys_jh
|
||||
WHERE sap_no = #{sapNo}
|
||||
AND xm_no = #{xmNo}
|
||||
AND wl_no = #{wlNo}
|
||||
AND is_delete != '1'
|
||||
</select> -->
|
||||
|
||||
<select id="selectByIds" resultMap="GysJhResult">
|
||||
SELECT * FROM gys_jh
|
||||
SELECT *
|
||||
FROM gys_jh
|
||||
WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<select id="selectMissingMtdItems" resultType="com.zg.project.wisdom.domain.vo.PlanToMtdVO">
|
||||
SELECT
|
||||
g.wl_no AS wlNo,
|
||||
MAX(g.wl_ms) AS wlMs,
|
||||
MAX(g.dw) AS dw,
|
||||
MAX(g.ht_dj) AS htDj
|
||||
FROM gys_jh g
|
||||
LEFT JOIN mtd m ON m.mid = g.wl_no
|
||||
WHERE g.wl_no IS NOT NULL AND g.wl_no <> ''
|
||||
AND m.mid IS NULL
|
||||
GROUP BY g.wl_no
|
||||
</select>
|
||||
|
||||
<insert id="insertGysJh" parameterType="GysJh" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into gys_jh
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
@@ -130,6 +134,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="sapNo != null">sap_no,</if>
|
||||
<if test="xh != null">xh,</if>
|
||||
<if test="jhQty != null">jh_qty,</if>
|
||||
<!-- 新增 -->
|
||||
<if test="realQty != null">real_qty,</if>
|
||||
<if test="htQty != null">ht_qty,</if>
|
||||
<if test="dw != null">dw,</if>
|
||||
<if test="status != null">status,</if>
|
||||
@@ -140,7 +146,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="updateBy != null">update_by,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
<if test="isDelete != null">is_delete,</if>
|
||||
</trim>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="indexNo != null">#{indexNo},</if>
|
||||
<if test="xj != null">#{xj},</if>
|
||||
@@ -155,6 +161,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="sapNo != null">#{sapNo},</if>
|
||||
<if test="xh != null">#{xh},</if>
|
||||
<if test="jhQty != null">#{jhQty},</if>
|
||||
<!-- 新增 -->
|
||||
<if test="realQty != null">#{realQty},</if>
|
||||
<if test="htQty != null">#{htQty},</if>
|
||||
<if test="dw != null">#{dw},</if>
|
||||
<if test="status != null">#{status},</if>
|
||||
@@ -165,9 +173,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="updateBy != null">#{updateBy},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
<if test="isDelete != null">#{isDelete},</if>
|
||||
</trim>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="increaseRealQtyById">
|
||||
UPDATE gys_jh
|
||||
SET real_qty = real_qty + #{realQty}
|
||||
WHERE id = #{gysJhId}
|
||||
</update>
|
||||
<update id="updateGysJh" parameterType="GysJh">
|
||||
update gys_jh
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
@@ -184,6 +197,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="sapNo != null">sap_no = #{sapNo},</if>
|
||||
<if test="xh != null">xh = #{xh},</if>
|
||||
<if test="jhQty != null">jh_qty = #{jhQty},</if>
|
||||
<!-- 新增 -->
|
||||
<if test="realQty != null">real_qty = #{realQty},</if>
|
||||
<if test="htQty != null">ht_qty = #{htQty},</if>
|
||||
<if test="dw != null">dw = #{dw},</if>
|
||||
<if test="status != null">status = #{status},</if>
|
||||
@@ -198,6 +213,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<!-- 下面原有方法全部保持不动 -->
|
||||
<update id="updateStatusById" parameterType="map">
|
||||
UPDATE gys_jh
|
||||
SET status = #{status}
|
||||
@@ -233,7 +249,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</delete>
|
||||
|
||||
<delete id="deleteGysJhByIds" parameterType="String">
|
||||
delete from gys_jh where id in
|
||||
delete from gys_jh where id in
|
||||
<foreach item="id" collection="array" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
@@ -246,10 +262,53 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
AND is_delete = '0'
|
||||
</select>
|
||||
|
||||
<select id="selectMissingMtdItems"
|
||||
resultType="com.zg.project.wisdom.domain.vo.PlanToMtdVO">
|
||||
<![CDATA[
|
||||
SELECT
|
||||
g.wl_no AS wlNo,
|
||||
MAX(g.wl_ms) AS wlMs,
|
||||
MAX(g.dw) AS dw,
|
||||
MAX(g.ht_dj) AS htDj
|
||||
FROM gys_jh g
|
||||
LEFT JOIN mtd m ON m.mid = g.wl_no
|
||||
WHERE g.wl_no IS NOT NULL
|
||||
AND g.wl_no <> ''
|
||||
AND m.mid IS NULL
|
||||
GROUP BY g.wl_no
|
||||
]]>
|
||||
</select>
|
||||
<!-- 查询当前已入库数量 -->
|
||||
<select id="selectRealQtyById" resultType="java.math.BigDecimal">
|
||||
SELECT real_qty
|
||||
FROM gys_jh
|
||||
WHERE id = #{jhId}
|
||||
</select>
|
||||
<update id="updateDwById">
|
||||
UPDATE gys_jh
|
||||
SET dw = #{dw}
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
</mapper>
|
||||
|
||||
<update id="rollbackInQty">
|
||||
UPDATE gys_jh
|
||||
SET real_qty = real_qty - #{rollbackQty}
|
||||
WHERE id = #{jhId}
|
||||
</update>
|
||||
|
||||
<!-- 回退状态 -->
|
||||
<update id="updateStatus">
|
||||
UPDATE gys_jh
|
||||
SET status = #{status}
|
||||
WHERE id = #{jhId}
|
||||
</update>
|
||||
|
||||
<update id="updateRealQtyById">
|
||||
UPDATE gys_jh
|
||||
SET
|
||||
real_qty = #{realQty},
|
||||
update_time = NOW()
|
||||
WHERE id = #{gysJhId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -9,20 +9,31 @@
|
||||
<resultMap type="com.zg.project.wisdom.domain.MoveRecord" id="MoveRecordResult">
|
||||
<result property="id" column="id"/>
|
||||
|
||||
<!-- 关键字段:rk_info_id -->
|
||||
<!-- 关键字段 -->
|
||||
<result property="rkInfoId" column="rk_info_id"/>
|
||||
|
||||
<result property="newRkInfoId" column="new_rk_info_id"/>
|
||||
<result property="entityId" column="entity_id"/>
|
||||
|
||||
<!-- 数量 -->
|
||||
<result property="realQty" column="real_qty"/>
|
||||
|
||||
<!-- from -->
|
||||
<result property="fromCangku" column="from_cangku"/>
|
||||
<result property="fromPcode" column="from_pcode"/>
|
||||
<result property="fromTrayCode" column="from_tray_code"/>
|
||||
|
||||
<!-- to -->
|
||||
<result property="toCangku" column="to_cangku"/>
|
||||
<result property="toPcode" column="to_pcode"/>
|
||||
<result property="toTrayCode" column="to_tray_code"/>
|
||||
|
||||
<!-- 业务 -->
|
||||
<result property="moveReason" column="move_reason"/>
|
||||
<result property="movedBy" column="moved_by"/>
|
||||
<result property="movedByName" column="moved_by_name"/>
|
||||
<result property="movedAt" column="moved_at"/>
|
||||
|
||||
<!-- 通用字段 -->
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
@@ -43,7 +54,9 @@
|
||||
SELECT
|
||||
id,
|
||||
rk_info_id,
|
||||
new_rk_info_id,
|
||||
entity_id,
|
||||
real_qty,
|
||||
from_cangku,
|
||||
from_pcode,
|
||||
from_tray_code,
|
||||
@@ -68,7 +81,9 @@
|
||||
keyProperty="id">
|
||||
INSERT INTO move_record (
|
||||
rk_info_id,
|
||||
new_rk_info_id,
|
||||
entity_id,
|
||||
real_qty,
|
||||
from_cangku,
|
||||
from_pcode,
|
||||
from_tray_code,
|
||||
@@ -85,7 +100,9 @@
|
||||
is_delete
|
||||
) VALUES (
|
||||
#{rkInfoId},
|
||||
#{newRkInfoId},
|
||||
#{entityId},
|
||||
#{realQty},
|
||||
#{fromCangku},
|
||||
#{fromPcode},
|
||||
#{fromTrayCode},
|
||||
@@ -120,6 +137,7 @@
|
||||
LEFT JOIN warehouse_info wi1 ON mr.from_cangku = wi1.warehouse_code
|
||||
LEFT JOIN warehouse_info wi2 ON mr.to_cangku = wi2.warehouse_code
|
||||
<where>
|
||||
mr.is_delete = 0
|
||||
<if test="entityId != null and entityId != ''">
|
||||
AND mr.entity_id = #{entityId}
|
||||
</if>
|
||||
@@ -153,7 +171,9 @@
|
||||
UPDATE move_record
|
||||
<set>
|
||||
<if test="rkInfoId != null">rk_info_id = #{rkInfoId},</if>
|
||||
<if test="newRkInfoId != null">new_rk_info_id = #{newRkInfoId},</if>
|
||||
<if test="entityId != null">entity_id = #{entityId},</if>
|
||||
<if test="realQty != null">real_qty = #{realQty},</if>
|
||||
<if test="fromCangku != null">from_cangku = #{fromCangku},</if>
|
||||
<if test="fromPcode != null">from_pcode = #{fromPcode},</if>
|
||||
<if test="fromTrayCode != null">from_tray_code = #{fromTrayCode},</if>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<!-- ==================== ResultMap ==================== -->
|
||||
<resultMap type="RkBill" id="RkBillResult">
|
||||
<result property="id" column="id"/>
|
||||
|
||||
<result property="wlType" column="wl_type"/>
|
||||
<result property="wlTypeName" column="wl_type_name"/>
|
||||
|
||||
@@ -27,9 +28,22 @@
|
||||
<result property="operatorName" column="operator_name"/>
|
||||
|
||||
<result property="teamCode" column="team_code"/>
|
||||
<result property="teamName" column="team_name"/>
|
||||
|
||||
<result property="borrowTime" column="borrow_time"/>
|
||||
<result property="returnTime" column="return_time"/>
|
||||
|
||||
<result property="xmNoCk" column="xm_no_ck"/>
|
||||
<result property="xmMsCk" column="xm_ms_ck"/>
|
||||
|
||||
<result property="remark" column="remark"/>
|
||||
<result property="isDelivery" column="is_delivery"/>
|
||||
<result property="isDelete" column="is_delete"/>
|
||||
|
||||
<result property="createBy" column="create_by"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateBy" column="update_by"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- ==================== Base Select ==================== -->
|
||||
@@ -45,15 +59,26 @@
|
||||
rb.exec_status,
|
||||
rb.operator,
|
||||
rb.team_code,
|
||||
|
||||
rb.borrow_time,
|
||||
rb.return_time,
|
||||
rb.xm_no_ck,
|
||||
rb.xm_ms_ck,
|
||||
|
||||
rb.remark,
|
||||
rb.is_delivery,
|
||||
rb.is_delete,
|
||||
rb.create_by,
|
||||
rb.create_time,
|
||||
rb.update_by,
|
||||
rb.update_time,
|
||||
|
||||
mt.type_name AS wl_type_name,
|
||||
COALESCE(sit.type_name, sot.type_name) AS operation_type_name,
|
||||
su.nick_name AS operator_name,
|
||||
wh.warehouse_name AS warehouse_name,
|
||||
wh.parent_warehouse_name AS parent_warehouse_name
|
||||
wh.parent_warehouse_name AS parent_warehouse_name,
|
||||
ct.team_name AS team_name
|
||||
|
||||
FROM rk_bill rb
|
||||
LEFT JOIN warehouse_info wh
|
||||
@@ -70,6 +95,9 @@
|
||||
AND (sot.is_delete = '0' OR sot.is_delete IS NULL)
|
||||
LEFT JOIN sys_user su
|
||||
ON rb.operator = su.user_id
|
||||
LEFT JOIN construction_team ct
|
||||
ON rb.team_code = ct.team_code
|
||||
AND ct.is_delete = '0'
|
||||
</sql>
|
||||
|
||||
<!-- ==================== List ==================== -->
|
||||
@@ -93,20 +121,23 @@
|
||||
AND rb.operation_type = #{operationType}
|
||||
</if>
|
||||
|
||||
<!-- 多 bizType -->
|
||||
<if test="bizTypeList != null and bizTypeList.size > 0">
|
||||
AND rb.biz_type IN
|
||||
<foreach collection="bizTypeList"
|
||||
item="bt"
|
||||
open="("
|
||||
separator=","
|
||||
close=")">
|
||||
<foreach collection="bizTypeList" item="bt" open="(" separator="," close=")">
|
||||
#{bt}
|
||||
</foreach>
|
||||
</if>
|
||||
|
||||
<if test="operationTime != null">
|
||||
AND rb.operation_time = #{operationTime}
|
||||
<if test="borrowTime != null">
|
||||
AND rb.borrow_time = #{borrowTime}
|
||||
</if>
|
||||
|
||||
<if test="returnTime != null">
|
||||
AND rb.return_time = #{returnTime}
|
||||
</if>
|
||||
|
||||
<if test="xmNoCk != null and xmNoCk != ''">
|
||||
AND rb.xm_no_ck = #{xmNoCk}
|
||||
</if>
|
||||
|
||||
<if test="startDate != null">
|
||||
@@ -147,9 +178,7 @@
|
||||
WHERE rb.id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="selectByBillNo"
|
||||
parameterType="String"
|
||||
resultMap="RkBillResult">
|
||||
<select id="selectByBillNo" parameterType="String" resultMap="RkBillResult">
|
||||
SELECT
|
||||
id,
|
||||
wl_type,
|
||||
@@ -161,6 +190,10 @@
|
||||
exec_status,
|
||||
operator,
|
||||
team_code,
|
||||
borrow_time,
|
||||
return_time,
|
||||
xm_no_ck,
|
||||
xm_ms_ck,
|
||||
is_delivery,
|
||||
remark,
|
||||
create_by,
|
||||
@@ -187,6 +220,11 @@
|
||||
operation_type,
|
||||
operation_time,
|
||||
operator,
|
||||
team_code,
|
||||
borrow_time,
|
||||
return_time,
|
||||
xm_no_ck,
|
||||
xm_ms_ck,
|
||||
exec_status,
|
||||
is_delivery,
|
||||
remark,
|
||||
@@ -201,6 +239,11 @@
|
||||
#{operationType},
|
||||
#{operationTime},
|
||||
#{operator},
|
||||
#{teamCode},
|
||||
#{borrowTime},
|
||||
#{returnTime},
|
||||
#{xmNoCk},
|
||||
#{xmMsCk},
|
||||
#{execStatus},
|
||||
#{isDelivery},
|
||||
#{remark},
|
||||
@@ -220,6 +263,10 @@
|
||||
<if test="operationType != null and operationType != ''">operation_type = #{operationType},</if>
|
||||
<if test="bizType != null and bizType != ''">biz_type = #{bizType},</if>
|
||||
<if test="operationTime != null">operation_time = #{operationTime},</if>
|
||||
<if test="borrowTime != null">borrow_time = #{borrowTime},</if>
|
||||
<if test="returnTime != null">return_time = #{returnTime},</if>
|
||||
<if test="xmNoCk != null and xmNoCk != ''">xm_no_ck = #{xmNoCk},</if>
|
||||
<if test="xmMsCk != null and xmMsCk != ''">xm_ms_ck = #{xmMsCk},</if>
|
||||
<if test="execStatus != null and execStatus != ''">exec_status = #{execStatus},</if>
|
||||
<if test="operator != null">operator = #{operator},</if>
|
||||
<if test="teamCode != null and teamCode != ''">team_code = #{teamCode},</if>
|
||||
@@ -230,12 +277,19 @@
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<!-- ==================== ExecStatus ==================== -->
|
||||
<update id="updateExecStatusByBillNo">
|
||||
UPDATE rk_bill
|
||||
SET exec_status = #{execStatus}
|
||||
WHERE bill_no = #{billNo}
|
||||
</update>
|
||||
|
||||
<update id="updateExecStatus">
|
||||
UPDATE rk_bill
|
||||
SET exec_status = #{execStatus}
|
||||
WHERE bill_no = #{billNo}
|
||||
</update>
|
||||
|
||||
<!-- ==================== Delete ==================== -->
|
||||
<delete id="deleteRkBillById" parameterType="Long">
|
||||
DELETE FROM rk_bill WHERE id = #{id}
|
||||
|
||||
@@ -103,6 +103,8 @@
|
||||
<include refid="selectRkInfoVo"/>
|
||||
<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>
|
||||
@@ -159,16 +161,44 @@
|
||||
WHERE ri.id = #{id}
|
||||
</select>
|
||||
|
||||
<select id="countByBillNo" resultType="int">
|
||||
SELECT COUNT(1)
|
||||
FROM rk_info
|
||||
WHERE bill_no = #{billNo}
|
||||
</select>
|
||||
|
||||
<select id="countNotPreByIds" resultType="int">
|
||||
SELECT COUNT(1)
|
||||
FROM rk_info
|
||||
WHERE id IN
|
||||
<foreach collection="rkInfoIds" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
AND exec_status != '0'
|
||||
</select>
|
||||
|
||||
<select id="selectRkInfoByIds"
|
||||
parameterType="java.util.List"
|
||||
resultMap="RkInfoResult">
|
||||
SELECT
|
||||
ri.*
|
||||
FROM rk_info ri
|
||||
WHERE ri.id IN
|
||||
<foreach collection="rkInfoIds" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<!-- ========================= 删除 ========================= -->
|
||||
<delete id="deleteRkInfoById" parameterType="Long">
|
||||
DELETE FROM rk_info WHERE id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteRkInfoByIds" parameterType="java.util.List">
|
||||
<delete id="deleteRkInfoByIds">
|
||||
DELETE FROM rk_info
|
||||
WHERE id IN
|
||||
<foreach item="item" collection="list" open="(" separator="," close=")">
|
||||
#{item}
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
@@ -277,4 +307,27 @@
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
<update id="updateRealQtyById">
|
||||
update rk_info
|
||||
set real_qty = #{realQty},
|
||||
update_time = now()
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="updateIsChukuById">
|
||||
update rk_info
|
||||
set is_chuku = #{isChuku},
|
||||
update_time = now()
|
||||
where id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="updateBorrowReturn">
|
||||
UPDATE rk_info
|
||||
SET is_borrowed = #{isBorrowed},
|
||||
return_time = #{returnTime},
|
||||
update_time = NOW()
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
||||
@@ -119,9 +119,21 @@
|
||||
<select id="selectRkRecordList" parameterType="RkRecord" resultMap="RkRecordResult">
|
||||
<include refid="selectRkRecordVo"/>
|
||||
<where>
|
||||
AND rr.exec_status = '1'
|
||||
<if test="operationType != null and operationType != ''">
|
||||
AND rr.operation_type = #{operationType}
|
||||
</if>
|
||||
<!-- 多 bizType -->
|
||||
<if test="bizTypeList != null and bizTypeList.size > 0">
|
||||
AND rb.biz_type IN
|
||||
<foreach collection="bizTypeList"
|
||||
item="bt"
|
||||
open="("
|
||||
separator=","
|
||||
close=")">
|
||||
#{bt}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="bizType != null and bizType != ''">
|
||||
AND rr.biz_type = #{bizType}
|
||||
</if>
|
||||
@@ -198,7 +210,7 @@
|
||||
AND rr.operation_time <= #{endDate}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY rr.operation_time DESC
|
||||
ORDER BY rr.exec_status = '0' DESC, rr.operation_time DESC
|
||||
</select>
|
||||
|
||||
<!-- ===================== 按 ID 查询 ===================== -->
|
||||
@@ -212,7 +224,7 @@
|
||||
<include refid="selectRkRecordVo"/>
|
||||
WHERE rr.bill_no = #{billNo}
|
||||
AND (rr.is_delete = '0' OR rr.is_delete = 0 OR rr.is_delete IS NULL)
|
||||
ORDER BY rr.operation_time ASC
|
||||
ORDER BY rr.exec_status = '0' DESC, rr.operation_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectRkRecordByIds" resultMap="RkRecordResult">
|
||||
@@ -224,6 +236,38 @@
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
<select id="countByBillNo" resultType="int">
|
||||
SELECT COUNT(1)
|
||||
FROM rk_record
|
||||
WHERE bill_no = #{billNo}
|
||||
</select>
|
||||
|
||||
<select id="countPreByBillNo" resultType="int">
|
||||
SELECT COUNT(1)
|
||||
FROM rk_record
|
||||
WHERE bill_no = #{billNo}
|
||||
AND biz_type = '0'
|
||||
AND exec_status = '0'
|
||||
AND is_delete = '0';
|
||||
</select>
|
||||
<select id="countPreOutByBillNo" resultType="java.lang.Integer" parameterType="java.lang.String">
|
||||
SELECT COUNT(1)
|
||||
FROM rk_record
|
||||
WHERE bill_no = #{billNo}
|
||||
AND biz_type = '1'
|
||||
AND exec_status = '0'
|
||||
AND is_delete = '0';
|
||||
</select>
|
||||
|
||||
<select id="selectRkRecordByRkInfoId" resultMap="RkRecordResult">
|
||||
SELECT *
|
||||
FROM rk_record
|
||||
WHERE rk_info_id = #{rkInfoId}
|
||||
AND (is_delete = '0' OR is_delete = 0 OR is_delete IS NULL)
|
||||
ORDER BY operation_time DESC, id DESC
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- ===================== 新增 ===================== -->
|
||||
<insert id="insertRkRecord"
|
||||
parameterType="RkRecord"
|
||||
|
||||
Reference in New Issue
Block a user