feat(wms): 添加库存台账功能

- 新增库存台账相关的 BO 和 VO 类
- 在 InventoryService 中添加查询库存台账的方法
- 在 InventoryController 中添加库存台账的 API 接口
- 在 InventoryMapper 中添加查询各类库存变动记录的方法
- 在 XML 文件中添加对应的 SQL 查询语句
hwmom-htk
zangch@mesnac.com 5 months ago
parent f8dcc512f0
commit 743e72a533

@ -17,7 +17,9 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.wms.domain.WmsInventory;
import org.dromara.wms.domain.bo.WmsInventoryBo;
import org.dromara.wms.domain.bo.WmsInventoryLedgerBo;
import org.dromara.wms.domain.vo.WmsInventoryVo;
import org.dromara.wms.domain.vo.WmsInventoryLedgerVo;
import org.dromara.wms.service.IWmsInventoryService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -136,4 +138,24 @@ public class WmsInventoryController extends BaseController {
public R<List<WmsInventoryVo>> getMaterialInfoList(WmsInventoryBo bo) {
return R.ok(wmsInventoryService.getMaterialInfoList(bo));
}
/**
*
*/
@SaCheckPermission("system:inventory:list")
@GetMapping("/ledger/list")
public TableDataInfo<WmsInventoryLedgerVo> ledgerList(WmsInventoryLedgerBo bo, PageQuery pageQuery) {
return wmsInventoryService.queryInventoryLedgerPageList(bo, pageQuery);
}
/**
*
*/
@SaCheckPermission("system:inventory:export")
@Log(title = "库存台账", businessType = BusinessType.EXPORT)
@PostMapping("/ledger/export")
public void exportLedger(WmsInventoryLedgerBo bo, HttpServletResponse response) {
List<WmsInventoryLedgerVo> list = wmsInventoryService.queryInventoryLedgerList(bo);
ExcelUtil.exportExcel(list, "库存台账", WmsInventoryLedgerVo.class, response);
}
}

@ -0,0 +1,86 @@
package org.dromara.wms.domain.bo;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.mybatis.core.domain.BaseEntity;
import java.util.Date;
/**
* wms_inventory_ledger
*
* @author LionLi
* @date 2025-01-07
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class WmsInventoryLedgerBo extends BaseEntity {
/**
* ID
*/
private Long materialId;
/**
*
*/
private String materialCode;
/**
*
*/
private String materialName;
/**
*
*/
private String batchCode;
/**
* ID
*/
private Long warehouseId;
/**
*
*/
private String warehouseCode;
/**
*
*/
private String locationCode;
/**
* 1234退5
*/
private String changeType;
/**
*
*/
private String relatedCode;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd")
private Date startDate;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd")
private Date endDate;
/**
* ID
*/
private Long materialCategoryId;
/**
* 12
*/
private String periodType;
}

@ -0,0 +1,147 @@
package org.dromara.wms.domain.vo;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* wms_inventory_ledger
*
* @author LionLi
* @date 2025-01-07
*/
@Data
@ExcelIgnoreUnannotated
public class WmsInventoryLedgerVo implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long materialId;
/**
*
*/
@ExcelProperty(value = "物料编码")
private String materialCode;
/**
*
*/
@ExcelProperty(value = "物料名称")
private String materialName;
/**
*
*/
@ExcelProperty(value = "物料规格")
private String materialSpec;
/**
*
*/
@ExcelProperty(value = "物料单位")
private String materialUnit;
/**
*
*/
@ExcelProperty(value = "批次码")
private String batchCode;
/**
* ID
*/
@ExcelProperty(value = "仓库ID")
private Long warehouseId;
/**
*
*/
@ExcelProperty(value = "仓库编码")
private String warehouseCode;
/**
*
*/
@ExcelProperty(value = "仓库名称")
private String warehouseName;
/**
*
*/
@ExcelProperty(value = "库位编码")
private String locationCode;
/**
*
*/
@ExcelProperty(value = "变动日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date changeDate;
/**
* 1234退5
*/
@ExcelProperty(value = "变动类型")
private String changeType;
/**
*
*/
@ExcelProperty(value = "变动类型名称")
private String changeTypeName;
/**
*
*/
@ExcelProperty(value = "关联单号")
private String relatedCode;
/**
*
*/
@ExcelProperty(value = "变动数量")
private BigDecimal changeQty;
/**
*
*/
@ExcelProperty(value = "结存数量")
private BigDecimal balanceQty;
/**
* ID
*/
private Long materialCategoryId;
/**
*
*/
private String materialCategoryName;
/**
*
*/
private String operatorName;
/**
*
*/
@ExcelProperty(value = "备注")
private String remark;
/**
* ID
*/
private String tenantId;
}

