# Conflicts:
#	pom.xml
#	yudao-gateway/src/main/resources/application.yaml
master
YunaiV 2026-05-16 17:52:38 +08:00
commit 3314376e59
188 changed files with 15208 additions and 9 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -31,8 +31,8 @@
| 【完整版】[yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [`master`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master-jdk17/) 分支 |
| 【精简版】[yudao-cloud-mini](https://gitee.com/yudaocode/yudao-cloud-mini) | [`master`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master-jdk17/) 分支 |
* 【完整版】包括系统功能、基础设施、会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP、MES、AI 大模型、IoT 物联网 等功能
* 【精简版】只包括系统功能、基础设施功能不包括会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP、MES、AI 大模型、IoT 物联网 等功能
* 【完整版】包括系统功能、基础设施、会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP、WMS、MES、AI 大模型、IoT 物联网 等功能
* 【精简版】只包括系统功能、基础设施功能不包括会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP、WMS、MES、AI 大模型、IoT 物联网 等功能
可参考 [《迁移文档》](https://cloud.iocoder.cn/migrate-module/) ,只需要 5-10 分钟,即可将【完整版】按需迁移到【精简版】
@ -115,7 +115,7 @@
* 通用模块(必选):系统功能、基础设施
* 通用模块(可选):工作流程、支付系统、数据报表、会员中心
* 业务系统(按需):ERP 系统、CRM 系统、MES 系统、商城系统、微信公众号、AI 大模型、IoT 物联网
* 业务系统(按需):Mall 电子商城、OA 办公自动化、ERP 企业资源计划系统、WMS 仓库管理系统、CRM 客户关系管理、CMS 内容管理系统、MES 执行制造系统、AI 大模型平台、IoT 物联网系统、IM 即时通讯系统、Mobile 手机移动端、Report 数据大屏
> 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。
>
@ -273,6 +273,14 @@
![功能图](/.image/common/erp-feature.png)
### WMS 系统
演示地址:<https://cloud.iocoder.cn/wms-preview/>
![功能图](/.image/common/wms-feature.png)
![功能图](/.image/common/wms-preview.png)
### CRM 系统
演示地址:<https://cloud.iocoder.cn/crm-preview/>
@ -321,6 +329,7 @@
| `yudao-module-erp` | ERP 系统的 Module 模块 |
| `yudao-module-crm` | CRM 系统的 Module 模块 |
| `yudao-module-mes` | MES 系统的 Module 模块 |
| `yudao-module-wms` | WMS 系统的 Module 模块 |
| `yudao-module-ai` | AI 大模型的 Module 模块 |
| `yudao-module-iot` | IoT 物联网的 Module 模块 |
| `yudao-module-mp` | 微信公众号的 Module 模块 |

View File

@ -26,6 +26,7 @@
<module>yudao-module-crm</module>
<module>yudao-module-iot</module>
<module>yudao-module-mes</module>
<module>yudao-module-wms</module>
<!-- 友情提示:基于 Spring AI 实现 LLM 大模型的接入,需要使用 JDK17 版本,详细可见 https://doc.iocoder.cn/ai/build/ -->
<!-- <module>yudao-module-ai</module>-->
</modules>

View File

@ -37,8 +37,14 @@ public class BannerApplicationRunner implements ApplicationRunner {
System.out.println("[商城系统 yudao-module-mall 教程][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
// ERP 系统
System.out.println("[ERP 系统 yudao-module-erp - 教程][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
// WMS 仓库管理系统
System.out.println("[WMS 仓库管理系统 yudao-module-wms - 教程][参考 https://cloud.iocoder.cn/wms/build/ 开启]");
// CRM 系统
System.out.println("[CRM 系统 yudao-module-crm - 教程][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
// MES 系统
System.out.println("[MES 系统 yudao-module-mes - 教程][参考 https://cloud.iocoder.cn/mes/build/ 开启]");
// IM 即时通讯
System.out.println("[IM 即时通讯 yudao-module-im - 教程][参考 https://cloud.iocoder.cn/im/build/ 开启]");
// 微信公众号
System.out.println("[微信公众号 yudao-module-mp 教程][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
// 支付平台

View File

@ -410,25 +410,43 @@ public class GlobalExceptionHandler {
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
}
// 6. CRM 系统
// 6. WMS 仓库管理系统
if (message.contains("wms_")) {
log.error("[WMS 仓库管理系统 yudao-module-wms - 表结构未导入][参考 https://cloud.iocoder.cn/wms/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[WMS 仓库管理系统 yudao-module-wms - 表结构未导入][参考 https://cloud.iocoder.cn/wms/build/ 开启]");
}
// 7. CRM 系统
if (message.contains("crm_")) {
log.error("[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[CRM 系统 yudao-module-crm - 表结构未导入][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
}
// 7. 支付平台
// 8. MES 系统
if (message.contains("mes_")) {
log.error("[MES 系统 yudao-module-mes - 表结构未导入][参考 https://cloud.iocoder.cn/mes/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[MES 系统 yudao-module-mes - 表结构未导入][参考 https://cloud.iocoder.cn/mes/build/ 开启]");
}
// 9. IM 即时通讯
if (message.contains("im_")) {
log.error("[IM 即时通讯 yudao-module-im - 表结构未导入][参考 https://cloud.iocoder.cn/im/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[IM 即时通讯 yudao-module-im - 表结构未导入][参考 https://cloud.iocoder.cn/im/build/ 开启]");
}
// 10. 支付平台
if (message.contains("pay_")) {
log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[支付模块 yudao-module-pay - 表结构未导入][参考 https://cloud.iocoder.cn/pay/build/ 开启]");
}
// 8. AI 大模型
// 11. AI 大模型
if (message.contains("ai_")) {
log.error("[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),
"[AI 大模型 yudao-module-ai - 表结构未导入][参考 https://cloud.iocoder.cn/ai/build/ 开启]");
}
// 9. IoT 物联网
// 12. IoT 物联网
if (message.contains("iot_")) {
log.error("[IoT 物联网 yudao-module-iot - 表结构未导入][参考 https://doc.iocoder.cn/iot/build/ 开启]");
return CommonResult.error(NOT_IMPLEMENTED.getCode(),

View File

@ -39,8 +39,14 @@ public class BannerApplicationRunner implements ApplicationRunner {
System.out.println("[商城系统 yudao-module-mall 教程][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
// ERP 系统
System.out.println("[ERP 系统 yudao-module-erp - 教程][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
// WMS 仓库管理系统
System.out.println("[WMS 仓库管理系统 yudao-module-wms - 教程][参考 https://cloud.iocoder.cn/wms/build/ 开启]");
// CRM 系统
System.out.println("[CRM 系统 yudao-module-crm - 教程][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
// MES 系统
System.out.println("[MES 系统 yudao-module-mes - 教程][参考 https://cloud.iocoder.cn/mes/build/ 开启]");
// IM 即时通讯
System.out.println("[IM 即时通讯 yudao-module-im - 教程][参考 https://cloud.iocoder.cn/im/build/ 开启]");
// 微信公众号
System.out.println("[微信公众号 yudao-module-mp 教程][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
// 支付平台

24
yudao-module-wms/pom.xml Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao</artifactId>
<version>${revision}</version>
</parent>
<modules>
<module>yudao-module-wms-api</module>
<module>yudao-module-wms-server</module>
</modules>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-wms</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<description>
wms 模块下仓库管理系统Warehouse Management System
例如说:仓库、物料、库存、入库、出库、移库、盘库等等
</description>
</project>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-wms</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-wms-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
wms 模块 API暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
<!-- 参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.wms.enums;
import cn.iocoder.yudao.framework.common.enums.RpcConstants;
/**
* API
*
* @author
*/
public class ApiConstants {
/**
*
*
* spring.application.name
*/
public static final String NAME = "wms-server";
public static final String PREFIX = RpcConstants.RPC_API_PREFIX + "/wms";
public static final String VERSION = "1.0.0";
}

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.wms.enums;
/**
* WMS
*
* @author
*/
public interface DictTypeConstants {
String MERCHANT_TYPE = "merchant_type";
String ORDER_STATUS = "wms_order_status";
String ORDER_TYPE = "wms_order_type";
String RECEIPT_ORDER_TYPE = "wms_receipt_order_type";
String SHIPMENT_ORDER_TYPE = "wms_shipment_order_type";
}

View File

@ -0,0 +1,91 @@
package cn.iocoder.yudao.module.wms.enums;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
/**
* WMS
* <p>
* wms 使 1-060-000-000
*/
public interface ErrorCodeConstants {
// ========== WMS 基础数据-仓库 1-060-100-000 ==========
ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_060_100_000, "仓库不存在");
ErrorCode WAREHOUSE_NAME_DUPLICATE = new ErrorCode(1_060_100_001, "仓库名称重复");
ErrorCode WAREHOUSE_CODE_DUPLICATE = new ErrorCode(1_060_100_002, "仓库编号重复");
ErrorCode WAREHOUSE_HAS_ORDER = new ErrorCode(1_060_100_004, "删除失败!仓库已被{}使用!");
ErrorCode WAREHOUSE_HAS_INVENTORY = new ErrorCode(1_060_100_005, "删除失败!仓库已存在库存余额!");
// ========== WMS 基础数据-商品分类 1-060-102-000 ==========
ErrorCode ITEM_CATEGORY_NOT_EXISTS = new ErrorCode(1_060_102_000, "商品分类不存在");
ErrorCode ITEM_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_060_102_001, "商品分类名称重复");
ErrorCode ITEM_CATEGORY_PARENT_NOT_EXISTS = new ErrorCode(1_060_102_002, "父商品分类不存在");
ErrorCode ITEM_CATEGORY_PARENT_ERROR = new ErrorCode(1_060_102_003, "不能设置自己为父商品分类");
ErrorCode ITEM_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_060_102_004, "不能设置自己的子商品分类为父商品分类");
ErrorCode ITEM_CATEGORY_HAS_CHILDREN = new ErrorCode(1_060_102_005, "删除失败!请先删除该分类下的子分类!");
ErrorCode ITEM_CATEGORY_HAS_ITEM = new ErrorCode(1_060_102_006, "删除失败!分类已被商品使用!");
ErrorCode ITEM_CATEGORY_CODE_DUPLICATE = new ErrorCode(1_060_102_007, "商品分类编号重复");
// ========== WMS 基础数据-商品品牌 1-060-103-000 ==========
ErrorCode ITEM_BRAND_NOT_EXISTS = new ErrorCode(1_060_103_000, "商品品牌不存在");
ErrorCode ITEM_BRAND_HAS_ITEM = new ErrorCode(1_060_103_001, "删除失败!品牌已被商品使用!");
ErrorCode ITEM_BRAND_CODE_DUPLICATE = new ErrorCode(1_060_103_002, "商品品牌编号重复");
ErrorCode ITEM_BRAND_NAME_DUPLICATE = new ErrorCode(1_060_103_003, "商品品牌名称重复");
// ========== WMS 基础数据-商品 1-060-104-000 ==========
ErrorCode ITEM_NOT_EXISTS = new ErrorCode(1_060_104_000, "商品不存在");
ErrorCode ITEM_NAME_DUPLICATE = new ErrorCode(1_060_104_001, "商品名称重复");
ErrorCode ITEM_CODE_DUPLICATE = new ErrorCode(1_060_104_007, "商品编号重复");
ErrorCode ITEM_SKU_REQUIRED = new ErrorCode(1_060_104_002, "至少包含一个商品规格");
ErrorCode ITEM_SKU_NAME_DUPLICATE = new ErrorCode(1_060_104_003, "商品规格名称【{}】重复");
ErrorCode ITEM_SKU_NOT_EXISTS = new ErrorCode(1_060_104_004, "商品规格不存在");
ErrorCode ITEM_SKU_HAS_INVENTORY = new ErrorCode(1_060_104_005, "删除失败!商品规格【{}】已被库存业务使用!");
ErrorCode ITEM_SKU_HAS_ORDER = new ErrorCode(1_060_104_006, "删除失败!商品规格【{}】已被{}使用!");
// ========== WMS 基础数据-往来企业 1-060-105-000 ==========
ErrorCode MERCHANT_NOT_EXISTS = new ErrorCode(1_060_105_000, "往来企业不存在");
ErrorCode MERCHANT_NOT_SUPPLIER = new ErrorCode(1_060_105_001, "往来企业必须是供应商或客户/供应商类型");
ErrorCode MERCHANT_NOT_CUSTOMER = new ErrorCode(1_060_105_002, "往来企业必须是客户或客户/供应商类型");
ErrorCode MERCHANT_HAS_ORDER = new ErrorCode(1_060_105_003, "删除失败!往来企业已被{}使用!");
ErrorCode MERCHANT_CODE_DUPLICATE = new ErrorCode(1_060_105_004, "往来企业编号重复");
ErrorCode MERCHANT_NAME_DUPLICATE = new ErrorCode(1_060_105_005, "往来企业名称重复");
// ========== WMS 入库单 1-060-200-000 ==========
ErrorCode RECEIPT_ORDER_NOT_EXISTS = new ErrorCode(1_060_200_000, "入库单不存在");
ErrorCode RECEIPT_ORDER_NO_DUPLICATE = new ErrorCode(1_060_200_001, "入库单号重复");
ErrorCode RECEIPT_ORDER_STATUS_NOT_PREPARE = new ErrorCode(1_060_200_002, "入库单状态不是草稿,不能操作");
ErrorCode RECEIPT_ORDER_DETAIL_REQUIRED = new ErrorCode(1_060_200_003, "入库单至少包含一条明细");
ErrorCode RECEIPT_ORDER_STATUS_NOT_DELETABLE = new ErrorCode(1_060_200_005, "入库单状态不是草稿或已作废,不能删除");
ErrorCode RECEIPT_ORDER_DETAIL_NOT_EXISTS = new ErrorCode(1_060_200_007, "入库单明细不存在");
// ========== WMS 出库单 1-060-201-000 ==========
ErrorCode SHIPMENT_ORDER_NOT_EXISTS = new ErrorCode(1_060_201_000, "出库单不存在");
ErrorCode SHIPMENT_ORDER_NO_DUPLICATE = new ErrorCode(1_060_201_001, "出库单号重复");
ErrorCode SHIPMENT_ORDER_STATUS_NOT_PREPARE = new ErrorCode(1_060_201_002, "出库单状态不是草稿,不能操作");
ErrorCode SHIPMENT_ORDER_DETAIL_REQUIRED = new ErrorCode(1_060_201_003, "出库单至少包含一条明细");
ErrorCode SHIPMENT_ORDER_STATUS_NOT_DELETABLE = new ErrorCode(1_060_201_005, "出库单状态不是草稿或已作废,不能删除");
ErrorCode SHIPMENT_ORDER_DETAIL_NOT_EXISTS = new ErrorCode(1_060_201_007, "出库单明细不存在");
// ========== WMS 移库单 1-060-202-000 ==========
ErrorCode MOVEMENT_ORDER_NOT_EXISTS = new ErrorCode(1_060_202_000, "移库单不存在");
ErrorCode MOVEMENT_ORDER_NO_DUPLICATE = new ErrorCode(1_060_202_001, "移库单号重复");
ErrorCode MOVEMENT_ORDER_STATUS_NOT_PREPARE = new ErrorCode(1_060_202_002, "移库单状态不是草稿,不能操作");
ErrorCode MOVEMENT_ORDER_DETAIL_REQUIRED = new ErrorCode(1_060_202_003, "移库单至少包含一条明细");
ErrorCode MOVEMENT_ORDER_STATUS_NOT_DELETABLE = new ErrorCode(1_060_202_005, "移库单状态不是草稿或已作废,不能删除");
ErrorCode MOVEMENT_ORDER_DETAIL_NOT_EXISTS = new ErrorCode(1_060_202_006, "移库单明细不存在");
ErrorCode MOVEMENT_ORDER_WAREHOUSE_SAME = new ErrorCode(1_060_202_007, "来源仓库和目标仓库不能相同");
// ========== WMS 盘库单 1-060-203-000 ==========
ErrorCode CHECK_ORDER_NOT_EXISTS = new ErrorCode(1_060_203_000, "盘库单不存在");
ErrorCode CHECK_ORDER_NO_DUPLICATE = new ErrorCode(1_060_203_001, "盘库单号重复");
ErrorCode CHECK_ORDER_STATUS_NOT_PREPARE = new ErrorCode(1_060_203_002, "盘库单状态不是草稿,不能操作");
ErrorCode CHECK_ORDER_DETAIL_REQUIRED = new ErrorCode(1_060_203_003, "盘库单至少包含一条明细");
ErrorCode CHECK_ORDER_STATUS_NOT_DELETABLE = new ErrorCode(1_060_203_005, "盘库单状态不是草稿或已作废,不能删除");
ErrorCode CHECK_ORDER_DETAIL_NOT_EXISTS = new ErrorCode(1_060_203_006, "盘库单明细不存在");
ErrorCode CHECK_ORDER_INVENTORY_CHANGED = new ErrorCode(1_060_203_007, "盘库单库存已变化,请重新加载库存后再完成");
// ========== WMS 库存 1-060-300-000 ==========
ErrorCode INVENTORY_QUANTITY_NOT_ENOUGH = new ErrorCode(1_060_300_000,
"库存不足,商品:{},商品规格:{},仓库:{},当前库存:{},变更数量:{}");
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.wms.enums.md;
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* WMS
*
* @author
*/
@Getter
@AllArgsConstructor
public enum WmsMerchantTypeEnum implements ArrayValuable<Integer> {
CUSTOMER(1, "客户"),
SUPPLIER(2, "供应商"),
CUSTOMER_SUPPLIER(3, "客户/供应商");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(WmsMerchantTypeEnum::getType).toArray(Integer[]::new);
/**
*
*/
private final Integer type;
/**
*
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.wms.enums.order;
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* WMS
*
* @author
*/
@Getter
@AllArgsConstructor
public enum WmsOrderStatusEnum implements ArrayValuable<Integer> {
PREPARE(0, "草稿"),
FINISHED(4, "已完成"),
CANCELED(5, "已作废");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(WmsOrderStatusEnum::getStatus)
.toArray(Integer[]::new);
/**
*
*/
private final Integer status;
/**
*
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.wms.enums.order;
/**
* WMS
*
*
*
*
* @author
*/
public final class WmsOrderTypeConstants {
private WmsOrderTypeConstants() {}
// ========== 入库单类型 [100, 200) ==========
public static final int RECEIPT_PRODUCTION = 100; // 生产入库WmsReceiptOrderDO
public static final int RECEIPT_PURCHASE = 101; // 采购入库WmsReceiptOrderDO
public static final int RECEIPT_RETURN = 102; // 退货入库WmsReceiptOrderDO
public static final int RECEIPT_GIVE_BACK = 103; // 归还入库WmsReceiptOrderDO
// ========== 出库单类型 [200, 300) ==========
public static final int SHIPMENT_RETURN = 200; // 退货出库WmsShipmentOrderDO
public static final int SHIPMENT_SALE = 201; // 销售出库WmsShipmentOrderDO
public static final int SHIPMENT_PRODUCTION = 202; // 生产出库WmsShipmentOrderDO
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.wms.enums.order;
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* WMS
*
* @author
*/
@Getter
@AllArgsConstructor
public enum WmsOrderTypeEnum implements ArrayValuable<Integer> {
RECEIPT(1, "入库单"),
SHIPMENT(2, "出库单"),
MOVEMENT(3, "移库单"),
CHECK(4, "盘库单");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(WmsOrderTypeEnum::getType).toArray(Integer[]::new);
/**
*
*/
private final Integer type;
/**
*
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.wms.enums.order;
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* WMS
*
* @author
*/
@Getter
@AllArgsConstructor
public enum WmsReceiptOrderTypeEnum implements ArrayValuable<Integer> {
PRODUCTION(WmsOrderTypeConstants.RECEIPT_PRODUCTION, "生产入库"),
PURCHASE(WmsOrderTypeConstants.RECEIPT_PURCHASE, "采购入库"),
RETURN(WmsOrderTypeConstants.RECEIPT_RETURN, "退货入库"),
GIVE_BACK(WmsOrderTypeConstants.RECEIPT_GIVE_BACK, "归还入库");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(WmsReceiptOrderTypeEnum::getType).toArray(Integer[]::new);
/**
*
*/
private final Integer type;
/**
*
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.wms.enums.order;
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* WMS
*
* @author
*/
@Getter
@AllArgsConstructor
public enum WmsShipmentOrderTypeEnum implements ArrayValuable<Integer> {
RETURN(WmsOrderTypeConstants.SHIPMENT_RETURN, "退货出库"),
SALE(WmsOrderTypeConstants.SHIPMENT_SALE, "销售出库"),
PRODUCTION(WmsOrderTypeConstants.SHIPMENT_PRODUCTION, "生产出库");
public static final Integer[] ARRAYS = Arrays.stream(values()).map(WmsShipmentOrderTypeEnum::getType).toArray(Integer[]::new);
/**
*
*/
private final Integer type;
/**
*
*/
private final String name;
@Override
public Integer[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,19 @@
## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
## 感谢复旦核博士的建议!灰子哥,牛皮!
FROM eclipse-temurin:21-jre
## 创建目录,并使用它作为工作目录
RUN mkdir -p /yudao-module-wms-server
WORKDIR /yudao-module-wms-server
## 将后端项目的 Jar 文件,复制到镜像中
COPY ./target/yudao-module-wms-server.jar app.jar
## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m"
## 暴露后端项目的 48092 端口
EXPOSE 48092
## 启动后端项目
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

View File

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-wms</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-wms-server</artifactId>
<name>${project.artifactId}</name>
<description>
wms 模块下仓库管理系统Warehouse Management System
例如说:仓库、物料、库存、入库、出库、移库、盘库等等
</description>
<dependencies>
<!-- Spring Cloud 基础 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-env</artifactId>
</dependency>
<!-- 依赖服务 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-module-wms-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-redis</artifactId>
</dependency>
<!-- RPC 远程调用相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-rpc</artifactId>
</dependency>
<!-- Registry 注册中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Config 配置中心相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 工具类相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
<!-- 监控相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-monitor</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<!-- 设置构建的 jar 包名 -->
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 打包 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.wms;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*
* <p>
* https://cloud.iocoder.cn/quick-start/ 文章
* https://cloud.iocoder.cn/quick-start/ 文章
* https://cloud.iocoder.cn/quick-start/ 文章
*
* @author
*/
@SpringBootApplication
public class WmsServerApplication {
public static void main(String[] args) {
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
SpringApplication.run(WmsServerApplication.class, args);
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
// 如果你碰到启动的问题,请认真阅读 https://cloud.iocoder.cn/quick-start/ 文章
}
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.yudao.module.wms.controller.admin.home;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeInventorySummaryRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderSummaryRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.home.vo.WmsHomeOrderTrendRespVO;
import cn.iocoder.yudao.module.wms.service.home.WmsHomeStatisticsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - WMS 首页统计")
@RestController
@RequestMapping("/wms/home-statistics")
@Validated
public class WmsHomeStatisticsController {
@Resource
private WmsHomeStatisticsService homeStatisticsService;
@GetMapping("/order-summary")
@Operation(summary = "获得首页单据汇总统计")
@Parameter(name = "warehouseId", description = "仓库编号", example = "1024")
@PreAuthorize("@ss.hasPermission('wms:home:query')")
public CommonResult<List<WmsHomeOrderSummaryRespVO>> getOrderSummary(
@RequestParam(value = "warehouseId", required = false) Long warehouseId) {
return success(homeStatisticsService.getOrderSummary(warehouseId));
}
@GetMapping("/order-trend")
@Operation(summary = "获得首页单据趋势")
@Parameter(name = "days", description = "天数", example = "7")
@PreAuthorize("@ss.hasPermission('wms:home:query')")
public CommonResult<List<WmsHomeOrderTrendRespVO>> getOrderTrend(
@RequestParam(value = "days", defaultValue = "7") @Min(1) @Max(90) Integer days,
@RequestParam(value = "warehouseId", required = false) Long warehouseId) {
return success(homeStatisticsService.getOrderTrend(days, warehouseId));
}
@GetMapping("/inventory-summary")
@Operation(summary = "获得首页库存汇总统计")
@Parameter(name = "warehouseId", description = "仓库编号", example = "1024")
@PreAuthorize("@ss.hasPermission('wms:home:query')")
public CommonResult<WmsHomeInventorySummaryRespVO> getInventorySummary(
@RequestParam(value = "warehouseId", required = false) Long warehouseId,
@RequestParam(value = "goodsLimit", defaultValue = "5") @Min(1) @Max(20) Integer goodsLimit,
@RequestParam(value = "warehouseLimit", defaultValue = "8") @Min(1) @Max(20) Integer warehouseLimit) {
return success(homeStatisticsService.getInventorySummary(warehouseId, goodsLimit, warehouseLimit));
}
}

View File

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.wms.controller.admin.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Schema(description = "管理后台 - WMS 首页库存汇总统计 Response VO")
@Data
public class WmsHomeInventorySummaryRespVO {
@Schema(description = "总库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000.00")
private BigDecimal totalQuantity;
@Schema(description = "商品库存占比列表")
private List<ItemRank> goodsShareList;
@Schema(description = "仓库库存分布列表")
private List<WarehouseRank> warehouseDistributionList;
@Schema(description = "管理后台 - WMS 首页商品库存排行 Response VO")
@Data
public static class ItemRank {
@Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "A4 复印纸")
private String name;
@Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal quantity;
}
@Schema(description = "管理后台 - WMS 首页仓库库存排行 Response VO")
@Data
public static class WarehouseRank {
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "上海仓")
private String name;
@Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal quantity;
}
}

View File

@ -0,0 +1,16 @@
package cn.iocoder.yudao.module.wms.controller.admin.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - WMS 首页单据状态统计 Response VO")
@Data
public class WmsHomeOrderStatusRespVO {
@Schema(description = "状态值", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer status;
@Schema(description = "单据数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12")
private Long count;
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.wms.controller.admin.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - WMS 首页单据汇总统计 Response VO")
@Data
public class WmsHomeOrderSummaryRespVO {
@Schema(description = "单据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer type;
@Schema(description = "单据总数", requiredMode = Schema.RequiredMode.REQUIRED, example = "12")
private Long total;
@Schema(description = "状态分布")
private List<WmsHomeOrderStatusRespVO> statuses;
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.wms.controller.admin.home.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 首页单据趋势 Response VO")
@Data
public class WmsHomeOrderTrendRespVO {
@Schema(description = "时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1778169600000")
private LocalDateTime time;
@Schema(description = "入库单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "12")
private Long receiptCount;
@Schema(description = "出库单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8")
private Long shipmentCount;
@Schema(description = "移库单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
private Long movementCount;
@Schema(description = "盘库单数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Long checkCount;
}

View File

@ -0,0 +1,87 @@
package cn.iocoder.yudao.module.wms.controller.admin.inventory;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryListReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.WmsInventoryRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - WMS 库存统计")
@RestController
@RequestMapping("/wms/inventory")
@Validated
public class WmsInventoryController {
@Resource
private WmsInventoryService inventoryService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private WmsWarehouseService warehouseService;
@GetMapping("/page")
@Operation(summary = "获得库存统计分页")
@PreAuthorize("@ss.hasPermission('wms:inventory:query')")
public CommonResult<PageResult<WmsInventoryRespVO>> getInventoryPage(@Valid WmsInventoryPageReqVO pageReqVO) {
PageResult<WmsInventoryDO> pageResult = inventoryService.getInventoryPage(pageReqVO);
return success(new PageResult<>(buildInventoryRespVOList(pageResult.getList()), pageResult.getTotal()));
}
@GetMapping("/list")
@Operation(summary = "获得库存统计列表")
@PreAuthorize("@ss.hasPermission('wms:inventory:query')")
public CommonResult<List<WmsInventoryRespVO>> getInventoryList(@Valid WmsInventoryListReqVO listReqVO) {
List<WmsInventoryDO> list = inventoryService.getInventoryList(listReqVO);
return success(buildInventoryRespVOList(list));
}
// ==================== 拼接 VO ====================
private List<WmsInventoryRespVO> buildInventoryRespVOList(List<WmsInventoryDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsInventoryDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(list, WmsInventoryDO::getWarehouseId));
return BeanUtils.toBean(list, WmsInventoryRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,79 @@
package cn.iocoder.yudao.module.wms.controller.admin.inventory;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.history.WmsInventoryHistoryPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.history.WmsInventoryHistoryRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryHistoryDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryHistoryService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - WMS 库存流水")
@RestController
@RequestMapping("/wms/inventory-history")
@Validated
public class WmsInventoryHistoryController {
@Resource
private WmsInventoryHistoryService inventoryHistoryService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private WmsWarehouseService warehouseService;
@GetMapping("/page")
@Operation(summary = "获得库存流水分页")
@PreAuthorize("@ss.hasPermission('wms:inventory-history:query')")
public CommonResult<PageResult<WmsInventoryHistoryRespVO>> getInventoryHistoryPage(
@Valid WmsInventoryHistoryPageReqVO pageReqVO) {
PageResult<WmsInventoryHistoryDO> pageResult = inventoryHistoryService.getInventoryHistoryPage(pageReqVO);
return success(new PageResult<>(buildInventoryHistoryRespVOList(pageResult.getList()), pageResult.getTotal()));
}
// ==================== 拼接 VO ====================
private List<WmsInventoryHistoryRespVO> buildInventoryHistoryRespVOList(List<WmsInventoryHistoryDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsInventoryHistoryDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(list, WmsInventoryHistoryDO::getWarehouseId));
return BeanUtils.toBean(list, WmsInventoryHistoryRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,15 @@
package cn.iocoder.yudao.module.wms.controller.admin.inventory.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Schema(description = "管理后台 - WMS 库存统计列表 Request VO")
@Data
public class WmsInventoryListReqVO {
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
@NotNull(message = "仓库编号不能为空")
private Long warehouseId;
}

View File

@ -0,0 +1,56 @@
package cn.iocoder.yudao.module.wms.controller.admin.inventory.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.math.BigDecimal;
@Schema(description = "管理后台 - WMS 库存统计分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsInventoryPageReqVO extends PageParam {
/**
*
*/
public static final String TYPE_WAREHOUSE = "warehouse";
/**
*
*/
public static final String TYPE_ITEM = "item";
@Schema(description = "统计维度", requiredMode = Schema.RequiredMode.REQUIRED, example = "warehouse")
@NotBlank(message = "统计维度不能为空")
private String type;
@Schema(description = "商品编号", example = "ITEM001")
private String itemCode;
@Schema(description = "商品名称", example = "红富士苹果")
private String itemName;
@Schema(description = "商品 SKU 编号", example = "1024")
private Long skuId;
@Schema(description = "规格编号", example = "SKU001")
private String skuCode;
@Schema(description = "规格名称", example = "10kg 箱装")
private String skuName;
@Schema(description = "仓库编号", example = "2048")
private Long warehouseId;
@Schema(description = "最小库存数量", example = "0.01")
private BigDecimal minQuantity;
@Schema(description = "是否只查询正库存", example = "true")
private Boolean onlyPositiveQuantity;
}

View File

@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.wms.controller.admin.inventory.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 库存统计 Response VO")
@Data
public class WmsInventoryRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long itemId;
@Schema(description = "商品编码", example = "ITEM001")
private String itemCode;
@Schema(description = "商品名称", example = "红富士苹果")
private String itemName;
@Schema(description = "商品单位", example = "箱")
private String unit;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
private Long skuId;
@Schema(description = "规格编号", example = "SKU001")
private String skuCode;
@Schema(description = "规格名称", example = "10kg 箱装")
private String skuName;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8192")
private Long warehouseId;
@Schema(description = "仓库名称", example = "成品仓")
private String warehouseName;
@Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal quantity;
@Schema(description = "备注", example = "备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,48 @@
package cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.history;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - WMS 库存流水分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsInventoryHistoryPageReqVO extends PageParam {
@Schema(description = "商品编号", example = "ITEM001")
private String itemCode;
@Schema(description = "商品名称", example = "红富士苹果")
private String itemName;
@Schema(description = "商品 SKU 编号", example = "1024")
private Long skuId;
@Schema(description = "规格编号", example = "SKU001")
private String skuCode;
@Schema(description = "规格名称", example = "10kg 箱装")
private String skuName;
@Schema(description = "仓库编号", example = "2048")
private Long warehouseId;
@Schema(description = "单据号", example = "RK202605110001")
private String orderNo;
@Schema(description = "单据类型", example = "1")
private Integer orderType;
@Schema(description = "操作时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,59 @@
package cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.history;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 库存流水 Response VO")
@Data
public class WmsInventoryHistoryRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long itemId;
@Schema(description = "商品编码", example = "ITEM001")
private String itemCode;
@Schema(description = "商品名称", example = "红富士苹果")
private String itemName;
@Schema(description = "商品单位", example = "箱")
private String unit;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "4096")
private Long skuId;
@Schema(description = "规格编号", example = "SKU001")
private String skuCode;
@Schema(description = "规格名称", example = "10kg 箱装")
private String skuName;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8192")
private Long warehouseId;
@Schema(description = "仓库名称", example = "成品仓")
private String warehouseName;
@Schema(description = "库存变化数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10.00")
private BigDecimal quantity;
@Schema(description = "变化前库存数量", example = "90.00")
private BigDecimal beforeQuantity;
@Schema(description = "变化后库存数量", example = "100.00")
private BigDecimal afterQuantity;
@Schema(description = "单价", example = "1000.00")
private BigDecimal price;
@Schema(description = "库存变化金额", example = "10000.00")
private BigDecimal totalPrice;
@Schema(description = "备注", example = "备注")
private String remark;
@Schema(description = "单据编号", example = "1024")
private Long orderId;
@Schema(description = "单据号", example = "RK202605110001")
private String orderNo;
@Schema(description = "单据类型", example = "1")
private Integer orderType;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,100 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand.WmsItemBrandPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand.WmsItemBrandRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand.WmsItemBrandSaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemBrandDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemBrandService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - WMS 商品品牌")
@RestController
@RequestMapping("/wms/item-brand")
@Validated
public class WmsItemBrandController {
@Resource
private WmsItemBrandService brandService;
@PostMapping("/create")
@Operation(summary = "创建商品品牌")
@PreAuthorize("@ss.hasPermission('wms:item-brand:create')")
public CommonResult<Long> createItemBrand(@Valid @RequestBody WmsItemBrandSaveReqVO createReqVO) {
return success(brandService.createItemBrand(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新商品品牌")
@PreAuthorize("@ss.hasPermission('wms:item-brand:update')")
public CommonResult<Boolean> updateItemBrand(@Valid @RequestBody WmsItemBrandSaveReqVO updateReqVO) {
brandService.updateItemBrand(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除商品品牌")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:item-brand:delete')")
public CommonResult<Boolean> deleteItemBrand(@RequestParam("id") Long id) {
brandService.deleteItemBrand(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得商品品牌")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:item-brand:query')")
public CommonResult<WmsItemBrandRespVO> getItemBrand(@RequestParam("id") Long id) {
WmsItemBrandDO brand = brandService.getItemBrand(id);
return success(BeanUtils.toBean(brand, WmsItemBrandRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得商品品牌分页")
@PreAuthorize("@ss.hasPermission('wms:item-brand:query')")
public CommonResult<PageResult<WmsItemBrandRespVO>> getItemBrandPage(@Valid WmsItemBrandPageReqVO pageReqVO) {
PageResult<WmsItemBrandDO> pageResult = brandService.getItemBrandPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, WmsItemBrandRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得商品品牌精简列表", description = "主要用于前端下拉")
@PreAuthorize("@ss.hasPermission('wms:item-brand:query')")
public CommonResult<List<WmsItemBrandRespVO>> getItemBrandSimpleList() {
List<WmsItemBrandDO> list = brandService.getItemBrandList();
return success(BeanUtils.toBean(list, WmsItemBrandRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出商品品牌 Excel")
@PreAuthorize("@ss.hasPermission('wms:item-brand:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportItemBrandExcel(@Valid WmsItemBrandPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<WmsItemBrandDO> list = brandService.getItemBrandPage(pageReqVO).getList();
ExcelUtils.write(response, "商品品牌.xls", "数据", WmsItemBrandRespVO.class,
BeanUtils.toBean(list, WmsItemBrandRespVO.class));
}
}

View File

@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.category.WmsItemCategoryListReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.category.WmsItemCategoryRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.category.WmsItemCategorySaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemCategoryDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemCategoryService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - WMS 商品分类")
@RestController
@RequestMapping("/wms/item-category")
@Validated
public class WmsItemCategoryController {
@Resource
private WmsItemCategoryService categoryService;
@PostMapping("/create")
@Operation(summary = "创建商品分类")
@PreAuthorize("@ss.hasPermission('wms:item-category:create')")
public CommonResult<Long> createItemCategory(@Valid @RequestBody WmsItemCategorySaveReqVO createReqVO) {
return success(categoryService.createItemCategory(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新商品分类")
@PreAuthorize("@ss.hasPermission('wms:item-category:update')")
public CommonResult<Boolean> updateItemCategory(@Valid @RequestBody WmsItemCategorySaveReqVO updateReqVO) {
categoryService.updateItemCategory(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除商品分类")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:item-category:delete')")
public CommonResult<Boolean> deleteItemCategory(@RequestParam("id") Long id) {
categoryService.deleteItemCategory(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得商品分类")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:item-category:query')")
public CommonResult<WmsItemCategoryRespVO> getItemCategory(@RequestParam("id") Long id) {
WmsItemCategoryDO category = categoryService.getItemCategory(id);
return success(BeanUtils.toBean(category, WmsItemCategoryRespVO.class));
}
@GetMapping("/list")
@Operation(summary = "获得商品分类列表")
@PreAuthorize("@ss.hasPermission('wms:item-category:query')")
public CommonResult<List<WmsItemCategoryRespVO>> getItemCategoryList(@Valid WmsItemCategoryListReqVO listReqVO) {
List<WmsItemCategoryDO> list = categoryService.getItemCategoryList(listReqVO);
return success(BeanUtils.toBean(list, WmsItemCategoryRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得商品分类精简列表", description = "主要用于前端下拉")
@PreAuthorize("@ss.hasPermission('wms:item-category:query')")
public CommonResult<List<WmsItemCategoryRespVO>> getItemCategorySimpleList() {
List<WmsItemCategoryDO> list = categoryService.getItemCategoryList(new WmsItemCategoryListReqVO());
return success(BeanUtils.toBean(list, WmsItemCategoryRespVO.class));
}
}

View File

@ -0,0 +1,150 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item.WmsItemListReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item.WmsItemPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item.WmsItemRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item.WmsItemSaveReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemBrandDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemCategoryDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemBrandService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemCategoryService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@Tag(name = "管理后台 - WMS 商品")
@RestController
@RequestMapping("/wms/item")
@Validated
public class WmsItemController {
@Resource
private WmsItemService itemService;
@Resource
private WmsItemCategoryService categoryService;
@Resource
private WmsItemBrandService brandService;
@Resource
private WmsItemSkuService itemSkuService;
@PostMapping("/create")
@Operation(summary = "创建商品")
@PreAuthorize("@ss.hasPermission('wms:item:create')")
public CommonResult<Long> createItem(@Valid @RequestBody WmsItemSaveReqVO createReqVO) {
return success(itemService.createItem(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新商品")
@PreAuthorize("@ss.hasPermission('wms:item:update')")
public CommonResult<Boolean> updateItem(@Valid @RequestBody WmsItemSaveReqVO updateReqVO) {
itemService.updateItem(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除商品")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:item:delete')")
public CommonResult<Boolean> deleteItem(@RequestParam("id") Long id) {
itemService.deleteItem(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得商品")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:item:query')")
public CommonResult<WmsItemRespVO> getItem(@RequestParam("id") Long id) {
WmsItemDO item = itemService.getItem(id);
return success(buildItemRespVO(item));
}
@GetMapping("/page")
@Operation(summary = "获得商品分页")
@PreAuthorize("@ss.hasPermission('wms:item:query')")
public CommonResult<PageResult<WmsItemRespVO>> getItemPage(@Valid WmsItemPageReqVO pageReqVO) {
PageResult<WmsItemDO> pageResult = itemService.getItemPage(pageReqVO);
return success(new PageResult<>(buildItemRespVOList(pageResult.getList()), pageResult.getTotal()));
}
@GetMapping("/simple-list")
@Operation(summary = "获得商品精简列表")
@PreAuthorize("@ss.hasPermission('wms:item:query')")
public CommonResult<List<WmsItemRespVO>> getItemSimpleList(@Valid WmsItemListReqVO listReqVO) {
List<WmsItemDO> list = itemService.getItemList(listReqVO);
return success(buildItemRespVOList(list));
}
@GetMapping("/export-excel")
@Operation(summary = "导出商品 Excel")
@PreAuthorize("@ss.hasPermission('wms:item:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportItemExcel(@Valid WmsItemPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<WmsItemDO> list = itemService.getItemPage(pageReqVO).getList();
ExcelUtils.write(response, "商品.xls", "数据", WmsItemRespVO.class,
buildItemRespVOList(list));
}
// ==================== 拼接 VO ====================
private WmsItemRespVO buildItemRespVO(WmsItemDO item) {
if (item == null) {
return null;
}
return getFirst(buildItemRespVOList(Collections.singletonList(item)));
}
private List<WmsItemRespVO> buildItemRespVOList(List<WmsItemDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 查询关联数据
Map<Long, WmsItemCategoryDO> categoryMap = categoryService.getItemCategoryMap(
convertSet(list, WmsItemDO::getCategoryId));
Map<Long, WmsItemBrandDO> brandMap = brandService.getItemBrandMap(
convertSet(list, WmsItemDO::getBrandId));
Map<Long, List<WmsItemSkuDO>> skuMap = itemSkuService.getItemSkuMultiMap(
convertSet(list, WmsItemDO::getId));
// 拼接 VO
return BeanUtils.toBean(list, WmsItemRespVO.class, vo -> {
MapUtils.findAndThen(categoryMap, vo.getCategoryId(), category ->
vo.setCategoryName(category.getName()));
MapUtils.findAndThen(brandMap, vo.getBrandId(), brand ->
vo.setBrandName(brand.getName()));
vo.setSkus(BeanUtils.toBean(skuMap.getOrDefault(vo.getId(), Collections.emptyList()),
WmsItemSkuRespVO.class));
});
}
}

View File

@ -0,0 +1,89 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemBrandDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemCategoryDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemBrandService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemCategoryService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
/**
* WMS SKU Controller
*
* <p>SKU / 使 SKU / /
* {@code wms:item:query}lite /SKU {@code wms:item:list}
*
* <p>SKU / / Controller
*/
@Tag(name = "管理后台 - WMS 商品 SKU")
@RestController
@RequestMapping("/wms/item-sku")
@Validated
public class WmsItemSkuController {
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemCategoryService categoryService;
@Resource
private WmsItemBrandService brandService;
@GetMapping("/page")
@Operation(summary = "获得商品 SKU 分页", description = "按 SKU 维度分页,支持商品 / 品牌 / 分类多表联查筛选")
@PreAuthorize("@ss.hasPermission('wms:item:query')")
public CommonResult<PageResult<WmsItemSkuRespVO>> getItemSkuPage(@Valid WmsItemSkuPageReqVO pageReqVO) {
PageResult<WmsItemSkuDO> pageResult = itemSkuService.getItemSkuPage(pageReqVO);
return success(new PageResult<>(buildItemSkuRespVOList(pageResult.getList()), pageResult.getTotal()));
}
// ==================== 拼接 VO ====================
private List<WmsItemSkuRespVO> buildItemSkuRespVOList(List<WmsItemSkuDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 查询关联数据
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(list, WmsItemSkuDO::getItemId));
Map<Long, WmsItemCategoryDO> categoryMap = categoryService.getItemCategoryMap(
convertSet(itemMap.values(), WmsItemDO::getCategoryId));
Map<Long, WmsItemBrandDO> brandMap = brandService.getItemBrandMap(
convertSet(itemMap.values(), WmsItemDO::getBrandId));
// 拼接 VO
return BeanUtils.toBean(list, WmsItemSkuRespVO.class, vo -> MapUtils.findAndThen(itemMap, vo.getItemId(), item -> {
vo.setItemCode(item.getCode()).setItemName(item.getName()).setUnit(item.getUnit())
.setCategoryId(item.getCategoryId()).setBrandId(item.getBrandId());
MapUtils.findAndThen(categoryMap, item.getCategoryId(), category ->
vo.setCategoryName(category.getName()));
MapUtils.findAndThen(brandMap, item.getBrandId(), brand ->
vo.setBrandName(brand.getName()));
}));
}
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - WMS 商品品牌分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsItemBrandPageReqVO extends PageParam {
@Schema(description = "品牌编号", example = "B00000001")
private String code;
@Schema(description = "品牌名称", example = "华为")
private String name;
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 商品品牌 Response VO")
@Data
@ExcelIgnoreUnannotated
public class WmsItemBrandRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("编号")
private Long id;
@Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "B00000001")
@ExcelProperty("品牌编号")
private String code;
@Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为")
@ExcelProperty("品牌名称")
private String name;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - WMS 商品品牌新增/修改 Request VO")
@Data
public class WmsItemBrandSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "B00000001")
@NotEmpty(message = "品牌编号不能为空")
@Size(max = 20, message = "品牌编号长度不能超过 20 个字符")
private String code;
@Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为")
@NotEmpty(message = "品牌名称不能为空")
@Size(max = 30, message = "品牌名称长度不能超过 30 个字符")
private String name;
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.category;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "管理后台 - WMS 商品分类列表 Request VO")
@Data
public class WmsItemCategoryListReqVO {
@Schema(description = "父级编号", example = "1")
private Long parentId;
@Schema(description = "分类编号", example = "C00000001")
private String code;
@Schema(description = "分类名称", example = "原料")
private String name;
@Schema(description = "状态", example = "0")
@InEnum(value = CommonStatusEnum.class, message = "状态必须是 {value}")
private Integer status;
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.category;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 商品分类 Response VO")
@Data
public class WmsItemCategoryRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Long parentId;
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00000001")
private String code;
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料")
private String name;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer status;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.category;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - WMS 商品分类新增/修改 Request VO")
@Data
public class WmsItemCategorySaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "父级编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "父级编号不能为空")
private Long parentId;
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00000001")
@NotEmpty(message = "分类编号不能为空")
@Size(max = 20, message = "分类编号长度不能超过 20 个字符")
private String code;
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料")
@NotEmpty(message = "分类名称不能为空")
@Size(max = 30, message = "分类名称长度不能超过 30 个字符")
private String name;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "排序不能为空")
private Integer sort;
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "状态必须是 {value}")
private Integer status;
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - WMS 商品列表 Request VO")
@Data
public class WmsItemListReqVO {
@Schema(description = "商品编号", example = "ITEM001")
private String code;
@Schema(description = "商品名称", example = "华为 nova flip")
private String name;
@Schema(description = "商品分类编号", example = "1024")
private Long categoryId;
@Schema(description = "商品品牌编号", example = "2048")
private Long brandId;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - WMS 商品分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsItemPageReqVO extends PageParam {
@Schema(description = "商品编号", example = "ITEM001")
private String code;
@Schema(description = "商品名称", example = "华为 nova flip")
private String name;
@Schema(description = "商品分类编号", example = "1024")
private Long categoryId;
@Schema(description = "商品品牌编号", example = "2048")
private Long brandId;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 商品 Response VO")
@Data
@ExcelIgnoreUnannotated
public class WmsItemRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("编号")
private Long id;
@Schema(description = "商品编号", example = "ITEM001")
@ExcelProperty("商品编号")
private String code;
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为 nova flip")
@ExcelProperty("商品名称")
private String name;
@Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long categoryId;
@Schema(description = "商品分类名称", example = "手机")
@ExcelProperty("商品分类")
private String categoryName;
@Schema(description = "单位", example = "台")
@ExcelProperty("单位")
private String unit;
@Schema(description = "商品品牌编号", example = "1")
private Long brandId;
@Schema(description = "商品品牌名称", example = "华为")
@ExcelProperty("商品品牌")
private String brandName;
@Schema(description = "备注", example = "备注")
@ExcelProperty("备注")
private String remark;
@Schema(description = "规格列表")
private List<WmsItemSkuRespVO> skus;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,51 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item;
import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuSaveReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - WMS 商品创建/更新 Request VO")
@Data
public class WmsItemSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "ITEM001")
@NotBlank(message = "商品编号不能为空")
@Size(max = 20, message = "商品编号长度不能超过 20 个字符")
private String code;
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为 nova flip")
@NotBlank(message = "商品名称不能为空")
@Size(max = 60, message = "商品名称长度不能超过 60 个字符")
private String name;
@Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品分类不能为空")
private Long categoryId;
@Schema(description = "单位", example = "台")
@Size(max = 20, message = "单位长度不能超过 20 个字符")
private String unit;
@Schema(description = "商品品牌编号", example = "1")
private Long brandId;
@Schema(description = "备注", example = "备注")
@Size(max = 255, message = "备注长度不能超过 255 个字符")
private String remark;
@Schema(description = "规格列表")
@Valid
@NotEmpty(message = "至少包含一个商品规格")
private List<WmsItemSkuSaveReqVO> skus;
}

View File

@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - WMS 商品 SKU 分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsItemSkuPageReqVO extends PageParam {
@Schema(description = "商品编号", example = "I00000001")
private String itemCode;
@Schema(description = "商品名称", example = "华为 nova flip")
private String itemName;
@Schema(description = "商品分类编号", example = "1")
private Long categoryId;
@Schema(description = "商品品牌编号", example = "1")
private Long brandId;
@Schema(description = "规格编号", example = "S00000001")
private String code;
@Schema(description = "规格名称", example = "黑色")
private String name;
@Schema(description = "条码", example = "12345678")
private String barCode;
}

View File

@ -0,0 +1,73 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 商品 SKU Response VO")
@Data
public class WmsItemSkuRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "规格名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "黑色")
private String name;
@Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long itemId;
@Schema(description = "商品编码", example = "ITEM001")
private String itemCode;
@Schema(description = "商品名称", example = "华为 nova flip")
private String itemName;
@Schema(description = "商品分类编号", example = "1")
private Long categoryId;
@Schema(description = "商品分类名称", example = "手机")
private String categoryName;
@Schema(description = "单位", example = "台")
private String unit;
@Schema(description = "商品品牌编号", example = "1")
private Long brandId;
@Schema(description = "商品品牌名称", example = "华为")
private String brandName;
@Schema(description = "条码", example = "690000000001")
private String barCode;
@Schema(description = "规格编号", example = "SKU001")
private String code;
@Schema(description = "长,单位 cm", example = "10.0")
private BigDecimal length;
@Schema(description = "宽,单位 cm", example = "8.0")
private BigDecimal width;
@Schema(description = "高,单位 cm", example = "1.0")
private BigDecimal height;
@Schema(description = "毛重,单位 kg", example = "1.000")
private BigDecimal grossWeight;
@Schema(description = "净重,单位 kg", example = "0.900")
private BigDecimal netWeight;
@Schema(description = "成本价,单位元", example = "5000.00")
private BigDecimal costPrice;
@Schema(description = "销售价,单位元", example = "5288.00")
private BigDecimal sellingPrice;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,62 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - WMS 商品 SKU 创建/更新 Request VO")
@Data
public class WmsItemSkuSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "规格名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "黑色")
@NotBlank(message = "规格名称不能为空")
@Size(max = 255, message = "规格名称长度不能超过 255 个字符")
private String name;
@Schema(description = "商品编号", example = "1")
private Long itemId;
@Schema(description = "条码", example = "690000000001")
@Size(max = 64, message = "条码长度不能超过 64 个字符")
private String barCode;
@Schema(description = "规格编号", example = "SKU001")
@Size(max = 64, message = "规格编号长度不能超过 64 个字符")
private String code;
@Schema(description = "长,单位 cm", example = "10.0")
@DecimalMin(value = "0", message = "长不能小于 0")
private BigDecimal length;
@Schema(description = "宽,单位 cm", example = "8.0")
@DecimalMin(value = "0", message = "宽不能小于 0")
private BigDecimal width;
@Schema(description = "高,单位 cm", example = "1.0")
@DecimalMin(value = "0", message = "高不能小于 0")
private BigDecimal height;
@Schema(description = "毛重,单位 kg", example = "1.000")
@DecimalMin(value = "0", message = "毛重不能小于 0")
private BigDecimal grossWeight;
@Schema(description = "净重,单位 kg", example = "0.900")
@DecimalMin(value = "0", message = "净重不能小于 0")
private BigDecimal netWeight;
@Schema(description = "成本价,单位元", example = "5000.00")
@DecimalMin(value = "0", message = "成本价不能小于 0")
private BigDecimal costPrice;
@Schema(description = "销售价,单位元", example = "5288.00")
@DecimalMin(value = "0", message = "销售价不能小于 0")
private BigDecimal sellingPrice;
}

View File

@ -0,0 +1,101 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.merchant;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo.WmsMerchantListReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo.WmsMerchantPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo.WmsMerchantRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo.WmsMerchantSaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.merchant.WmsMerchantDO;
import cn.iocoder.yudao.module.wms.service.md.merchant.WmsMerchantService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - WMS 往来企业")
@RestController
@RequestMapping("/wms/merchant")
@Validated
public class WmsMerchantController {
@Resource
private WmsMerchantService merchantService;
@PostMapping("/create")
@Operation(summary = "创建往来企业")
@PreAuthorize("@ss.hasPermission('wms:merchant:create')")
public CommonResult<Long> createMerchant(@Valid @RequestBody WmsMerchantSaveReqVO createReqVO) {
return success(merchantService.createMerchant(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新往来企业")
@PreAuthorize("@ss.hasPermission('wms:merchant:update')")
public CommonResult<Boolean> updateMerchant(@Valid @RequestBody WmsMerchantSaveReqVO updateReqVO) {
merchantService.updateMerchant(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除往来企业")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:merchant:delete')")
public CommonResult<Boolean> deleteMerchant(@RequestParam("id") Long id) {
merchantService.deleteMerchant(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得往来企业")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:merchant:query')")
public CommonResult<WmsMerchantRespVO> getMerchant(@RequestParam("id") Long id) {
WmsMerchantDO merchant = merchantService.getMerchant(id);
return success(BeanUtils.toBean(merchant, WmsMerchantRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得往来企业分页")
@PreAuthorize("@ss.hasPermission('wms:merchant:query')")
public CommonResult<PageResult<WmsMerchantRespVO>> getMerchantPage(@Valid WmsMerchantPageReqVO pageReqVO) {
PageResult<WmsMerchantDO> pageResult = merchantService.getMerchantPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, WmsMerchantRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得往来企业精简列表", description = "主要用于前端下拉")
@PreAuthorize("@ss.hasPermission('wms:merchant:query')")
public CommonResult<List<WmsMerchantRespVO>> getMerchantSimpleList(@Valid WmsMerchantListReqVO listReqVO) {
List<WmsMerchantDO> list = merchantService.getMerchantList(listReqVO);
return success(BeanUtils.toBean(list, WmsMerchantRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出往来企业 Excel")
@PreAuthorize("@ss.hasPermission('wms:merchant:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportMerchantExcel(@Valid WmsMerchantPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<WmsMerchantDO> list = merchantService.getMerchantPage(pageReqVO).getList();
ExcelUtils.write(response, "往来企业.xls", "数据", WmsMerchantRespVO.class,
BeanUtils.toBean(list, WmsMerchantRespVO.class));
}
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.enums.md.WmsMerchantTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - WMS 往来企业列表 Request VO")
@Data
public class WmsMerchantListReqVO {
@Schema(description = "往来企业编号", example = "MER001")
private String code;
@Schema(description = "往来企业名称", example = "华为")
private String name;
@Schema(description = "往来企业类型", example = "2")
@InEnum(value = WmsMerchantTypeEnum.class, message = "往来企业类型必须是 {value}")
private Integer type;
@Schema(description = "往来企业类型数组", example = "2,3")
@InEnum(value = WmsMerchantTypeEnum.class, message = "往来企业类型必须是 {value}")
private List<Integer> types;
}

View File

@ -0,0 +1,33 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.enums.md.WmsMerchantTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.util.List;
@Schema(description = "管理后台 - WMS 往来企业分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsMerchantPageReqVO extends PageParam {
@Schema(description = "往来企业编号", example = "MER001")
private String code;
@Schema(description = "往来企业名称", example = "华为")
private String name;
@Schema(description = "往来企业类型", example = "2")
@InEnum(value = WmsMerchantTypeEnum.class, message = "往来企业类型必须是 {value}")
private Integer type;
@Schema(description = "往来企业类型数组", example = "2,3")
@InEnum(value = WmsMerchantTypeEnum.class, message = "往来企业类型必须是 {value}")
private List<Integer> types;
}

View File

@ -0,0 +1,68 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.wms.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 往来企业 Response VO")
@Data
@ExcelIgnoreUnannotated
public class WmsMerchantRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("编号")
private Long id;
@Schema(description = "往来企业编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MER001")
@ExcelProperty("往来企业编号")
private String code;
@Schema(description = "往来企业名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为")
@ExcelProperty("往来企业名称")
private String name;
@Schema(description = "往来企业类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@ExcelProperty(value = "往来企业类型", converter = DictConvert.class)
@DictFormat(DictTypeConstants.MERCHANT_TYPE)
private Integer type;
@Schema(description = "级别", example = "A")
@ExcelProperty("级别")
private String level;
@Schema(description = "开户行", example = "招商银行")
private String bankName;
@Schema(description = "银行账户", example = "6225888888888888")
private String bankAccount;
@Schema(description = "地址", example = "深圳市南山区")
private String address;
@Schema(description = "手机号", example = "15601691300")
private String mobile;
@Schema(description = "座机号", example = "0755-88888888")
private String telephone;
@Schema(description = "联系人", example = "王五")
@ExcelProperty("联系人")
private String contact;
@Schema(description = "Email", example = "wms@example.com")
private String email;
@Schema(description = "备注", example = "备注")
@ExcelProperty("备注")
private String remark;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,69 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.enums.md.WmsMerchantTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - WMS 往来企业创建/更新 Request VO")
@Data
public class WmsMerchantSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "往来企业编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "MER001")
@NotBlank(message = "往来企业编号不能为空")
@Size(max = 20, message = "往来企业编号长度不能超过 20 个字符")
private String code;
@Schema(description = "往来企业名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "华为")
@NotBlank(message = "往来企业名称不能为空")
@Size(max = 60, message = "往来企业名称长度不能超过 60 个字符")
private String name;
@Schema(description = "往来企业类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "往来企业类型不能为空")
@InEnum(value = WmsMerchantTypeEnum.class, message = "往来企业类型必须是 {value}")
private Integer type;
@Schema(description = "级别", example = "A")
@Size(max = 10, message = "级别长度不能超过 10 个字符")
private String level;
@Schema(description = "开户行", example = "招商银行")
@Size(max = 255, message = "开户行长度不能超过 255 个字符")
private String bankName;
@Schema(description = "银行账户", example = "6225888888888888")
@Size(max = 40, message = "银行账户长度不能超过 40 个字符")
private String bankAccount;
@Schema(description = "地址", example = "深圳市南山区")
@Size(max = 200, message = "地址长度不能超过 200 个字符")
private String address;
@Schema(description = "手机号", example = "15601691300")
@Size(max = 13, message = "手机号长度不能超过 13 个字符")
private String mobile;
@Schema(description = "座机号", example = "0755-88888888")
@Size(max = 13, message = "座机号长度不能超过 13 个字符")
private String telephone;
@Schema(description = "联系人", example = "王五")
@Size(max = 30, message = "联系人长度不能超过 30 个字符")
private String contact;
@Schema(description = "Email", example = "wms@example.com")
@Size(max = 50, message = "Email 长度不能超过 50 个字符")
private String email;
@Schema(description = "备注", example = "备注")
@Size(max = 255, message = "备注长度不能超过 255 个字符")
private String remark;
}

View File

@ -0,0 +1,100 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.warehouse;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.wms.controller.admin.md.warehouse.vo.WmsWarehousePageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.warehouse.vo.WmsWarehouseRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.md.warehouse.vo.WmsWarehouseSaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - WMS 仓库")
@RestController
@RequestMapping("/wms/warehouse")
@Validated
public class WmsWarehouseController {
@Resource
private WmsWarehouseService warehouseService;
@PostMapping("/create")
@Operation(summary = "创建仓库")
@PreAuthorize("@ss.hasPermission('wms:warehouse:create')")
public CommonResult<Long> createWarehouse(@Valid @RequestBody WmsWarehouseSaveReqVO createReqVO) {
return success(warehouseService.createWarehouse(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新仓库")
@PreAuthorize("@ss.hasPermission('wms:warehouse:update')")
public CommonResult<Boolean> updateWarehouse(@Valid @RequestBody WmsWarehouseSaveReqVO updateReqVO) {
warehouseService.updateWarehouse(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除仓库")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:warehouse:delete')")
public CommonResult<Boolean> deleteWarehouse(@RequestParam("id") Long id) {
warehouseService.deleteWarehouse(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得仓库")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:warehouse:query')")
public CommonResult<WmsWarehouseRespVO> getWarehouse(@RequestParam("id") Long id) {
WmsWarehouseDO warehouse = warehouseService.getWarehouse(id);
return success(BeanUtils.toBean(warehouse, WmsWarehouseRespVO.class));
}
@GetMapping("/page")
@Operation(summary = "获得仓库分页")
@PreAuthorize("@ss.hasPermission('wms:warehouse:query')")
public CommonResult<PageResult<WmsWarehouseRespVO>> getWarehousePage(@Valid WmsWarehousePageReqVO pageReqVO) {
PageResult<WmsWarehouseDO> pageResult = warehouseService.getWarehousePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, WmsWarehouseRespVO.class));
}
@GetMapping("/simple-list")
@Operation(summary = "获得仓库精简列表", description = "主要用于前端下拉")
@PreAuthorize("@ss.hasPermission('wms:warehouse:query')")
public CommonResult<List<WmsWarehouseRespVO>> getWarehouseSimpleList() {
List<WmsWarehouseDO> list = warehouseService.getWarehouseList();
return success(BeanUtils.toBean(list, WmsWarehouseRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出仓库 Excel")
@PreAuthorize("@ss.hasPermission('wms:warehouse:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportWarehouseExcel(@Valid WmsWarehousePageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<WmsWarehouseDO> list = warehouseService.getWarehousePage(pageReqVO).getList();
ExcelUtils.write(response, "仓库.xls", "数据", WmsWarehouseRespVO.class,
BeanUtils.toBean(list, WmsWarehouseRespVO.class));
}
}

View File

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.warehouse.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "管理后台 - WMS 仓库分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsWarehousePageReqVO extends PageParam {
@Schema(description = "仓库编号", example = "WH001")
private String code;
@Schema(description = "仓库名称", example = "原料仓")
private String name;
}

View File

@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.warehouse.vo;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 仓库 Response VO")
@Data
@ExcelIgnoreUnannotated
public class WmsWarehouseRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@ExcelProperty("编号")
private Long id;
@Schema(description = "仓库编号", example = "WH001")
@ExcelProperty("仓库编号")
private String code;
@Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料仓")
@ExcelProperty("仓库名称")
private String name;
@Schema(description = "备注", example = "备注")
@ExcelProperty("备注")
private String remark;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@ExcelProperty("排序")
private Integer sort;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.wms.controller.admin.md.warehouse.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
@Schema(description = "管理后台 - WMS 仓库新增/修改 Request VO")
@Data
public class WmsWarehouseSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "WH001")
@NotEmpty(message = "仓库编号不能为空")
@Size(max = 20, message = "仓库编号长度不能超过 20 个字符")
private String code;
@Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原料仓")
@NotEmpty(message = "仓库名称不能为空")
private String name;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "排序不能为空")
private Integer sort;
@Schema(description = "备注", example = "备注")
private String remark;
}

View File

@ -0,0 +1,198 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.check;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail.WmsCheckOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order.WmsCheckOrderPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order.WmsCheckOrderRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order.WmsCheckOrderSaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDetailDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import cn.iocoder.yudao.module.wms.service.order.check.WmsCheckOrderDetailService;
import cn.iocoder.yudao.module.wms.service.order.check.WmsCheckOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
@Tag(name = "管理后台 - WMS 盘库单")
@RestController
@RequestMapping("/wms/check-order")
@Validated
public class WmsCheckOrderController {
@Resource
private WmsCheckOrderService checkOrderService;
@Resource
private WmsCheckOrderDetailService checkOrderDetailService;
@Resource
private WmsWarehouseService warehouseService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private AdminUserApi adminUserApi;
@PostMapping("/create")
@Operation(summary = "创建盘库单")
@PreAuthorize("@ss.hasPermission('wms:check-order:create')")
public CommonResult<Long> createCheckOrder(@Valid @RequestBody WmsCheckOrderSaveReqVO createReqVO) {
return success(checkOrderService.createCheckOrder(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新盘库单")
@PreAuthorize("@ss.hasPermission('wms:check-order:update')")
public CommonResult<Boolean> updateCheckOrder(@Valid @RequestBody WmsCheckOrderSaveReqVO updateReqVO) {
checkOrderService.updateCheckOrder(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除盘库单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:check-order:delete')")
public CommonResult<Boolean> deleteCheckOrder(@RequestParam("id") Long id) {
checkOrderService.deleteCheckOrder(id);
return success(true);
}
@PutMapping("/complete")
@Operation(summary = "完成盘库")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:check-order:complete')")
public CommonResult<Boolean> completeCheckOrder(@RequestParam("id") Long id) {
checkOrderService.completeCheckOrder(id);
return success(true);
}
@PutMapping("/cancel")
@Operation(summary = "作废盘库单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:check-order:cancel')")
public CommonResult<Boolean> cancelCheckOrder(@RequestParam("id") Long id) {
checkOrderService.cancelCheckOrder(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得盘库单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:check-order:query')")
public CommonResult<WmsCheckOrderRespVO> getCheckOrder(@RequestParam("id") Long id) {
WmsCheckOrderDO order = checkOrderService.getCheckOrder(id);
if (order == null) {
return success(null);
}
// 获得盘库单的明细列表
List<WmsCheckOrderDetailDO> detailList = checkOrderDetailService.getCheckOrderDetailList(id);
// 拼接结果返回
WmsCheckOrderRespVO respVO = buildCheckOrderRespVO(order)
.setDetails(buildCheckOrderDetailRespVOList(detailList));
return success(respVO);
}
@GetMapping("/page")
@Operation(summary = "获得盘库单分页")
@PreAuthorize("@ss.hasPermission('wms:check-order:query')")
public CommonResult<PageResult<WmsCheckOrderRespVO>> getCheckOrderPage(@Valid WmsCheckOrderPageReqVO pageReqVO) {
PageResult<WmsCheckOrderDO> pageResult = checkOrderService.getCheckOrderPage(pageReqVO);
return success(new PageResult<>(buildCheckOrderRespVOList(pageResult.getList()), pageResult.getTotal()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出盘库单 Excel")
@PreAuthorize("@ss.hasPermission('wms:check-order:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportCheckOrderExcel(@Valid WmsCheckOrderPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<WmsCheckOrderDO> list = checkOrderService.getCheckOrderPage(pageReqVO).getList();
ExcelUtils.write(response, "盘库单.xls", "数据", WmsCheckOrderRespVO.class,
buildCheckOrderRespVOList(list));
}
// ==================== 拼接 VO ====================
private WmsCheckOrderRespVO buildCheckOrderRespVO(WmsCheckOrderDO order) {
if (order == null) {
return null;
}
List<WmsCheckOrderRespVO> list = buildCheckOrderRespVOList(Collections.singletonList(order));
return CollUtil.getFirst(list);
}
private List<WmsCheckOrderRespVO> buildCheckOrderRespVOList(List<WmsCheckOrderDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 获取相关的仓库、用户等数据
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertSet(list, WmsCheckOrderDO::getWarehouseId));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(list,
order -> Stream.of(parseUserId(order.getCreator()), parseUserId(order.getUpdater()))));
// 拼接数据
return BeanUtils.toBean(list, WmsCheckOrderRespVO.class, vo -> {
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
MapUtils.findAndThen(userMap, parseUserId(vo.getCreator()), user -> vo.setCreatorName(user.getNickname()));
MapUtils.findAndThen(userMap, parseUserId(vo.getUpdater()), user -> vo.setUpdaterName(user.getNickname()));
});
}
private Long parseUserId(String userId) {
return NumberUtil.parseLong(userId, null);
}
private List<WmsCheckOrderDetailRespVO> buildCheckOrderDetailRespVOList(List<WmsCheckOrderDetailDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 获取相关的商品、SKU、仓库等数据
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsCheckOrderDetailDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(list, WmsCheckOrderDetailDO::getWarehouseId));
// 拼接数据
return BeanUtils.toBean(list, WmsCheckOrderDetailRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.check;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail.WmsCheckOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.check.WmsCheckOrderDetailDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import cn.iocoder.yudao.module.wms.service.order.check.WmsCheckOrderDetailService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - WMS 盘库单明细")
@RestController
@RequestMapping("/wms/check-order-detail")
@Validated
public class WmsCheckOrderDetailController {
@Resource
private WmsCheckOrderDetailService checkOrderDetailService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private WmsWarehouseService warehouseService;
@GetMapping("/list-by-order-id")
@Operation(summary = "获得盘库单明细列表")
@Parameter(name = "orderId", description = "盘库单编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:check-order:query')")
public CommonResult<List<WmsCheckOrderDetailRespVO>> getCheckOrderDetailListByOrderId(
@RequestParam("orderId") Long orderId) {
List<WmsCheckOrderDetailDO> list = checkOrderDetailService.getCheckOrderDetailList(orderId);
return success(buildCheckOrderDetailRespVOList(list));
}
// ==================== 拼接 VO ====================
private List<WmsCheckOrderDetailRespVO> buildCheckOrderDetailRespVOList(List<WmsCheckOrderDetailDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 查询关联数据
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsCheckOrderDetailDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(list, WmsCheckOrderDetailDO::getWarehouseId));
// 拼接数据
return BeanUtils.toBean(list, WmsCheckOrderDetailRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 盘库单明细 Response VO")
@Data
public class WmsCheckOrderDetailRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "盘库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderId;
@Schema(description = "商品编号", example = "2048")
private Long itemId;
@Schema(description = "商品编号", example = "SPU-APPLE")
private String itemCode;
@Schema(description = "商品名称", example = "红富士苹果")
private String itemName;
@Schema(description = "商品单位", example = "箱")
private String unit;
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long skuId;
@Schema(description = "规格编号", example = "SKU-APPLE-10KG")
private String skuCode;
@Schema(description = "规格名称", example = "10kg 箱装")
private String skuName;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long warehouseId;
@Schema(description = "仓库名称", example = "北京仓")
private String warehouseName;
@Schema(description = "库存编号", example = "1024")
private Long inventoryId;
@Schema(description = "入库时间")
private LocalDateTime receiptTime;
@Schema(description = "账面数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal quantity;
@Schema(description = "实盘数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "98.00")
private BigDecimal checkQuantity;
@Schema(description = "单价", example = "1000.00")
private BigDecimal price;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 盘库单明细保存 Request VO")
@Data
public class WmsCheckOrderDetailSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
@NotNull(message = "SKU 不能为空")
private Long skuId;
@Schema(description = "库存编号", example = "1024")
private Long inventoryId;
@Schema(description = "入库时间")
private LocalDateTime receiptTime;
@Schema(description = "账面数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
@NotNull(message = "账面数量不能为空")
@DecimalMin(value = "0", message = "账面数量不能小于 0")
private BigDecimal quantity;
@Schema(description = "实盘数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "98.00")
@NotNull(message = "实盘数量不能为空")
@DecimalMin(value = "0", message = "实盘数量不能小于 0")
private BigDecimal checkQuantity;
@Schema(description = "单价", example = "1000.00")
@DecimalMin(value = "0", message = "单价不能小于 0")
private BigDecimal price;
}

View File

@ -0,0 +1,69 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - WMS 盘库单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsCheckOrderPageReqVO extends PageParam {
@Schema(description = "盘库单号", example = "PK202605110001")
private String no;
@Schema(description = "单据状态", example = "0")
@InEnum(WmsOrderStatusEnum.class)
private Integer status;
@Schema(description = "仓库编号", example = "1024")
private Long warehouseId;
@Schema(description = "单据日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] orderTime;
@Schema(description = "最小盈亏数量", example = "-10.00")
private BigDecimal totalQuantityMin;
@Schema(description = "最大盈亏数量", example = "100.00")
private BigDecimal totalQuantityMax;
@Schema(description = "最小总金额", example = "1.00")
private BigDecimal totalPriceMin;
@Schema(description = "最大总金额", example = "1000.00")
private BigDecimal totalPriceMax;
@Schema(description = "最小实际金额", example = "1.00")
private BigDecimal actualPriceMin;
@Schema(description = "最大实际金额", example = "1000.00")
private BigDecimal actualPriceMax;
@Schema(description = "创建用户", example = "1")
private String creator;
@Schema(description = "更新用户", example = "1")
private String updater;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "更新时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] updateTime;
}

View File

@ -0,0 +1,79 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail.WmsCheckOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 盘库单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class WmsCheckOrderRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "盘库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "PK202605110001")
@ExcelProperty("盘库单号")
private String no;
@Schema(description = "单据日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("单据日期")
private LocalDateTime orderTime;
@Schema(description = "盘库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@ExcelProperty(value = "盘库状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.ORDER_STATUS)
private Integer status;
@Schema(description = "备注", example = "备注")
private String remark;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long warehouseId;
@Schema(description = "仓库名称", example = "北京仓")
@ExcelProperty("仓库")
private String warehouseName;
@Schema(description = "盈亏数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
@ExcelProperty("盈亏数量")
private BigDecimal totalQuantity;
@Schema(description = "总金额(账面金额)", example = "1000.00")
@ExcelProperty("总金额")
private BigDecimal totalPrice;
@Schema(description = "实际金额", example = "980.00")
@ExcelProperty("实际金额")
private BigDecimal actualPrice;
@Schema(description = "盘库明细")
private List<WmsCheckOrderDetailRespVO> details;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "创建者", example = "1")
private String creator;
@Schema(description = "创建者名称", example = "芋道")
private String creatorName;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime updateTime;
@Schema(description = "更新者", example = "1")
private String updater;
@Schema(description = "更新者名称", example = "芋道")
private String updaterName;
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order;
import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail.WmsCheckOrderDetailSaveReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 盘库单保存 Request VO")
@Data
public class WmsCheckOrderSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "盘库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "PK202605110001")
@NotBlank(message = "盘库单号不能为空")
@Size(max = 64, message = "盘库单号长度不能超过 64 个字符")
private String no;
@Schema(description = "单据日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "单据日期不能为空")
private LocalDateTime orderTime;
@Schema(description = "备注", example = "备注")
@Size(max = 255, message = "备注长度不能超过 255 个字符")
private String remark;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "仓库不能为空")
private Long warehouseId;
@Schema(description = "盘库明细")
@Valid
private List<WmsCheckOrderDetailSaveReqVO> details;
}

View File

@ -0,0 +1,206 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.movement;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail.WmsMovementOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order.WmsMovementOrderPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order.WmsMovementOrderRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order.WmsMovementOrderSaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDetailDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import cn.iocoder.yudao.module.wms.service.order.movement.WmsMovementOrderDetailService;
import cn.iocoder.yudao.module.wms.service.order.movement.WmsMovementOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
@Tag(name = "管理后台 - WMS 移库单")
@RestController
@RequestMapping("/wms/movement-order")
@Validated
public class WmsMovementOrderController {
@Resource
private WmsMovementOrderService movementOrderService;
@Resource
private WmsMovementOrderDetailService movementOrderDetailService;
@Resource
private WmsWarehouseService warehouseService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private AdminUserApi adminUserApi;
@PostMapping("/create")
@Operation(summary = "创建移库单")
@PreAuthorize("@ss.hasPermission('wms:movement-order:create')")
public CommonResult<Long> createMovementOrder(@Valid @RequestBody WmsMovementOrderSaveReqVO createReqVO) {
return success(movementOrderService.createMovementOrder(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新移库单")
@PreAuthorize("@ss.hasPermission('wms:movement-order:update')")
public CommonResult<Boolean> updateMovementOrder(@Valid @RequestBody WmsMovementOrderSaveReqVO updateReqVO) {
movementOrderService.updateMovementOrder(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除移库单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:movement-order:delete')")
public CommonResult<Boolean> deleteMovementOrder(@RequestParam("id") Long id) {
movementOrderService.deleteMovementOrder(id);
return success(true);
}
@PutMapping("/complete")
@Operation(summary = "完成移库")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:movement-order:complete')")
public CommonResult<Boolean> completeMovementOrder(@RequestParam("id") Long id) {
movementOrderService.completeMovementOrder(id);
return success(true);
}
@PutMapping("/cancel")
@Operation(summary = "作废移库单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:movement-order:cancel')")
public CommonResult<Boolean> cancelMovementOrder(@RequestParam("id") Long id) {
movementOrderService.cancelMovementOrder(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得移库单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:movement-order:query')")
public CommonResult<WmsMovementOrderRespVO> getMovementOrder(@RequestParam("id") Long id) {
WmsMovementOrderDO order = movementOrderService.getMovementOrder(id);
if (order == null) {
return success(null);
}
// 获得移库单的明细列表
List<WmsMovementOrderDetailDO> detailList = movementOrderDetailService.getMovementOrderDetailList(id);
// 拼接结果返回
WmsMovementOrderRespVO respVO = buildMovementOrderRespVO(order)
.setDetails(buildMovementOrderDetailRespVOList(detailList));
return success(respVO);
}
@GetMapping("/page")
@Operation(summary = "获得移库单分页")
@PreAuthorize("@ss.hasPermission('wms:movement-order:query')")
public CommonResult<PageResult<WmsMovementOrderRespVO>> getMovementOrderPage(
@Valid WmsMovementOrderPageReqVO pageReqVO) {
PageResult<WmsMovementOrderDO> pageResult = movementOrderService.getMovementOrderPage(pageReqVO);
return success(new PageResult<>(buildMovementOrderRespVOList(pageResult.getList()), pageResult.getTotal()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出移库单 Excel")
@PreAuthorize("@ss.hasPermission('wms:movement-order:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportMovementOrderExcel(@Valid WmsMovementOrderPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<WmsMovementOrderDO> list = movementOrderService.getMovementOrderPage(pageReqVO).getList();
ExcelUtils.write(response, "移库单.xls", "数据", WmsMovementOrderRespVO.class,
buildMovementOrderRespVOList(list));
}
// ==================== 拼接 VO ====================
private WmsMovementOrderRespVO buildMovementOrderRespVO(WmsMovementOrderDO order) {
if (order == null) {
return null;
}
List<WmsMovementOrderRespVO> list = buildMovementOrderRespVOList(Collections.singletonList(order));
return CollUtil.getFirst(list);
}
private List<WmsMovementOrderRespVO> buildMovementOrderRespVOList(List<WmsMovementOrderDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 获取相关的仓库、用户等数据
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertSetByFlatMap(list,
order -> Stream.of(order.getSourceWarehouseId(), order.getTargetWarehouseId())));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(list,
order -> Stream.of(parseUserId(order.getCreator()), parseUserId(order.getUpdater()))));
// 拼接数据
return BeanUtils.toBean(list, WmsMovementOrderRespVO.class, vo -> {
MapUtils.findAndThen(warehouseMap, vo.getSourceWarehouseId(),
warehouse -> vo.setSourceWarehouseName(warehouse.getName()));
MapUtils.findAndThen(warehouseMap, vo.getTargetWarehouseId(),
warehouse -> vo.setTargetWarehouseName(warehouse.getName()));
MapUtils.findAndThen(userMap, parseUserId(vo.getCreator()), user -> vo.setCreatorName(user.getNickname()));
MapUtils.findAndThen(userMap, parseUserId(vo.getUpdater()), user -> vo.setUpdaterName(user.getNickname()));
});
}
private Long parseUserId(String userId) {
return NumberUtil.parseLong(userId, null);
}
private List<WmsMovementOrderDetailRespVO> buildMovementOrderDetailRespVOList(List<WmsMovementOrderDetailDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 获取相关的商品、SKU、仓库等数据
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsMovementOrderDetailDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertSetByFlatMap(list,
detail -> Stream.of(detail.getSourceWarehouseId(), detail.getTargetWarehouseId())));
// 拼接数据
return BeanUtils.toBean(list, WmsMovementOrderDetailRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getSourceWarehouseId(),
warehouse -> vo.setSourceWarehouseName(warehouse.getName()));
MapUtils.findAndThen(warehouseMap, vo.getTargetWarehouseId(),
warehouse -> vo.setTargetWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,86 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.movement;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail.WmsMovementOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.movement.WmsMovementOrderDetailDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import cn.iocoder.yudao.module.wms.service.order.movement.WmsMovementOrderDetailService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
@Tag(name = "管理后台 - WMS 移库单明细")
@RestController
@RequestMapping("/wms/movement-order-detail")
@Validated
public class WmsMovementOrderDetailController {
@Resource
private WmsMovementOrderDetailService movementOrderDetailService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private WmsWarehouseService warehouseService;
@GetMapping("/list-by-order-id")
@Operation(summary = "获得移库单明细列表")
@Parameter(name = "orderId", description = "移库单编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:movement-order:query')")
public CommonResult<List<WmsMovementOrderDetailRespVO>> getMovementOrderDetailListByOrderId(
@RequestParam("orderId") Long orderId) {
List<WmsMovementOrderDetailDO> list = movementOrderDetailService.getMovementOrderDetailList(orderId);
return success(buildMovementOrderDetailRespVOList(list));
}
// ==================== 拼接 VO ====================
private List<WmsMovementOrderDetailRespVO> buildMovementOrderDetailRespVOList(List<WmsMovementOrderDetailDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 查询关联数据
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsMovementOrderDetailDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertSetByFlatMap(list,
detail -> Stream.of(detail.getSourceWarehouseId(), detail.getTargetWarehouseId())));
// 拼接数据
return BeanUtils.toBean(list, WmsMovementOrderDetailRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getSourceWarehouseId(),
warehouse -> vo.setSourceWarehouseName(warehouse.getName()));
MapUtils.findAndThen(warehouseMap, vo.getTargetWarehouseId(),
warehouse -> vo.setTargetWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,64 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 移库单明细 Response VO")
@Data
public class WmsMovementOrderDetailRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "移库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderId;
@Schema(description = "商品编号", example = "2048")
private Long itemId;
@Schema(description = "商品编号", example = "SPU-APPLE")
private String itemCode;
@Schema(description = "商品名称", example = "红富士苹果")
private String itemName;
@Schema(description = "商品单位", example = "箱")
private String unit;
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long skuId;
@Schema(description = "规格编号", example = "SKU-APPLE-10KG")
private String skuCode;
@Schema(description = "规格名称", example = "10kg 箱装")
private String skuName;
@Schema(description = "来源仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long sourceWarehouseId;
@Schema(description = "来源仓库名称", example = "北京仓")
private String sourceWarehouseName;
@Schema(description = "目标仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long targetWarehouseId;
@Schema(description = "目标仓库名称", example = "上海仓")
private String targetWarehouseName;
@Schema(description = "移库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal quantity;
@Schema(description = "单价", example = "100.00")
private BigDecimal price;
@Schema(description = "行金额", example = "1000.00")
private BigDecimal totalPrice;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - WMS 移库单明细保存 Request VO")
@Data
public class WmsMovementOrderDetailSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
@NotNull(message = "SKU 不能为空")
private Long skuId;
@Schema(description = "移库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
@NotNull(message = "移库数量不能为空")
@DecimalMin(value = "0", inclusive = false, message = "移库数量必须大于 0")
private BigDecimal quantity;
@Schema(description = "单价", example = "100.00")
@DecimalMin(value = "0", message = "单价不能小于 0")
private BigDecimal price;
@Schema(description = "行金额", example = "1000.00")
@DecimalMin(value = "0", message = "行金额不能小于 0")
private BigDecimal totalPrice;
}

View File

@ -0,0 +1,66 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - WMS 移库单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsMovementOrderPageReqVO extends PageParam {
@Schema(description = "移库单号", example = "YK202605110001")
private String no;
@Schema(description = "单据状态", example = "0")
@InEnum(WmsOrderStatusEnum.class)
private Integer status;
@Schema(description = "来源仓库编号", example = "1024")
private Long sourceWarehouseId;
@Schema(description = "目标仓库编号", example = "2048")
private Long targetWarehouseId;
@Schema(description = "单据日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] orderTime;
@Schema(description = "最小数量", example = "1.00")
private BigDecimal totalQuantityMin;
@Schema(description = "最大数量", example = "100.00")
private BigDecimal totalQuantityMax;
@Schema(description = "最小总金额", example = "1.00")
private BigDecimal totalPriceMin;
@Schema(description = "最大总金额", example = "1000.00")
private BigDecimal totalPriceMax;
@Schema(description = "创建用户", example = "1")
private String creator;
@Schema(description = "更新用户", example = "1")
private String updater;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "更新时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] updateTime;
}

View File

@ -0,0 +1,82 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail.WmsMovementOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 移库单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class WmsMovementOrderRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "移库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "YK202605110001")
@ExcelProperty("移库单号")
private String no;
@Schema(description = "单据日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("单据日期")
private LocalDateTime orderTime;
@Schema(description = "移库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@ExcelProperty(value = "移库状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.ORDER_STATUS)
private Integer status;
@Schema(description = "备注", example = "备注")
private String remark;
@Schema(description = "来源仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long sourceWarehouseId;
@Schema(description = "来源仓库名称", example = "北京仓")
@ExcelProperty("来源仓库")
private String sourceWarehouseName;
@Schema(description = "目标仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long targetWarehouseId;
@Schema(description = "目标仓库名称", example = "上海仓")
@ExcelProperty("目标仓库")
private String targetWarehouseName;
@Schema(description = "移库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
@ExcelProperty("移库数量")
private BigDecimal totalQuantity;
@Schema(description = "总金额", example = "1000.00")
@ExcelProperty("总金额")
private BigDecimal totalPrice;
@Schema(description = "移库明细")
private List<WmsMovementOrderDetailRespVO> details;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "创建者", example = "1")
private String creator;
@Schema(description = "创建者名称", example = "芋道")
private String creatorName;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime updateTime;
@Schema(description = "更新者", example = "1")
private String updater;
@Schema(description = "更新者名称", example = "芋道")
private String updaterName;
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order;
import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail.WmsMovementOrderDetailSaveReqVO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 移库单保存 Request VO")
@Data
public class WmsMovementOrderSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "移库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "YK202605110001")
@NotBlank(message = "移库单号不能为空")
@Size(max = 64, message = "移库单号长度不能超过 64 个字符")
private String no;
@Schema(description = "单据日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "单据日期不能为空")
private LocalDateTime orderTime;
@Schema(description = "备注", example = "备注")
@Size(max = 255, message = "备注长度不能超过 255 个字符")
private String remark;
@Schema(description = "来源仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "来源仓库不能为空")
private Long sourceWarehouseId;
@Schema(description = "目标仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
@NotNull(message = "目标仓库不能为空")
private Long targetWarehouseId;
@Schema(description = "移库明细")
@Valid
private List<WmsMovementOrderDetailSaveReqVO> details;
}

View File

@ -0,0 +1,204 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.receipt;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail.WmsReceiptOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order.WmsReceiptOrderPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order.WmsReceiptOrderRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order.WmsReceiptOrderSaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.merchant.WmsMerchantDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.receipt.WmsReceiptOrderDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.receipt.WmsReceiptOrderDetailDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.merchant.WmsMerchantService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import cn.iocoder.yudao.module.wms.service.order.receipt.WmsReceiptOrderDetailService;
import cn.iocoder.yudao.module.wms.service.order.receipt.WmsReceiptOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
@Tag(name = "管理后台 - WMS 入库单")
@RestController
@RequestMapping("/wms/receipt-order")
@Validated
public class WmsReceiptOrderController {
@Resource
private WmsReceiptOrderService receiptOrderService;
@Resource
private WmsReceiptOrderDetailService receiptOrderDetailService;
@Resource
private WmsMerchantService merchantService;
@Resource
private WmsWarehouseService warehouseService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private AdminUserApi adminUserApi;
@PostMapping("/create")
@Operation(summary = "创建入库单")
@PreAuthorize("@ss.hasPermission('wms:receipt-order:create')")
public CommonResult<Long> createReceiptOrder(@Valid @RequestBody WmsReceiptOrderSaveReqVO createReqVO) {
return success(receiptOrderService.createReceiptOrder(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新入库单")
@PreAuthorize("@ss.hasPermission('wms:receipt-order:update')")
public CommonResult<Boolean> updateReceiptOrder(@Valid @RequestBody WmsReceiptOrderSaveReqVO updateReqVO) {
receiptOrderService.updateReceiptOrder(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除入库单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:receipt-order:delete')")
public CommonResult<Boolean> deleteReceiptOrder(@RequestParam("id") Long id) {
receiptOrderService.deleteReceiptOrder(id);
return success(true);
}
@PutMapping("/complete")
@Operation(summary = "完成入库")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:receipt-order:complete')")
public CommonResult<Boolean> completeReceiptOrder(@RequestParam("id") Long id) {
receiptOrderService.completeReceiptOrder(id);
return success(true);
}
@PutMapping("/cancel")
@Operation(summary = "作废入库单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:receipt-order:cancel')")
public CommonResult<Boolean> cancelReceiptOrder(@RequestParam("id") Long id) {
receiptOrderService.cancelReceiptOrder(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得入库单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:receipt-order:query')")
public CommonResult<WmsReceiptOrderRespVO> getReceiptOrder(@RequestParam("id") Long id) {
WmsReceiptOrderDO order = receiptOrderService.getReceiptOrder(id);
if (order == null) {
return success(null);
}
// 获得入库单的明细列表
List<WmsReceiptOrderDetailDO> detailList = receiptOrderDetailService.getReceiptOrderDetailList(id);
// 拼接结果返回
WmsReceiptOrderRespVO respVO = buildReceiptOrderRespVO(order)
.setDetails(buildReceiptOrderDetailRespVOList(detailList));
return success(respVO);
}
@GetMapping("/page")
@Operation(summary = "获得入库单分页")
@PreAuthorize("@ss.hasPermission('wms:receipt-order:query')")
public CommonResult<PageResult<WmsReceiptOrderRespVO>> getReceiptOrderPage(@Valid WmsReceiptOrderPageReqVO pageReqVO) {
PageResult<WmsReceiptOrderDO> pageResult = receiptOrderService.getReceiptOrderPage(pageReqVO);
return success(new PageResult<>(buildReceiptOrderRespVOList(pageResult.getList()), pageResult.getTotal()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出入库单 Excel")
@PreAuthorize("@ss.hasPermission('wms:receipt-order:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportReceiptOrderExcel(@Valid WmsReceiptOrderPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<WmsReceiptOrderDO> list = receiptOrderService.getReceiptOrderPage(pageReqVO).getList();
ExcelUtils.write(response, "入库单.xls", "数据", WmsReceiptOrderRespVO.class,
buildReceiptOrderRespVOList(list));
}
// ==================== 拼接 VO ====================
private WmsReceiptOrderRespVO buildReceiptOrderRespVO(WmsReceiptOrderDO order) {
if (order == null) {
return null;
}
List<WmsReceiptOrderRespVO> list = buildReceiptOrderRespVOList(Collections.singletonList(order));
return CollUtil.getFirst(list);
}
private List<WmsReceiptOrderRespVO> buildReceiptOrderRespVOList(List<WmsReceiptOrderDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 获取相关的商户、仓库、用户等数据
Map<Long, WmsMerchantDO> merchantMap = merchantService.getMerchantMap(convertSet(list, WmsReceiptOrderDO::getMerchantId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertSet(list, WmsReceiptOrderDO::getWarehouseId));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(list,
order -> Stream.of(parseUserId(order.getCreator()), parseUserId(order.getUpdater()))));
// 拼接数据
return BeanUtils.toBean(list, WmsReceiptOrderRespVO.class, vo -> {
MapUtils.findAndThen(merchantMap, vo.getMerchantId(), merchant -> vo.setMerchantName(merchant.getName()));
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
MapUtils.findAndThen(userMap, parseUserId(vo.getCreator()), user -> vo.setCreatorName(user.getNickname()));
MapUtils.findAndThen(userMap, parseUserId(vo.getUpdater()), user -> vo.setUpdaterName(user.getNickname()));
});
}
private Long parseUserId(String userId) {
return NumberUtil.parseLong(userId, null);
}
private List<WmsReceiptOrderDetailRespVO> buildReceiptOrderDetailRespVOList(List<WmsReceiptOrderDetailDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 获取相关的商品、SKU、仓库等数据
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsReceiptOrderDetailDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(list, WmsReceiptOrderDetailDO::getWarehouseId));
// 拼接数据
return BeanUtils.toBean(list, WmsReceiptOrderDetailRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.receipt;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail.WmsReceiptOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.receipt.WmsReceiptOrderDetailDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import cn.iocoder.yudao.module.wms.service.order.receipt.WmsReceiptOrderDetailService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - WMS 入库单明细")
@RestController
@RequestMapping("/wms/receipt-order-detail")
@Validated
public class WmsReceiptOrderDetailController {
@Resource
private WmsReceiptOrderDetailService receiptOrderDetailService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private WmsWarehouseService warehouseService;
@GetMapping("/list-by-order-id")
@Operation(summary = "获得入库单明细列表")
@Parameter(name = "orderId", description = "入库单编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:receipt-order:query')")
public CommonResult<List<WmsReceiptOrderDetailRespVO>> getReceiptOrderDetailListByOrderId(
@RequestParam("orderId") Long orderId) {
List<WmsReceiptOrderDetailDO> list = receiptOrderDetailService.getReceiptOrderDetailList(orderId);
return success(buildReceiptOrderDetailRespVOList(list));
}
// ==================== 拼接 VO ====================
private List<WmsReceiptOrderDetailRespVO> buildReceiptOrderDetailRespVOList(List<WmsReceiptOrderDetailDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 查询关联数据
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsReceiptOrderDetailDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(list, WmsReceiptOrderDetailDO::getWarehouseId));
// 拼接数据
return BeanUtils.toBean(list, WmsReceiptOrderDetailRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 入库单明细 Response VO")
@Data
public class WmsReceiptOrderDetailRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderId;
@Schema(description = "商品编号", example = "2048")
private Long itemId;
@Schema(description = "商品编号", example = "SPU-APPLE")
private String itemCode;
@Schema(description = "商品名称", example = "红富士苹果")
private String itemName;
@Schema(description = "商品单位", example = "箱")
private String unit;
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long skuId;
@Schema(description = "规格编号", example = "SKU-APPLE-10KG")
private String skuCode;
@Schema(description = "规格名称", example = "10kg 箱装")
private String skuName;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long warehouseId;
@Schema(description = "仓库名称", example = "北京仓")
private String warehouseName;
@Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal quantity;
@Schema(description = "单价", example = "1000.00")
private BigDecimal price;
@Schema(description = "行金额", example = "1500.00")
private BigDecimal totalPrice;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - WMS 入库单明细保存 Request VO")
@Data
public class WmsReceiptOrderDetailSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
@NotNull(message = "SKU 不能为空")
private Long skuId;
@Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
@NotNull(message = "入库数量不能为空")
@DecimalMin(value = "0", inclusive = false, message = "入库数量必须大于 0")
private BigDecimal quantity;
@Schema(description = "单价", example = "1000.00")
@DecimalMin(value = "0", message = "单价不能小于 0")
private BigDecimal price;
@Schema(description = "行金额", example = "1500.00")
@DecimalMin(value = "0", message = "行金额不能小于 0")
private BigDecimal totalPrice;
}

View File

@ -0,0 +1,74 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
import cn.iocoder.yudao.module.wms.enums.order.WmsReceiptOrderTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - WMS 入库单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsReceiptOrderPageReqVO extends PageParam {
@Schema(description = "入库单号", example = "RK202605110001")
private String no;
@Schema(description = "单据状态", example = "0")
@InEnum(WmsOrderStatusEnum.class)
private Integer status;
@Schema(description = "仓库编号", example = "1024")
private Long warehouseId;
@Schema(description = "供应商编号", example = "1024")
private Long merchantId;
@Schema(description = "单据日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] orderTime;
@Schema(description = "最小数量", example = "1.00")
private BigDecimal totalQuantityMin;
@Schema(description = "最大数量", example = "100.00")
private BigDecimal totalQuantityMax;
@Schema(description = "最小总金额", example = "1.00")
private BigDecimal totalPriceMin;
@Schema(description = "最大总金额", example = "1000.00")
private BigDecimal totalPriceMax;
@Schema(description = "入库类型", example = "101")
@InEnum(WmsReceiptOrderTypeEnum.class)
private Integer type;
@Schema(description = "业务单号", example = "PO202605110001")
private String bizOrderNo;
@Schema(description = "创建用户", example = "1")
private String creator;
@Schema(description = "更新用户", example = "1")
private String updater;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "更新时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] updateTime;
}

View File

@ -0,0 +1,91 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail.WmsReceiptOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 入库单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class WmsReceiptOrderRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "入库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RK202605110001")
@ExcelProperty("入库单号")
private String no;
@Schema(description = "入库类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "101")
@ExcelProperty(value = "入库类型", converter = DictConvert.class)
@DictFormat(DictTypeConstants.RECEIPT_ORDER_TYPE)
private Integer type;
@Schema(description = "单据日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("单据日期")
private LocalDateTime orderTime;
@Schema(description = "入库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@ExcelProperty(value = "入库状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.ORDER_STATUS)
private Integer status;
@Schema(description = "业务单号", example = "PO202605110001")
@ExcelProperty("业务单号")
private String bizOrderNo;
@Schema(description = "供应商编号", example = "1024")
private Long merchantId;
@Schema(description = "供应商名称", example = "某某公司")
@ExcelProperty("供应商")
private String merchantName;
@Schema(description = "备注", example = "备注")
private String remark;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long warehouseId;
@Schema(description = "仓库名称", example = "北京仓")
@ExcelProperty("仓库")
private String warehouseName;
@Schema(description = "入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
@ExcelProperty("入库数量")
private BigDecimal totalQuantity;
@Schema(description = "总金额", example = "1000.00")
@ExcelProperty("总金额")
private BigDecimal totalPrice;
@Schema(description = "入库明细")
private List<WmsReceiptOrderDetailRespVO> details;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "创建者", example = "1")
private String creator;
@Schema(description = "创建者名称", example = "芋道")
private String creatorName;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime updateTime;
@Schema(description = "更新者", example = "1")
private String updater;
@Schema(description = "更新者名称", example = "芋道")
private String updaterName;
}

View File

@ -0,0 +1,56 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail.WmsReceiptOrderDetailSaveReqVO;
import cn.iocoder.yudao.module.wms.enums.order.WmsReceiptOrderTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 入库单保存 Request VO")
@Data
public class WmsReceiptOrderSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "入库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "RK202605110001")
@NotBlank(message = "入库单号不能为空")
@Size(max = 64, message = "入库单号长度不能超过 64 个字符")
private String no;
@Schema(description = "入库类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "101")
@NotNull(message = "入库类型不能为空")
@InEnum(WmsReceiptOrderTypeEnum.class)
private Integer type;
@Schema(description = "单据日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "单据日期不能为空")
private LocalDateTime orderTime;
@Schema(description = "业务单号", example = "PO202605110001")
@Size(max = 64, message = "业务单号长度不能超过 64 个字符")
private String bizOrderNo;
@Schema(description = "供应商编号", example = "1024")
private Long merchantId;
@Schema(description = "备注", example = "备注")
@Size(max = 255, message = "备注长度不能超过 255 个字符")
private String remark;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "仓库不能为空")
private Long warehouseId;
@Schema(description = "入库明细")
@Valid
private List<WmsReceiptOrderDetailSaveReqVO> details;
}

View File

@ -0,0 +1,204 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.shipment;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderPageReqVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderRespVO;
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.merchant.WmsMerchantDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.merchant.WmsMerchantService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderDetailService;
import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
@Tag(name = "管理后台 - WMS 出库单")
@RestController
@RequestMapping("/wms/shipment-order")
@Validated
public class WmsShipmentOrderController {
@Resource
private WmsShipmentOrderService shipmentOrderService;
@Resource
private WmsShipmentOrderDetailService shipmentOrderDetailService;
@Resource
private WmsMerchantService merchantService;
@Resource
private WmsWarehouseService warehouseService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private AdminUserApi adminUserApi;
@PostMapping("/create")
@Operation(summary = "创建出库单")
@PreAuthorize("@ss.hasPermission('wms:shipment-order:create')")
public CommonResult<Long> createShipmentOrder(@Valid @RequestBody WmsShipmentOrderSaveReqVO createReqVO) {
return success(shipmentOrderService.createShipmentOrder(createReqVO));
}
@PutMapping("/update")
@Operation(summary = "更新出库单")
@PreAuthorize("@ss.hasPermission('wms:shipment-order:update')")
public CommonResult<Boolean> updateShipmentOrder(@Valid @RequestBody WmsShipmentOrderSaveReqVO updateReqVO) {
shipmentOrderService.updateShipmentOrder(updateReqVO);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除出库单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:shipment-order:delete')")
public CommonResult<Boolean> deleteShipmentOrder(@RequestParam("id") Long id) {
shipmentOrderService.deleteShipmentOrder(id);
return success(true);
}
@PutMapping("/complete")
@Operation(summary = "完成出库")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:shipment-order:complete')")
public CommonResult<Boolean> completeShipmentOrder(@RequestParam("id") Long id) {
shipmentOrderService.completeShipmentOrder(id);
return success(true);
}
@PutMapping("/cancel")
@Operation(summary = "作废出库单")
@Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('wms:shipment-order:cancel')")
public CommonResult<Boolean> cancelShipmentOrder(@RequestParam("id") Long id) {
shipmentOrderService.cancelShipmentOrder(id);
return success(true);
}
@GetMapping("/get")
@Operation(summary = "获得出库单")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:shipment-order:query')")
public CommonResult<WmsShipmentOrderRespVO> getShipmentOrder(@RequestParam("id") Long id) {
WmsShipmentOrderDO order = shipmentOrderService.getShipmentOrder(id);
if (order == null) {
return success(null);
}
// 获得出库单的明细列表
List<WmsShipmentOrderDetailDO> detailList = shipmentOrderDetailService.getShipmentOrderDetailList(id);
// 拼接结果返回
WmsShipmentOrderRespVO respVO = buildShipmentOrderRespVO(order)
.setDetails(buildShipmentOrderDetailRespVOList(detailList));
return success(respVO);
}
@GetMapping("/page")
@Operation(summary = "获得出库单分页")
@PreAuthorize("@ss.hasPermission('wms:shipment-order:query')")
public CommonResult<PageResult<WmsShipmentOrderRespVO>> getShipmentOrderPage(@Valid WmsShipmentOrderPageReqVO pageReqVO) {
PageResult<WmsShipmentOrderDO> pageResult = shipmentOrderService.getShipmentOrderPage(pageReqVO);
return success(new PageResult<>(buildShipmentOrderRespVOList(pageResult.getList()), pageResult.getTotal()));
}
@GetMapping("/export-excel")
@Operation(summary = "导出出库单 Excel")
@PreAuthorize("@ss.hasPermission('wms:shipment-order:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportShipmentOrderExcel(@Valid WmsShipmentOrderPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<WmsShipmentOrderDO> list = shipmentOrderService.getShipmentOrderPage(pageReqVO).getList();
ExcelUtils.write(response, "出库单.xls", "数据", WmsShipmentOrderRespVO.class,
buildShipmentOrderRespVOList(list));
}
// ==================== 拼接 VO ====================
private WmsShipmentOrderRespVO buildShipmentOrderRespVO(WmsShipmentOrderDO order) {
if (order == null) {
return null;
}
List<WmsShipmentOrderRespVO> list = buildShipmentOrderRespVOList(Collections.singletonList(order));
return CollUtil.getFirst(list);
}
private List<WmsShipmentOrderRespVO> buildShipmentOrderRespVOList(List<WmsShipmentOrderDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 获取相关的商户、仓库、用户等数据
Map<Long, WmsMerchantDO> merchantMap = merchantService.getMerchantMap(convertSet(list, WmsShipmentOrderDO::getMerchantId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertSet(list, WmsShipmentOrderDO::getWarehouseId));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(list,
order -> Stream.of(parseUserId(order.getCreator()), parseUserId(order.getUpdater()))));
// 拼接数据
return BeanUtils.toBean(list, WmsShipmentOrderRespVO.class, vo -> {
MapUtils.findAndThen(merchantMap, vo.getMerchantId(), merchant -> vo.setMerchantName(merchant.getName()));
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
MapUtils.findAndThen(userMap, parseUserId(vo.getCreator()), user -> vo.setCreatorName(user.getNickname()));
MapUtils.findAndThen(userMap, parseUserId(vo.getUpdater()), user -> vo.setUpdaterName(user.getNickname()));
});
}
private Long parseUserId(String userId) {
return NumberUtil.parseLong(userId, null);
}
private List<WmsShipmentOrderDetailRespVO> buildShipmentOrderDetailRespVOList(List<WmsShipmentOrderDetailDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 获取相关的商品、SKU、仓库等数据
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsShipmentOrderDetailDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(list, WmsShipmentOrderDetailDO::getWarehouseId));
// 拼接数据
return BeanUtils.toBean(list, WmsShipmentOrderDetailRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.shipment;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService;
import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService;
import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService;
import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderDetailService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - WMS 出库单明细")
@RestController
@RequestMapping("/wms/shipment-order-detail")
@Validated
public class WmsShipmentOrderDetailController {
@Resource
private WmsShipmentOrderDetailService shipmentOrderDetailService;
@Resource
private WmsItemService itemService;
@Resource
private WmsItemSkuService itemSkuService;
@Resource
private WmsWarehouseService warehouseService;
@GetMapping("/list-by-order-id")
@Operation(summary = "获得出库单明细列表")
@Parameter(name = "orderId", description = "出库单编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('wms:shipment-order:query')")
public CommonResult<List<WmsShipmentOrderDetailRespVO>> getShipmentOrderDetailListByOrderId(
@RequestParam("orderId") Long orderId) {
List<WmsShipmentOrderDetailDO> list = shipmentOrderDetailService.getShipmentOrderDetailList(orderId);
return success(buildShipmentOrderDetailRespVOList(list));
}
// ==================== 拼接 VO ====================
private List<WmsShipmentOrderDetailRespVO> buildShipmentOrderDetailRespVOList(List<WmsShipmentOrderDetailDO> list) {
if (CollUtil.isEmpty(list)) {
return Collections.emptyList();
}
// 查询关联数据
Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsShipmentOrderDetailDO::getSkuId));
Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId));
Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(list, WmsShipmentOrderDetailDO::getWarehouseId));
// 拼接数据
return BeanUtils.toBean(list, WmsShipmentOrderDetailRespVO.class, vo -> {
MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> {
vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId());
MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode())
.setItemName(item.getName()).setUnit(item.getUnit()));
});
MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName()));
});
}
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - WMS 出库单明细 Response VO")
@Data
public class WmsShipmentOrderDetailRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long orderId;
@Schema(description = "商品编号", example = "2048")
private Long itemId;
@Schema(description = "商品编号", example = "SPU-APPLE")
private String itemCode;
@Schema(description = "商品名称", example = "红富士苹果")
private String itemName;
@Schema(description = "商品单位", example = "箱")
private String unit;
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long skuId;
@Schema(description = "规格编号", example = "SKU-APPLE-10KG")
private String skuCode;
@Schema(description = "规格名称", example = "10kg 箱装")
private String skuName;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long warehouseId;
@Schema(description = "仓库名称", example = "北京仓")
private String warehouseName;
@Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal quantity;
@Schema(description = "单价", example = "100.00")
private BigDecimal price;
@Schema(description = "行金额", example = "1000.00")
private BigDecimal totalPrice;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - WMS 出库单明细保存 Request VO")
@Data
public class WmsShipmentOrderDetailSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
@NotNull(message = "SKU 不能为空")
private Long skuId;
@Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
@NotNull(message = "出库数量不能为空")
@DecimalMin(value = "0", inclusive = false, message = "出库数量必须大于 0")
private BigDecimal quantity;
@Schema(description = "单价", example = "100.00")
@DecimalMin(value = "0", message = "单价不能小于 0")
private BigDecimal price;
@Schema(description = "行金额", example = "1000.00")
@DecimalMin(value = "0", message = "行金额不能小于 0")
private BigDecimal totalPrice;
}

View File

@ -0,0 +1,74 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum;
import cn.iocoder.yudao.module.wms.enums.order.WmsShipmentOrderTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - WMS 出库单分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class WmsShipmentOrderPageReqVO extends PageParam {
@Schema(description = "出库单号", example = "CK202605110001")
private String no;
@Schema(description = "单据状态", example = "0")
@InEnum(WmsOrderStatusEnum.class)
private Integer status;
@Schema(description = "仓库编号", example = "1024")
private Long warehouseId;
@Schema(description = "客户编号", example = "1024")
private Long merchantId;
@Schema(description = "单据日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] orderTime;
@Schema(description = "最小数量", example = "1.00")
private BigDecimal totalQuantityMin;
@Schema(description = "最大数量", example = "100.00")
private BigDecimal totalQuantityMax;
@Schema(description = "最小总金额", example = "1.00")
private BigDecimal totalPriceMin;
@Schema(description = "最大总金额", example = "1000.00")
private BigDecimal totalPriceMax;
@Schema(description = "出库类型", example = "201")
@InEnum(WmsShipmentOrderTypeEnum.class)
private Integer type;
@Schema(description = "业务单号", example = "SO202605110001")
private String bizOrderNo;
@Schema(description = "创建用户", example = "1")
private String creator;
@Schema(description = "更新用户", example = "1")
private String updater;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
@Schema(description = "更新时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] updateTime;
}

View File

@ -0,0 +1,91 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailRespVO;
import cn.iocoder.yudao.module.wms.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 出库单 Response VO")
@Data
@ExcelIgnoreUnannotated
public class WmsShipmentOrderRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "出库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "CK202605110001")
@ExcelProperty("出库单号")
private String no;
@Schema(description = "出库类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "201")
@ExcelProperty(value = "出库类型", converter = DictConvert.class)
@DictFormat(DictTypeConstants.SHIPMENT_ORDER_TYPE)
private Integer type;
@Schema(description = "单据日期", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("单据日期")
private LocalDateTime orderTime;
@Schema(description = "出库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@ExcelProperty(value = "出库状态", converter = DictConvert.class)
@DictFormat(DictTypeConstants.ORDER_STATUS)
private Integer status;
@Schema(description = "业务单号", example = "SO202605110001")
@ExcelProperty("业务单号")
private String bizOrderNo;
@Schema(description = "客户编号", example = "1024")
private Long merchantId;
@Schema(description = "客户名称", example = "某某公司")
@ExcelProperty("客户")
private String merchantName;
@Schema(description = "备注", example = "备注")
private String remark;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long warehouseId;
@Schema(description = "仓库名称", example = "北京仓")
@ExcelProperty("仓库")
private String warehouseName;
@Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
@ExcelProperty("出库数量")
private BigDecimal totalQuantity;
@Schema(description = "总金额", example = "1000.00")
@ExcelProperty("总金额")
private BigDecimal totalPrice;
@Schema(description = "出库明细")
private List<WmsShipmentOrderDetailRespVO> details;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
private LocalDateTime createTime;
@Schema(description = "创建者", example = "1")
private String creator;
@Schema(description = "创建者名称", example = "芋道")
private String creatorName;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime updateTime;
@Schema(description = "更新者", example = "1")
private String updater;
@Schema(description = "更新者名称", example = "芋道")
private String updaterName;
}

View File

@ -0,0 +1,56 @@
package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailSaveReqVO;
import cn.iocoder.yudao.module.wms.enums.order.WmsShipmentOrderTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - WMS 出库单保存 Request VO")
@Data
public class WmsShipmentOrderSaveReqVO {
@Schema(description = "编号", example = "1024")
private Long id;
@Schema(description = "出库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "CK202605110001")
@NotBlank(message = "出库单号不能为空")
@Size(max = 64, message = "出库单号长度不能超过 64 个字符")
private String no;
@Schema(description = "出库类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "201")
@NotNull(message = "出库类型不能为空")
@InEnum(WmsShipmentOrderTypeEnum.class)
private Integer type;
@Schema(description = "单据日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "单据日期不能为空")
private LocalDateTime orderTime;
@Schema(description = "业务单号", example = "SO202605110001")
@Size(max = 64, message = "业务单号长度不能超过 64 个字符")
private String bizOrderNo;
@Schema(description = "客户编号", example = "1024")
private Long merchantId;
@Schema(description = "备注", example = "备注")
@Size(max = 255, message = "备注长度不能超过 255 个字符")
private String remark;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "仓库不能为空")
private Long warehouseId;
@Schema(description = "出库明细")
@Valid
private List<WmsShipmentOrderDetailSaveReqVO> details;
}

View File

@ -0,0 +1,4 @@
/**
* WMS API
*/
package cn.iocoder.yudao.module.wms.controller.admin;

View File

@ -0,0 +1,6 @@
/**
* RESTful API
* 1. admin yudao-ui-admin
* 2. app APP yudao-ui-app Controller VO App
*/
package cn.iocoder.yudao.module.wms.controller;

View File

@ -0,0 +1,54 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.inventory;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
/**
* WMS DO
*
* @author
*/
@TableName("wms_inventory")
@KeySequence("wms_inventory_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsInventoryDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
* SKU
*
* {@link WmsItemSkuDO#getId()}
*/
private Long skuId;
/**
*
*
* {@link WmsWarehouseDO#getId()}
*/
private Long warehouseId;
/**
*
*/
private BigDecimal quantity;
/**
*
*/
private String remark;
}

View File

@ -0,0 +1,94 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.inventory;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
/**
* WMS DO
*
* @author
*/
@TableName("wms_inventory_history")
@KeySequence("wms_inventory_history_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsInventoryHistoryDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
// ========= 库存维度相关字段 =========
/**
*
*
* {@link WmsWarehouseDO#getId()}
*/
private Long warehouseId;
/**
* SKU
*
* {@link WmsItemSkuDO#getId()}
*/
private Long skuId;
/**
*
*/
private BigDecimal quantity;
/**
*
*/
private BigDecimal beforeQuantity;
/**
*
*/
private BigDecimal afterQuantity;
// ========= 单价备注相关字段 =========
/**
*
*/
private BigDecimal price;
/**
*
*/
private BigDecimal totalPrice;
/**
*
*/
private String remark;
// ========= 来源单据相关字段 =========
/**
*
*/
private Long orderId;
/**
*
*/
private String orderNo;
/**
*
*
* {@link WmsOrderTypeEnum#getType()}
*/
private Integer orderType;
}

View File

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.md.item;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* WMS DO
*
* @author
*/
@TableName("wms_item_brand")
@KeySequence("wms_item_brand_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsItemBrandDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String code;
/**
*
*/
private String name;
}

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.md.item;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* WMS DO
*
* @author
*/
@TableName("wms_item_category")
@KeySequence("wms_item_category_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsItemCategoryDO extends BaseDO {
/**
* -
*/
public static final Long PARENT_ID_ROOT = 0L;
/**
*
*/
@TableId
private Long id;
/**
*
*
* {@link #id}
*/
private Long parentId;
/**
*
*/
private String code;
/**
*
*/
private String name;
/**
*
*/
private Integer sort;
/**
*
*
* {@link CommonStatusEnum}
*/
private Integer status;
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.md.item;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* WMS DO
*
* @author
*/
@TableName("wms_item")
@KeySequence("wms_item_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsItemDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String code;
/**
*
*/
private String name;
/**
*
*/
private String unit;
/**
*
*
* {@link WmsItemCategoryDO#getId()}
*/
private Long categoryId;
/**
*
*
* {@link WmsItemBrandDO#getId()}
*/
private Long brandId;
/**
*
*/
private String remark;
}

View File

@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.md.item;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
/**
* WMS SKU DO
*
* @author
*/
@TableName("wms_item_sku")
@KeySequence("wms_item_sku_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsItemSkuDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String name;
/**
*
*
* {@link WmsItemDO#getId()}
*/
private Long itemId;
/**
*
*/
private String barCode;
/**
*
*/
private String code;
/**
* cm
*/
private BigDecimal length;
/**
* cm
*/
private BigDecimal width;
/**
* cm
*/
private BigDecimal height;
/**
* kg
*/
private BigDecimal grossWeight;
/**
* kg
*/
private BigDecimal netWeight;
/**
*
*/
private BigDecimal costPrice;
/**
*
*/
private BigDecimal sellingPrice;
}

View File

@ -0,0 +1,81 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.md.merchant;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.wms.enums.md.WmsMerchantTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* WMS DO
*
* @author
*/
@TableName("wms_merchant")
@KeySequence("wms_merchant_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsMerchantDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String code;
/**
*
*/
private String name;
/**
*
*
* {@link WmsMerchantTypeEnum}
*/
private Integer type;
/**
*
*/
private String level;
/**
*
*/
private String bankName;
/**
*
*/
private String bankAccount;
/**
*
*/
private String address;
/**
*
*/
private String mobile;
/**
*
*/
private String telephone;
/**
*
*/
private String contact;
/**
* Email
*/
private String email;
/**
*
*/
private String remark;
}

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* WMS DO
*
* @author
*/
@TableName("wms_warehouse")
@KeySequence("wms_warehouse_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsWarehouseDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String code;
/**
*
*/
private String name;
/**
*
*/
private String remark;
/**
*
*/
private Integer sort;
}

View File

@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.order.check;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import cn.iocoder.yudao.module.wms.enums.DictTypeConstants;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* WMS DO
*
* @author
*/
@TableName("wms_check_order")
@KeySequence("wms_check_order_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsCheckOrderDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
/**
*
*/
private String no;
/**
*
*/
private LocalDateTime orderTime;
/**
*
*
* {@link DictTypeConstants#ORDER_STATUS}
*/
private Integer status;
/**
*
*/
private String remark;
// ========= 仓库字段 =========
/**
*
*
* {@link WmsWarehouseDO#getId()}
*/
private Long warehouseId;
// ========= 汇总金额字段 =========
/**
* -
*/
private BigDecimal totalQuantity;
/**
* *
*/
private BigDecimal totalPrice;
/**
* *
*/
private BigDecimal actualPrice;
}

View File

@ -0,0 +1,85 @@
package cn.iocoder.yudao.module.wms.dal.dataobject.order.check;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO;
import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* WMS DO
*
* @author
*/
@TableName("wms_check_order_detail")
@KeySequence("wms_check_order_detail_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WmsCheckOrderDetailDO extends BaseDO {
/**
*
*/
@TableId
private Long id;
// ========= 单据商品字段 =========
/**
*
*
* {@link WmsCheckOrderDO#getId()}
*/
private Long orderId;
/**
* SKU
*
* {@link WmsItemSkuDO#getId()}
*/
private Long skuId;
// ========= 仓库字段 =========
/**
*
*
* {@link WmsWarehouseDO#getId()}
*/
private Long warehouseId;
/**
*
*
* {@link WmsInventoryDO#getId()}
*/
private Long inventoryId;
/**
*
*/
private LocalDateTime receiptTime;
// ========= 数量金额字段 =========
/**
*
*/
private BigDecimal quantity;
/**
*
*/
private BigDecimal checkQuantity;
/**
*
*/
private BigDecimal price;
}

Some files were not shown because too many files have changed in this diff Show More