Compare commits

...

5 Commits

@ -0,0 +1,25 @@
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 ErpStockInStatusEnum implements IntArrayValuable {
WAIT_IN(0, "待入库"),
IN_STOCK(20, "已入库");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockInStatusEnum::getStatus).toArray();
private final Integer status;
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

@ -0,0 +1,25 @@
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 ErpStockOutStatusEnum implements IntArrayValuable {
WAIT_OUT(0, "待出库"),
OUT_STOCK(20, "已出库");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockOutStatusEnum::getStatus).toArray();
private final Integer status;
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

@ -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;
}
}

@ -32,6 +32,11 @@
<artifactId>yudao-module-infra-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-mes-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->

@ -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<ErpStockRespVO> 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();
}
}

@ -26,6 +26,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
import cn.iocoder.yudao.module.erp.enums.ErpStockInStatusEnum;
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;
@ -51,11 +52,15 @@ import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
@ -168,6 +173,7 @@ public class ErpStockInController {
@PreAuthorize("@ss.hasPermission('erp:stock-in:query')")
public CommonResult<PageResult<ErpStockInRespVO>> getStockInPage(@Valid ErpStockInPageReqVO pageReqVO) {
fillPageReqDefault(pageReqVO);
applyItemFilter(pageReqVO);
return success(buildStockInVOPageResult(stockInService.getStockInPage(pageReqVO)));
}
@ -178,11 +184,34 @@ public class ErpStockInController {
public void exportStockInExcel(@Valid ErpStockInPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
fillPageReqDefault(pageReqVO);
applyItemFilter(pageReqVO);
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<ErpStockInRespVO> list = buildStockInVOPageResult(stockInService.getStockInPage(pageReqVO)).getList();
ExcelUtils.write(response, "其它入库单.xls", "数据", ErpStockInRespVO.class, list);
}
private void applyItemFilter(ErpStockInPageReqVO pageReqVO) {
if (pageReqVO.getProductId() == null && pageReqVO.getWarehouseId() == null) {
return;
}
List<Long> ids = stockInService.getStockInIdsByItemFilter(pageReqVO.getProductId(), pageReqVO.getWarehouseId());
if (StringUtils.isNotBlank(pageReqVO.getIds())) {
List<Long> reqIds = Stream.of(pageReqVO.getIds().split(","))
.map(String::trim)
.filter(StringUtils::isNotBlank)
.map(Long::valueOf)
.collect(Collectors.toList());
ids = ids.stream().filter(reqIds::contains).collect(Collectors.toList());
}
if (CollUtil.isEmpty(ids)) {
pageReqVO.setIds("-1");
return;
}
pageReqVO.setIds(CollUtil.join(ids, ","));
pageReqVO.setProductId(null);
pageReqVO.setWarehouseId(null);
}
private void fillPageReqDefault(ErpStockInPageReqVO pageReqVO) {
if (StringUtils.isEmpty(pageReqVO.getInType())) {
List<String> list = new ArrayList<>();
@ -198,19 +227,55 @@ public class ErpStockInController {
if (CollUtil.isEmpty(pageResult.getList())) {
return PageResult.empty(pageResult.getTotal());
}
List<ErpStockInRespVO> list = convertList(pageResult.getList(), stockIn -> buildStockInRespVO(
stockIn, stockInService.getStockInItemListByInId(stockIn.getId()), Collections.emptyList()));
List<ErpStockInDO> stockIns = pageResult.getList();
Map<Long, List<ErpStockInItemDO>> itemMap = stockInService.getStockInItemListByInIds(
convertSet(stockIns, ErpStockInDO::getId)).stream()
.collect(Collectors.groupingBy(ErpStockInItemDO::getInId));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(stockIns,
item -> Stream.of(NumberUtils.parseLong(item.getCreator()), item.getStockUserId(), item.getAuditUserId())));
Map<Long, ErpSupplierDO> supplierMap = supplierService.getSupplierMap(
convertSet(stockIns, ErpStockInDO::getSupplierId));
List<ErpStockInItemDO> allItems = convertListByFlatMap(itemMap.values(), Collection::stream);
Map<Long, ErpWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(allItems, ErpStockInItemDO::getWarehouseId));
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
convertSet(allItems, ErpStockInItemDO::getAreaId));
Map<Long, ErpProductRespVO> productMap = productService.getProductSimpleVOMap(
convertSet(allItems, ErpStockInItemDO::getProductId));
Map<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap(
convertSet(allItems, ErpStockInItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> moldListMap = moldService.getMoldListMapByBrandIds(
convertSet(allItems, ErpStockInItemDO::getMoldSetId));
Map<String, ErpStockDO> stockMap = buildStockMap(allItems);
List<ErpStockInRespVO> list = convertList(stockIns, stockIn -> buildStockInRespVO(
stockIn, itemMap.getOrDefault(stockIn.getId(), Collections.emptyList()), Collections.emptyList(),
userMap, supplierMap, stockMap, warehouseMap, areaMap, productMap, moldMap, moldListMap));
return new PageResult<>(list, pageResult.getTotal());
}
private ErpStockInRespVO buildStockInRespVO(ErpStockInDO stockIn, List<ErpStockInItemDO> stockInItemList,
List<ErpStockInApproveRecordDO> approveRecords) {
return buildStockInRespVO(stockIn, stockInItemList, approveRecords,
null, null, null, null, null, null, null, null);
}
private ErpStockInRespVO buildStockInRespVO(ErpStockInDO stockIn, List<ErpStockInItemDO> stockInItemList,
List<ErpStockInApproveRecordDO> approveRecords,
Map<Long, AdminUserRespDTO> pageUserMap,
Map<Long, ErpSupplierDO> pageSupplierMap,
Map<String, ErpStockDO> pageStockMap,
Map<Long, ErpWarehouseDO> pageWarehouseMap,
Map<Long, WarehouseAreaDO> pageAreaMap,
Map<Long, ErpProductRespVO> pageProductMap,
Map<Long, MoldBrandDO> pageMoldMap,
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> pageMoldListMap) {
ErpStockInRespVO stockInVO = BeanUtils.toBean(stockIn, ErpStockInRespVO.class);
Map<Long, ErpWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
stockInVO.setStatusName(getStockInStatusName(stockIn.getStatus()));
Map<Long, ErpWarehouseDO> warehouseMap = pageWarehouseMap != null ? pageWarehouseMap : warehouseService.getWarehouseMap(
convertSet(stockInItemList, ErpStockInItemDO::getWarehouseId));
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
Map<Long, WarehouseAreaDO> areaMap = pageAreaMap != null ? pageAreaMap : warehouseAreaService.getWarehouseAreaMap(
convertSet(stockInItemList, ErpStockInItemDO::getAreaId));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(
Map<Long, AdminUserRespDTO> userMap = pageUserMap != null ? pageUserMap : adminUserApi.getUserMap(convertListByFlatMap(
Collections.singletonList(stockIn), item -> Stream.of(NumberUtils.parseLong(item.getCreator()),
item.getStockUserId(), item.getAuditUserId())));
MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockIn.getCreator()), user -> stockInVO.setCreatorName(user.getNickname()));
@ -218,13 +283,14 @@ public class ErpStockInController {
MapUtils.findAndThen(userMap, stockIn.getAuditUserId(), user -> stockInVO.setAuditUserName(user.getNickname()));
if (Objects.equals(stockIn.getInType(), "模具入库")) {
Map<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap(
convertSet(stockInItemList, ErpStockInItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> moldListMap = moldService.getMoldListMapByBrandIds(
Map<Long, MoldBrandDO> moldMap = pageMoldMap != null ? pageMoldMap : moldBrandService.getMoldVOMap(
convertSet(stockInItemList, ErpStockInItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> moldListMap = pageMoldListMap != null ? pageMoldListMap
: moldService.getMoldListMapByBrandIds(convertSet(stockInItemList, ErpStockInItemDO::getMoldSetId));
stockInVO.setItems(convertList(stockInItemList, source -> {
ErpStockInRespVO.Item item = BeanUtils.toBean(source, ErpStockInRespVO.Item.class);
ErpStockDO stock = stockService.getStock(source.getMoldSetId(), source.getWarehouseId(), source.getAreaId());
ErpStockDO stock = pageStockMap != null ? pageStockMap.get(buildStockKey(source.getMoldSetId(), source.getWarehouseId(), source.getAreaId()))
: stockService.getStock(source.getMoldSetId(), source.getWarehouseId(), source.getAreaId());
item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO);
item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>()));
fillWarehouseInfo(item, source, warehouseMap, areaMap);
@ -238,10 +304,11 @@ public class ErpStockInController {
stockInVO.setMoldSetNames(CollUtil.join(stockInVO.getItems(), ",", ErpStockInRespVO.Item::getMoldSetName));
stockInVO.setProductNames(stockInVO.getMoldSetNames());
} else {
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(
Map<Long, ErpProductRespVO> productMap = pageProductMap != null ? pageProductMap : productService.getProductSimpleVOMap(
convertSet(stockInItemList, ErpStockInItemDO::getProductId));
stockInVO.setItems(BeanUtils.toBean(stockInItemList, ErpStockInRespVO.Item.class, item -> {
ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId(), item.getAreaId());
ErpStockDO stock = pageStockMap != null ? pageStockMap.get(buildStockKey(item.getProductId(), item.getWarehouseId(), item.getAreaId()))
: stockService.getStock(item.getProductId(), item.getWarehouseId(), item.getAreaId());
item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO);
if (StringUtils.isBlank(item.getWarehouseName())) {
MapUtils.findAndThen(warehouseMap, item.getWarehouseId(), warehouse -> item.setWarehouseName(warehouse.getName()));
@ -267,13 +334,31 @@ public class ErpStockInController {
}
if (stockIn.getSupplierId() != null) {
Map<Long, ErpSupplierDO> supplierMap = supplierService.getSupplierMap(Collections.singleton(stockIn.getSupplierId()));
Map<Long, ErpSupplierDO> supplierMap = pageSupplierMap != null ? pageSupplierMap
: supplierService.getSupplierMap(Collections.singleton(stockIn.getSupplierId()));
MapUtils.findAndThen(supplierMap, stockIn.getSupplierId(), supplier -> stockInVO.setSupplierName(supplier.getName()));
}
stockInVO.setApproveRecords(buildApproveRecordRespList(approveRecords));
return stockInVO;
}
private Map<String, ErpStockDO> buildStockMap(List<ErpStockInItemDO> items) {
if (CollUtil.isEmpty(items)) {
return Collections.emptyMap();
}
boolean containsNullArea = items.stream().anyMatch(item -> item.getAreaId() == null);
return stockService.getStockList(
convertSet(convertListByFlatMap(items, item -> Stream.of(item.getProductId(), item.getMoldSetId())), Function.identity()),
convertSet(items, ErpStockInItemDO::getWarehouseId),
containsNullArea ? null : convertSet(items, ErpStockInItemDO::getAreaId)).stream()
.collect(Collectors.toMap(stock -> buildStockKey(stock.getProductId(), stock.getWarehouseId(), stock.getAreaId()),
Function.identity(), (left, right) -> left, HashMap::new));
}
private String buildStockKey(Long productId, Long warehouseId, Long areaId) {
return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId);
}
private List<ErpStockInApproveRecordRespVO> buildApproveRecordRespList(List<ErpStockInApproveRecordDO> records) {
if (CollUtil.isEmpty(records)) {
return new ArrayList<>();
@ -283,6 +368,8 @@ public class ErpStockInController {
return BeanUtils.toBean(records, ErpStockInApproveRecordRespVO.class, record -> {
MapUtils.findAndThen(userMap, NumberUtils.parseLong(record.getCreator()), user -> record.setCreatorName(user.getNickname()));
MapUtils.findAndThen(userMap, record.getTargetUserId(), user -> record.setTargetUserName(user.getNickname()));
record.setFromStatusName(getStockInStatusName(record.getFromStatus()));
record.setToStatusName(getStockInStatusName(record.getToStatus()));
});
}
@ -334,4 +421,8 @@ public class ErpStockInController {
stockInService.updateMoldStatus(id, status);
return success(true);
}
private String getStockInStatusName(Integer status) {
return ErpStockInStatusEnum.IN_STOCK.getStatus().equals(status) ? "已入库" : "待入库";
}
}

@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO;
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.service.mold.MoldBrandService;
import cn.iocoder.yudao.module.erp.service.mold.MoldService;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
@ -53,11 +54,15 @@ import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
@ -176,6 +181,7 @@ public class ErpStockOutController {
@PreAuthorize("@ss.hasPermission('erp:stock-out:query')")
public CommonResult<PageResult<ErpStockOutRespVO>> getStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) {
fillPageReqDefault(pageReqVO);
applyItemFilter(pageReqVO);
return success(buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)));
}
@ -186,11 +192,34 @@ public class ErpStockOutController {
public void exportStockOutExcel(@Valid ErpStockOutPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
fillPageReqDefault(pageReqVO);
applyItemFilter(pageReqVO);
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<ErpStockOutRespVO> list = buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)).getList();
ExcelUtils.write(response, "其它出库单.xls", "数据", ErpStockOutRespVO.class, list);
}
private void applyItemFilter(ErpStockOutPageReqVO pageReqVO) {
if (pageReqVO.getProductId() == null && pageReqVO.getWarehouseId() == null) {
return;
}
List<Long> ids = stockOutService.getStockOutIdsByItemFilter(pageReqVO.getProductId(), pageReqVO.getWarehouseId());
if (StringUtils.isNotBlank(pageReqVO.getIds())) {
List<Long> reqIds = Stream.of(pageReqVO.getIds().split(","))
.map(String::trim)
.filter(StringUtils::isNotBlank)
.map(Long::valueOf)
.collect(Collectors.toList());
ids = ids.stream().filter(reqIds::contains).collect(Collectors.toList());
}
if (CollUtil.isEmpty(ids)) {
pageReqVO.setIds("-1");
return;
}
pageReqVO.setIds(CollUtil.join(ids, ","));
pageReqVO.setProductId(null);
pageReqVO.setWarehouseId(null);
}
private void fillPageReqDefault(ErpStockOutPageReqVO pageReqVO) {
if (StringUtils.isEmpty(pageReqVO.getOutType())) {
List<String> list = new ArrayList<>();
@ -206,15 +235,45 @@ public class ErpStockOutController {
if (CollUtil.isEmpty(pageResult.getList())) {
return PageResult.empty(pageResult.getTotal());
}
List<ErpStockOutRespVO> list = convertList(pageResult.getList(), stockOut -> buildStockOutRespVO(
stockOut, stockOutService.getStockOutItemListByOutId(stockOut.getId()), Collections.emptyList()));
List<ErpStockOutDO> stockOuts = pageResult.getList();
Map<Long, List<ErpStockOutItemDO>> itemMap = stockOutService.getStockOutItemListByOutIds(
convertSet(stockOuts, ErpStockOutDO::getId)).stream()
.collect(Collectors.groupingBy(ErpStockOutItemDO::getOutId));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(stockOuts,
item -> Stream.of(NumberUtils.parseLong(item.getCreator()), item.getResponserId(), item.getAuditUserId())));
Map<Long, ErpCustomerDO> customerMap = customerService.getCustomerMap(
convertSet(stockOuts, ErpStockOutDO::getCustomerId));
List<ErpStockOutItemDO> allItems = convertListByFlatMap(itemMap.values(), Collection::stream);
Map<Long, ErpProductRespVO> productMap = productService.getProductSimpleVOMap(
convertSet(allItems, ErpStockOutItemDO::getProductId));
Map<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap(
convertSet(allItems, ErpStockOutItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> moldListMap = moldService.getMoldListMapByBrandIds(
convertSet(allItems, ErpStockOutItemDO::getMoldSetId));
Map<String, ErpStockDO> stockMap = buildStockMap(allItems);
List<ErpStockOutRespVO> list = convertList(stockOuts, stockOut -> buildStockOutRespVO(
stockOut, itemMap.getOrDefault(stockOut.getId(), Collections.emptyList()), Collections.emptyList(),
userMap, customerMap, stockMap, productMap, moldMap, moldListMap));
return new PageResult<>(list, pageResult.getTotal());
}
private ErpStockOutRespVO buildStockOutRespVO(ErpStockOutDO stockOut, List<ErpStockOutItemDO> stockOutItemList,
List<ErpStockOutApproveRecordDO> approveRecords) {
return buildStockOutRespVO(stockOut, stockOutItemList, approveRecords,
null, null, null, null, null, null);
}
private ErpStockOutRespVO buildStockOutRespVO(ErpStockOutDO stockOut, List<ErpStockOutItemDO> stockOutItemList,
List<ErpStockOutApproveRecordDO> approveRecords,
Map<Long, AdminUserRespDTO> pageUserMap,
Map<Long, ErpCustomerDO> pageCustomerMap,
Map<String, ErpStockDO> pageStockMap,
Map<Long, ErpProductRespVO> pageProductMap,
Map<Long, MoldBrandDO> pageMoldMap,
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> pageMoldListMap) {
ErpStockOutRespVO stockOutVO = BeanUtils.toBean(stockOut, ErpStockOutRespVO.class);
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(
stockOutVO.setStatusName(getStockOutStatusName(stockOut.getStatus()));
Map<Long, AdminUserRespDTO> userMap = pageUserMap != null ? pageUserMap : adminUserApi.getUserMap(convertListByFlatMap(
Collections.singletonList(stockOut), item -> Stream.of(NumberUtils.parseLong(item.getCreator()),
item.getResponserId(), item.getAuditUserId())));
MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockOut.getCreator()), user -> stockOutVO.setCreatorName(user.getNickname()));
@ -222,13 +281,14 @@ public class ErpStockOutController {
MapUtils.findAndThen(userMap, stockOut.getAuditUserId(), user -> stockOutVO.setAuditUserName(user.getNickname()));
if (Objects.equals(stockOut.getOutType(), "模具出库")) {
Map<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap(
convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> moldListMap = moldService.getMoldListMapByBrandIds(
Map<Long, MoldBrandDO> moldMap = pageMoldMap != null ? pageMoldMap : moldBrandService.getMoldVOMap(
convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> moldListMap = pageMoldListMap != null ? pageMoldListMap
: moldService.getMoldListMapByBrandIds(convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
stockOutVO.setItems(convertList(stockOutItemList, source -> {
ErpStockOutRespVO.Item item = BeanUtils.toBean(source, ErpStockOutRespVO.Item.class);
ErpStockDO stock = stockService.getStock(source.getMoldSetId(), source.getWarehouseId(), source.getAreaId());
ErpStockDO stock = pageStockMap != null ? pageStockMap.get(buildStockKey(source.getMoldSetId(), source.getWarehouseId(), source.getAreaId()))
: stockService.getStock(source.getMoldSetId(), source.getWarehouseId(), source.getAreaId());
item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO);
item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>()));
MapUtils.findAndThen(moldMap, source.getMoldSetId(), mold -> {
@ -241,10 +301,11 @@ public class ErpStockOutController {
stockOutVO.setMoldSetNames(CollUtil.join(stockOutVO.getItems(), ",", ErpStockOutRespVO.Item::getMoldSetName));
stockOutVO.setProductNames(stockOutVO.getMoldSetNames());
} else {
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(
Map<Long, ErpProductRespVO> productMap = pageProductMap != null ? pageProductMap : productService.getProductSimpleVOMap(
convertSet(stockOutItemList, ErpStockOutItemDO::getProductId));
stockOutVO.setItems(BeanUtils.toBean(stockOutItemList, ErpStockOutRespVO.Item.class, item -> {
ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId(), item.getAreaId());
ErpStockDO stock = pageStockMap != null ? pageStockMap.get(buildStockKey(item.getProductId(), item.getWarehouseId(), item.getAreaId()))
: stockService.getStock(item.getProductId(), item.getWarehouseId(), item.getAreaId());
item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO);
MapUtils.findAndThen(productMap, item.getProductId(), product -> {
item.setProductName(product.getName());
@ -262,14 +323,52 @@ public class ErpStockOutController {
}));
stockOutVO.setProductNames(CollUtil.join(stockOutVO.getItems(), ",", ErpStockOutRespVO.Item::getProductName));
}
if (CollUtil.isNotEmpty(stockOutVO.getItems())) {
ErpStockOutRespVO.Item firstItem = stockOutVO.getItems().get(0);
stockOutVO.setOutUsageType(firstItem.getOutUsageType());
stockOutVO.setOutUsageTypeName(firstItem.getOutUsageTypeName());
stockOutVO.setRepairId(firstItem.getRepairId());
stockOutVO.setRepairName(firstItem.getRepairName());
stockOutVO.setRepairDeviceId(firstItem.getRepairDeviceId());
stockOutVO.setRepairDeviceName(firstItem.getRepairDeviceName());
stockOutVO.setMaintenanceId(firstItem.getMaintenanceId());
stockOutVO.setMaintenanceName(firstItem.getMaintenanceName());
} else {
stockOutVO.setOutUsageType(null);
stockOutVO.setOutUsageTypeName(null);
stockOutVO.setRepairId(null);
stockOutVO.setRepairName(null);
stockOutVO.setRepairDeviceId(null);
stockOutVO.setRepairDeviceName(null);
stockOutVO.setMaintenanceId(null);
stockOutVO.setMaintenanceName(null);
}
if (stockOut.getCustomerId() != null) {
Map<Long, ErpCustomerDO> customerMap = customerService.getCustomerMap(Collections.singleton(stockOut.getCustomerId()));
Map<Long, ErpCustomerDO> customerMap = pageCustomerMap != null ? pageCustomerMap
: customerService.getCustomerMap(Collections.singleton(stockOut.getCustomerId()));
MapUtils.findAndThen(customerMap, stockOut.getCustomerId(), customer -> stockOutVO.setCustomerName(customer.getName()));
}
stockOutVO.setApproveRecords(buildApproveRecordRespList(approveRecords));
return stockOutVO;
}
private Map<String, ErpStockDO> buildStockMap(List<ErpStockOutItemDO> items) {
if (CollUtil.isEmpty(items)) {
return Collections.emptyMap();
}
boolean containsNullArea = items.stream().anyMatch(item -> item.getAreaId() == null);
return stockService.getStockList(
convertSet(convertListByFlatMap(items, item -> Stream.of(item.getProductId(), item.getMoldSetId())), Function.identity()),
convertSet(items, ErpStockOutItemDO::getWarehouseId),
containsNullArea ? null : convertSet(items, ErpStockOutItemDO::getAreaId)).stream()
.collect(Collectors.toMap(stock -> buildStockKey(stock.getProductId(), stock.getWarehouseId(), stock.getAreaId()),
Function.identity(), (left, right) -> left, HashMap::new));
}
private String buildStockKey(Long productId, Long warehouseId, Long areaId) {
return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId);
}
private List<ErpStockOutApproveRecordRespVO> buildApproveRecordRespList(List<ErpStockOutApproveRecordDO> records) {
if (CollUtil.isEmpty(records)) {
return new ArrayList<>();
@ -279,6 +378,8 @@ public class ErpStockOutController {
return BeanUtils.toBean(records, ErpStockOutApproveRecordRespVO.class, record -> {
MapUtils.findAndThen(userMap, NumberUtils.parseLong(record.getCreator()), user -> record.setCreatorName(user.getNickname()));
MapUtils.findAndThen(userMap, record.getTargetUserId(), user -> record.setTargetUserName(user.getNickname()));
record.setFromStatusName(getStockOutStatusName(record.getFromStatus()));
record.setToStatusName(getStockOutStatusName(record.getToStatus()));
});
}
@ -298,4 +399,7 @@ public class ErpStockOutController {
return success(buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)));
}
private String getStockOutStatusName(Integer status) {
return ErpStockOutStatusEnum.OUT_STOCK.getStatus().equals(status) ? "已出库" : "待出库";
}
}

@ -21,9 +21,15 @@ public class ErpStockInApproveRecordRespVO {
@Schema(description = "变更前状态", example = "0")
private Integer fromStatus;
@Schema(description = "变更前状态名称", example = "待入库")
private String fromStatusName;
@Schema(description = "变更后状态", example = "10")
private Integer toStatus;
@Schema(description = "变更后状态名称", example = "已入库")
private String toStatusName;
@Schema(description = "目标审核人编号", example = "1")
private Long targetUserId;

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import cn.iocoder.yudao.module.erp.enums.ErpStockInStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -31,8 +31,8 @@ public class ErpStockInPageReqVO extends PageParam {
private LocalDateTime[] inTime;
@Schema(description = "状态", example = "10")
@InEnum(ErpAuditStatus.class)
private Integer status;
@InEnum(ErpStockInStatusEnum.class)
private List<Integer> statusList;
@Schema(description = "入库类型", example = "其它入库")
private String inType;

@ -66,6 +66,9 @@ public class ErpStockInRespVO {
@DictFormat(AUDIT_STATUS)
private Integer status;
@Schema(description = "状态名称", example = "待入库")
private String statusName;
@Schema(description = "备注", example = "随便")
@ExcelProperty("备注")
private String remark;
@ -97,6 +100,14 @@ public class ErpStockInRespVO {
@Schema(description = "模具组名称")
private String moldSetNames;
@Schema(description = "最近入库时间")
@ExcelProperty("最近入库时间")
private LocalDateTime recentInTime;
@Schema(description = "最近出库时间")
@ExcelProperty("最近出库时间")
private LocalDateTime recentOutTime;
@Schema(description = "审核记录")
private List<ErpStockInApproveRecordRespVO> approveRecords;

@ -21,9 +21,15 @@ public class ErpStockOutApproveRecordRespVO {
@Schema(description = "变更前状态", example = "0")
private Integer fromStatus;
@Schema(description = "变更前状态名称", example = "待出库")
private String fromStatusName;
@Schema(description = "变更后状态", example = "10")
private Integer toStatus;
@Schema(description = "变更后状态名称", example = "已出库")
private String toStatusName;
@Schema(description = "目标审核人编号", example = "1")
private Long targetUserId;

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import cn.iocoder.yudao.module.erp.enums.ErpStockOutStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
@ -40,8 +40,8 @@ public class ErpStockOutPageReqVO extends PageParam {
private LocalDateTime[] outTime;
@Schema(description = "状态", example = "10")
@InEnum(ErpAuditStatus.class)
private Integer status;
@InEnum(ErpStockOutStatusEnum.class)
private List<Integer> statusList;
@Schema(description = "审核人编号", example = "1")
private Long auditUserId;

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
@ -43,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;
@ -60,6 +85,9 @@ public class ErpStockOutRespVO {
@DictFormat(AUDIT_STATUS)
private Integer status;
@Schema(description = "状态名称", example = "待出库")
private String statusName;
@Schema(description = "是否需要审核", example = "true")
private Boolean needAudit;
@ -96,6 +124,24 @@ public class ErpStockOutRespVO {
@ExcelProperty("产品信息")
private String productNames;
@Schema(description = "默认包装方案")
private ProductPackagingSchemeRespVO defaultPackagingScheme;
@Schema(description = "默认包装方案ID", example = "1")
private Long defaultPackagingSchemeId;
@Schema(description = "单位ID", example = "1")
private Long unitId;
@Schema(description = "采购单位ID", example = "2")
private Long purchaseUnitId;
@Schema(description = "采购单位名称", example = "箱")
private String purchaseUnitName;
@Schema(description = "采购单位换算数量", example = "100")
private BigDecimal purchaseUnitConvertQuantity;
@Schema(description = "模具组名称")
private String moldSetNames;
@ -135,6 +181,30 @@ public class ErpStockOutRespVO {
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal count;
@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 = "备注", example = "备注信息")
private String remark;

@ -1,12 +1,12 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@ -39,40 +39,11 @@ public class ErpStockOutSaveReqVO {
@Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc")
private String fileUrl;
@Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED)
@Schema(description = "出库项列表", implementation = ErpStockOutSaveReqVOItem.class)
@NotEmpty(message = "出库项列表不能为空")
@Valid
private List<Item> items;
private List<ErpStockOutSaveReqVOItem> items;
@Schema(description = "计划单 Code", example = "PLAN20240601")
private String planCode;
@Data
public static class Item {
@Schema(description = "出库项编号", example = "11756")
private Long id;
@Schema(description = "模具组 id", example = "101")
private Long moldSetId;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
private Long warehouseId;
@Schema(description = "库区编号", example = "1")
private Long areaId;
@Schema(description = "产品 id", example = "3113")
private Long productId;
@Schema(description = "产品单价", example = "100.00")
private BigDecimal productPrice;
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal count;
@Schema(description = "备注", example = "备注信息")
private String remark;
}
}

@ -0,0 +1,52 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.erp.enums.ErpStockOutUsageTypeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@Schema(description = "ERP 其它出库单明细项")
@Data
public class ErpStockOutSaveReqVOItem {
@Schema(description = "出库项编号", example = "11756")
private Long id;
@Schema(description = "模具组 id", example = "101")
private Long moldSetId;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
private Long warehouseId;
@Schema(description = "库区编号", example = "1")
private Long areaId;
@Schema(description = "产品 id", example = "3113")
private Long productId;
@Schema(description = "产品单价", example = "100.00")
private BigDecimal productPrice;
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal count;
@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 = "备注", example = "备注信息")
private String remark;
}

@ -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 = "李四")

@ -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;
/**
*
*/

@ -37,6 +37,40 @@ public class ErpStockOutItemDO extends BaseDO {
* {@link ErpStockOutDO#getId()}
*/
private Long outId;
/**
*
*
* {@link cn.iocoder.yudao.module.erp.enums.ErpStockOutUsageTypeEnum}
*/
private Integer outUsageType;
/**
*
*/
private String outUsageTypeName;
/**
*
*/
private Long repairId;
/**
*
*/
private String repairName;
/**
*
*/
private Long repairDeviceId;
/**
*
*/
private String repairDeviceName;
/**
*
*/
private Long maintenanceId;
/**
*
*/
private String maintenanceName;
/**
*
*

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
@ -27,4 +28,6 @@ public interface ErpStockInItemMapper extends BaseMapperX<ErpStockInItemDO> {
return delete(ErpStockInItemDO::getInId, inId);
}
}
List<Long> selectInIds(@Param("productId") Long productId, @Param("warehouseId") Long warehouseId);
}

@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
@ -22,19 +21,13 @@ public interface ErpStockInMapper extends BaseMapperX<ErpStockInDO> {
.likeIfPresent(ErpStockInDO::getNo, reqVO.getNo())
.eqIfPresent(ErpStockInDO::getSupplierId, reqVO.getSupplierId())
.betweenIfPresent(ErpStockInDO::getInTime, reqVO.getInTime())
.eqIfPresent(ErpStockInDO::getStatus, reqVO.getStatus())
.inIfPresent(ErpStockInDO::getStatus, reqVO.getStatusList())
.eqIfPresent(ErpStockInDO::getInType, reqVO.getInType())
.inIfPresent(ErpStockInDO::getInType, reqVO.getInTypeList())
.likeIfPresent(ErpStockInDO::getRemark, reqVO.getRemark())
.eqIfPresent(ErpStockInDO::getCreator, reqVO.getCreator())
.eqIfPresent(ErpStockInDO::getAuditUserId, reqVO.getAuditUserId())
.orderByDesc(ErpStockInDO::getId);
if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) {
query.leftJoin(ErpStockInItemDO.class, ErpStockInItemDO::getInId, ErpStockInDO::getId)
.eq(reqVO.getWarehouseId() != null, ErpStockInItemDO::getWarehouseId, reqVO.getWarehouseId())
.eq(reqVO.getProductId() != null, ErpStockInItemDO::getProductId, reqVO.getProductId())
.groupBy(ErpStockInDO::getId);
}
if (StringUtils.isNotBlank(reqVO.getIds())) {
List<Long> idList = Arrays.stream(reqVO.getIds().split(","))
.map(String::trim)

@ -15,6 +15,7 @@ import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -87,6 +88,15 @@ public interface ErpStockMapper extends BaseMapperX<ErpStockDO> {
.inIfPresent(ErpStockDO::getProductId, productIds));
}
default List<ErpStockDO> selectListByProductIdsAndWarehouseIdsAndAreaIds(Collection<Long> productIds,
Collection<Long> warehouseIds,
Collection<Long> areaIds) {
return selectList(new LambdaQueryWrapperX<ErpStockDO>()
.inIfPresent(ErpStockDO::getProductId, productIds)
.inIfPresent(ErpStockDO::getWarehouseId, warehouseIds)
.inIfPresent(ErpStockDO::getAreaId, areaIds));
}
default int updateCountIncrement(Long id, BigDecimal count, boolean negativeEnable) {
LambdaUpdateWrapper<ErpStockDO> updateWrapper = new LambdaUpdateWrapper<ErpStockDO>()
.eq(ErpStockDO::getId, id);

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
@ -27,4 +28,6 @@ public interface ErpStockOutItemMapper extends BaseMapperX<ErpStockOutItemDO> {
return delete(ErpStockOutItemDO::getOutId, outId);
}
}
List<Long> selectOutIds(@Param("productId") Long productId, @Param("warehouseId") Long warehouseId);
}

@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@ -26,17 +25,11 @@ public interface ErpStockOutMapper extends BaseMapperX<ErpStockOutDO> {
.eqIfPresent(ErpStockOutDO::getOutType, reqVO.getOutType())
.inIfPresent(ErpStockOutDO::getOutType, reqVO.getOutTypeList())
.betweenIfPresent(ErpStockOutDO::getOutTime, reqVO.getOutTime())
.eqIfPresent(ErpStockOutDO::getStatus, reqVO.getStatus())
.inIfPresent(ErpStockOutDO::getStatus, reqVO.getStatusList())
.likeIfPresent(ErpStockOutDO::getRemark, reqVO.getRemark())
.eqIfPresent(ErpStockOutDO::getCreator, reqVO.getCreator())
.eqIfPresent(ErpStockOutDO::getAuditUserId, reqVO.getAuditUserId())
.orderByDesc(ErpStockOutDO::getId);
if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) {
query.leftJoin(ErpStockOutItemDO.class, ErpStockOutItemDO::getOutId, ErpStockOutDO::getId)
.eq(reqVO.getWarehouseId() != null, ErpStockOutItemDO::getWarehouseId, reqVO.getWarehouseId())
.eq(reqVO.getProductId() != null, ErpStockOutItemDO::getProductId, reqVO.getProductId())
.groupBy(ErpStockOutDO::getId);
}
if (StringUtils.isNotBlank(reqVO.getIds())) {
List<Long> idList = Arrays.stream(reqVO.getIds().split(","))
.map(String::trim)

@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProduc
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductListReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSupplierRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
@ -95,6 +96,8 @@ public interface ErpProductService {
return convertMap(getProductVOList(ids), ErpProductRespVO::getId);
}
Map<Long, ErpProductRespVO> getProductSimpleVOMap(Collection<Long> ids);
/**
* VO
*

@ -554,6 +554,58 @@ public class ErpProductServiceImpl implements ErpProductService {
return buildProductVOList(list);
}
@Override
public Map<Long, ErpProductRespVO> getProductSimpleVOMap(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyMap();
}
List<ErpProductDO> list = productMapper.selectListByIdsWithDeleted(ids);
if (CollUtil.isEmpty(list)) {
return Collections.emptyMap();
}
List<ProductSupplierRelDO> supplierRels = productSupplierRelMapper.selectListByProductIds(convertSet(list, ErpProductDO::getId));
Map<Long, ProductSupplierRelDO> defaultSupplierMap = supplierRels.stream()
.filter(item -> Integer.valueOf(1).equals(item.getDefaultStatus()))
.collect(Collectors.toMap(ProductSupplierRelDO::getProductId, item -> item, (left, right) -> left));
Map<Long, ErpProductCategoryDO> categoryMap = productCategoryService.getProductCategoryMap(
convertSet(list, ErpProductDO::getCategoryId));
Map<Long, ErpProductCategoryDO> subCategoryMap = productCategoryService.getProductCategoryMap(
convertSet(list, ErpProductDO::getSubCategoryId));
Map<Long, ErpProductUnitDO> unitMap = productUnitService.getProductUnitMap(
convertSet(list, ErpProductDO::getUnitId));
Map<Long, ErpProductUnitDO> purchaseUnitMap = productUnitService.getProductUnitMap(
convertSet(list, ErpProductDO::getPurchaseUnitId));
return convertMap(BeanUtils.toBean(list, ErpProductRespVO.class, product -> {
MapUtils.findAndThen(categoryMap, product.getCategoryId(), category -> {
product.setCategoryName(category.getName());
if (product.getCategoryType() == null) {
product.setCategoryType(category.getType());
}
});
MapUtils.findAndThen(subCategoryMap, product.getSubCategoryId(), subCategory -> {
product.setSubCategoryName(subCategory.getName());
product.setCategoryType(subCategory.getType());
});
MapUtils.findAndThen(unitMap, product.getUnitId(), unit -> product.setUnitName(unit.getName()));
MapUtils.findAndThen(purchaseUnitMap, product.getPurchaseUnitId(), unit -> product.setPurchaseUnitName(unit.getName()));
ProductSupplierRelDO defaultSupplier = defaultSupplierMap.get(product.getId());
if (defaultSupplier != null) {
product.setDefaultSupplierId(defaultSupplier.getSupplierId());
ProductSupplierRespVO supplier = new ProductSupplierRespVO();
supplier.setId(defaultSupplier.getId());
supplier.setSupplierId(defaultSupplier.getSupplierId());
supplier.setSupplierName(defaultSupplier.getSupplierName());
supplier.setDefaultStatus(defaultSupplier.getDefaultStatus());
product.setSuppliers(Collections.singletonList(supplier));
} else {
product.setSuppliers(Collections.emptyList());
}
if (Boolean.TRUE.equals(product.getDeleted())) {
product.setName(product.getName() + "(已被删除)");
}
}), ErpProductRespVO::getId);
}
@Override
public PageResult<ErpProductRespVO> getProductVOPage(ErpProductPageReqVO pageReqVO) {
PageResult<ErpProductDO> pageResult = productMapper.selectPage(pageReqVO);

@ -31,6 +31,8 @@ public interface ErpStockInService {
PageResult<ErpStockInDO> getStockInPage(ErpStockInPageReqVO pageReqVO);
List<Long> getStockInIdsByItemFilter(Long productId, Long warehouseId);
List<ErpStockInItemDO> getStockInItemListByInId(Long inId);
List<ErpStockInItemDO> getStockInItemListByInIds(Collection<Long> inIds);

@ -319,6 +319,14 @@ public class ErpStockInServiceImpl implements ErpStockInService {
return stockInMapper.selectPage(pageReqVO);
}
@Override
public List<Long> getStockInIdsByItemFilter(Long productId, Long warehouseId) {
if (productId == null && warehouseId == null) {
return Collections.emptyList();
}
return stockInItemMapper.selectInIds(productId, warehouseId);
}
@Override
public List<ErpStockInItemDO> getStockInItemListByInId(Long inId) {
return stockInItemMapper.selectListByInId(inId);

@ -70,6 +70,8 @@ public interface ErpStockOutService {
*/
PageResult<ErpStockOutDO> getStockOutPage(ErpStockOutPageReqVO pageReqVO);
List<Long> getStockOutIdsByItemFilter(Long productId, Long warehouseId);
// ==================== 出库项 ====================
/**

@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProduc
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutAuditReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVOItem;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSubmitReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO;
@ -26,8 +27,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 +102,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,13 +133,14 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
.setStatus(status)
.setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add))
.setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)));
fillUsageSnapshot(stockOutItems, createReqVO.getItems());
stockOutMapper.insert(stockOut);
stockOutItems.forEach(item -> item.setOutId(stockOut.getId()));
stockOutItemMapper.insertBatch(stockOutItems);
if (createReqVO.getOutType().equals("模具出库")) {
//修改模具组状态
for (ErpStockOutSaveReqVO.Item item : createReqVO.getItems()) {
for (ErpStockOutSaveReqVOItem item : createReqVO.getItems()) {
MoldBrandDO moldBrandDO = moldBrandMapper.selectById(item.getMoldSetId());
moldBrandDO.setStatus(MoldBrandStatusEnum.STANDBY.getStatus());
moldBrandMapper.updateById(moldBrandDO);
@ -165,6 +176,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
.setNeedAudit(needAudit)
.setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add))
.setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)));
fillUsageSnapshot(stockOutItems, updateReqVO.getItems());
stockOutMapper.updateById(updateObj);
updateStockOutItemList(updateReqVO.getId(), stockOutItems);
}
@ -307,6 +319,14 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
return stockOutMapper.selectPage(pageReqVO);
}
@Override
public List<Long> getStockOutIdsByItemFilter(Long productId, Long warehouseId) {
if (productId == null && warehouseId == null) {
return Collections.emptyList();
}
return stockOutItemMapper.selectOutIds(productId, warehouseId);
}
@Override
public List<ErpStockOutItemDO> getStockOutItemListByOutId(Long outId) {
return stockOutItemMapper.selectListByOutId(outId);
@ -394,6 +414,37 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
return !AUDIT_CONFIG_DISABLE_VALUE.equals(configApi.getConfigValueByCategoryAndKey(AUDIT_CONFIG_CATEGORY, AUDIT_CONFIG_KEY));
}
private void fillUsageSnapshot(List<ErpStockOutItemDO> stockOutItems, List<ErpStockOutSaveReqVOItem> items) {
for (int i = 0; i < stockOutItems.size(); i++) {
ErpStockOutItemDO stockOutItem = stockOutItems.get(i);
ErpStockOutSaveReqVOItem item = items.get(i);
stockOutItem.setOutUsageType(item.getOutUsageType());
stockOutItem.setOutUsageTypeName(ErpStockOutUsageTypeEnum.getNameByType(item.getOutUsageType()));
stockOutItem.setRepairId(null);
stockOutItem.setRepairName(null);
stockOutItem.setRepairDeviceId(null);
stockOutItem.setRepairDeviceName(null);
stockOutItem.setMaintenanceId(null);
stockOutItem.setMaintenanceName(null);
if (ErpStockOutUsageTypeEnum.REPAIR_RECEIVE.getType().equals(item.getOutUsageType()) && item.getRepairId() != null) {
DvRepairRespDTO repair = dvRepairApi.getDvRepair(item.getRepairId());
if (repair != null) {
stockOutItem.setRepairId(repair.getId());
stockOutItem.setRepairName(repair.getRepairName());
stockOutItem.setRepairDeviceId(item.getRepairDeviceId() != null ? item.getRepairDeviceId() : repair.getMachineryId());
stockOutItem.setRepairDeviceName(repair.getMachineryName());
}
} else if (ErpStockOutUsageTypeEnum.MAINTENANCE_RECEIVE.getType().equals(item.getOutUsageType()) && item.getMaintenanceId() != null) {
TicketManagementRespDTO maintenance = ticketManagementApi.getTicketManagement(item.getMaintenanceId());
if (maintenance != null) {
stockOutItem.setMaintenanceId(maintenance.getId());
stockOutItem.setMaintenanceName(maintenance.getPlanNo());
}
}
}
}
private void createApproveRecord(Long stockOutId, ErpStockOutApproveActionEnum action, Integer fromStatus,
Integer toStatus, Long targetUserId, String remark) {
stockOutApproveRecordMapper.insert(ErpStockOutApproveRecordDO.builder()
@ -406,13 +457,13 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
.build());
}
private List<ErpStockOutItemDO> validateStockOutItems(List<ErpStockOutSaveReqVO.Item> list, String outType) {
private List<ErpStockOutItemDO> validateStockOutItems(List<ErpStockOutSaveReqVOItem> list, String outType) {
validateWarehouseAreas(list);
if (Objects.equals(outType, "模具出库")) {
List<MoldBrandDO> moldList = moldBrandService.validMoldList(convertSet(list, ErpStockOutSaveReqVO.Item::getMoldSetId));
List<MoldBrandDO> moldList = moldBrandService.validMoldList(convertSet(list, ErpStockOutSaveReqVOItem::getMoldSetId));
Map<Long, MoldBrandDO> moldMap = convertMap(moldList, MoldBrandDO::getId);
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
convertSet(list, ErpStockOutSaveReqVO.Item::getAreaId));
convertSet(list, ErpStockOutSaveReqVOItem::getAreaId));
return convertList(list, item -> {
MoldBrandDO moldBrand = moldMap.get(item.getMoldSetId());
return ErpStockOutItemDO.builder()
@ -427,26 +478,39 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
.productPrice(item.getProductPrice())
.count(item.getCount())
.totalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount()))
.outUsageType(item.getOutUsageType())
.outUsageTypeName(ErpStockOutUsageTypeEnum.getNameByType(item.getOutUsageType()))
.repairId(item.getRepairId())
.repairDeviceId(item.getRepairDeviceId())
.maintenanceId(item.getMaintenanceId())
.remark(item.getRemark())
.build();
});
}
List<ErpProductDO> productList = productService.validProductList(convertSet(list, ErpStockOutSaveReqVO.Item::getProductId));
List<ErpProductDO> productList = productService.validProductList(convertSet(list, ErpStockOutSaveReqVOItem::getProductId));
Map<Long, ErpProductDO> productMap = convertMap(productList, ErpProductDO::getId);
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
convertSet(list, ErpStockOutSaveReqVO.Item::getAreaId));
convertSet(list, ErpStockOutSaveReqVOItem::getAreaId));
return convertList(list, item -> BeanUtils.toBean(item, ErpStockOutItemDO.class, target -> target
.setAreaName(areaMap.containsKey(target.getAreaId()) ? areaMap.get(target.getAreaId()).getAreaName() : null)
.setProductUnitId(productMap.get(target.getProductId()).getUnitId())
.setTotalPrice(MoneyUtils.priceMultiply(target.getProductPrice(), target.getCount()))));
.setTotalPrice(MoneyUtils.priceMultiply(target.getProductPrice(), target.getCount()))
.setOutUsageType(item.getOutUsageType())
.setOutUsageTypeName(ErpStockOutUsageTypeEnum.getNameByType(item.getOutUsageType()))
.setRepairId(item.getRepairId())
.setRepairDeviceId(item.getRepairDeviceId())
.setRepairName(null)
.setRepairDeviceName(null)
.setMaintenanceId(item.getMaintenanceId())
.setMaintenanceName(null)));
}
private void validateWarehouseAreas(List<ErpStockOutSaveReqVO.Item> list) {
private void validateWarehouseAreas(List<ErpStockOutSaveReqVOItem> list) {
Map<Long, ErpWarehouseDO> warehouseMap = convertMap(
warehouseService.validWarehouseList(convertSet(list, ErpStockOutSaveReqVO.Item::getWarehouseId)),
warehouseService.validWarehouseList(convertSet(list, ErpStockOutSaveReqVOItem::getWarehouseId)),
ErpWarehouseDO::getId);
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
convertSet(list, ErpStockOutSaveReqVO.Item::getAreaId));
convertSet(list, ErpStockOutSaveReqVOItem::getAreaId));
list.forEach(item -> {
if (item.getAreaId() == null) {
return;

@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageR
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
/**
@ -41,6 +42,8 @@ public interface ErpStockService {
ErpStockDO getStock(Long productId, Long warehouseId, Long areaId);
List<ErpStockDO> getStockList(Collection<Long> productIds, Collection<Long> warehouseIds, Collection<Long> areaIds);
/**
*
* 0

@ -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;
@ -12,6 +13,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -69,6 +71,12 @@ public class ErpStockServiceImpl implements ErpStockService {
}
return stock;
}
@Override
public List<ErpStockDO> getStockList(Collection<Long> productIds, Collection<Long> warehouseIds, Collection<Long> areaIds) {
return stockMapper.selectListByProductIdsAndWarehouseIdsAndAreaIds(productIds, warehouseIds, areaIds);
}
@Override
public List<ErpStockDO> getStockByProductId(Long productId) {
return stockMapper.selectByProductId(productId);
@ -90,12 +98,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 +115,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 +137,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());
}
}

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper">
<select id="selectInIds" resultType="java.lang.Long">
SELECT DISTINCT in_id
FROM erp_stock_in_item
<where>
<if test="productId != null">
AND product_id = #{productId}
</if>
<if test="warehouseId != null">
AND warehouse_id = #{warehouseId}
</if>
</where>
</select>
</mapper>

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper">
<select id="selectOutIds" resultType="java.lang.Long">
SELECT DISTINCT out_id
FROM erp_stock_out_item
<where>
<if test="productId != null">
AND product_id = #{productId}
</if>
<if test="warehouseId != null">
AND warehouse_id = #{warehouseId}
</if>
</where>
</select>
</mapper>

@ -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);
}

@ -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;
}

@ -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);
}

@ -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;
}

@ -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);
}
}

@ -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);
}
}

@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVOItem;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper;
@ -260,7 +261,7 @@ public class PlanServiceImpl implements PlanService {
itemRequisitionService.updateItemRequisition(saveReqVO);
// 创建入领料出库单
ErpStockOutSaveReqVO stockOut = new ErpStockOutSaveReqVO();
List<ErpStockOutSaveReqVO.Item> itemList = new ArrayList<>();
List<ErpStockOutSaveReqVOItem> itemList = new ArrayList<>();
stockOut.setOutTime(LocalDateTime.now());
stockOut.setOutType("领料出库");
@ -270,7 +271,7 @@ public class PlanServiceImpl implements PlanService {
.last("limit 1")
);
for (ItemRequisitionAndStock requisition : list) {
ErpStockOutSaveReqVO.Item item = new ErpStockOutSaveReqVO.Item();
ErpStockOutSaveReqVOItem item = new ErpStockOutSaveReqVOItem();
item.setWarehouseId(warehouse.getId());
item.setProductId(requisition.getItemId());
item.setCount(calculateLossNumber(requisition.getItemId(), requisition.getNumber(), bomYieldRateMap, createReqVO.getIsCalculateLoss()));

@ -105,8 +105,17 @@ public class UserController {
@GetMapping({"/list-all-simple", "/simple-list"})
@Operation(summary = "获取用户精简信息列表", description = "只包含被开启的用户,主要用于前端的下拉选项")
public CommonResult<List<UserSimpleRespVO>> getSimpleUserList() {
public CommonResult<List<UserSimpleRespVO>> getSimpleUserList(@RequestParam(value = "username", required = false) String username,
@RequestParam(value = "nickname", required = false) String nickname) {
List<AdminUserDO> 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<Long, DeptDO> deptMap = deptService.getDeptMap(
convertList(list, AdminUserDO::getDeptId));

Loading…
Cancel
Save