diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpStockOutUsageTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpStockOutUsageTypeEnum.java
new file mode 100644
index 000000000..cd3668eda
--- /dev/null
+++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpStockOutUsageTypeEnum.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.erp.enums;
+
+import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import java.util.Arrays;
+
+@RequiredArgsConstructor
+@Getter
+public enum ErpStockOutUsageTypeEnum implements IntArrayValuable {
+
+ REPAIR_RECEIVE(1, "维修领用"),
+ MAINTENANCE_RECEIVE(2, "保养领用"),
+ OTHER_OUT(3, "其他出库");
+
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockOutUsageTypeEnum::getType).toArray();
+
+ private final Integer type;
+ private final String name;
+
+ @Override
+ public int[] array() {
+ return ARRAYS;
+ }
+
+ public static String getNameByType(Integer type) {
+ if (type == null) {
+ return null;
+ }
+ for (ErpStockOutUsageTypeEnum value : values()) {
+ if (value.getType().equals(type)) {
+ return value.getName();
+ }
+ }
+ return null;
+ }
+}
diff --git a/yudao-module-erp/yudao-module-erp-biz/pom.xml b/yudao-module-erp/yudao-module-erp-biz/pom.xml
index 41b280faf..7155e92e2 100644
--- a/yudao-module-erp/yudao-module-erp-biz/pom.xml
+++ b/yudao-module-erp/yudao-module-erp-biz/pom.xml
@@ -32,6 +32,11 @@
yudao-module-infra-api
${revision}
+
+ cn.iocoder.boot
+ yudao-module-mes-api
+ ${revision}
+
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java
index 0f0f9ff68..eb47ffc3f 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java
@@ -63,8 +63,8 @@ public class ErpStockController {
@GetMapping("/get")
@Operation(summary = "获得产品库存")
@Parameters({
- @Parameter(name = "id", description = "编号", example = "1"), // 方案一:传递 id
- @Parameter(name = "productId", description = "产品编号", example = "10"), // 方案二:传递 productId + warehouseId
+ @Parameter(name = "id", description = "编号", example = "1"),
+ @Parameter(name = "productId", description = "产品编号", example = "10"),
@Parameter(name = "warehouseId", description = "仓库编号", example = "2")
})
@PreAuthorize("@ss.hasPermission('erp:stock:query')")
@@ -96,10 +96,9 @@ public class ErpStockController {
@PreAuthorize("@ss.hasPermission('erp:stock:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportStockExcel(@Valid ErpStockPageReqVO pageReqVO,
- HttpServletResponse response) throws IOException {
+ HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List list = buildStockVOPageResult(stockService.getStockPage(pageReqVO)).getList();
- // 导出 Excel
ExcelUtils.write(response, "产品库存.xls", "数据", ErpStockRespVO.class, list);
}
@@ -119,7 +118,10 @@ public class ErpStockController {
.setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())
.setCategoryType(product.getCategoryType());
fillProductExtraInfo(stock, product);
+ fillPackagingSnapshot(stock, product);
});
+ stock.setPackagingRule(buildPackagingRule(stock));
+ stock.setStockDisplay(buildStockDisplay(stock));
MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> stock.setWarehouseName(warehouse.getName()));
if (stock.getAreaName() == null) {
MapUtils.findAndThen(areaMap, stock.getAreaId(), area -> stock.setAreaName(area.getAreaName()));
@@ -138,10 +140,18 @@ public class ErpStockController {
respVO.setProductName(product.getName());
respVO.setBarCode(product.getBarCode());
respVO.setCategoryName(product.getCategoryName());
- respVO.setUnitName(product.getUnitName());
- respVO.setCategoryType(product.getCategoryType());
+ if (respVO.getUnitName() == null) {
+ respVO.setUnitName(product.getUnitName());
+ }
+ if (respVO.getCategoryType() == null) {
+ respVO.setCategoryType(product.getCategoryType());
+ }
fillProductExtraInfo(respVO, product);
+ fillPackagingSnapshot(respVO, product);
}
+ fillDerivedFields(respVO);
+ respVO.setPackagingRule(buildPackagingRule(respVO));
+ respVO.setStockDisplay(buildStockDisplay(respVO));
ErpWarehouseDO warehouse = warehouseService.getWarehouse(stock.getWarehouseId());
if (warehouse != null) {
respVO.setWarehouseName(warehouse.getName());
@@ -162,16 +172,64 @@ public class ErpStockController {
stock.setRecentOutTime(stockRecordService.getLatestRecordTime(
stock.getProductId(), stock.getWarehouseId(), stock.getAreaId(), false));
}
+
private void fillProductExtraInfo(ErpStockRespVO stock, ErpProductRespVO product) {
- stock.setUnitId(product.getUnitId());
- stock.setPurchaseUnitId(product.getPurchaseUnitId());
- stock.setPurchaseUnitName(product.getPurchaseUnitName());
- stock.setPurchaseUnitConvertQuantity(product.getPurchaseUnitConvertQuantity());
- stock.setDefaultPackagingSchemeId(product.getDefaultPackagingSchemeId());
- stock.setDefaultPackagingScheme(findDefaultPackagingScheme(product));
+ if (stock.getUnitId() == null) {
+ stock.setUnitId(product.getUnitId());
+ }
+ if (stock.getPurchaseUnitId() == null) {
+ stock.setPurchaseUnitId(product.getPurchaseUnitId());
+ }
+ if (stock.getPurchaseUnitName() == null) {
+ stock.setPurchaseUnitName(product.getPurchaseUnitName());
+ }
+ if (stock.getPurchaseUnitConvertQuantity() == null) {
+ stock.setPurchaseUnitConvertQuantity(product.getPurchaseUnitConvertQuantity());
+ }
+ if (stock.getDefaultPackagingSchemeId() == null) {
+ stock.setDefaultPackagingSchemeId(product.getDefaultPackagingSchemeId());
+ }
+ if (stock.getDefaultPackagingScheme() == null) {
+ stock.setDefaultPackagingScheme(findDefaultPackagingScheme(product));
+ }
+ }
+
+ private void fillPackagingSnapshot(ErpStockRespVO stock, ErpProductRespVO product) {
+ if (stock.getDefaultPackagingSchemeName() != null
+ && stock.getPackageQuantity() != null
+ && stock.getPalletPackageQuantity() != null
+ && stock.getPalletTotalQuantity() != null) {
+ return;
+ }
+ ProductPackagingSchemeRespVO defaultScheme = findDefaultPackagingScheme(product);
+ if (defaultScheme == null) {
+ return;
+ }
+ if (stock.getDefaultPackagingSchemeName() == null) {
+ stock.setDefaultPackagingSchemeName(defaultScheme.getPackagingSchemeName());
+ }
+ if (stock.getPackageQuantity() == null) {
+ stock.setPackageQuantity(defaultScheme.getPackageQuantity());
+ }
+ if (stock.getPalletPackageQuantity() == null) {
+ stock.setPalletPackageQuantity(defaultScheme.getPalletPackageQuantity());
+ }
+ if (stock.getPalletTotalQuantity() == null) {
+ stock.setPalletTotalQuantity(defaultScheme.getPalletTotalQuantity());
+ }
+ }
+
+ private void fillDerivedFields(ErpStockRespVO stock) {
+ if (stock.getUnitName() == null && stock.getUnitId() != null) {
+ // no-op: 目前库存单位名称只能从产品侧回填
+ }
+ if (stock.getDefaultPackagingSchemeId() == null && stock.getDefaultPackagingScheme() != null) {
+ stock.setDefaultPackagingSchemeId(stock.getDefaultPackagingScheme().getPackagingSchemeId());
+ }
}
+
private ProductPackagingSchemeRespVO findDefaultPackagingScheme(ErpProductRespVO product) {
- if (product.getDefaultPackagingSchemeId() == null || CollUtil.isEmpty(product.getPackagingSchemes())) {
+ if (product == null || product.getDefaultPackagingSchemeId() == null || CollUtil.isEmpty(product.getPackagingSchemes())) {
return null;
}
return product.getPackagingSchemes().stream()
@@ -179,4 +237,68 @@ public class ErpStockController {
.findFirst()
.orElse(null);
}
+
+ private String buildPackagingRule(ErpStockRespVO stock) {
+ if (stock == null) {
+ return null;
+ }
+ if (isProductType(stock.getCategoryType())) {
+ if (stock.getPackageQuantity() == null || stock.getPalletPackageQuantity() == null) {
+ return null;
+ }
+ return "1托=" + formatNumber(stock.getPalletPackageQuantity()) + "包 1包=" + formatNumber(stock.getPackageQuantity()) + "个";
+ }
+ if (stock.getPurchaseUnitName() == null || stock.getPurchaseUnitConvertQuantity() == null) {
+ return null;
+ }
+ return "1" + stock.getPurchaseUnitName() + "=" + formatNumber(stock.getPurchaseUnitConvertQuantity()) + "个";
+ }
+
+ private String buildStockDisplay(ErpStockRespVO stock) {
+ if (stock == null || stock.getCount() == null) {
+ return null;
+ }
+ if (isProductType(stock.getCategoryType())) {
+ if (stock.getPalletTotalQuantity() == null || stock.getPalletTotalQuantity().compareTo(BigDecimal.ZERO) <= 0) {
+ return formatNumber(stock.getCount()) + stock.getUnitName();
+ }
+ BigDecimal palletCount = stock.getCount().divideToIntegralValue(stock.getPalletTotalQuantity());
+ return formatNumber(palletCount) + "托,0包,0个";
+ }
+ if (stock.getPurchaseUnitConvertQuantity() == null || stock.getPurchaseUnitConvertQuantity().compareTo(BigDecimal.ZERO) <= 0
+ || stock.getPurchaseUnitName() == null || stock.getUnitName() == null) {
+ return formatNumber(stock.getCount()) + stock.getUnitName();
+ }
+ BigDecimal purchaseCount = stock.getCount().divideToIntegralValue(stock.getPurchaseUnitConvertQuantity());
+ BigDecimal unitCount = stock.getCount().remainder(stock.getPurchaseUnitConvertQuantity());
+ StringBuilder display = new StringBuilder();
+ appendQuantity(display, purchaseCount, stock.getPurchaseUnitName(), true);
+ appendQuantity(display, unitCount, stock.getUnitName(), false);
+ return display.length() > 0 ? display.toString() : formatNumber(stock.getCount()) + stock.getUnitName();
+ }
+
+ private void appendQuantity(StringBuilder display, BigDecimal quantity, String unitName, boolean keepZero) {
+ if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0 || unitName == null) {
+ if (!keepZero) {
+ return;
+ }
+ if (display.length() > 0) {
+ display.append(",");
+ }
+ display.append("0").append(unitName);
+ return;
+ }
+ if (display.length() > 0) {
+ display.append(",");
+ }
+ display.append(formatNumber(quantity)).append(unitName);
+ }
+
+ private boolean isProductType(Integer categoryType) {
+ return Integer.valueOf(1).equals(categoryType);
+ }
+
+ private String formatNumber(BigDecimal value) {
+ return value == null ? "0" : value.stripTrailingZeros().toPlainString();
+ }
}
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java
index e471db81a..f7cfae1d7 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java
@@ -25,6 +25,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecord
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO;
import cn.iocoder.yudao.module.erp.enums.ErpStockOutStatusEnum;
+import cn.iocoder.yudao.module.erp.enums.ErpStockOutUsageTypeEnum;
import cn.iocoder.yudao.module.erp.service.mold.MoldBrandService;
import cn.iocoder.yudao.module.erp.service.mold.MoldService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
@@ -216,6 +217,7 @@ public class ErpStockOutController {
List approveRecords) {
ErpStockOutRespVO stockOutVO = BeanUtils.toBean(stockOut, ErpStockOutRespVO.class);
stockOutVO.setStatusName(getStockOutStatusName(stockOut.getStatus()));
+ stockOutVO.setOutUsageTypeName(ErpStockOutUsageTypeEnum.getNameByType(stockOut.getOutUsageType()));
Map userMap = adminUserApi.getUserMap(convertListByFlatMap(
Collections.singletonList(stockOut), item -> Stream.of(NumberUtils.parseLong(item.getCreator()),
item.getResponserId(), item.getAuditUserId())));
@@ -305,4 +307,4 @@ public class ErpStockOutController {
private String getStockOutStatusName(Integer status) {
return ErpStockOutStatusEnum.OUT_STOCK.getStatus().equals(status) ? "已出库" : "待出库";
}
-}
\ No newline at end of file
+}
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java
index 114f8341e..1a6b29eb9 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java
@@ -44,6 +44,30 @@ public class ErpStockOutRespVO {
@Schema(description = "出库类型", example = "其他出库")
private String outType;
+ @Schema(description = "出库用途", example = "1")
+ private Integer outUsageType;
+
+ @Schema(description = "出库用途名称", example = "维修领用")
+ private String outUsageTypeName;
+
+ @Schema(description = "维修单编号", example = "1001")
+ private Long repairId;
+
+ @Schema(description = "维修单名称快照", example = "设备维修单A")
+ private String repairName;
+
+ @Schema(description = "维修单设备编号", example = "2001")
+ private Long repairDeviceId;
+
+ @Schema(description = "维修单设备名称快照", example = "设备A")
+ private String repairDeviceName;
+
+ @Schema(description = "保养单编号", example = "3001")
+ private Long maintenanceId;
+
+ @Schema(description = "保养单名称快照", example = "设备保养单A")
+ private String maintenanceName;
+
@Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("出库时间")
private LocalDateTime outTime;
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java
index 4f4df93a1..62469c6e9 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out;
import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.validation.InEnum;
import lombok.Data;
import javax.validation.Valid;
@@ -10,6 +11,8 @@ import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
+import cn.iocoder.yudao.module.erp.enums.ErpStockOutUsageTypeEnum;
+
@Schema(description = "管理后台 - ERP 其它出库单新增/修改 Request VO")
@Data
public class ErpStockOutSaveReqVO {
@@ -26,6 +29,20 @@ public class ErpStockOutSaveReqVO {
@Schema(description = "出库类型", example = "其他出库")
private String outType;
+ @Schema(description = "出库用途", example = "1")
+ @InEnum(ErpStockOutUsageTypeEnum.class)
+ @NotNull(message = "出库用途不能为空")
+ private Integer outUsageType;
+
+ @Schema(description = "维修单编号", example = "1001")
+ private Long repairId;
+
+ @Schema(description = "维修单设备编号", example = "2001")
+ private Long repairDeviceId;
+
+ @Schema(description = "保养单编号", example = "3001")
+ private Long maintenanceId;
+
@Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "出库时间不能为空")
private LocalDateTime outTime;
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java
index 9fde24c78..ffb58ab76 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java
@@ -75,6 +75,26 @@ public class ErpStockRespVO {
@Schema(description = "Default Packaging Scheme")
private ProductPackagingSchemeRespVO defaultPackagingScheme;
+ @Schema(description = "默认包装方案名称", example = "标准包装")
+ private String defaultPackagingSchemeName;
+
+ @Schema(description = "每包数量(库存单位)", example = "50")
+ private BigDecimal packageQuantity;
+
+ @Schema(description = "每托包数(包)", example = "20")
+ private BigDecimal palletPackageQuantity;
+
+ @Schema(description = "每托总数量(库存单位)", example = "1000")
+ private BigDecimal palletTotalQuantity;
+
+ @Schema(description = "包装/换算规则", example = "1托=20包 1包=50个")
+ @ExcelProperty("包装/换算规则")
+ private String packagingRule;
+
+ @Schema(description = "库存展示", example = "2托8包30个")
+ @ExcelProperty("库存展示")
+ private String stockDisplay;
+
// ========== 仓库信息 ==========
@Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java
index 2784ee908..641aa696a 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java
@@ -54,6 +54,46 @@ public class ErpStockDO extends BaseDO {
* 库存数量
*/
private BigDecimal count;
+ /**
+ * 库存单位编号
+ */
+ private Long unitId;
+ /**
+ * 库存单位名称
+ */
+ private String unitName;
+ /**
+ * 包装单位编号
+ */
+ private Long purchaseUnitId;
+ /**
+ * 包装单位名称
+ */
+ private String purchaseUnitName;
+ /**
+ * 包装单位与库存单位换算数量
+ */
+ private BigDecimal purchaseUnitConvertQuantity;
+ /**
+ * 默认包装方案编号
+ */
+ private Long defaultPackagingSchemeId;
+ /**
+ * 默认包装方案名称
+ */
+ private String defaultPackagingSchemeName;
+ /**
+ * 每包数量(库存单位)
+ */
+ private BigDecimal packageQuantity;
+ /**
+ * 每托包数(包)
+ */
+ private BigDecimal palletPackageQuantity;
+ /**
+ * 每托总数量(库存单位)
+ */
+ private BigDecimal palletTotalQuantity;
/**
* 产品分类编号
*/
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java
index 51753f700..cfb03caba 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java
@@ -48,6 +48,36 @@ public class ErpStockOutDO extends BaseDO {
private Long responserId;
//@Schema(description = "出库类型", example = "随便")
private String outType;
+ /**
+ * 出库用途
+ *
+ * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpStockOutUsageTypeEnum}
+ */
+ private Integer outUsageType;
+ /**
+ * 维修单名称快照
+ */
+ private String repairName;
+ /**
+ * 维修单编号
+ */
+ private Long repairId;
+ /**
+ * 维修单设备编号
+ */
+ private Long repairDeviceId;
+ /**
+ * 维修单设备名称快照
+ */
+ private String repairDeviceName;
+ /**
+ * 保养单编号
+ */
+ private Long maintenanceId;
+ /**
+ * 保养单名称快照
+ */
+ private String maintenanceName;
/**
* 出库时间
*/
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java
index d9d7999c0..e836824d2 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java
@@ -26,8 +26,13 @@ import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutMapper;
import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
+import cn.iocoder.yudao.module.erp.enums.ErpStockOutUsageTypeEnum;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockOutApproveActionEnum;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum;
+import cn.iocoder.yudao.module.mes.api.dvrepair.DvRepairApi;
+import cn.iocoder.yudao.module.mes.api.dvrepair.dto.DvRepairRespDTO;
+import cn.iocoder.yudao.module.mes.api.ticketmanagement.TicketManagementApi;
+import cn.iocoder.yudao.module.mes.api.ticketmanagement.dto.TicketManagementRespDTO;
import cn.iocoder.yudao.module.erp.service.mold.MoldBrandService;
import cn.iocoder.yudao.module.erp.service.mold.MoldService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
@@ -96,6 +101,10 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
private ConfigApi configApi;
@Resource
private PermissionApi permissionApi;
+ @Resource
+ private DvRepairApi dvRepairApi;
+ @Resource
+ private TicketManagementApi ticketManagementApi;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -123,6 +132,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
.setStatus(status)
.setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add))
.setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)));
+ fillUsageSnapshot(stockOut, createReqVO.getOutUsageType(), createReqVO.getRepairId(),
+ createReqVO.getRepairDeviceId(), createReqVO.getMaintenanceId());
stockOutMapper.insert(stockOut);
stockOutItems.forEach(item -> item.setOutId(stockOut.getId()));
stockOutItemMapper.insertBatch(stockOutItems);
@@ -165,6 +176,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
.setNeedAudit(needAudit)
.setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add))
.setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)));
+ fillUsageSnapshot(updateObj, updateReqVO.getOutUsageType(), updateReqVO.getRepairId(),
+ updateReqVO.getRepairDeviceId(), updateReqVO.getMaintenanceId());
stockOutMapper.updateById(updateObj);
updateStockOutItemList(updateReqVO.getId(), stockOutItems);
}
@@ -394,6 +407,33 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
return !AUDIT_CONFIG_DISABLE_VALUE.equals(configApi.getConfigValueByCategoryAndKey(AUDIT_CONFIG_CATEGORY, AUDIT_CONFIG_KEY));
}
+ private void fillUsageSnapshot(ErpStockOutDO stockOut, Integer outUsageType, Long repairId,
+ Long repairDeviceId, Long maintenanceId) {
+ stockOut.setOutUsageType(outUsageType);
+ stockOut.setRepairId(null);
+ stockOut.setRepairName(null);
+ stockOut.setRepairDeviceId(null);
+ stockOut.setRepairDeviceName(null);
+ stockOut.setMaintenanceId(null);
+ stockOut.setMaintenanceName(null);
+
+ if (ErpStockOutUsageTypeEnum.REPAIR_RECEIVE.getType().equals(outUsageType) && repairId != null) {
+ DvRepairRespDTO repair = dvRepairApi.getDvRepair(repairId);
+ if (repair != null) {
+ stockOut.setRepairId(repair.getId());
+ stockOut.setRepairName(repair.getRepairName());
+ stockOut.setRepairDeviceId(repairDeviceId != null ? repairDeviceId : repair.getMachineryId());
+ stockOut.setRepairDeviceName(repair.getMachineryName());
+ }
+ } else if (ErpStockOutUsageTypeEnum.MAINTENANCE_RECEIVE.getType().equals(outUsageType) && maintenanceId != null) {
+ TicketManagementRespDTO maintenance = ticketManagementApi.getTicketManagement(maintenanceId);
+ if (maintenance != null) {
+ stockOut.setMaintenanceId(maintenance.getId());
+ stockOut.setMaintenanceName(maintenance.getPlanNo());
+ }
+ }
+ }
+
private void createApproveRecord(Long stockOutId, ErpStockOutApproveActionEnum action, Integer fromStatus,
Integer toStatus, Long targetUserId, String remark) {
stockOutApproveRecordMapper.insert(ErpStockOutApproveRecordDO.builder()
diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java
index c3ef910ef..25d6a680a 100644
--- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java
+++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.service.stock;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
+import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper;
@@ -90,12 +91,14 @@ public class ErpStockServiceImpl implements ErpStockService {
String areaName, BigDecimal count) {
ErpProductRespVO product = productService.getProduct(productId);
Integer categoryType = product != null ? product.getCategoryType() : null;
+ ProductPackagingSchemeRespVO defaultPackagingScheme = product != null ? findDefaultPackagingScheme(product) : null;
// 1.1 查询当前库存
ErpStockDO stock = stockMapper.selectByProductIdAndWarehouseIdAndAreaId(productId, warehouseId, areaId);
if (stock == null) {
stock = new ErpStockDO().setProductId(productId).setWarehouseId(warehouseId).setAreaId(areaId)
.setAreaName(areaName).setCount(BigDecimal.ZERO).setCategoryType(categoryType);
stock.setCategoryId(categoryId);
+ fillStockSnapshot(stock, product, defaultPackagingScheme);
stockMapper.insert(stock);
} else if (stock.getCategoryType() == null) {
stock.setCategoryType(categoryType);
@@ -105,6 +108,10 @@ public class ErpStockServiceImpl implements ErpStockService {
stock.setAreaName(areaName);
stockMapper.updateById(new ErpStockDO().setId(stock.getId()).setAreaName(areaName));
}
+ if (product != null && isStockSnapshotMissing(stock)) {
+ fillStockSnapshot(stock, product, defaultPackagingScheme);
+ stockMapper.updateById(buildStockSnapshotUpdate(stock));
+ }
// 1.2 校验库存是否充足
if (!NEGATIVE_STOCK_COUNT_ENABLE && stock.getCount().add(count).compareTo(BigDecimal.ZERO) < 0) {
throw exception(STOCK_COUNT_NEGATIVE, productService.getProduct(productId).getName(),
@@ -123,4 +130,60 @@ public class ErpStockServiceImpl implements ErpStockService {
return stock.getCount().add(count);
}
+ private void fillStockSnapshot(ErpStockDO stock, ErpProductRespVO product,
+ ProductPackagingSchemeRespVO defaultPackagingScheme) {
+ if (product == null) {
+ return;
+ }
+ stock.setUnitId(product.getUnitId());
+ stock.setUnitName(product.getUnitName());
+ stock.setPurchaseUnitId(product.getPurchaseUnitId());
+ stock.setPurchaseUnitName(product.getPurchaseUnitName());
+ stock.setPurchaseUnitConvertQuantity(product.getPurchaseUnitConvertQuantity());
+ if (defaultPackagingScheme != null) {
+ stock.setDefaultPackagingSchemeId(defaultPackagingScheme.getPackagingSchemeId());
+ stock.setDefaultPackagingSchemeName(defaultPackagingScheme.getPackagingSchemeName());
+ stock.setPackageQuantity(defaultPackagingScheme.getPackageQuantity());
+ stock.setPalletPackageQuantity(defaultPackagingScheme.getPalletPackageQuantity());
+ stock.setPalletTotalQuantity(defaultPackagingScheme.getPalletTotalQuantity());
+ }
+ }
+
+ private ProductPackagingSchemeRespVO findDefaultPackagingScheme(ErpProductRespVO product) {
+ if (product.getDefaultPackagingSchemeId() == null || product.getPackagingSchemes() == null) {
+ return null;
+ }
+ return product.getPackagingSchemes().stream()
+ .filter(item -> product.getDefaultPackagingSchemeId().equals(item.getPackagingSchemeId()))
+ .findFirst()
+ .orElse(null);
+ }
+
+ private boolean isStockSnapshotMissing(ErpStockDO stock) {
+ return stock.getUnitId() == null
+ || stock.getUnitName() == null
+ || stock.getPurchaseUnitId() == null
+ || stock.getPurchaseUnitName() == null
+ || stock.getPurchaseUnitConvertQuantity() == null
+ || stock.getDefaultPackagingSchemeId() == null
+ || stock.getDefaultPackagingSchemeName() == null
+ || stock.getPackageQuantity() == null
+ || stock.getPalletPackageQuantity() == null
+ || stock.getPalletTotalQuantity() == null;
+ }
+
+ private ErpStockDO buildStockSnapshotUpdate(ErpStockDO stock) {
+ return new ErpStockDO().setId(stock.getId())
+ .setUnitId(stock.getUnitId())
+ .setUnitName(stock.getUnitName())
+ .setPurchaseUnitId(stock.getPurchaseUnitId())
+ .setPurchaseUnitName(stock.getPurchaseUnitName())
+ .setPurchaseUnitConvertQuantity(stock.getPurchaseUnitConvertQuantity())
+ .setDefaultPackagingSchemeId(stock.getDefaultPackagingSchemeId())
+ .setDefaultPackagingSchemeName(stock.getDefaultPackagingSchemeName())
+ .setPackageQuantity(stock.getPackageQuantity())
+ .setPalletPackageQuantity(stock.getPalletPackageQuantity())
+ .setPalletTotalQuantity(stock.getPalletTotalQuantity());
+ }
+
}
diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/DvRepairApi.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/DvRepairApi.java
new file mode 100644
index 000000000..16b6e7ccc
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/DvRepairApi.java
@@ -0,0 +1,11 @@
+package cn.iocoder.yudao.module.mes.api.dvrepair;
+
+import cn.iocoder.yudao.module.mes.api.dvrepair.dto.DvRepairRespDTO;
+
+/**
+ * 设备维修 API
+ */
+public interface DvRepairApi {
+
+ DvRepairRespDTO getDvRepair(Long id);
+}
diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/dto/DvRepairRespDTO.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/dto/DvRepairRespDTO.java
new file mode 100644
index 000000000..3773d04a3
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/dto/DvRepairRespDTO.java
@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.mes.api.dvrepair.dto;
+
+import lombok.Data;
+
+/**
+ * 设备维修响应 DTO
+ */
+@Data
+public class DvRepairRespDTO {
+
+ private Long id;
+ private String repairCode;
+ private String repairName;
+ private Long machineryId;
+ private String machineryCode;
+ private String machineryName;
+}
diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/TicketManagementApi.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/TicketManagementApi.java
new file mode 100644
index 000000000..a7e08be90
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/TicketManagementApi.java
@@ -0,0 +1,11 @@
+package cn.iocoder.yudao.module.mes.api.ticketmanagement;
+
+import cn.iocoder.yudao.module.mes.api.ticketmanagement.dto.TicketManagementRespDTO;
+
+/**
+ * 保养单 API
+ */
+public interface TicketManagementApi {
+
+ TicketManagementRespDTO getTicketManagement(Long id);
+}
diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/dto/TicketManagementRespDTO.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/dto/TicketManagementRespDTO.java
new file mode 100644
index 000000000..10ab0a114
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/dto/TicketManagementRespDTO.java
@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.module.mes.api.ticketmanagement.dto;
+
+import lombok.Data;
+
+/**
+ * 保养单响应 DTO
+ */
+@Data
+public class TicketManagementRespDTO {
+
+ private Long id;
+ private String planNo;
+ private String deviceName;
+ private String configName;
+}
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/DvRepairApiImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/DvRepairApiImpl.java
new file mode 100644
index 000000000..582c06a23
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/dvrepair/DvRepairApiImpl.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.mes.api.dvrepair;
+
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.api.dvrepair.dto.DvRepairRespDTO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.dvrepair.DvRepairDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.dvrepair.DvRepairMapper;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+@Service
+public class DvRepairApiImpl implements DvRepairApi {
+
+ @Resource
+ private DvRepairMapper dvRepairMapper;
+
+ @Override
+ public DvRepairRespDTO getDvRepair(Long id) {
+ DvRepairDO repair = dvRepairMapper.selectById(id);
+ return BeanUtils.toBean(repair, DvRepairRespDTO.class);
+ }
+}
diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/TicketManagementApiImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/TicketManagementApiImpl.java
new file mode 100644
index 000000000..c677d3220
--- /dev/null
+++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/api/ticketmanagement/TicketManagementApiImpl.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.mes.api.ticketmanagement;
+
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.mes.api.ticketmanagement.dto.TicketManagementRespDTO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.ticketmanagement.TicketManagementDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.ticketmanagement.TicketManagementMapper;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+@Service
+public class TicketManagementApiImpl implements TicketManagementApi {
+
+ @Resource
+ private TicketManagementMapper ticketManagementMapper;
+
+ @Override
+ public TicketManagementRespDTO getTicketManagement(Long id) {
+ TicketManagementDO ticketManagement = ticketManagementMapper.selectById(id);
+ return BeanUtils.toBean(ticketManagement, TicketManagementRespDTO.class);
+ }
+}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java
index 3f7dc6127..1fd74ade4 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java
@@ -105,8 +105,17 @@ public class UserController {
@GetMapping({"/list-all-simple", "/simple-list"})
@Operation(summary = "获取用户精简信息列表", description = "只包含被开启的用户,主要用于前端的下拉选项")
- public CommonResult> getSimpleUserList() {
+ public CommonResult> getSimpleUserList(@RequestParam(value = "username", required = false) String username,
+ @RequestParam(value = "nickname", required = false) String nickname) {
List list = userService.getUserListByStatus(CommonStatusEnum.ENABLE.getStatus());
+ if (username != null && !username.isEmpty()) {
+ list = list.stream().filter(user -> user.getUsername() != null && user.getUsername().contains(username))
+ .collect(java.util.stream.Collectors.toList());
+ }
+ if (nickname != null && !nickname.isEmpty()) {
+ list = list.stream().filter(user -> user.getNickname() != null && user.getNickname().contains(nickname))
+ .collect(java.util.stream.Collectors.toList());
+ }
// 拼接数据
Map deptMap = deptService.getDeptMap(
convertList(list, AdminUserDO::getDeptId));