新增物料字典模块

修改出入库单据号逻辑
新增出入库撤销和恢复功能
This commit is contained in:
2025-08-01 09:27:07 +08:00
parent 20f6be7790
commit ef833bec2f
18 changed files with 788 additions and 230 deletions

View File

@@ -1,54 +1,104 @@
package com.zg.project.information.controller;
import java.util.List;
import com.zg.common.utils.poi.ExcelUtil;
import com.zg.framework.web.controller.BaseController;
import com.zg.framework.web.domain.AjaxResult;
import com.zg.framework.web.page.TableDataInfo;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
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;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.zg.framework.aspectj.lang.annotation.Log;
import com.zg.framework.aspectj.lang.enums.BusinessType;
import com.zg.project.information.domain.Mtd;
import com.zg.project.information.service.IMtdService;
import com.zg.framework.web.controller.BaseController;
import com.zg.framework.web.domain.AjaxResult;
import com.zg.common.utils.poi.ExcelUtil;
import com.zg.framework.web.page.TableDataInfo;
/**
* 物料字典Controller
*
* @author zg
* @date 2025-07-31
*/
@RestController
@RequestMapping("/information/mtd")
public class MtdController extends BaseController {
public class MtdController extends BaseController
{
@Autowired
private IMtdService mtdService;
/**
* 查询物料字典列表
*/
@PreAuthorize("@ss.hasPermi('information:mtd:list')")
@GetMapping("/list")
public TableDataInfo list(Mtd mtd) {
public TableDataInfo list(Mtd mtd)
{
startPage();
List<Mtd> list = mtdService.selectMtdList(mtd);
return getDataTable(list);
}
/**
* 导出物料字典列表
*/
@PreAuthorize("@ss.hasPermi('information:mtd:export')")
@Log(title = "物料字典", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, Mtd mtd)
{
List<Mtd> list = mtdService.selectMtdList(mtd);
ExcelUtil<Mtd> util = new ExcelUtil<Mtd>(Mtd.class);
util.exportExcel(response, list, "物料字典数据");
}
/**
* 获取物料字典详细信息
*/
@PreAuthorize("@ss.hasPermi('information:mtd:query')")
@GetMapping(value = "/{Id}")
public AjaxResult getInfo(@PathVariable("Id") Long Id)
{
return success(mtdService.selectMtdById(Id));
}
/**
* 新增物料字典
*/
@PreAuthorize("@ss.hasPermi('information:mtd:add')")
@Log(title = "物料字典", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody Mtd mtd) {
public AjaxResult add(@RequestBody Mtd mtd)
{
return toAjax(mtdService.insertMtd(mtd));
}
/**
* 修改物料字典
*/
@PreAuthorize("@ss.hasPermi('information:mtd:edit')")
@Log(title = "物料字典", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody Mtd mtd) {
public AjaxResult edit(@RequestBody Mtd mtd)
{
return toAjax(mtdService.updateMtd(mtd));
}
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(mtdService.deleteMtdByIds(ids));
}
@GetMapping("/export")
public AjaxResult export(Mtd mtd) {
List<Mtd> list = mtdService.selectMtdList(mtd);
ExcelUtil<Mtd> util = new ExcelUtil<>(Mtd.class);
return util.exportExcel(list, "物料信息");
}
@GetMapping("/{id}")
public AjaxResult getInfo(@PathVariable Long id) {
return AjaxResult.success(mtdService.selectMtdById(id));
/**
* 删除物料字典
*/
@PreAuthorize("@ss.hasPermi('information:mtd:remove')")
@Log(title = "物料字典", businessType = BusinessType.DELETE)
@DeleteMapping("/{Ids}")
public AjaxResult remove(@PathVariable Long[] Ids)
{
return toAjax(mtdService.deleteMtdByIds(Ids));
}
}

View File

@@ -1,15 +1,22 @@
package com.zg.project.information.domain;
import com.zg.framework.aspectj.lang.annotation.Excel;
import com.zg.framework.web.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.zg.framework.aspectj.lang.annotation.Excel;
import com.zg.framework.web.domain.BaseEntity;
public class Mtd extends BaseEntity {
/**
* 物料字典对象 mtd
*
* @author zg
* @date 2025-07-31
*/
public class Mtd extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键ID */
private Long id;
/** $column.columnComment */
private Long Id;
/** 物料号 */
@Excel(name = "物料号")
@@ -31,98 +38,112 @@ public class Mtd extends BaseEntity {
@Excel(name = "单价")
private String uprc;
/** 类型1 */
@Excel(name = "btpe")
/** $column.columnComment */
@Excel(name = "大类")
private String btpe;
/** 类型2 */
@Excel(name = "mtpe")
/** $column.columnComment */
@Excel(name = "中类")
private String mtpe;
/** 类型3 */
@Excel(name = "stpe")
/** $column.columnComment */
@Excel(name = "小类")
private String stpe;
// ---------------- Getter & Setter ----------------
public void setId(Long id) {
this.id = id;
public void setId(Long Id)
{
this.Id = Id;
}
public Long getId() {
return id;
public Long getId()
{
return Id;
}
public void setMid(String mid) {
public void setMid(String mid)
{
this.mid = mid;
}
public String getMid() {
public String getMid()
{
return mid;
}
public void setDesMat(String desMat) {
public void setDesMat(String desMat)
{
this.desMat = desMat;
}
public String getDesMat() {
public String getDesMat()
{
return desMat;
}
public void setGrp(String grp) {
public void setGrp(String grp)
{
this.grp = grp;
}
public String getGrp() {
public String getGrp()
{
return grp;
}
public void setUnt(String unt) {
public void setUnt(String unt)
{
this.unt = unt;
}
public String getUnt() {
public String getUnt()
{
return unt;
}
public void setUprc(String uprc) {
public void setUprc(String uprc)
{
this.uprc = uprc;
}
public String getUprc() {
public String getUprc()
{
return uprc;
}
public void setBtpe(String btpe) {
public void setBtpe(String btpe)
{
this.btpe = btpe;
}
public String getBtpe() {
public String getBtpe()
{
return btpe;
}
public void setMtpe(String mtpe) {
public void setMtpe(String mtpe)
{
this.mtpe = mtpe;
}
public String getMtpe() {
public String getMtpe()
{
return mtpe;
}
public void setStpe(String stpe) {
public void setStpe(String stpe)
{
this.stpe = stpe;
}
public String getStpe() {
public String getStpe()
{
return stpe;
}
// ---------------- ToString ----------------
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("Id", getId())
.append("mid", getMid())
.append("desMat", getDesMat())
.append("grp", getGrp())
@@ -131,11 +152,6 @@ public class Mtd extends BaseEntity {
.append("btpe", getBtpe())
.append("mtpe", getMtpe())
.append("stpe", getStpe())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.append("remark", getRemark())
.toString();
}
}

View File

@@ -3,13 +3,61 @@ package com.zg.project.information.mapper;
import java.util.List;
import com.zg.project.information.domain.Mtd;
public interface MtdMapper {
Mtd selectMtdById(Long id);
List<Mtd> selectMtdList(Mtd mtd);
int insertMtd(Mtd mtd);
int updateMtd(Mtd mtd);
int deleteMtdById(Long id);
int deleteMtdByIds(Long[] ids);
/**
* 物料字典Mapper接口
*
* @author zg
* @date 2025-07-31
*/
public interface MtdMapper
{
/**
* 查询物料字典
*
* @param Id 物料字典主键
* @return 物料字典
*/
public Mtd selectMtdById(Long Id);
/**
* 查询物料字典列表
*
* @param mtd 物料字典
* @return 物料字典集合
*/
public List<Mtd> selectMtdList(Mtd mtd);
/**
* 新增物料字典
*
* @param mtd 物料字典
* @return 结果
*/
public int insertMtd(Mtd mtd);
/**
* 修改物料字典
*
* @param mtd 物料字典
* @return 结果
*/
public int updateMtd(Mtd mtd);
/**
* 删除物料字典
*
* @param Id 物料字典主键
* @return 结果
*/
public int deleteMtdById(Long Id);
/**
* 批量删除物料字典
*
* @param Ids 需要删除的数据主键集合
* @return 结果
*/
public int deleteMtdByIds(Long[] Ids);
/**
* 根据物料编码查询物料描述

View File

@@ -3,11 +3,59 @@ package com.zg.project.information.service;
import java.util.List;
import com.zg.project.information.domain.Mtd;
public interface IMtdService {
Mtd selectMtdById(Long id);
List<Mtd> selectMtdList(Mtd mtd);
int insertMtd(Mtd mtd);
int updateMtd(Mtd mtd);
int deleteMtdById(Long id);
int deleteMtdByIds(Long[] ids);
/**
* 物料字典Service接口
*
* @author zg
* @date 2025-07-31
*/
public interface IMtdService
{
/**
* 查询物料字典
*
* @param Id 物料字典主键
* @return 物料字典
*/
public Mtd selectMtdById(Long Id);
/**
* 查询物料字典列表
*
* @param mtd 物料字典
* @return 物料字典集合
*/
public List<Mtd> selectMtdList(Mtd mtd);
/**
* 新增物料字典
*
* @param mtd 物料字典
* @return 结果
*/
public int insertMtd(Mtd mtd);
/**
* 修改物料字典
*
* @param mtd 物料字典
* @return 结果
*/
public int updateMtd(Mtd mtd);
/**
* 批量删除物料字典
*
* @param Ids 需要删除的物料字典主键集合
* @return 结果
*/
public int deleteMtdByIds(Long[] Ids);
/**
* 删除物料字典信息
*
* @param Id 物料字典主键
* @return 结果
*/
public int deleteMtdById(Long Id);
}

View File

@@ -7,38 +7,87 @@ import com.zg.project.information.mapper.MtdMapper;
import com.zg.project.information.domain.Mtd;
import com.zg.project.information.service.IMtdService;
/**
* 物料字典Service业务层处理
*
* @author zg
* @date 2025-07-31
*/
@Service
public class MtdServiceImpl implements IMtdService {
public class MtdServiceImpl implements IMtdService
{
@Autowired
private MtdMapper mtdMapper;
/**
* 查询物料字典
*
* @param Id 物料字典主键
* @return 物料字典
*/
@Override
public Mtd selectMtdById(Long id) {
return mtdMapper.selectMtdById(id);
public Mtd selectMtdById(Long Id)
{
return mtdMapper.selectMtdById(Id);
}
/**
* 查询物料字典列表
*
* @param mtd 物料字典
* @return 物料字典
*/
@Override
public List<Mtd> selectMtdList(Mtd mtd) {
public List<Mtd> selectMtdList(Mtd mtd)
{
return mtdMapper.selectMtdList(mtd);
}
/**
* 新增物料字典
*
* @param mtd 物料字典
* @return 结果
*/
@Override
public int insertMtd(Mtd mtd) {
public int insertMtd(Mtd mtd)
{
return mtdMapper.insertMtd(mtd);
}
/**
* 修改物料字典
*
* @param mtd 物料字典
* @return 结果
*/
@Override
public int updateMtd(Mtd mtd) {
public int updateMtd(Mtd mtd)
{
return mtdMapper.updateMtd(mtd);
}
/**
* 批量删除物料字典
*
* @param Ids 需要删除的物料字典主键
* @return 结果
*/
@Override
public int deleteMtdById(Long id) {
return mtdMapper.deleteMtdById(id);
public int deleteMtdByIds(Long[] Ids)
{
return mtdMapper.deleteMtdByIds(Ids);
}
/**
* 删除物料字典信息
*
* @param Id 物料字典主键
* @return 结果
*/
@Override
public int deleteMtdByIds(Long[] ids) {
return mtdMapper.deleteMtdByIds(ids);
public int deleteMtdById(Long Id)
{
return mtdMapper.deleteMtdById(Id);
}
}

View File

@@ -7,6 +7,7 @@ import javax.servlet.http.HttpServletResponse;
import com.zg.project.wisdom.domain.dto.PcRkInfoBatchDTO;
import com.zg.project.wisdom.domain.dto.RefundRequestDTO;
import com.zg.project.wisdom.domain.dto.RkCancelDTO;
import com.zg.project.wisdom.domain.dto.StockOutDTO;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -35,7 +36,7 @@ public class RkInfoController extends BaseController
/**
* 查询库单据主列表
* 查询出库,借料,待审批,撤销出入库单据主列表
*/
@PreAuthorize("@ss.hasPermi('wisdom:stock:list')")
@PostMapping("/list")
@@ -46,6 +47,7 @@ public class RkInfoController extends BaseController
return getDataTable(list);
}
/**
* 导出库存单据主列表
*/
@@ -118,7 +120,7 @@ public class RkInfoController extends BaseController
}
/**
* 撤销出库
* App撤销出库
* @param
* @return
*/
@@ -136,6 +138,47 @@ public class RkInfoController extends BaseController
: AjaxResult.error("撤销失败,出库单据: " + billNoCk + " 不存在或已处理");
}
/**
* 根据主键ID撤销入库
*/
@PostMapping("/cancel")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteByBillNo')")
public AjaxResult deleteById(@RequestBody RkCancelDTO dto) {
rkInfoService.deleteRkInfoById(dto);
return AjaxResult.success("撤销成功");
}
/**
* 根据主键ID撤销出库
*/
@PostMapping("/cancelById/{id}")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteByBillNo')")
public AjaxResult cancelOutStockById(@PathVariable Long id) {
rkInfoService.cancelOutStockById(id);
return AjaxResult.success("撤销出库成功");
}
/**
* 根据主键id进行删除
* 出入库撤销记录删除
*/
@PostMapping("/deleteByIds")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteById')")
public AjaxResult deleteByIds(@RequestBody Long[] ids) {
return AjaxResult.success(rkInfoService.deleteRkInfoByIds(ids));
}
/**
* 根据ids恢复出库或入库
*/
@PostMapping("/revertByIds")
@PreAuthorize("@ss.hasPermi('wisdom:stock:deleteById')")
public AjaxResult revertByIds(@RequestBody Long[] ids) {
rkInfoService.revertByIds(ids);
return AjaxResult.success();
}
/**
* 出库操作
* @param

View File

@@ -64,7 +64,7 @@ public class AppRkInfoController extends BaseController {
/**
* 根据单据号进行撤销
* 根据单据号进行撤销入库
* @param billNo
* @return
*/

View File

@@ -39,6 +39,7 @@ public class RkInfo extends BaseEntity
private String approverId;
/** 库龄 */
@Excel(name = "库龄")
private Long stockAge;
/** 入库类型 */
@@ -50,6 +51,10 @@ public class RkInfo extends BaseEntity
/** 所属仓库 */
private String cangku;
/** 多状态查询:是否出库(如 0=入库, 1=出库 等) */
@TableField(exist = false)
private List<String> isChukuList;
/** 入库类型名称(联查显示用,导出专用) */
@Excel(name = "入库类型名称")
private String rkTypeName;
@@ -84,7 +89,7 @@ public class RkInfo extends BaseEntity
private String lihuoYName;
/** 是否已出库0未出库1已出库 */
@Excel(name = "是否已出库", readConverterExp = "0=已入库1已出库")
@Excel(name = "是否已出库", readConverterExp = "0已入库1已出库2待审批3借料出库4入库撤销5出库撤销")
private String isChuku;
/** 单据号 */
@@ -225,11 +230,23 @@ public class RkInfo extends BaseEntity
private String auditResult;
/** 入库开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date startTime;
/** 入库结束时间*/
/** 入库结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date endTime;
/** 领用开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@TableField(exist = false)
private Date lyStartTime;
/** 领用结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@TableField(exist = false)
private Date lyEndTime;
/** 是否删除0 表示正常1 表示已删除) */
private String isDelete;
@@ -296,6 +313,14 @@ public class RkInfo extends BaseEntity
public String getLihuoYName() { return lihuoYName; }
public void setLihuoYName(String lihuoYName) { this.lihuoYName = lihuoYName; }
public List<String> getIsChukuList() {
return isChukuList;
}
public void setIsChukuList(List<String> isChukuList) {
this.isChukuList = isChukuList;
}
public String getIsChuku() { return isChuku; }
public void setIsChuku(String isChuku) { this.isChuku = isChuku; }
public String getBillNo() { return billNo; }
@@ -397,6 +422,22 @@ public class RkInfo extends BaseEntity
this.endTime = endTime;
}
public Date getLyStartTime() {
return lyStartTime;
}
public void setLyStartTime(Date lyStartTime) {
this.lyStartTime = lyStartTime;
}
public Date getLyEndTime() {
return lyEndTime;
}
public void setLyEndTime(Date lyEndTime) {
this.lyEndTime = lyEndTime;
}
public String getIsBorrowed() {
return isBorrowed;
}
@@ -489,6 +530,9 @@ public class RkInfo extends BaseEntity
.append("signImageUrl", getSignImageUrl())
.append("scenePhotoUrl", getScenePhotoUrl())
.append("auditResult", getAuditResult())
.append("isChukuList", getIsChukuList())
.append("lyStartTime", getLyStartTime())
.append("lyEndTime", getLyEndTime())
.append("isDelete", getIsDelete())
.toString();
}

View File

@@ -0,0 +1,17 @@
package com.zg.project.wisdom.domain.dto;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class RkCancelDTO {
/** 主键ID */
private Long id;
/** 实际入库数量 */
private BigDecimal realQty;
/** 供应计划ID */
private Long gysJhId;
}

View File

@@ -1,5 +1,6 @@
package com.zg.project.wisdom.domain.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.zg.project.wisdom.domain.dto.StockOutItemDTO;
import lombok.Data;
@@ -13,6 +14,7 @@ import java.util.List;
public class StockOutDTO {
/** 领用时间(出库时间) */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date lyTime;
/** 借用时间 */

View File

@@ -207,4 +207,11 @@ public interface RkInfoMapper
* 出库驳回时恢复单据表数据状态
*/
void revertRkInfoStatusByBillNoCk(RkInfo revert);
/**
* 根据id查询入库单据
* @param ids
* @return
*/
List<RkInfo> selectRkInfoByIds(@Param("ids") Long[] ids);
}

View File

@@ -6,10 +6,7 @@ import java.util.Map;
import com.zg.project.Inventory.domain.dto.QueryDTO;
import com.zg.project.Inventory.domain.vo.ChartDataVO;
import com.zg.project.wisdom.domain.RkInfo;
import com.zg.project.wisdom.domain.dto.PcRkInfoBatchDTO;
import com.zg.project.wisdom.domain.dto.RefundRequestDTO;
import com.zg.project.wisdom.domain.dto.RkInfoBatchDTO;
import com.zg.project.wisdom.domain.dto.StockOutDTO;
import com.zg.project.wisdom.domain.dto.*;
import com.zg.project.wisdom.domain.vo.RkSubmitResultVO;
/**
@@ -56,10 +53,10 @@ public interface IRkInfoService
/**
* 删除库存单据主信息
*
* @param id 库存单据主主键
* @param
* @return 结果
*/
public int deleteRkInfoById(Long id);
int deleteRkInfoById(RkCancelDTO dto);
/**
* 批量新增入库记录
@@ -134,4 +131,17 @@ public interface IRkInfoService
* @return
*/
int refundMaterial(RefundRequestDTO dto);
/**
* 撤销出库
* @param id
*/
void cancelOutStockById(Long id);
/**
* 根据ids恢复出库或入库
* @param ids
*/
void revertByIds(Long[] ids);
}

View File

@@ -7,7 +7,6 @@ import com.zg.common.utils.DateUtils;
import com.zg.common.utils.SecurityUtils;
import com.zg.common.utils.StringUtils;
import com.zg.common.utils.http.HttpUtils;
import com.zg.framework.web.domain.AjaxResult;
import com.zg.project.information.mapper.MtdMapper;
import com.zg.project.wisdom.domain.AgvTaskResult;
import com.zg.project.wisdom.domain.AgyWcs;
@@ -20,17 +19,11 @@ import com.zg.project.wisdom.mapper.AgyWcsMapper;
import com.zg.project.wisdom.mapper.DdTaskMapper;
import com.zg.project.wisdom.mapper.WcsTaskResultMapper;
import com.zg.project.wisdom.service.IDdTaskService;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import static com.zg.framework.datasource.DynamicDataSourceContextHolder.log;

View File

@@ -124,6 +124,7 @@ public class RkInfoServiceImpl implements IRkInfoService
return list;
}
/**
* 修改库存单据主
*
@@ -139,29 +140,118 @@ public class RkInfoServiceImpl implements IRkInfoService
}
/**
* 批量删除库存单据主
* 批量处理撤销入库 / 撤销出库的逻辑(不是通用删除接口)
*
* @param ids 需要删除的库存单据主主键
* @return 结果
* 规则说明:
* - isChuku = 4表示撤销入库
* - 若存在 gysJhId 和 realQty则处理供应计划回补
* - 最终物理删除该库存单据
* - isChuku = 5表示撤销出库
* - 不删除,只将 isChuku 改为 0未出库状态
* - 其他 isChuku 状态:不做任何处理
*
* @param ids 需要处理的库存单据ID数组必须是入库/出库撤销)
* @return 实际删除的条数(仅统计撤销入库场景)
*/
@Override
public int deleteRkInfoByIds(Long[] ids)
{
return rkInfoMapper.deleteRkInfoByIds(ids);
@Transactional(rollbackFor = Exception.class)
public int deleteRkInfoByIds(Long[] ids) {
int deleteCount = 0;
Date now = new Date();
String userId = SecurityUtils.getUserId().toString();
for (Long id : ids) {
RkInfo info = rkInfoMapper.selectRkInfoById(id);
if (info == null) continue;
String isChuku = info.getIsChuku();
// 撤销出库:只更新状态为“未出库”,不删除
if ("5".equals(isChuku)) {
info.setIsChuku("0");
info.setUpdateBy(userId);
info.setUpdateTime(now);
rkInfoMapper.updateRkInfo(info);
continue;
}
// 撤销入库:更新供应计划,删除单据
if ("4".equals(isChuku)) {
Long gysJhId = info.getGysJhId();
BigDecimal realQty = info.getRealQty();
if (gysJhId != null && realQty != null) {
GysJh jh = gysJhMapper.selectGysJhById(gysJhId);
if (jh != null) {
String status = jh.getStatus();
if ("2".equals(status)) {
// 回补 jh_qty改为未到货
BigDecimal updatedQty = (jh.getJhQty() == null ? BigDecimal.ZERO : new BigDecimal(jh.getJhQty()))
.add(realQty);
jh.setJhQty(updatedQty.longValue());
jh.setStatus("0");
jh.setUpdateBy(userId);
jh.setUpdateTime(now);
gysJhMapper.updateGysJh(jh);
} else if ("1".equals(status)) {
// 只更新状态
jh.setStatus("0");
jh.setUpdateBy(userId);
jh.setUpdateTime(now);
gysJhMapper.updateGysJh(jh);
}
}
}
rkInfoMapper.deleteRkInfoById(id);
deleteCount++;
}
}
return deleteCount;
}
/**
* 删除库存单据主信息
*
* @param id 库存单据主主键
* @param
* @return 结果
*/
/**
* 撤销入库单据,并根据供应计划状态回退数量或修改状态
* 逻辑说明:
* - 如果供应计划ID存在查询对应供应计划记录
* - 若状态为“2”部分出库且实际入库数量 realQty 不为空:
* - 将供应计划中的 jhQty 加上 realQty 回退数量
* - 并将状态修改为“0”未入库
* - 若状态不是“2”也将状态修改为“0”
* - 最后根据入库单据ID删除 rk_info 表中的对应入库记录
*
* @param dto 包含主键id、实际入库数量realQty、供应计划IDgysJhId
* @return 删除成功的记录数
*/
@Override
public int deleteRkInfoById(Long id)
{
return rkInfoMapper.deleteRkInfoById(id);
@Transactional(rollbackFor = Exception.class)
public int deleteRkInfoById(RkCancelDTO dto) {
Long id = dto.getId(); // 获取要撤销的入库记录ID
// 校验是否存在
RkInfo rkInfo = rkInfoMapper.selectRkInfoById(id);
if (rkInfo == null) {
throw new ServiceException("入库记录不存在");
}
// 仅更新 is_chuku 字段为 "4" 表示已撤销
RkInfo update = new RkInfo();
update.setId(id);
update.setIsChuku("4"); // 4 = 已撤销
update.setUpdateBy(SecurityUtils.getUsername());
update.setUpdateTime(DateUtils.getNowDate());
return rkInfoMapper.updateRkInfo(update);
}
/**
* 新增入库单据
* @param dto
@@ -796,4 +886,56 @@ public class RkInfoServiceImpl implements IRkInfoService
return rows;
}
@Override
public void cancelOutStockById(Long id) {
// 构造只更新 is_chuku 字段的对象
RkInfo update = new RkInfo();
update.setId(id);
update.setIsChuku("5");
update.setUpdateBy(SecurityUtils.getUsername());
update.setUpdateTime(DateUtils.getNowDate());
// 执行更新
rkInfoMapper.updateRkInfo(update);
}
/**
* 根据 IDs 恢复入库或出库状态(撤销撤销操作)
*
* 说明:
* - 如果 isChuku = 4撤销入库改为 0已入库
* - 如果 isChuku = 5撤销出库改为 1已出库
* - 其他状态不处理;
*
* @param ids 单据 ID 数组
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void revertByIds(Long[] ids) {
Date now = new Date();
String userId = SecurityUtils.getUserId().toString();
for (Long id : ids) {
RkInfo info = rkInfoMapper.selectRkInfoById(id);
if (info == null) continue;
String isChuku = info.getIsChuku();
if ("4".equals(isChuku)) {
// 撤销入库 -> 恢复为已入库
info.setIsChuku("0");
info.setUpdateBy(userId);
info.setUpdateTime(now);
rkInfoMapper.updateRkInfo(info);
} else if ("5".equals(isChuku)) {
// 撤销出库 -> 恢复为已出库
info.setIsChuku("1");
info.setUpdateBy(userId);
info.setUpdateTime(now);
rkInfoMapper.updateRkInfo(info);
}
}
}
}

View File

@@ -2,19 +2,33 @@ package com.zg.project.wisdom.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
public class BillNoUtil {
// 内存缓存key = prefix + datevalue = 当前递增号
private static final Map<String, AtomicInteger> DAILY_SEQUENCE_MAP = new ConcurrentHashMap<>();
/**
* 生成当天单据号:支持传入前缀(如 "RK" 或 "CK"
* 示例结果RK20240610153015999
* 生成当天单据号格式RK20250731_1、CK20250731_2
* @param prefix 单据前缀(如 RK 或 CK
* @return 单据号
*/
public static String generateTodayBillNo(String prefix) {
public static synchronized String generateTodayBillNo(String prefix) {
if (prefix == null || prefix.trim().isEmpty()) {
prefix = "RK"; // 默认用 RK
prefix = "RK";
}
String time = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
return prefix + time;
// 获取当天日期字符串 yyyyMMdd
String today = new SimpleDateFormat("yyyyMMdd").format(new Date());
String key = prefix + today;
// 获取并递增序号
AtomicInteger counter = DAILY_SEQUENCE_MAP.computeIfAbsent(key, k -> new AtomicInteger(1));
int sequence = counter.getAndIncrement();
return prefix + today + "_" + sequence;
}
}

View File

@@ -1,66 +1,97 @@
<?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">
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zg.project.information.mapper.MtdMapper">
<resultMap id="MtdResultMap" type="com.zg.project.information.domain.Mtd">
<id property="id" column="id"/>
<result property="mid" column="mid"/>
<result property="desMat" column="des_mat"/>
<result property="grp" column="grp"/>
<result property="unt" column="unt"/>
<result property="uprc" column="uprc"/>
<result property="btpe" column="btpe"/>
<result property="mtpe" column="mtpe"/>
<result property="stpe" column="stpe"/>
<resultMap type="Mtd" id="MtdResult">
<result property="Id" column="Id" />
<result property="mid" column="mid" />
<result property="desMat" column="des_mat" />
<result property="grp" column="grp" />
<result property="unt" column="unt" />
<result property="uprc" column="uprc" />
<result property="btpe" column="btpe" />
<result property="mtpe" column="mtpe" />
<result property="stpe" column="stpe" />
</resultMap>
<select id="selectMtdById" parameterType="Long" resultMap="MtdResultMap">
SELECT * FROM mtd WHERE id = #{id}
</select>
<sql id="selectMtdVo">
select Id, mid, des_mat, grp, unt, uprc, btpe, mtpe, stpe from mtd
</sql>
<select id="selectMtdList" parameterType="Mtd" resultMap="MtdResultMap">
SELECT * FROM mtd
<select id="selectMtdList" parameterType="Mtd" resultMap="MtdResult">
<include refid="selectMtdVo"/>
<where>
<if test="mid != null and mid != ''">AND mid = #{mid}</if>
<if test="desMat != null and desMat != ''">AND des_mat like concat('%', #{desMat}, '%')</if>
<if test="grp != null and grp != ''">AND grp = #{grp}</if>
<if test="unt != null and unt != ''">AND unt = #{unt}</if>
<if test="mid != null and mid != ''"> AND mid LIKE CONCAT('%', #{mid}, '%')</if>
<if test="desMat != null and desMat != ''"> AND des_mat LIKE CONCAT('%', #{desMat}, '%')</if>
<if test="grp != null and grp != ''"> AND grp LIKE CONCAT('%', #{grp}, '%')</if>
<if test="unt != null and unt != ''"> AND unt LIKE CONCAT('%', #{unt}, '%')</if>
<if test="uprc != null and uprc != ''"> AND uprc LIKE CONCAT('%', #{uprc}, '%')</if>
<if test="btpe != null and btpe != ''"> AND btpe LIKE CONCAT('%', #{btpe}, '%')</if>
<if test="mtpe != null and mtpe != ''"> AND mtpe LIKE CONCAT('%', #{mtpe}, '%')</if>
<if test="stpe != null and stpe != ''"> AND stpe LIKE CONCAT('%', #{stpe}, '%')</if>
</where>
</select>
<select id="selectMtdById" parameterType="Long" resultMap="MtdResult">
<include refid="selectMtdVo"/>
where Id = #{Id}
</select>
<select id="selectWlmsByWlbh" resultType="java.lang.String" parameterType="java.lang.String">
SELECT des_mat FROM mtd WHERE mid = #{materialCode}
SELECT des_mat
FROM mtd
WHERE mid = #{materialCode}
</select>
<insert id="insertMtd" parameterType="Mtd">
INSERT INTO mtd (mid, des_mat, grp, unt, uprc, btpe, mtpe, stpe)
VALUES (#{mid}, #{desMat}, #{grp}, #{unt}, #{uprc}, #{btpe}, #{mtpe}, #{stpe})
<insert id="insertMtd" parameterType="Mtd" useGeneratedKeys="true" keyProperty="Id">
insert into mtd
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="mid != null">mid,</if>
<if test="desMat != null">des_mat,</if>
<if test="grp != null">grp,</if>
<if test="unt != null">unt,</if>
<if test="uprc != null">uprc,</if>
<if test="btpe != null">btpe,</if>
<if test="mtpe != null">mtpe,</if>
<if test="stpe != null">stpe,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="mid != null">#{mid},</if>
<if test="desMat != null">#{desMat},</if>
<if test="grp != null">#{grp},</if>
<if test="unt != null">#{unt},</if>
<if test="uprc != null">#{uprc},</if>
<if test="btpe != null">#{btpe},</if>
<if test="mtpe != null">#{mtpe},</if>
<if test="stpe != null">#{stpe},</if>
</trim>
</insert>
<update id="updateMtd" parameterType="Mtd">
UPDATE mtd
SET mid = #{mid},
des_mat = #{desMat},
grp = #{grp},
unt = #{unt},
uprc = #{uprc},
btpe = #{btpe},
mtpe = #{mtpe},
stpe = #{stpe}
WHERE id = #{id}
update mtd
<trim prefix="SET" suffixOverrides=",">
<if test="mid != null">mid = #{mid},</if>
<if test="desMat != null">des_mat = #{desMat},</if>
<if test="grp != null">grp = #{grp},</if>
<if test="unt != null">unt = #{unt},</if>
<if test="uprc != null">uprc = #{uprc},</if>
<if test="btpe != null">btpe = #{btpe},</if>
<if test="mtpe != null">mtpe = #{mtpe},</if>
<if test="stpe != null">stpe = #{stpe},</if>
</trim>
where Id = #{Id}
</update>
<delete id="deleteMtdById" parameterType="Long">
DELETE FROM mtd WHERE id = #{id}
delete from mtd where Id = #{Id}
</delete>
<delete id="deleteMtdByIds" parameterType="Long">
DELETE FROM mtd WHERE id IN
<foreach collection="array" item="id" open="(" separator="," close=")">
#{id}
<delete id="deleteMtdByIds" parameterType="String">
delete from mtd where Id in
<foreach item="Id" collection="array" open="(" separator="," close=")">
#{Id}
</foreach>
</delete>
</mapper>
</mapper>

View File

@@ -37,13 +37,31 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectGysJhList" parameterType="GysJh" resultMap="GysJhResult">
<include refid="selectGysJhVo"/>
<where>
<if test="xmNo != null and xmNo != ''"> and xm_no like concat('%', #{xmNo}, '%')</if>
<if test="wlNo != null and wlNo != ''"> and wl_no like concat('%', #{wlNo}, '%')</if>
<if test="gysMc != null and gysMc != ''"> and gys_mc like concat('%', #{gysMc}, '%')</if>
<if test="sapNo != null and sapNo != ''"> and sap_no like concat('%', #{sapNo}, '%')</if>
<if test="status != null and status != ''"> and status = #{status}</if>
<if test="isDelete != null and isDelete != ''"> and is_delete = #{isDelete}</if>
<where>
<if test="xmNo != null and xmNo != ''">
and xm_no like concat('%', #{xmNo}, '%')
</if>
<if test="xmMs != null and xmMs != ''">
and xm_ms like concat('%', #{xmMs}, '%')
</if>
<if test="wlNo != null and wlNo != ''">
and wl_no like concat('%', #{wlNo}, '%')
</if>
<if test="wlMs != null and wlMs != ''">
and wl_ms like concat('%', #{wlMs}, '%')
</if>
<if test="gysMc != null and gysMc != ''">
and gys_mc like concat('%', #{gysMc}, '%')
</if>
<if test="sapNo != null and sapNo != ''">
and sap_no like concat('%', #{sapNo}, '%')
</if>
<if test="status != null and status != ''">
and status = #{status}
</if>
<if test="isDelete != null and isDelete != ''">
and is_delete = #{isDelete}
</if>
</where>
</select>

View File

@@ -74,7 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ri.ly_time,
ri.borrow_time, ri.return_time,
ri.xj, ri.xm_no, ri.xm_ms, ri.wl_no, ri.wl_ms,ri.xm_no_ck, ri.xm_ms_ck,
ri.gys_no, ri.gys_mc, ri.jh_amt, ri.ht_dj, ri.sap_no, ri.xh,
ri.gys_no, ri.gys_mc, ri.jh_amt, ri.ht_dj, ri.sap_no, ri.xh,ri.gys_jh_id,
ri.jh_qty, ri.ht_qty, ri.dw, ri.real_qty,
ri.pcode, ri.pcode_id, ri.tray_code, ri.entity_id,
ri.create_by, ri.create_time, ri.update_by, ri.update_time, ri.is_delete,
@@ -166,34 +166,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectRkInfoList" parameterType="RkInfo" resultMap="RkInfoResult">
<include refid="selectRkInfoVo"/>
<where>
<if test="isChuku != null and isChuku != ''">
and is_chuku = #{isChuku}
</if>
<choose>
<when test="isChukuList != null and isChukuList.size > 0">
AND ri.is_chuku IN
<foreach collection="isChukuList" item="val" open="(" separator="," close=")">
#{val}
</foreach>
</when>
<when test="isChuku != null and isChuku != ''">
AND ri.is_chuku = #{isChuku}
</when>
</choose>
<if test="keyword != null and keyword != ''">
and (
xm_no like concat('%', #{keyword}, '%')
or xm_ms like concat('%', #{keyword}, '%')
or wl_no like concat('%', #{keyword}, '%')
or wl_ms like concat('%', #{keyword}, '%')
or gys_no like concat('%', #{keyword}, '%')
or gys_mc like concat('%', #{keyword}, '%')
or sap_no like concat('%', #{keyword}, '%')
or bill_no like concat('%', #{keyword}, '%')
or bill_no_ck like concat('%', #{keyword}, '%')
or ck_type like concat('%', #{keyword}, '%')
or pcode like concat('%', #{keyword}, '%')
AND (
ri.xm_no like concat('%', #{keyword}, '%')
or ri.xm_ms like concat('%', #{keyword}, '%')
or ri.wl_no like concat('%', #{keyword}, '%')
or ri.wl_ms like concat('%', #{keyword}, '%')
or ri.gys_no like concat('%', #{keyword}, '%')
or ri.gys_mc like concat('%', #{keyword}, '%')
or ri.sap_no like concat('%', #{keyword}, '%')
or ri.bill_no like concat('%', #{keyword}, '%')
or ri.bill_no_ck like concat('%', #{keyword}, '%')
or ri.ck_type like concat('%', #{keyword}, '%')
or ri.pcode like concat('%', #{keyword}, '%')
)
</if>
<if test="rkType != null and rkType != ''">
and rk_type like concat('%', #{rkType}, '%')
AND ri.rk_type like concat('%', #{rkType}, '%')
</if>
<if test="wlType != null and wlType != ''">
and wl_type like concat('%', #{wlType}, '%')
AND ri.wl_type like concat('%', #{wlType}, '%')
</if>
<if test="cangku != null and cangku != ''">
and cangku like concat('%', #{cangku}, '%')
AND ri.cangku like concat('%', #{cangku}, '%')
</if>
<if test="ids != null and ids.size > 0">
@@ -204,100 +212,109 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if>
<if test="startTime != null">
<![CDATA[ and rk_time >= #{startTime} ]]>
<![CDATA[ AND ri.rk_time >= #{startTime} ]]>
</if>
<if test="endTime != null">
<![CDATA[ and rk_time <= #{endTime} ]]>
<![CDATA[ AND ri.rk_time <= #{endTime} ]]>
</if>
<if test="lyStartTime != null">
<![CDATA[ AND ri.ly_time >= #{lyStartTime} ]]>
</if>
<if test="lyEndTime != null">
<![CDATA[ AND ri.ly_time <= #{lyEndTime} ]]>
</if>
<if test="lihuoY != null and lihuoY != ''">
and lihuo_y like concat('%', #{lihuoY}, '%')
AND ri.lihuo_y like concat('%', #{lihuoY}, '%')
</if>
<if test="xj != null and xj != ''">
and xj like concat('%', #{xj}, '%')
AND ri.xj like concat('%', #{xj}, '%')
</if>
<if test="billNo != null and billNo != ''">
and bill_no like concat('%', #{billNo}, '%')
AND ri.bill_no like concat('%', #{billNo}, '%')
</if>
<if test="billNoCk != null and billNoCk != ''">
and bill_no_ck like concat('%', #{billNoCk}, '%')
AND ri.bill_no_ck like concat('%', #{billNoCk}, '%')
</if>
<if test="xmNo != null and xmNo != ''">
and xm_no like concat('%', #{xmNo}, '%')
AND ri.xm_no like concat('%', #{xmNo}, '%')
</if>
<if test="xmMs != null and xmMs != ''">
and xm_ms like concat('%', #{xmMs}, '%')
AND ri.xm_ms like concat('%', #{xmMs}, '%')
</if>
<if test="wlNo != null and wlNo != ''">
and wl_no like concat('%', #{wlNo}, '%')
AND ri.wl_no like concat('%', #{wlNo}, '%')
</if>
<if test="wlMs != null and wlMs != ''">
and wl_ms like concat('%', #{wlMs}, '%')
AND ri.wl_ms like concat('%', #{wlMs}, '%')
</if>
<if test="gysNo != null and gysNo != ''">
and gys_no like concat('%', #{gysNo}, '%')
AND ri.gys_no like concat('%', #{gysNo}, '%')
</if>
<if test="gysMc != null and gysMc != ''">
and gys_mc like concat('%', #{gysMc}, '%')
AND ri.gys_mc like concat('%', #{gysMc}, '%')
</if>
<if test="jhAmt != null">
and jh_amt = #{jhAmt}
AND ri.jh_amt = #{jhAmt}
</if>
<if test="htDj != null">
and ht_dj = #{htDj}
AND ri.ht_dj = #{htDj}
</if>
<if test="sapNo != null and sapNo != ''">
and sap_no like concat('%', #{sapNo}, '%')
AND ri.sap_no like concat('%', #{sapNo}, '%')
</if>
<if test="xh != null and xh != ''">
and xh like concat('%', #{xh}, '%')
AND ri.xh like concat('%', #{xh}, '%')
</if>
<if test="jhQty != null">
and jh_qty = #{jhQty}
AND ri.jh_qty = #{jhQty}
</if>
<if test="htQty != null">
and ht_qty = #{htQty}
AND ri.ht_qty = #{htQty}
</if>
<if test="dw != null and dw != ''">
and dw like concat('%', #{dw}, '%')
AND ri.dw like concat('%', #{dw}, '%')
</if>
<if test="realQty != null">
and real_qty = #{realQty}
AND ri.real_qty = #{realQty}
</if>
<if test="pcode != null and pcode != ''">
and pcode like concat('%', #{pcode}, '%')
AND ri.pcode like concat('%', #{pcode}, '%')
</if>
<if test="lyTime != null">
and ri.ly_time = #{lyTime}
AND ri.ly_time = #{lyTime}
</if>
<if test="returnTime != null">
and ri.return_time = #{returnTime}
AND ri.return_time = #{returnTime}
</if>
<if test="trayCode != null and trayCode != ''">
and tray_code like concat('%', #{trayCode}, '%')
AND ri.tray_code like concat('%', #{trayCode}, '%')
</if>
<if test="entityId != null and entityId != ''">
and entity_id like concat('%', #{entityId}, '%')
AND ri.entity_id like concat('%', #{entityId}, '%')
</if>
<if test="ckType != null and ckType != ''">
and ck_type like concat('%', #{ckType}, '%')
AND ri.ck_type like concat('%', #{ckType}, '%')
</if>
<if test="isDelete != null and isDelete != ''">
and ri.is_delete = #{isDelete}
</if>
<if test="isDelete == null or isDelete == ''">
and ri.is_delete = 0
</if>
<choose>
<when test="isDelete != null and isDelete != ''">
AND ri.is_delete = #{isDelete}
</when>
<otherwise>
AND ri.is_delete = 0
</otherwise>
</choose>
</where>
order by rk_time desc
ORDER BY ri.rk_time DESC
</select>
<select id="selectRkInfoById" parameterType="Long" resultMap="RkInfoResult">
<include refid="selectRkInfoVo"/>
where ri.id = #{id} and ri.is_delete = 0
@@ -470,6 +487,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND bill_no_ck = #{billNo}
</select>
<select id="selectRkInfoByIds" resultMap="RkInfoResult">
SELECT * FROM rk_info
WHERE is_delete = '0'
AND id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<update id="updateRkInfo" parameterType="RkInfo">
update rk_info
<trim prefix="SET" suffixOverrides=",">