@ -4,7 +4,9 @@ import org.apache.ibatis.annotations.Param;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.wms.domain.WmsInventory;
import org.dromara.wms.domain.bo.WmsInventoryBo;
import org.dromara.wms.domain.bo.WmsInventoryLedgerBo;
import org.dromara.wms.domain.vo.WmsInventoryVo;
import org.dromara.wms.domain.vo.WmsInventoryLedgerVo;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
@ -28,4 +30,29 @@ public interface WmsInventoryMapper extends BaseMapperPlus<WmsInventory, WmsInve
List<WmsInventoryVo> selectSemiInventoryListByLocation(@Param("locationCode") String locationCode);
// WmsInventoryVo outSelectInVentoryByBatch(WmsOutstockRecord outstockRecord);
/**
*
*/
List<WmsInventoryLedgerVo> selectInstockLedgerRecords(@Param("bo") WmsInventoryLedgerBo bo);
/**
*
*/
List<WmsInventoryLedgerVo> selectOutstockLedgerRecords(@Param("bo") WmsInventoryLedgerBo bo);
/**
*
*/
List<WmsInventoryLedgerVo> selectInventoryCheckLedgerRecords(@Param("bo") WmsInventoryLedgerBo bo);
/**
* 退
*/
List<WmsInventoryLedgerVo> selectReturnOrderLedgerRecords(@Param("bo") WmsInventoryLedgerBo bo);
/**
*
*/
List<WmsInventoryLedgerVo> selectTransferLedgerRecords(@Param("bo") WmsInventoryLedgerBo bo);
}

@ -4,8 +4,10 @@ import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.wms.domain.WmsInventory;
import org.dromara.wms.domain.bo.WmsInventoryBo;
import org.dromara.wms.domain.bo.WmsInventoryLedgerBo;
import org.dromara.wms.domain.bo.WmsMoveOrderBo;
import org.dromara.wms.domain.vo.WmsInventoryVo;
import org.dromara.wms.domain.vo.WmsInventoryLedgerVo;
import java.math.BigDecimal;
import java.util.ArrayList;
@ -99,4 +101,21 @@ public interface IWmsInventoryService {
* @return VO
*/
WmsInventoryVo queryByBatchAndLocation(String batchCode);
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
TableDataInfo<WmsInventoryLedgerVo> queryInventoryLedgerPageList(WmsInventoryLedgerBo bo, PageQuery pageQuery);
/**
*
*
* @param bo
* @return
*/
List<WmsInventoryLedgerVo> queryInventoryLedgerList(WmsInventoryLedgerBo bo);
}

@ -16,8 +16,10 @@ import org.dromara.wms.domain.BaseMaterialInfo;
import org.dromara.wms.domain.WmsBaseWarehouse;
import org.dromara.wms.domain.WmsInventory;
import org.dromara.wms.domain.bo.WmsInventoryBo;
import org.dromara.wms.domain.bo.WmsInventoryLedgerBo;
import org.dromara.wms.domain.bo.WmsMoveOrderBo;
import org.dromara.wms.domain.vo.WmsInventoryVo;
import org.dromara.wms.domain.vo.WmsInventoryLedgerVo;
import org.dromara.wms.mapper.WmsInventoryMapper;
import org.dromara.wms.service.IWmsInventoryService;
import org.springframework.stereotype.Service;
@ -280,5 +282,114 @@ public class WmsInventoryServiceImpl implements IWmsInventoryService {
return baseMapper.selectVoOne(lqw);
}
/**
*
*
* @param bo
* @param pageQuery
* @return
*/
@Override
public TableDataInfo<WmsInventoryLedgerVo> queryInventoryLedgerPageList(WmsInventoryLedgerBo bo, PageQuery pageQuery) {
List<WmsInventoryLedgerVo> ledgerList = queryInventoryLedgerList(bo);
// 手动分页处理
int total = ledgerList.size();
int pageNum = pageQuery.getPageNum();
int pageSize = pageQuery.getPageSize();
int fromIndex = (pageNum - 1) * pageSize;
int toIndex = Math.min(fromIndex + pageSize, total);
List<WmsInventoryLedgerVo> pageList = fromIndex < total ? ledgerList.subList(fromIndex, toIndex) : new ArrayList<>();
TableDataInfo<WmsInventoryLedgerVo> dataInfo = TableDataInfo.build(pageList);
dataInfo.setTotal(total);
return dataInfo;
}
/**
*
*
* @param bo
* @return
*/
@Override
public List<WmsInventoryLedgerVo> queryInventoryLedgerList(WmsInventoryLedgerBo bo) {
List<WmsInventoryLedgerVo> ledgerList = new ArrayList<>();
// 1. 查询入库记录
ledgerList.addAll(getInstockRecords(bo));
// 2. 查询出库记录
ledgerList.addAll(getOutstockRecords(bo));
// 3. 查询盘点调账记录
ledgerList.addAll(getInventoryCheckRecords(bo));
// 4. 查询退库记录
ledgerList.addAll(getReturnOrderRecords(bo));
// 5. 查询调拨记录
ledgerList.addAll(getTransferRecords(bo));
// 按时间排序
ledgerList.sort(Comparator.comparing(WmsInventoryLedgerVo::getChangeDate));
// 计算结存数量
calculateBalanceQty(ledgerList);
return ledgerList;
}
/**
*
*/
private List<WmsInventoryLedgerVo> getInstockRecords(WmsInventoryLedgerBo bo) {
return baseMapper.selectInstockLedgerRecords(bo);
}
/**
*
*/
private List<WmsInventoryLedgerVo> getOutstockRecords(WmsInventoryLedgerBo bo) {
return baseMapper.selectOutstockLedgerRecords(bo);
}
/**
*
*/
private List<WmsInventoryLedgerVo> getInventoryCheckRecords(WmsInventoryLedgerBo bo) {
return baseMapper.selectInventoryCheckLedgerRecords(bo);
}
/**
* 退
*/
private List<WmsInventoryLedgerVo> getReturnOrderRecords(WmsInventoryLedgerBo bo) {
return baseMapper.selectReturnOrderLedgerRecords(bo);
}
/**
*
*/
private List<WmsInventoryLedgerVo> getTransferRecords(WmsInventoryLedgerBo bo) {
return baseMapper.selectTransferLedgerRecords(bo);
}
/**
*
*/
private void calculateBalanceQty(List<WmsInventoryLedgerVo> ledgerList) {
Map<String, BigDecimal> balanceMap = new HashMap<>();
for (WmsInventoryLedgerVo record : ledgerList) {
String key = record.getMaterialId() + "_" + record.getBatchCode() + "_" + record.getLocationCode();
BigDecimal currentBalance = balanceMap.getOrDefault(key, BigDecimal.ZERO);
BigDecimal newBalance = currentBalance.add(record.getChangeQty());
balanceMap.put(key, newBalance);
record.setBalanceQty(newBalance);
}
}
}

@ -26,6 +26,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
MAX(b.min_stock_amount) min_stock_amount,
MAX(b.max_stock_amount) max_stock_amount,
MAX(c.warehouse_code) warehouse_code,
MAX(c.warehouse_name) warehouse_name,
MAX(b.material_code) material_code,
MAX(b.material_name) material_name,
MAX(x.lock_state) lock_state,
@ -103,4 +104,275 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where store_place_code= #{locationCode}
</select>
<!-- 库存台账查询 - 入库记录 -->
<select id="selectInstockLedgerRecords" resultType="org.dromara.wms.domain.vo.WmsInventoryLedgerVo">
SELECT
ir.material_id,
ir.batch_code,
ir.location_code,
ir.instock_qty as changeQty,
ir.instock_code as relatedCode,
ir.create_time as changeDate,
ir.create_by as operatorName,
'1' as changeType,
'入库' as changeTypeName,
bmi.material_code,
bmi.material_name,
bmi.material_spec,
bmi.material_unit,
wbw.warehouse_code,
wbw.warehouse_name,
wbw.warehouse_id,
bmc.material_category_name,
bmi.material_category_id
FROM wms_instock_record ir
LEFT JOIN base_material_info_copy1 bmi ON ir.material_id = bmi.material_id
LEFT JOIN wms_base_warehouse wbw ON ir.warehouse_id = wbw.warehouse_id
LEFT JOIN base_material_category bmc ON bmi.material_category_id = bmc.material_category_id
<where>
<if test="bo.materialCode != null and bo.materialCode != ''">
AND bmi.material_code LIKE CONCAT('%', #{bo.materialCode}, '%')
</if>
<if test="bo.materialName != null and bo.materialName != ''">
AND bmi.material_name LIKE CONCAT('%', #{bo.materialName}, '%')
</if>
<if test="bo.batchCode != null and bo.batchCode != ''">
AND ir.batch_code LIKE CONCAT('%', #{bo.batchCode}, '%')
</if>
<if test="bo.warehouseId != null">
AND ir.warehouse_id = #{bo.warehouseId}
</if>
<if test="bo.locationCode != null and bo.locationCode != ''">
AND ir.location_code LIKE CONCAT('%', #{bo.locationCode}, '%')
</if>
<if test="bo.materialCategoryId != null">
AND bmi.material_category_id = #{bo.materialCategoryId}
</if>
<if test="bo.startDate != null">
AND ir.create_time >= #{bo.startDate}
</if>
<if test="bo.endDate != null">
AND ir.create_time &lt;= #{bo.endDate}
</if>
<if test="bo.changeType != null and bo.changeType != ''">
AND '1' = #{bo.changeType}
</if>
</where>
ORDER BY ir.create_time ASC
</select>
<!-- 库存台账查询 - 出库记录 -->
<select id="selectOutstockLedgerRecords" resultType="org.dromara.wms.domain.vo.WmsInventoryLedgerVo">
SELECT
ors.material_id,
ors.batch_code,
ors.location_code,
-ors.outstock_qty as changeQty,
ors.outstock_code as relatedCode,
ors.create_time as changeDate,
ors.create_by as operatorName,
'2' as changeType,
'出库' as changeTypeName,
bmi.material_code,
bmi.material_name,
bmi.material_spec,
bmi.material_unit,
wbw.warehouse_code,
wbw.warehouse_name,
woo.warehouse_id,
bmc.material_category_name,
bmi.material_category_id
FROM wms_outstock_record ors
LEFT JOIN wms_outstock_order woo ON ors.outstock_id = woo.outstock_id
LEFT JOIN base_material_info_copy1 bmi ON ors.material_id = bmi.material_id
LEFT JOIN wms_base_warehouse wbw ON woo.warehouse_id = wbw.warehouse_id
LEFT JOIN base_material_category bmc ON bmi.material_category_id = bmc.material_category_id
<where>
<if test="bo.materialCode != null and bo.materialCode != ''">
AND bmi.material_code LIKE CONCAT('%', #{bo.materialCode}, '%')
</if>
<if test="bo.materialName != null and bo.materialName != ''">
AND bmi.material_name LIKE CONCAT('%', #{bo.materialName}, '%')
</if>
<if test="bo.batchCode != null and bo.batchCode != ''">
AND ors.batch_code LIKE CONCAT('%', #{bo.batchCode}, '%')
</if>
<if test="bo.warehouseId != null">
AND woo.warehouse_id = #{bo.warehouseId}
</if>
<if test="bo.locationCode != null and bo.locationCode != ''">
AND ors.location_code LIKE CONCAT('%', #{bo.locationCode}, '%')
</if>
<if test="bo.materialCategoryId != null">
AND bmi.material_category_id = #{bo.materialCategoryId}
</if>
<if test="bo.startDate != null">
AND ors.create_time >= #{bo.startDate}
</if>
<if test="bo.endDate != null">
AND ors.create_time &lt;= #{bo.endDate}
</if>
<if test="bo.changeType != null and bo.changeType != ''">
AND '2' = #{bo.changeType}
</if>
</where>
ORDER BY ors.create_time ASC
</select>
<!-- 库存台账查询 - 盘点调账记录 -->
<select id="selectInventoryCheckLedgerRecords" resultType="org.dromara.wms.domain.vo.WmsInventoryLedgerVo">
SELECT
icr.material_id,
icr.batch_code,
icr.location_code,
(icr.check_qty - icr.inventory_qty) as changeQty,
icr.check_code as relatedCode,
icr.create_time as changeDate,
icr.create_by as operatorName,
'5' as changeType,
'盘点调账' as changeTypeName,
icr.material_code,
icr.material_name,
bmi.material_spec,
bmi.material_unit,
'' as warehouse_code,
'' as warehouse_name,
NULL as warehouse_id
FROM wms_inventory_check_record icr
LEFT JOIN base_material_info_copy1 bmi ON icr.material_id = bmi.material_id
<where>
AND icr.is_adjust = '1'
<if test="bo.materialCode != null and bo.materialCode != ''">
AND icr.material_code LIKE CONCAT('%', #{bo.materialCode}, '%')
</if>
<if test="bo.materialName != null and bo.materialName != ''">
AND icr.material_name LIKE CONCAT('%', #{bo.materialName}, '%')
</if>
<if test="bo.batchCode != null and bo.batchCode != ''">
AND icr.batch_code LIKE CONCAT('%', #{bo.batchCode}, '%')
</if>
<if test="bo.locationCode != null and bo.locationCode != ''">
AND icr.location_code LIKE CONCAT('%', #{bo.locationCode}, '%')
</if>
<if test="bo.materialCategoryId != null">
AND icr.material_category_id = #{bo.materialCategoryId}
</if>
<if test="bo.startDate != null">
AND icr.create_time >= #{bo.startDate}
</if>
<if test="bo.endDate != null">
AND icr.create_time &lt;= #{bo.endDate}
</if>
<if test="bo.changeType != null and bo.changeType != ''">
AND '5' = #{bo.changeType}
</if>
</where>
ORDER BY icr.create_time ASC
</select>
<!-- 库存台账查询 - 退库记录 -->
<select id="selectReturnOrderLedgerRecords" resultType="org.dromara.wms.domain.vo.WmsInventoryLedgerVo">
SELECT
ro.material_id,
ro.batch_code,
ro.return_location_code as location_code,
-ro.return_amount as changeQty,
CONCAT('RO', ro.ro_id) as relatedCode,
ro.create_time as changeDate,
ro.create_by as operatorName,
'4' as changeType,
'退库' as changeTypeName,
bmi.material_code,
bmi.material_name,
bmi.material_spec,
bmi.material_unit,
wbw.warehouse_code,
wbw.warehouse_name,
ro.warehouse_id,
bmc.material_category_name,
bmi.material_category_id
FROM wms_return_order ro
LEFT JOIN base_material_info_copy1 bmi ON ro.material_id = bmi.material_id
LEFT JOIN wms_base_warehouse wbw ON ro.warehouse_id = wbw.warehouse_id
LEFT JOIN base_material_category bmc ON bmi.material_category_id = bmc.material_category_id
<where>
AND ro.order_status = '2'
<if test="bo.materialCode != null and bo.materialCode != ''">
AND bmi.material_code LIKE CONCAT('%', #{bo.materialCode}, '%')
</if>
<if test="bo.materialName != null and bo.materialName != ''">
AND bmi.material_name LIKE CONCAT('%', #{bo.materialName}, '%')
</if>
<if test="bo.batchCode != null and bo.batchCode != ''">
AND ro.batch_code LIKE CONCAT('%', #{bo.batchCode}, '%')
</if>
<if test="bo.warehouseId != null">
AND ro.warehouse_id = #{bo.warehouseId}
</if>
<if test="bo.materialCategoryId != null">
AND bmi.material_category_id = #{bo.materialCategoryId}
</if>
<if test="bo.startDate != null">
AND ro.create_time >= #{bo.startDate}
</if>
<if test="bo.endDate != null">
AND ro.create_time &lt;= #{bo.endDate}
</if>
<if test="bo.changeType != null and bo.changeType != ''">
AND '4' = #{bo.changeType}
</if>
</where>
ORDER BY ro.create_time ASC
</select>
<!-- 库存台账查询 - 调拨记录 -->
<select id="selectTransferLedgerRecords" resultType="org.dromara.wms.domain.vo.WmsInventoryLedgerVo">
SELECT
ht.material_id,
ht.card_no as batch_code,
ht.store_place_code as location_code,
0 as changeQty,
CONCAT('TF', ht.transfer_id) as relatedCode,
ht.create_time as changeDate,
ht.create_by as operatorName,
'3' as changeType,
'调拨' as changeTypeName,
bmi.material_code,
bmi.material_name,
bmi.material_spec,
bmi.material_unit,
'' as warehouse_code,
'' as warehouse_name,
NULL as warehouse_id
FROM wms_hpp_transfer ht
LEFT JOIN base_material_info_copy1 bmi ON ht.material_id = bmi.material_id
<where>
<if test="bo.materialCode != null and bo.materialCode != ''">
AND bmi.material_code LIKE CONCAT('%', #{bo.materialCode}, '%')
</if>
<if test="bo.materialName != null and bo.materialName != ''">
AND bmi.material_name LIKE CONCAT('%', #{bo.materialName}, '%')
</if>
<if test="bo.batchCode != null and bo.batchCode != ''">
AND ht.card_no LIKE CONCAT('%', #{bo.batchCode}, '%')
</if>
<if test="bo.locationCode != null and bo.locationCode != ''">
AND ht.store_place_code LIKE CONCAT('%', #{bo.locationCode}, '%')
</if>
<if test="bo.materialCategoryId != null">
AND bmi.material_category_id = #{bo.materialCategoryId}
</if>
<if test="bo.startDate != null">
AND ht.create_time >= #{bo.startDate}
</if>
<if test="bo.endDate != null">
AND ht.create_time &lt;= #{bo.endDate}
</if>
<if test="bo.changeType != null and bo.changeType != ''">
AND '3' = #{bo.changeType}
</if>
</where>
ORDER BY ht.create_time ASC
</select>
</mapper>

Loading…
Cancel
Save