Merge remote-tracking branch 'origin/main'

main
liutao 1 week ago
commit 410921ac2d

@ -50,6 +50,9 @@ public class MoldBrandPageReqVO extends PageParam {
@Schema(description = "设备名称", example = "注塑机")
private String deviceName;
@Schema(description = "当前设备,模糊匹配设备名称", example = "注塑机")
private String currentDevice;
@Schema(description = "预期寿命(小时)")
private BigDecimal useTime;

@ -13,7 +13,8 @@ public enum QrcodeBizTypeEnum {
KEY_PART("KEY_PART", "关键件"),
MOLD("MOLD", "模具"),
PALLET("PALLET", "托盘"),
SPARE("SPARE", "备件");
SPARE("SPARE", "备件"),
WAREHOUSE_AREA("WAREHOUSE_AREA", "库区");
private final String code;
private final String name;

@ -153,6 +153,13 @@ public interface ErrorCodeConstants {
ErrorCode STOCK_MOVE_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的调拨单才能审核");
ErrorCode STOCK_MOVE_NO_EXISTS = new ErrorCode(1_030_402_004, "生成调拨号失败,请重新提交");
ErrorCode STOCK_MOVE_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "库存调拨单({})已审核,无法修改");
ErrorCode STOCK_MOVE_UPDATE_FAIL_PROCESS = new ErrorCode(1_030_402_006, "库存调拨单({})审核中,无法修改");
ErrorCode STOCK_MOVE_DELETE_FAIL_PROCESS = new ErrorCode(1_030_402_007, "库存调拨单({})审核中,无法删除");
ErrorCode STOCK_MOVE_SUBMIT_FAIL_STATUS = new ErrorCode(1_030_402_008, "提交审核失败,只有待提交或已驳回的调拨单才能提交");
ErrorCode STOCK_MOVE_SUBMIT_FAIL_USER = new ErrorCode(1_030_402_009, "提交审核失败,只有创建人才能提交审核");
ErrorCode STOCK_MOVE_AUDIT_FAIL_STATUS = new ErrorCode(1_030_402_010, "审核失败,只有审核中的调拨单才能审核");
ErrorCode STOCK_MOVE_AUDIT_FAIL_USER = new ErrorCode(1_030_402_011, "审核失败,当前用户不是指定审核人");
ErrorCode STOCK_MOVE_AUDIT_FAIL_RESULT = new ErrorCode(1_030_402_012, "审核失败,审核结果只支持通过或驳回");
// ========== ERP 库存盘点单 1-030-403-000 ==========
ErrorCode STOCK_CHECK_NOT_EXISTS = new ErrorCode(1_030_403_000, "库存盘点单不存在");

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.erp.enums.stock;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum ErpStockMoveApproveActionEnum {
SUBMIT("SUBMIT"),
APPROVE("APPROVE"),
REJECT("REJECT"),
AUTO_APPROVE("AUTO_APPROVE");
private final String actionType;
}

@ -118,8 +118,9 @@ public class ErpProductController {
}
@GetMapping("/simple-list-all")
@Operation(summary = "获得所有精简列表", description = "只包含被开启的产品,主要用于前端的下拉选项")
public CommonResult<List<ErpProductRespVO>> getAllSimpleList(@RequestParam(name = "categoryId", required = false) Integer categoryId) {
List<ErpProductRespVO> list = productService.getProductVOListByStatus(CommonStatusEnum.ENABLE.getStatus(),categoryId);
public CommonResult<List<ErpProductRespVO>> getAllSimpleList(@RequestParam(name = "categoryId", required = false) Integer categoryId,
@RequestParam(name = "categoryType", required = false) Integer categoryType) {
List<ErpProductRespVO> list = productService.getProductVOListByStatus(CommonStatusEnum.ENABLE.getStatus(), categoryId, categoryType);
return success(convertList(list, product -> new ErpProductRespVO().setId(product.getId())
.setName(product.getName()).setBarCode(product.getBarCode())
.setCategoryId(product.getCategoryId()).setCategoryName(product.getCategoryName())

@ -10,16 +10,10 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckApproveRecordRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckAuditReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckGenerateByLocationReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckGenerateByProductReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSubmitReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.*;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckApproveRecordDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO;
@ -186,6 +180,64 @@ public class ErpStockCheckController {
ExcelUtils.write(response, "库存盘点单.xls", "数据", ErpStockCheckRespVO.class, list);
}
@GetMapping("/record-page")
@Operation(summary = "获得库存盘点记录分页")
@PreAuthorize("@ss.hasPermission('erp:stock-check:query')")
public CommonResult<PageResult<ErpStockCheckRecordRespVO>> getStockCheckRecordPage(
@Valid ErpStockCheckRecordPageReqVO pageReqVO) {
return success(buildStockCheckRecordVOPageResult(stockCheckService.getStockCheckRecordPage(pageReqVO)));
}
@GetMapping("/record-export-excel")
@Operation(summary = "导出库存盘点记录 Excel")
@PreAuthorize("@ss.hasPermission('erp:stock-check:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportStockCheckRecordExcel(@Valid ErpStockCheckRecordPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<ErpStockCheckRecordRespVO> list = buildStockCheckRecordVOPageResult(
stockCheckService.getStockCheckRecordPage(pageReqVO)).getList();
ExcelUtils.write(response, "库存盘点记录.xls", "数据", ErpStockCheckRecordRespVO.class, list);
}
private PageResult<ErpStockCheckRecordRespVO> buildStockCheckRecordVOPageResult(PageResult<ErpStockCheckItemDO> pageResult) {
if (CollUtil.isEmpty(pageResult.getList())) {
return PageResult.empty(pageResult.getTotal());
}
Map<Long, ErpStockCheckDO> stockCheckMap = stockCheckService.getStockCheckMap(
convertSet(pageResult.getList(), ErpStockCheckItemDO::getCheckId));
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(
convertSet(pageResult.getList(), ErpStockCheckItemDO::getProductId));
Map<Long, ErpProductUnitDO> unitMap = productUnitService.getProductUnitMap(convertSet(productMap.values(), ErpProductRespVO::getUnitId));
Map<Long, ErpWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(
convertSet(pageResult.getList(), ErpStockCheckItemDO::getWarehouseId));
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
convertSet(pageResult.getList(), ErpStockCheckItemDO::getAreaId));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(stockCheckMap.values(),
stockCheck -> Stream.of(NumberUtils.parseLong(stockCheck.getCreator()))));
return BeanUtils.toBean(pageResult, ErpStockCheckRecordRespVO.class, record -> {
MapUtils.findAndThen(stockCheckMap, record.getCheckId(), stockCheck -> {
record.setNo(stockCheck.getNo())
.setCheckTime(stockCheck.getCheckTime())
.setSourceType(stockCheck.getSourceType())
.setCategoryType(stockCheck.getCategoryType())
.setCheckStatus(stockCheck.getCheckStatus())
.setStatus(stockCheck.getStatus())
.setCreator(stockCheck.getCreator())
.setCreateTime(stockCheck.getCreateTime());
MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockCheck.getCreator()), user -> record.setCreatorName(user.getNickname()));
});
MapUtils.findAndThen(productMap, record.getProductId(), product -> record.setProductName(product.getName())
.setProductBarCode(product.getBarCode()).setCategoryName(product.getCategoryName()));
MapUtils.findAndThen(productMap, record.getProductId(), product ->
MapUtils.findAndThen(unitMap, product.getUnitId(), unit -> record.setProductUnitName(unit.getName())));
MapUtils.findAndThen(warehouseMap, record.getWarehouseId(), warehouse -> record.setWarehouseName(warehouse.getName()));
if (record.getAreaName() == null) {
MapUtils.findAndThen(areaMap, record.getAreaId(), area -> record.setAreaName(area.getAreaName()));
}
});
}
private PageResult<ErpStockCheckRespVO> buildStockCheckVOPageResult(PageResult<ErpStockCheckDO> pageResult) {
if (CollUtil.isEmpty(pageResult.getList())) {
return PageResult.empty(pageResult.getTotal());

@ -38,11 +38,13 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
@ -95,8 +97,10 @@ public class ErpStockController {
@Operation(summary = "获得产品库存分页")
@PreAuthorize("@ss.hasPermission('erp:stock:query')")
public CommonResult<PageResult<ErpStockRespVO>> getStockPage(@Valid ErpStockPageReqVO pageReqVO) {
PageResult<ErpStockDO> pageResult = stockService.getStockPage(pageReqVO);
return success(buildStockVOPageResult(pageResult));
ErpStockPageReqVO queryReqVO = BeanUtils.toBean(pageReqVO, ErpStockPageReqVO.class);
queryReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
PageResult<ErpStockRespVO> groupedResult = buildStockVOPageResult(stockService.getStockPage(queryReqVO));
return success(new PageResult<>(paginateStockList(groupedResult.getList(), pageReqVO), groupedResult.getTotal()));
}
@GetMapping("/export-excel")
@ -121,7 +125,7 @@ public class ErpStockController {
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
convertSet(pageResult.getList(), ErpStockDO::getAreaId));
Map<String, Long> palletCountMap = buildPalletCountMap(pageResult.getList());
return BeanUtils.toBean(pageResult, ErpStockRespVO.class, stock -> {
PageResult<ErpStockRespVO> respPageResult = BeanUtils.toBean(pageResult, ErpStockRespVO.class, stock -> {
MapUtils.findAndThen(productMap, stock.getProductId(), product -> {
stock.setProductName(product.getName()).setBarCode(product.getBarCode())
.setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())
@ -138,6 +142,8 @@ public class ErpStockController {
}
fillRecentRecordTime(stock);
});
List<ErpStockRespVO> mergedList = mergeStockByProductAndWarehouse(respPageResult.getList());
return new PageResult<>(mergedList, (long) mergedList.size());
}
private ErpStockRespVO buildStockRespVO(ErpStockDO stock) {
@ -177,6 +183,79 @@ public class ErpStockController {
return respVO;
}
private List<ErpStockRespVO> mergeStockByProductAndWarehouse(List<ErpStockRespVO> stockList) {
if (CollUtil.isEmpty(stockList)) {
return Collections.emptyList();
}
Map<String, ErpStockRespVO> mergedMap = new LinkedHashMap<>();
stockList.forEach(stock -> {
String key = buildStockGroupKey(stock.getProductId(), stock.getWarehouseId());
ErpStockRespVO merged = mergedMap.computeIfAbsent(key, item -> {
ErpStockRespVO target = BeanUtils.toBean(stock, ErpStockRespVO.class);
target.setId(null);
target.setAreaId(null);
target.setAreaName(null);
target.setCount(BigDecimal.ZERO);
target.setPalletCount(0L);
target.setAreaStocks(new ArrayList<>());
return target;
});
merged.setCount(defaultZero(merged.getCount()).add(defaultZero(stock.getCount())));
merged.setPalletCount((merged.getPalletCount() == null ? 0L : merged.getPalletCount())
+ (stock.getPalletCount() == null ? 0L : stock.getPalletCount()));
merged.getAreaStocks().add(buildAreaStock(stock));
if (merged.getRecentInTime() == null || stock.getRecentInTime() != null
&& stock.getRecentInTime().isAfter(merged.getRecentInTime())) {
merged.setRecentInTime(stock.getRecentInTime());
}
if (merged.getRecentOutTime() == null || stock.getRecentOutTime() != null
&& stock.getRecentOutTime().isAfter(merged.getRecentOutTime())) {
merged.setRecentOutTime(stock.getRecentOutTime());
}
});
mergedMap.values().forEach(stock -> {
stock.setTotalBaseCount(stock.getCount());
stock.setTotalPackageCount(calculatePackageCount(stock, stock.getCount()));
stock.setPackagingRule(buildPackagingRule(stock));
stock.setStockDisplay(buildStockDisplay(stock));
});
return new ArrayList<>(mergedMap.values());
}
private List<ErpStockRespVO> paginateStockList(List<ErpStockRespVO> list, PageParam pageReqVO) {
if (CollUtil.isEmpty(list) || Objects.equals(pageReqVO.getPageSize(), PageParam.PAGE_SIZE_NONE)) {
return list;
}
int fromIndex = (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize();
if (fromIndex >= list.size()) {
return Collections.emptyList();
}
int toIndex = Math.min(fromIndex + pageReqVO.getPageSize(), list.size());
return list.subList(fromIndex, toIndex);
}
private ErpStockRespVO.AreaStock buildAreaStock(ErpStockRespVO stock) {
ErpStockRespVO.AreaStock areaStock = new ErpStockRespVO.AreaStock();
areaStock.setAreaId(stock.getAreaId());
areaStock.setAreaName(stock.getAreaName());
areaStock.setCount(defaultZero(stock.getCount()));
areaStock.setPackageCount(calculatePackageCount(stock, stock.getCount()));
areaStock.setBaseCount(calculateBaseCount(stock, stock.getCount()));
areaStock.setStockDisplay(buildAreaStockDisplay(stock, areaStock));
return areaStock;
}
private String buildAreaStockDisplay(ErpStockRespVO stock, ErpStockRespVO.AreaStock areaStock) {
String prefix = areaStock.getAreaName() != null ? areaStock.getAreaName() + "" : "";
String countDisplay = "" + formatNumber(areaStock.getCount()) + nullToEmpty(stock.getUnitName()) + "";
if (isProductType(stock.getCategoryType())) {
return prefix + formatNumber(areaStock.getPackageCount()) + "包"
+ formatNumber(areaStock.getBaseCount()) + stock.getUnitName() + countDisplay;
}
return prefix + formatNumber(areaStock.getPackageCount()) + nullToEmpty(stock.getPurchaseUnitName())
+ formatNumber(areaStock.getBaseCount()) + nullToEmpty(stock.getUnitName()) + countDisplay;
}
private void fillRecentRecordTime(ErpStockRespVO stock) {
stock.setRecentInTime(stockRecordService.getLatestRecordTime(
stock.getProductId(), stock.getWarehouseId(), stock.getAreaId(), true));
@ -188,24 +267,32 @@ public class ErpStockController {
if (stock.getUnitId() == null) {
stock.setUnitId(product.getUnitId());
}
stock.setUnitName(product.getUnitName());
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());
}
stock.setPurchaseUnitName(product.getPurchaseUnitName());
stock.setPurchaseUnitConvertQuantity(product.getPurchaseUnitConvertQuantity());
stock.setDefaultPackagingSchemeId(product.getDefaultPackagingSchemeId());
if (stock.getDefaultPackagingScheme() == null) {
stock.setDefaultPackagingScheme(findDefaultPackagingScheme(product));
}
}
private void fillPackagingSnapshot(ErpStockRespVO stock, ErpProductRespVO product) {
if (isProductType(stock.getCategoryType())) {
ProductPackagingSchemeRespVO defaultScheme = findDefaultPackagingScheme(product);
if (defaultScheme == null) {
return;
}
stock.setDefaultPackagingSchemeId(defaultScheme.getPackagingSchemeId());
stock.setDefaultPackagingScheme(defaultScheme);
stock.setDefaultPackagingSchemeName(defaultScheme.getPackagingSchemeName());
stock.setPackageQuantity(defaultScheme.getPackageQuantity());
stock.setPalletPackageQuantity(defaultScheme.getPalletPackageQuantity());
stock.setPalletTotalQuantity(defaultScheme.getPalletTotalQuantity());
return;
}
if (stock.getDefaultPackagingSchemeName() != null
&& stock.getPackageQuantity() != null
&& stock.getPalletPackageQuantity() != null
@ -273,9 +360,10 @@ public class ErpStockController {
if (stock.getPackageQuantity() == null || stock.getPackageQuantity().compareTo(BigDecimal.ZERO) <= 0) {
return formatNumber(stock.getCount()) + stock.getUnitName();
}
BigDecimal packageCount = stock.getCount().divide(stock.getPackageQuantity(), 0, RoundingMode.CEILING);
BigDecimal packageCount = calculatePackageCount(stock, stock.getCount());
BigDecimal baseCount = calculateBaseCount(stock, stock.getCount());
return formatNumber(BigDecimal.valueOf(stock.getPalletCount() != null ? stock.getPalletCount() : 0L)) + "\u6258"
+ formatNumber(packageCount) + "\u5305" + formatNumber(stock.getCount()) + stock.getUnitName();
+ formatNumber(packageCount) + "\u5305" + formatNumber(baseCount) + stock.getUnitName();
}
if (stock.getPurchaseUnitConvertQuantity() == null || stock.getPurchaseUnitConvertQuantity().compareTo(BigDecimal.ZERO) <= 0
|| stock.getPurchaseUnitName() == null || stock.getUnitName() == null) {
@ -306,6 +394,37 @@ public class ErpStockController {
display.append(formatNumber(quantity)).append(unitName);
}
private BigDecimal calculatePackageCount(ErpStockRespVO stock, BigDecimal count) {
BigDecimal convertQuantity = getDisplayConvertQuantity(stock);
if (convertQuantity == null || convertQuantity.compareTo(BigDecimal.ZERO) <= 0) {
return BigDecimal.ZERO;
}
return defaultZero(count).divideToIntegralValue(convertQuantity);
}
private BigDecimal calculateBaseCount(ErpStockRespVO stock, BigDecimal count) {
BigDecimal convertQuantity = getDisplayConvertQuantity(stock);
if (convertQuantity == null || convertQuantity.compareTo(BigDecimal.ZERO) <= 0) {
return defaultZero(count);
}
return defaultZero(count).remainder(convertQuantity);
}
private BigDecimal getDisplayConvertQuantity(ErpStockRespVO stock) {
if (isProductType(stock.getCategoryType())) {
return stock.getPackageQuantity();
}
return stock.getPurchaseUnitConvertQuantity();
}
private BigDecimal defaultZero(BigDecimal value) {
return value != null ? value : BigDecimal.ZERO;
}
private String nullToEmpty(String value) {
return value != null ? value : "";
}
private boolean isProductType(Integer categoryType) {
return Integer.valueOf(1).equals(categoryType);
}
@ -332,6 +451,10 @@ public class ErpStockController {
return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId);
}
private String buildStockGroupKey(Long productId, Long warehouseId) {
return String.valueOf(productId) + "_" + String.valueOf(warehouseId);
}
private String formatNumber(BigDecimal value) {
return value == null ? "0" : value.stripTrailingZeros().toPlainString();
}

@ -179,7 +179,6 @@ 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)));
}
@ -190,34 +189,11 @@ 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<>();
@ -341,8 +317,11 @@ public class ErpStockInController {
item.setProductBarCode(product.getBarCode());
item.setProductUnitName(product.getUnitName());
item.setCategoryType(product.getCategoryType());
item.setSupplierId(product.getDefaultSupplierId());
if (product.getDefaultSupplierId() != null && CollUtil.isNotEmpty(product.getSuppliers())) {
if (item.getSupplierId() == null) {
item.setSupplierId(product.getDefaultSupplierId());
}
if (StringUtils.isBlank(item.getSupplierName())
&& product.getDefaultSupplierId() != null && CollUtil.isNotEmpty(product.getSuppliers())) {
product.getSuppliers().stream()
.filter(supplier -> Objects.equals(supplier.getSupplierId(), product.getDefaultSupplierId()))
.findFirst()

@ -6,18 +6,30 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveApproveRecordRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveAuditReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveProductStockRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSubmitReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveApproveRecordDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO;
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.ErpAuditStatus;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockMoveService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockService;
import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService;
import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
@ -32,11 +44,19 @@ import javax.servlet.http.HttpServletResponse;
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.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.concurrent.TimeUnit;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@ -52,6 +72,10 @@ public class ErpStockMoveController {
private ErpStockService stockService;
@Resource
private ErpProductService productService;
@Resource
private ErpWarehouseService warehouseService;
@Resource
private WarehouseAreaService warehouseAreaService;
@Resource
private AdminUserApi adminUserApi;
@ -80,6 +104,42 @@ public class ErpStockMoveController {
return success(true);
}
@PutMapping("/submit")
@Operation(summary = "提交库存调拨单审核")
@PreAuthorize("@ss.hasPermission('erp:stock-move:submit')")
@RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS)
public CommonResult<Boolean> submitStockMoveAudit(@Valid @RequestBody ErpStockMoveSubmitReqVO submitReqVO) {
stockMoveService.submitStockMoveAudit(submitReqVO);
return success(true);
}
@PutMapping("/audit")
@Operation(summary = "审核库存调拨单")
@PreAuthorize("@ss.hasPermission('erp:stock-move:audit')")
@RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS)
public CommonResult<Boolean> auditStockMove(@Valid @RequestBody ErpStockMoveAuditReqVO auditReqVO) {
stockMoveService.auditStockMove(auditReqVO);
return success(true);
}
@GetMapping("/approve-record-list")
@Operation(summary = "获得库存调拨单审核记录")
@PreAuthorize("@ss.hasPermission('erp:stock-move:query')")
public CommonResult<List<ErpStockMoveApproveRecordRespVO>> getApproveRecordList(@RequestParam("id") Long id) {
return success(buildApproveRecordRespList(stockMoveService.getStockMoveApproveRecordList(id)));
}
@GetMapping("/product-stock-list")
@Operation(summary = "获得产品仓库库区库存列表")
@PreAuthorize("@ss.hasPermission('erp:stock-move:query')")
public CommonResult<List<ErpStockMoveProductStockRespVO>> getProductStockList(
@RequestParam("productId") Long productId,
@RequestParam(value = "warehouseId", required = false) Long warehouseId) {
List<ErpStockDO> stockList = stockService.getStockList(Collections.singleton(productId),
warehouseId == null ? Collections.emptySet() : Collections.singleton(warehouseId), Collections.emptySet());
return success(buildProductStockRespList(stockList));
}
@DeleteMapping("/delete")
@Operation(summary = "删除库存调拨单")
@Parameter(name = "ids", description = "编号数组", required = true)
@ -98,16 +158,9 @@ public class ErpStockMoveController {
if (stockMove == null) {
return success(null);
}
List<ErpStockMoveItemDO> stockMoveItemList = stockMoveService.getStockMoveItemListByMoveId(id);
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(
convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId));
return success(BeanUtils.toBean(stockMove, ErpStockMoveRespVO.class, stockMoveVO ->
stockMoveVO.setItems(BeanUtils.toBean(stockMoveItemList, ErpStockMoveRespVO.Item.class, item -> {
ErpStockDO stock = stockService.getStock(item.getProductId(), item.getFromWarehouseId());
item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO);
MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName())
.setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName()));
}))));
return success(buildStockMoveRespVO(stockMove,
stockMoveService.getStockMoveItemListByMoveId(id),
stockMoveService.getStockMoveApproveRecordList(id)));
}
@GetMapping("/page")
@ -134,27 +187,135 @@ public class ErpStockMoveController {
if (CollUtil.isEmpty(pageResult.getList())) {
return PageResult.empty(pageResult.getTotal());
}
// 1.1 调拨项
List<ErpStockMoveDO> stockMoves = pageResult.getList();
List<ErpStockMoveItemDO> stockMoveItemList = stockMoveService.getStockMoveItemListByMoveIds(
convertSet(pageResult.getList(), ErpStockMoveDO::getId));
convertSet(stockMoves, ErpStockMoveDO::getId));
Map<Long, List<ErpStockMoveItemDO>> stockMoveItemMap = convertMultiMap(stockMoveItemList, ErpStockMoveItemDO::getMoveId);
// 1.2 产品信息
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(
convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId));
// 1.3 TODO 芋艿:搞仓库信息
// 1.4 管理员信息
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(pageResult.getList(), stockMove -> Long.parseLong(stockMove.getCreator())));
// 2. 开始拼接
Map<Long, ErpWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertListByFlatMap(stockMoveItemList,
item -> Stream.of(item.getFromWarehouseId(), item.getToWarehouseId())));
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(convertListByFlatMap(stockMoveItemList,
item -> Stream.of(item.getFromAreaId(), item.getToAreaId())));
Map<String, ErpStockDO> stockMap = buildStockMap(stockMoveItemList);
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(stockMoves,
stockMove -> Stream.of(NumberUtils.parseLong(stockMove.getCreator()), stockMove.getAuditUserId())));
return BeanUtils.toBean(pageResult, ErpStockMoveRespVO.class, stockMove -> {
stockMove.setItems(BeanUtils.toBean(stockMoveItemMap.get(stockMove.getId()), ErpStockMoveRespVO.Item.class,
item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName())
.setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName()))));
item -> fillStockMoveItem(item, productMap, warehouseMap, areaMap, stockMap)));
stockMove.setProductNames(CollUtil.join(stockMove.getItems(), "", ErpStockMoveRespVO.Item::getProductName));
// TODO 芋艿:
// MapUtils.findAndThen(customerMap, stockMove.getCustomerId(), supplier -> stockMove.setCustomerName(supplier.getName()));
MapUtils.findAndThen(userMap, Long.parseLong(stockMove.getCreator()), user -> stockMove.setCreatorName(user.getNickname()));
stockMove.setStatusName(getAuditStatusName(stockMove.getStatus()));
MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockMove.getCreator()), user -> stockMove.setCreatorName(user.getNickname()));
MapUtils.findAndThen(userMap, stockMove.getAuditUserId(), user -> stockMove.setAuditUserName(user.getNickname()));
});
}
private List<ErpStockMoveProductStockRespVO> buildProductStockRespList(List<ErpStockDO> stockList) {
if (CollUtil.isEmpty(stockList)) {
return Collections.emptyList();
}
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(convertSet(stockList, ErpStockDO::getProductId));
Map<Long, ErpWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertSet(stockList, ErpStockDO::getWarehouseId));
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(convertSet(stockList, ErpStockDO::getAreaId));
return stockList.stream()
.sorted(Comparator.comparing(ErpStockDO::getWarehouseId, Comparator.nullsLast(Long::compareTo))
.thenComparing(ErpStockDO::getAreaId, Comparator.nullsLast(Long::compareTo)))
.map(stock -> BeanUtils.toBean(stock, ErpStockMoveProductStockRespVO.class, respVO -> {
respVO.setStockCount(stock.getCount());
MapUtils.findAndThen(productMap, stock.getProductId(), product -> respVO.setProductName(product.getName())
.setProductBarCode(product.getBarCode()));
MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> respVO.setWarehouseName(warehouse.getName()));
if (respVO.getAreaName() == null) {
MapUtils.findAndThen(areaMap, stock.getAreaId(), area -> respVO.setAreaName(area.getAreaName()));
}
}))
.collect(Collectors.toList());
}
private ErpStockMoveRespVO buildStockMoveRespVO(ErpStockMoveDO stockMove, List<ErpStockMoveItemDO> stockMoveItemList,
List<ErpStockMoveApproveRecordDO> approveRecords) {
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(
convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId));
Map<Long, ErpWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertListByFlatMap(stockMoveItemList,
item -> Stream.of(item.getFromWarehouseId(), item.getToWarehouseId())));
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(convertListByFlatMap(stockMoveItemList,
item -> Stream.of(item.getFromAreaId(), item.getToAreaId())));
Map<String, ErpStockDO> stockMap = buildStockMap(stockMoveItemList);
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(approveRecords,
record -> Stream.of(NumberUtils.parseLong(record.getCreator()), record.getTargetUserId())));
userMap.putAll(adminUserApi.getUserMap(convertListByFlatMap(Collections.singletonList(stockMove),
item -> Stream.of(NumberUtils.parseLong(item.getCreator()), item.getAuditUserId()))));
return BeanUtils.toBean(stockMove, ErpStockMoveRespVO.class, respVO -> {
respVO.setItems(BeanUtils.toBean(stockMoveItemList, ErpStockMoveRespVO.Item.class,
item -> fillStockMoveItem(item, productMap, warehouseMap, areaMap, stockMap)));
respVO.setProductNames(CollUtil.join(respVO.getItems(), "", ErpStockMoveRespVO.Item::getProductName));
respVO.setStatusName(getAuditStatusName(respVO.getStatus()));
respVO.setApproveRecords(buildApproveRecordRespList(approveRecords, userMap));
MapUtils.findAndThen(userMap, NumberUtils.parseLong(respVO.getCreator()), user -> respVO.setCreatorName(user.getNickname()));
MapUtils.findAndThen(userMap, respVO.getAuditUserId(), user -> respVO.setAuditUserName(user.getNickname()));
});
}
}
private void fillStockMoveItem(ErpStockMoveRespVO.Item item, Map<Long, ErpProductRespVO> productMap,
Map<Long, ErpWarehouseDO> warehouseMap, Map<Long, WarehouseAreaDO> areaMap,
Map<String, ErpStockDO> stockMap) {
MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName())
.setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName()));
MapUtils.findAndThen(warehouseMap, item.getFromWarehouseId(), warehouse -> item.setFromWarehouseName(warehouse.getName()));
MapUtils.findAndThen(warehouseMap, item.getToWarehouseId(), warehouse -> item.setToWarehouseName(warehouse.getName()));
MapUtils.findAndThen(areaMap, item.getFromAreaId(), area -> item.setFromAreaName(area.getAreaName()));
MapUtils.findAndThen(areaMap, item.getToAreaId(), area -> item.setToAreaName(area.getAreaName()));
ErpStockDO stock = stockMap.get(buildStockKey(item.getProductId(), item.getFromWarehouseId(), item.getFromAreaId()));
item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO);
}
private Map<String, ErpStockDO> buildStockMap(List<ErpStockMoveItemDO> stockMoveItemList) {
if (CollUtil.isEmpty(stockMoveItemList)) {
return Collections.emptyMap();
}
List<ErpStockDO> stockList = stockService.getStockList(convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId),
convertSet(stockMoveItemList, ErpStockMoveItemDO::getFromWarehouseId),
convertSet(stockMoveItemList, ErpStockMoveItemDO::getFromAreaId));
Map<String, ErpStockDO> stockMap = new java.util.HashMap<>();
for (ErpStockDO stock : stockList) {
stockMap.put(buildStockKey(stock.getProductId(), stock.getWarehouseId(), stock.getAreaId()), stock);
}
return stockMap;
}
private String buildStockKey(Long productId, Long warehouseId, Long areaId) {
return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId);
}
private List<ErpStockMoveApproveRecordRespVO> buildApproveRecordRespList(List<ErpStockMoveApproveRecordDO> records) {
if (CollUtil.isEmpty(records)) {
return new ArrayList<>();
}
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(records,
record -> Stream.of(NumberUtils.parseLong(record.getCreator()), record.getTargetUserId())));
return buildApproveRecordRespList(records, userMap);
}
private List<ErpStockMoveApproveRecordRespVO> buildApproveRecordRespList(List<ErpStockMoveApproveRecordDO> records,
Map<Long, AdminUserRespDTO> userMap) {
if (CollUtil.isEmpty(records)) {
return new ArrayList<>();
}
return BeanUtils.toBean(records, ErpStockMoveApproveRecordRespVO.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(getAuditStatusName(record.getFromStatus()));
record.setToStatusName(getAuditStatusName(record.getToStatus()));
});
}
private String getAuditStatusName(Integer status) {
for (ErpAuditStatus item : ErpAuditStatus.values()) {
if (item.getStatus().equals(status)) {
return item.getName();
}
}
return null;
}
}

@ -0,0 +1,54 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - ERP 库存盘点记录分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ErpStockCheckRecordPageReqVO extends PageParam {
@Schema(description = "盘点单号", example = "QCPD20260623001")
private String no;
@Schema(description = "盘点时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] checkTime;
@Schema(description = "生成来源类型1-按库存2-按产品", example = "1")
private Integer sourceType;
@Schema(description = "产品分类类型", example = "1")
private Integer categoryType;
@Schema(description = "盘点状态0-未盘点1-已盘点", example = "1")
private Integer checkStatus;
@Schema(description = "审核状态", example = "20")
private Integer status;
@Schema(description = "产品编号", example = "1")
private Long productId;
@Schema(description = "仓库编号", example = "1")
private Long warehouseId;
@Schema(description = "库区编号", example = "1")
private Long areaId;
@Schema(description = "创建人")
private String creator;
@Schema(description = "盘点记录项 id 集合,导出使用")
private String ids;
}

@ -0,0 +1,124 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
import cn.iocoder.yudao.module.erp.enums.DictTypeConstants;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS;
import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.PRODUCT_CATEGORY_TYPE;
@Schema(description = "管理后台 - ERP 库存盘点记录 Response VO")
@Data
@ExcelIgnoreUnannotated
public class ErpStockCheckRecordRespVO {
@Schema(description = "盘点记录项编号", example = "11756")
@ExcelProperty("盘点记录项编号")
private Long id;
@Schema(description = "盘点单编号", example = "11756")
private Long checkId;
@Schema(description = "盘点单号", example = "QCPD20260623001")
@ExcelProperty("盘点单号")
private String no;
@Schema(description = "盘点时间")
@ExcelProperty("盘点时间")
private LocalDateTime checkTime;
@Schema(description = "生成来源类型1-按库存2-按产品", example = "1")
@ExcelProperty(value = "生成来源类型", converter = DictConvert.class)
@DictFormat("erp_stock_check_source_type")
private Integer sourceType;
@Schema(description = "产品分类类型", example = "1")
@ExcelProperty(value = "产品分类类型", converter = DictConvert.class)
@DictFormat(PRODUCT_CATEGORY_TYPE)
private Integer categoryType;
@Schema(description = "盘点状态0-未盘点1-已盘点", example = "1")
@ExcelProperty("盘点状态")
private Integer checkStatus;
@Schema(description = "审核状态", example = "20")
@ExcelProperty(value = "审核状态", converter = DictConvert.class)
@DictFormat(AUDIT_STATUS)
private Integer status;
@Schema(description = "产品编号", example = "3113")
private Long productId;
@Schema(description = "产品名称", example = "苹果")
@ExcelProperty("产品名称")
private String productName;
@Schema(description = "产品条码", example = "A9985")
@ExcelProperty("产品条码")
private String productBarCode;
@Schema(description = "产品分类", example = "水果")
@ExcelProperty("产品分类")
private String categoryName;
@Schema(description = "产品单位名称", example = "个")
@ExcelProperty("单位")
private String productUnitName;
@Schema(description = "仓库编号", example = "3113")
private Long warehouseId;
@Schema(description = "仓库名称", example = "成品仓")
@ExcelProperty("仓库名称")
private String warehouseName;
@Schema(description = "库区编号", example = "1")
private Long areaId;
@Schema(description = "库区名称", example = "A区")
@ExcelProperty("库区名称")
private String areaName;
@Schema(description = "产品单价", example = "100.00")
@ExcelProperty("产品单价")
private BigDecimal productPrice;
@Schema(description = "账面数量", example = "100.00")
@ExcelProperty("账面数量")
private BigDecimal stockCount;
@Schema(description = "实际数量", example = "95.00")
@ExcelProperty("实际数量")
private BigDecimal actualCount;
@Schema(description = "盈亏数量", example = "-5.00")
@ExcelProperty("盈亏数量")
private BigDecimal count;
@Schema(description = "合计金额", example = "500.00")
@ExcelProperty("合计金额")
private BigDecimal totalPrice;
@Schema(description = "备注", example = "随便")
@ExcelProperty("备注")
private String remark;
@Schema(description = "创建人", example = "1")
private String creator;
@Schema(description = "创建人名称", example = "张三")
@ExcelProperty("创建人")
private String creatorName;
@Schema(description = "创建时间")
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}

@ -66,6 +66,12 @@ public class ErpStockInSaveReqVO {
@Schema(description = "产品编号", example = "3113")
private Long productId;
@Schema(description = "供应商编号", example = "3113")
private Long supplierId;
@Schema(description = "供应商名称", example = "供应商A")
private String supplierName;
@Schema(description = "产品单价", example = "100.00")
private BigDecimal productPrice;

@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - ERP 库存调拨单审核记录 Response VO")
@Data
public class ErpStockMoveApproveRecordRespVO {
@Schema(description = "编号", example = "1")
private Long id;
@Schema(description = "调拨单编号", example = "1")
private Long stockMoveId;
@Schema(description = "操作类型", example = "SUBMIT")
private String actionType;
@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;
@Schema(description = "目标审核人名称", example = "李四")
private String targetUserName;
@Schema(description = "备注", example = "请审核")
private String remark;
@Schema(description = "操作人", example = "1")
private String creator;
@Schema(description = "操作人名称", example = "张三")
private String creatorName;
@Schema(description = "创建时间")
private LocalDateTime createTime;
}

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - ERP 库存调拨单审核 Request VO")
@Data
public class ErpStockMoveAuditReqVO {
@Schema(description = "调拨单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756")
@NotNull(message = "调拨单编号不能为空")
private Long id;
@Schema(description = "审核结果 20-通过 1-驳回", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
@NotNull(message = "审核结果不能为空")
private Integer status;
@Schema(description = "审核备注", example = "审核通过")
private String remark;
}

@ -39,11 +39,23 @@ public class ErpStockMovePageReqVO extends PageParam {
@Schema(description = "产品编号", example = "1")
private Long productId;
@Schema(description = "产品分类类型", example = "1")
private Integer categoryType;
@Schema(description = "调出仓库编号", example = "1")
private Long fromWarehouseId;
@Schema(description = "调出库区编号", example = "1")
private Long fromAreaId;
@Schema(description = "调入仓库编号", example = "1")
private Long toWarehouseId;
@Schema(description = "调入库区编号", example = "1")
private Long toAreaId;
@Schema(description = "id集合导出用")
private String ids;
}
}

@ -0,0 +1,50 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - ERP 库存调拨产品库区库存 Response VO")
@Data
public class ErpStockMoveProductStockRespVO {
@Schema(description = "产品编号", example = "1")
private Long productId;
@Schema(description = "产品名称", example = "产品A")
private String productName;
@Schema(description = "产品编码", example = "CP001")
private String productBarCode;
@Schema(description = "仓库编号", example = "10")
private Long warehouseId;
@Schema(description = "仓库名称", example = "成品仓")
private String warehouseName;
@Schema(description = "库区编号", example = "100")
private Long areaId;
@Schema(description = "库区名称", example = "A区")
private String areaName;
@Schema(description = "当前库存数量", example = "120")
private BigDecimal stockCount;
@Schema(description = "库存单位编号", example = "1")
private Long unitId;
@Schema(description = "库存单位名称", example = "个")
private String unitName;
@Schema(description = "包装单位编号", example = "2")
private Long purchaseUnitId;
@Schema(description = "包装单位名称", example = "箱")
private String purchaseUnitName;
@Schema(description = "包装单位与库存单位换算数量", example = "20")
private BigDecimal purchaseUnitConvertQuantity;
}

@ -43,6 +43,18 @@ public class ErpStockMoveRespVO {
@DictFormat(AUDIT_STATUS)
private Integer status;
@Schema(description = "状态名称", example = "待提交")
private String statusName;
@Schema(description = "是否需要审核", example = "true")
private Boolean needAudit;
@Schema(description = "审核人编号", example = "1888")
private Long auditUserId;
@Schema(description = "审核人名称", example = "李四")
private String auditUserName;
@Schema(description = "备注", example = "随便")
@ExcelProperty("备注")
private String remark;
@ -62,6 +74,9 @@ public class ErpStockMoveRespVO {
@Schema(description = "调拨项列表", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Item> items;
@Schema(description = "审核记录")
private List<ErpStockMoveApproveRecordRespVO> approveRecords;
@Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("产品信息")
private String productNames;
@ -75,9 +90,27 @@ public class ErpStockMoveRespVO {
@Schema(description = "调出仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
private Long fromWarehouseId;
@Schema(description = "调出仓库名称", example = "A仓")
private String fromWarehouseName;
@Schema(description = "调出库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
private Long fromAreaId;
@Schema(description = "调出库区名称", example = "A-01")
private String fromAreaName;
@Schema(description = "调入仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
private Long toWarehouseId;
@Schema(description = "调入仓库名称", example = "B仓")
private String toWarehouseName;
@Schema(description = "调入库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
private Long toAreaId;
@Schema(description = "调入库区名称", example = "B-01")
private String toAreaName;
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
private Long productId;
@ -104,4 +137,4 @@ public class ErpStockMoveRespVO {
}
}
}

@ -1,7 +1,9 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutApproveRecordRespVO;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ -33,7 +35,10 @@ public class ErpStockMoveSaveReqVO {
@Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc")
private String fileUrl;
@Schema(description = "调拨项列表", requiredMode = Schema.RequiredMode.REQUIRED)
@Schema(description = "审核人编号", example = "1888")
private Long auditUserId;
@Schema(description = "调拨项列表", implementation = ErpStockMoveSaveReqVO.Item.class)
@NotEmpty(message = "调拨项列表不能为空")
@Valid
private List<Item> items;
@ -48,10 +53,18 @@ public class ErpStockMoveSaveReqVO {
@NotNull(message = "调出仓库编号不能为空")
private Long fromWarehouseId;
@Schema(description = "调出库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
@NotNull(message = "调出库区编号不能为空")
private Long fromAreaId;
@Schema(description = "调入仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
@NotNull(message = "调入仓库编号不能为空")
private Long toWarehouseId;
@Schema(description = "调入库区编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888")
@NotNull(message = "调入库区编号不能为空")
private Long toAreaId;
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
@NotNull(message = "产品编号不能为空")
private Long productId;
@ -69,9 +82,9 @@ public class ErpStockMoveSaveReqVO {
@AssertTrue(message = "调出、调仓仓库不能相同")
@JsonIgnore
public boolean isWarehouseValid() {
return ObjectUtil.notEqual(fromWarehouseId, toWarehouseId);
return ObjectUtil.notEqual(fromWarehouseId, toWarehouseId) || ObjectUtil.notEqual(fromAreaId, toAreaId);
}
}
}
}

@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - ERP 库存调拨单提交审核 Request VO")
@Data
public class ErpStockMoveSubmitReqVO {
@Schema(description = "调拨单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756")
@NotNull(message = "调拨单编号不能为空")
private Long id;
@Schema(description = "审核人编号", example = "1888")
private Long auditUserId;
@Schema(description = "提交备注", example = "请审核")
private String remark;
}

@ -9,6 +9,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.PRODUCT_CATEGORY_TYPE;
@ -95,6 +96,15 @@ public class ErpStockRespVO {
@ExcelProperty("库存展示")
private String stockDisplay;
@Schema(description = "总包数", example = "10")
private BigDecimal totalPackageCount;
@Schema(description = "总基本数量", example = "100")
private BigDecimal totalBaseCount;
@Schema(description = "库区库存明细")
private List<AreaStock> areaStocks;
@Schema(description = "托盘数量", example = "2")
private Long palletCount;
@ -112,4 +122,26 @@ public class ErpStockRespVO {
@ExcelProperty("最近出库时间")
private java.time.LocalDateTime recentOutTime;
@Data
public static class AreaStock {
@Schema(description = "库区编号", example = "1")
private Long areaId;
@Schema(description = "库区名称", example = "A-01")
private String areaName;
@Schema(description = "库存数量", example = "100")
private BigDecimal count;
@Schema(description = "包数", example = "10")
private BigDecimal packageCount;
@Schema(description = "基本数量", example = "0")
private BigDecimal baseCount;
@Schema(description = "库存展示", example = "A-0110包0个")
private String stockDisplay;
}
}

@ -1,6 +1,8 @@
package cn.iocoder.yudao.module.erp.controller.admin.warehousearea;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO;
import org.springframework.web.bind.annotation.*;
@ -13,6 +15,7 @@ import io.swagger.v3.oas.annotations.Operation;
import java.util.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -25,6 +28,7 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.*;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
@ -43,10 +47,13 @@ public class WarehouseAreaController {
@Resource
private WarehouseAreaService warehouseAreaService;
@Resource
private QrcodeRecordService qrcodeService;
@PostMapping("/create")
@Operation(summary = "创建ERP 库区信息")
@PreAuthorize("@ss.hasPermission('erp:warehouse-area:create')")
public CommonResult<Long> createWarehouseArea(@Valid @RequestBody WarehouseAreaSaveReqVO createReqVO) {
public CommonResult<Long> createWarehouseArea(@Valid @RequestBody WarehouseAreaSaveReqVO createReqVO) throws UnsupportedEncodingException {
return success(warehouseAreaService.createWarehouseArea(createReqVO));
}
@ -73,7 +80,10 @@ public class WarehouseAreaController {
@PreAuthorize("@ss.hasPermission('erp:warehouse-area:query')")
public CommonResult<WarehouseAreaRespVO> getWarehouseArea(@RequestParam("id") Long id) {
WarehouseAreaDO warehouseArea = warehouseAreaService.getWarehouseArea(id);
return success(BeanUtils.toBean(warehouseArea, WarehouseAreaRespVO.class));
WarehouseAreaRespVO respVO = BeanUtils.toBean(warehouseArea, WarehouseAreaRespVO.class);
fillQrcodeUrl(respVO, warehouseArea);
fillTemplateJson(respVO);
return success(respVO);
}
@GetMapping("/page")
@ -81,7 +91,10 @@ public class WarehouseAreaController {
@PreAuthorize("@ss.hasPermission('erp:warehouse-area:query')")
public CommonResult<PageResult<WarehouseAreaRespVO>> getWarehouseAreaPage(@Valid WarehouseAreaPageReqVO pageReqVO) {
PageResult<WarehouseAreaDO> pageResult = warehouseAreaService.getWarehouseAreaPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, WarehouseAreaRespVO.class));
PageResult<WarehouseAreaRespVO> result = BeanUtils.toBean(pageResult, WarehouseAreaRespVO.class);
fillQrcodeUrl(result.getList());
fillTemplateJson(result.getList());
return success(result);
}
@ -89,12 +102,47 @@ public class WarehouseAreaController {
@Operation(summary = "获得库区精简列表", description = "只包含被开启的仓库库区,主要用于前端的下拉选项")
public CommonResult<List<WarehouseAreaRespVO>> getWarehouseSimpleList(@RequestParam(value = "warehouseId", required = false) Long warehouseId) {
List<WarehouseAreaDO> list = warehouseAreaService.getWarehouseListByStatusAndWarehouseId(CommonStatusEnum.ENABLE.getStatus(), warehouseId);
return success(convertList(list, area -> new WarehouseAreaRespVO()
List<WarehouseAreaRespVO> result = convertList(list, area -> new WarehouseAreaRespVO()
.setId(area.getId())
.setWarehouseId(area.getWarehouseId())
.setAreaCode(area.getAreaCode())
.setAreaName(area.getAreaName())
.setStatus(area.getStatus())));
.setStatus(area.getStatus()));
fillQrcodeUrl(result);
return success(result);
}
private void fillQrcodeUrl(WarehouseAreaRespVO respVO, WarehouseAreaDO warehouseArea) {
if (respVO == null || warehouseArea == null) {
return;
}
respVO.setQrcodeUrl(qrcodeService.selectQrcodeUrlByIdAndCode(
QrcodeBizTypeEnum.WAREHOUSE_AREA.getCode(), warehouseArea.getId(), warehouseArea.getAreaCode()));
}
private void fillQrcodeUrl(List<WarehouseAreaRespVO> list) {
Map<Long, String> qrcodeUrlMap = qrcodeService.selectQrcodeUrlMapByBizTypeAndIds(
QrcodeBizTypeEnum.WAREHOUSE_AREA.getCode(), convertSet(list, WarehouseAreaRespVO::getId));
for (WarehouseAreaRespVO respVO : list) {
respVO.setQrcodeUrl(qrcodeUrlMap.get(respVO.getId()));
}
}
private void fillTemplateJson(WarehouseAreaRespVO respVO) {
if (respVO == null) {
return;
}
respVO.setTemplateJson(warehouseAreaService.selectPrintTemplate());
}
private void fillTemplateJson(List<WarehouseAreaRespVO> list) {
if (list == null || list.isEmpty()) {
return;
}
String templateJson = warehouseAreaService.selectPrintTemplate();
for (WarehouseAreaRespVO respVO : list) {
respVO.setTemplateJson(templateJson);
}
}
@ -111,4 +159,11 @@ public class WarehouseAreaController {
BeanUtils.toBean(list, WarehouseAreaRespVO.class));
}
@PostMapping("/regenerate-code")
public CommonResult<Boolean> regenerateCode(@RequestParam("id") Long id,
@RequestParam("code") String code) throws UnsupportedEncodingException {
warehouseAreaService.regenerateCode(id, code);
return success(true);
}
}

@ -25,6 +25,12 @@ public class WarehouseAreaRespVO {
@ExcelProperty("库区编码")
private String areaCode;
@Schema(description = "二维码 URL")
private String qrcodeUrl;
@Schema(description = "打印模板Json", example = "")
private String templateJson;
@Schema(description = "库区名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "赵六")
@ExcelProperty("库区名称")
private String areaName;
@ -45,4 +51,4 @@ public class WarehouseAreaRespVO {
@ExcelProperty("创建时间")
private LocalDateTime createTime;
}
}

@ -66,6 +66,11 @@ public class ErpProductDO extends BaseDO {
*/
private Long unitId;
/**
*
*/
private String unitName;
/**
*
*

@ -56,6 +56,14 @@ public class ErpStockInItemDO extends BaseDO {
*
*/
private String productName;
/**
*
*/
private Long supplierId;
/**
*
*/
private String supplierName;
/**
*
*

@ -0,0 +1,38 @@
package cn.iocoder.yudao.module.erp.dal.dataobject.stock;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
@TableName("erp_stock_move_approve_record")
@KeySequence("erp_stock_move_approve_record_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ErpStockMoveApproveRecordDO extends BaseDO {
@TableId
private Long id;
private Long stockMoveId;
private String actionType;
private Integer fromStatus;
private Integer toStatus;
private Long targetUserId;
private String remark;
}

@ -45,6 +45,8 @@ public class ErpStockMoveDO extends BaseDO {
*
*/
private BigDecimal totalPrice;
private Boolean needAudit;
private Long auditUserId;
/**
*
*
@ -60,4 +62,4 @@ public class ErpStockMoveDO extends BaseDO {
*/
private String fileUrl;
}
}

@ -41,12 +41,16 @@ public class ErpStockMoveItemDO extends BaseDO {
* {@link ErpWarehouseDO#getId()}
*/
private Long fromWarehouseId;
private Long fromAreaId;
private String fromAreaName;
/**
*
*
* {@link ErpWarehouseDO#getId()}
*/
private Long toWarehouseId;
private Long toAreaId;
private String toAreaName;
/**
*
*
@ -76,4 +80,4 @@ public class ErpStockMoveItemDO extends BaseDO {
*/
private String remark;
}
}

@ -133,9 +133,13 @@ public interface ErpProductMapper extends BaseMapperX<ErpProductDO> {
}
/**查询不同类型的产品**/
default List<ErpProductDO> selectByCategorys(List<Integer> categoryIds) {
return selectByCategorys(categoryIds, CommonStatusEnum.ENABLE.getStatus());
}
default List<ErpProductDO> selectByCategorys(List<Integer> categoryIds, Integer status) {
LambdaQueryWrapper<ErpProductDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ErpProductDO::getStatus, 0);
wrapper.eq(status != null, ErpProductDO::getStatus, status);
if (categoryIds!=null && !categoryIds.isEmpty() ) {
wrapper.in(ErpProductDO::getCategoryId, categoryIds);

@ -1,11 +1,19 @@
package cn.iocoder.yudao.module.erp.dal.mysql.stock;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRecordPageReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import com.alibaba.excel.util.StringUtils;
import org.apache.ibatis.annotations.Mapper;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* ERP Mapper
@ -15,6 +23,53 @@ import java.util.List;
@Mapper
public interface ErpStockCheckItemMapper extends BaseMapperX<ErpStockCheckItemDO> {
DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
Integer STOCK_CHECK_STATUS_CHECKED = 1;
default PageResult<ErpStockCheckItemDO> selectRecordPage(ErpStockCheckRecordPageReqVO reqVO) {
LambdaQueryWrapperX<ErpStockCheckItemDO> query = new LambdaQueryWrapperX<ErpStockCheckItemDO>()
.eqIfPresent(ErpStockCheckItemDO::getProductId, reqVO.getProductId())
.eqIfPresent(ErpStockCheckItemDO::getWarehouseId, reqVO.getWarehouseId())
.eqIfPresent(ErpStockCheckItemDO::getAreaId, reqVO.getAreaId())
.orderByDesc(ErpStockCheckItemDO::getId);
query.inSql(ErpStockCheckItemDO::getCheckId, buildCheckFilterSql(reqVO));
if (StringUtils.isNotBlank(reqVO.getIds())) {
List<Long> idList = Arrays.stream(reqVO.getIds().split(","))
.map(String::trim)
.map(Long::valueOf)
.collect(Collectors.toList());
query.in(ErpStockCheckItemDO::getId, idList);
}
return selectPage(reqVO, query);
}
default String buildCheckFilterSql(ErpStockCheckRecordPageReqVO reqVO) {
StringBuilder checkFilterSql = new StringBuilder("select id from erp_stock_check where deleted = 0");
checkFilterSql.append(" and check_status = ").append(STOCK_CHECK_STATUS_CHECKED);
checkFilterSql.append(" and status = ").append(ErpAuditStatus.APPROVE.getStatus());
if (StringUtils.isNotBlank(reqVO.getNo())) {
checkFilterSql.append(" and no like '%").append(reqVO.getNo().replace("'", "''")).append("%'");
}
if (reqVO.getCheckTime() != null && reqVO.getCheckTime().length == 2) {
if (reqVO.getCheckTime()[0] != null) {
checkFilterSql.append(" and check_time >= '").append(DATE_TIME_FORMATTER.format(reqVO.getCheckTime()[0])).append("'");
}
if (reqVO.getCheckTime()[1] != null) {
checkFilterSql.append(" and check_time <= '").append(DATE_TIME_FORMATTER.format(reqVO.getCheckTime()[1])).append("'");
}
}
if (reqVO.getSourceType() != null) {
checkFilterSql.append(" and source_type = ").append(reqVO.getSourceType());
}
if (reqVO.getCategoryType() != null) {
checkFilterSql.append(" and category_type = ").append(reqVO.getCategoryType());
}
if (StringUtils.isNotBlank(reqVO.getCreator())) {
checkFilterSql.append(" and creator = '").append(reqVO.getCreator().replace("'", "''")).append("'");
}
return checkFilterSql.toString();
}
default List<ErpStockCheckItemDO> selectListByCheckId(Long checkId) {
return selectList(ErpStockCheckItemDO::getCheckId, checkId);
}
@ -27,4 +82,4 @@ public interface ErpStockCheckItemMapper extends BaseMapperX<ErpStockCheckItemDO
return delete(ErpStockCheckItemDO::getCheckId, checkId);
}
}
}

@ -2,10 +2,8 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
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.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@ -22,17 +20,20 @@ public interface ErpStockInMapper extends BaseMapperX<ErpStockInDO> {
default PageResult<ErpStockInDO> selectPage(ErpStockInPageReqVO reqVO) {
MPJLambdaWrapperX<ErpStockInDO> query = new MPJLambdaWrapperX<>();
if(StringUtil.isNotBlank(reqVO.getNo())){
if(reqVO.getNo().contains("PRODUCTMATERIAL-")){
query.eq(ErpProductDO::getId, reqVO.getNo().replace("PRODUCTMATERIAL-",""));
}else{
Long productId = reqVO.getProductId();
if (StringUtil.isNotBlank(reqVO.getNo())) {
if (reqVO.getNo().contains("PRODUCTMATERIAL-")) {
productId = Long.valueOf(reqVO.getNo().replace("PRODUCTMATERIAL-", ""));
} else {
query.likeIfPresent(ErpStockInDO::getNo, reqVO.getNo());
}
}
if (productId != null || reqVO.getWarehouseId() != null) {
query.inSql(ErpStockInDO::getId, buildItemFilterSql(productId, reqVO.getWarehouseId()));
}
query
// .likeIfPresent(ErpStockInDO::getNo, reqVO.getNo())
.eqIfPresent(ErpStockInDO::getSupplierId, reqVO.getSupplierId())
.betweenIfPresent(ErpStockInDO::getInTime, reqVO.getInTime())
.inIfPresent(ErpStockInDO::getStatus, reqVO.getStatusList())
@ -52,6 +53,17 @@ public interface ErpStockInMapper extends BaseMapperX<ErpStockInDO> {
return selectJoinPage(reqVO, ErpStockInDO.class, query);
}
default String buildItemFilterSql(Long productId, Long warehouseId) {
StringBuilder itemFilterSql = new StringBuilder("select distinct in_id from erp_stock_in_item where deleted = 0");
if (productId != null) {
itemFilterSql.append(" and product_id = ").append(productId);
}
if (warehouseId != null) {
itemFilterSql.append(" and warehouse_id = ").append(warehouseId);
}
return itemFilterSql.toString();
}
default int updateByIdAndStatus(Long id, Integer status, ErpStockInDO updateObj) {
return update(updateObj, new LambdaUpdateWrapper<ErpStockInDO>()
.eq(ErpStockInDO::getId, id)

@ -5,6 +5,7 @@ import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO;
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.dataobject.stock.ErpWarehouseDO;
@ -31,8 +32,33 @@ public interface ErpStockMapper extends BaseMapperX<ErpStockDO> {
default PageResult<ErpStockDO> selectPage(ErpStockPageReqVO reqVO) {
LambdaQueryWrapperX<ErpStockDO> erpStockDOLambdaQueryWrapperX = new LambdaQueryWrapperX<ErpStockDO>()
.eqIfPresent(ErpStockDO::getProductId, reqVO.getProductId())
LambdaQueryWrapperX<ErpStockDO> erpStockDOLambdaQueryWrapperX = new LambdaQueryWrapperX<ErpStockDO>();
// if(StringUtils.isNotBlank(reqVO.getCode())&&StringUtils.isNotBlank(reqVO.getName())&&reqVO.getCode().equals(reqVO.getName())){
// if(reqVO.getCode().contains("PRODUCTMATERIAL-")){
// queryWrapper.eq(MoldBrandDO::getId, reqVO.getCode().replace("PRODUCTMATERIAL-",""));
// }else{
// queryWrapper.and(w -> w
// .like(MoldBrandDO::getCode, reqVO.getCode())
// .or()
// .like(MoldBrandDO::getName, reqVO.getName())
// );
// }
// }else{
// queryWrapper.likeIfPresent(MoldBrandDO::getCode, reqVO.getCode())
// .likeIfPresent(MoldBrandDO::getName, reqVO.getName());
// }
erpStockDOLambdaQueryWrapperX.eqIfPresent(ErpStockDO::getProductId, reqVO.getProductId())
.eqIfPresent(ErpStockDO::getWarehouseId, reqVO.getWarehouseId())
.eqIfPresent(ErpStockDO::getAreaId, reqVO.getAreaId())
.eqIfPresent(ErpStockDO::getCategoryId, reqVO.getCategoryId())

@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.erp.dal.mysql.stock;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveApproveRecordDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface ErpStockMoveApproveRecordMapper extends BaseMapperX<ErpStockMoveApproveRecordDO> {
default List<ErpStockMoveApproveRecordDO> selectListByStockMoveId(Long stockMoveId) {
return selectList(new LambdaQueryWrapperX<ErpStockMoveApproveRecordDO>()
.eq(ErpStockMoveApproveRecordDO::getStockMoveId, stockMoveId)
.orderByAsc(ErpStockMoveApproveRecordDO::getId));
}
default int deleteByStockMoveId(Long stockMoveId) {
return delete(ErpStockMoveApproveRecordDO::getStockMoveId, stockMoveId);
}
}

@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
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.move.ErpStockMovePageReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO;
@ -31,11 +33,21 @@ public interface ErpStockMoveMapper extends BaseMapperX<ErpStockMoveDO> {
.likeIfPresent(ErpStockMoveDO::getRemark, reqVO.getRemark())
.eqIfPresent(ErpStockMoveDO::getCreator, reqVO.getCreator())
.orderByDesc(ErpStockMoveDO::getId);
if (reqVO.getFromWarehouseId() != null || reqVO.getProductId() != null) {
if (reqVO.getFromWarehouseId() != null || reqVO.getFromAreaId() != null
|| reqVO.getToWarehouseId() != null || reqVO.getToAreaId() != null
|| reqVO.getProductId() != null || reqVO.getCategoryType() != null) {
query.leftJoin(ErpStockMoveItemDO.class, ErpStockMoveItemDO::getMoveId, ErpStockMoveDO::getId)
.eq(reqVO.getFromWarehouseId() != null, ErpStockMoveItemDO::getFromWarehouseId, reqVO.getFromWarehouseId())
.eq(reqVO.getProductId() != null, ErpStockMoveItemDO::getProductId, reqVO.getProductId())
.groupBy(ErpStockMoveDO::getId); // 避免 1 对多查询,产生相同的 1
.eq(reqVO.getFromAreaId() != null, ErpStockMoveItemDO::getFromAreaId, reqVO.getFromAreaId())
.eq(reqVO.getToWarehouseId() != null, ErpStockMoveItemDO::getToWarehouseId, reqVO.getToWarehouseId())
.eq(reqVO.getToAreaId() != null, ErpStockMoveItemDO::getToAreaId, reqVO.getToAreaId())
.eq(reqVO.getProductId() != null, ErpStockMoveItemDO::getProductId, reqVO.getProductId());
if (reqVO.getCategoryType() != null) {
query.leftJoin(ErpProductDO.class, ErpProductDO::getId, ErpStockMoveItemDO::getProductId)
.leftJoin(ErpProductCategoryDO.class, ErpProductCategoryDO::getId, ErpProductDO::getCategoryId)
.eq(ErpProductCategoryDO::getType, reqVO.getCategoryType());
}
query.groupBy(ErpStockMoveDO::getId); // 避免 1 对多查询,产生相同的 1
}
@ -62,4 +74,4 @@ public interface ErpStockMoveMapper extends BaseMapperX<ErpStockMoveDO> {
return selectOne(ErpStockMoveDO::getNo, no);
}
}
}

@ -9,6 +9,7 @@ import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.poi.util.StringUtil;
import java.util.Arrays;
import java.util.List;
@ -18,8 +19,22 @@ import java.util.stream.Collectors;
public interface ErpStockOutMapper extends BaseMapperX<ErpStockOutDO> {
default PageResult<ErpStockOutDO> selectPage(ErpStockOutPageReqVO reqVO) {
MPJLambdaWrapperX<ErpStockOutDO> query = new MPJLambdaWrapperX<ErpStockOutDO>()
.likeIfPresent(ErpStockOutDO::getNo, reqVO.getNo())
MPJLambdaWrapperX<ErpStockOutDO> query = new MPJLambdaWrapperX<>();
Long productId = reqVO.getProductId();
if (StringUtil.isNotBlank(reqVO.getNo())) {
if (reqVO.getNo().contains("PRODUCTMATERIAL-")) {
productId = Long.valueOf(reqVO.getNo().replace("PRODUCTMATERIAL-", ""));
} else {
query.likeIfPresent(ErpStockOutDO::getNo, reqVO.getNo());
}
}
if (productId != null || reqVO.getWarehouseId() != null) {
query.inSql(ErpStockOutDO::getId, buildItemFilterSql(productId, reqVO.getWarehouseId()));
}
query
.eqIfPresent(ErpStockOutDO::getCustomerId, reqVO.getCustomerId())
.eqIfPresent(ErpStockOutDO::getStockUserId, reqVO.getStockUserId())
.eqIfPresent(ErpStockOutDO::getOutType, reqVO.getOutType())
@ -40,6 +55,17 @@ public interface ErpStockOutMapper extends BaseMapperX<ErpStockOutDO> {
return selectJoinPage(reqVO, ErpStockOutDO.class, query);
}
default String buildItemFilterSql(Long productId, Long warehouseId) {
StringBuilder itemFilterSql = new StringBuilder("select distinct out_id from erp_stock_out_item where deleted = 0");
if (productId != null) {
itemFilterSql.append(" and product_id = ").append(productId);
}
if (warehouseId != null) {
itemFilterSql.append(" and warehouse_id = ").append(warehouseId);
}
return itemFilterSql.toString();
}
default int updateByIdAndStatus(Long id, Integer status, ErpStockOutDO updateObj) {
return update(updateObj, new LambdaUpdateWrapper<ErpStockOutDO>()
.eq(ErpStockOutDO::getId, id)

@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.*;
/**
@ -50,4 +51,6 @@ public interface WarehouseAreaMapper extends BaseMapperX<WarehouseAreaDO> {
return selectCount(WarehouseAreaDO::getWarehouseId, warehouseId);
}
String selectPrintTemplate(@Param("templateType") Integer templateType);
}

@ -10,11 +10,11 @@ import java.util.Arrays;
@AllArgsConstructor
public enum ProductTypeEnum implements IntArrayValuable {
ITEM(1, "原料"),
PRODUCT(2, "产品"),
TOOL(3, "工具"),
ITEM(1, "产品"),
PRODUCT(2, "物料"),
BEIJIAN(3, "备件"),
HAOCAI(4, "耗材"),
BEIJIAN(5, "备件");
TOOL(5, "工具");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductTypeEnum::getTypeId).toArray();
/**

@ -215,6 +215,7 @@ public class MoldBrandServiceImpl implements MoldBrandService {
@Override
public PageResult<MoldBrandRespVO> getMoldBrandPage(MoldBrandPageReqVO pageReqVO) {
applyCurrentDeviceFilter(pageReqVO);
if (StrUtil.isNotBlank(pageReqVO.getDeviceName())) {
List<MoldBrandDO> filteredList = selectByDeviceName(pageReqVO);
List<MoldBrandDO> pageList = paginateList(filteredList, pageReqVO);
@ -241,6 +242,7 @@ public class MoldBrandServiceImpl implements MoldBrandService {
@Override
public MoldBrandStatusStatisticsRespVO getMoldBrandStatusStatistics(MoldBrandPageReqVO pageReqVO) {
MoldBrandPageReqVO statisticsReqVO = BeanUtils.toBean(pageReqVO, MoldBrandPageReqVO.class);
applyCurrentDeviceFilter(statisticsReqVO);
statisticsReqVO.setStatus(null);
List<MoldBrandDO> list = StrUtil.isNotBlank(statisticsReqVO.getDeviceName())
? selectByDeviceName(statisticsReqVO)
@ -363,6 +365,12 @@ public class MoldBrandServiceImpl implements MoldBrandService {
return latestOperateMap;
}
private void applyCurrentDeviceFilter(MoldBrandPageReqVO reqVO) {
if (reqVO != null && StrUtil.isBlank(reqVO.getDeviceName()) && StrUtil.isNotBlank(reqVO.getCurrentDevice())) {
reqVO.setDeviceName(reqVO.getCurrentDevice());
}
}
private void fillCurrentDeviceNameByLatestOperate(MoldBrandRespVO item, MoldOperateSimpleDO latestOperate) {
if (latestOperate == null) {
item.setDeviceName(null);

@ -73,7 +73,7 @@ public interface ErpProductService {
* @param status
* @return VO
*/
List<ErpProductRespVO> getProductVOListByStatus(Integer status,Integer categoryId);
List<ErpProductRespVO> getProductVOListByStatus(Integer status, Integer categoryId, Integer categoryType);
List<ErpProductRespVO> getProductVOListByCategory(Integer categoryId);
List<ErpProductRespVO> getProductVOListByCategory(Integer categoryId, Integer categoryType);
List<ErpProductRespVO> buildProductVOList(List<ErpProductDO> list);

@ -33,6 +33,7 @@ import cn.iocoder.yudao.module.erp.dal.mysql.productpackagingschemerel.ProductPa
import cn.iocoder.yudao.module.erp.dal.mysql.productmoldrel.ProductMoldRelMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.productsupplierrel.ProductSupplierRelMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper;
import cn.iocoder.yudao.module.erp.framework.bean.ProductTypeEnum;
import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService;
import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService;
import cn.iocoder.yudao.module.erp.service.stock.ErpStockService;
@ -361,15 +362,24 @@ public class ErpProductServiceImpl implements ErpProductService {
if (productUnitService.getProductUnit(purchaseUnitId) == null) {
throw exception(PRODUCT_UNIT_NOT_EXISTS);
}
if (unitId.equals(purchaseUnitId)) {
throw exception(PRODUCT_UNIT_CONVERT_SELF_NOT_ALLOWED);
}
// if (unitId.equals(purchaseUnitId)) {
// throw exception(PRODUCT_UNIT_CONVERT_SELF_NOT_ALLOWED);
// }
if (purchaseUnitConvertQuantity == null || purchaseUnitConvertQuantity.compareTo(BigDecimal.ZERO) <= 0) {
throw exception(PRODUCT_PURCHASE_UNIT_CONVERT_QUANTITY_INVALID);
}
}
private void fillProductUnitName(ErpProductDO product) {
if (product.getUnitId() == null) {
product.setUnitName(null);
} else {
ErpProductUnitDO unit = productUnitService.getProductUnit(product.getUnitId());
if (unit == null) {
throw exception(PRODUCT_UNIT_NOT_EXISTS);
}
product.setUnitName(unit.getName());
}
if (product.getPurchaseUnitId() == null) {
product.setPurchaseUnitName(null);
return;
@ -494,12 +504,7 @@ public class ErpProductServiceImpl implements ErpProductService {
if (id != null) {
ErpProductRespVO product = getProduct(id);
if (product != null) {
Integer templateType = 0;
if (product.getCategoryType() == 1 ) {
templateType = 1; // 打印模板产品值
} else if(product.getCategoryId() == 5){
templateType = 5; // 打印模板备件值
}
Integer templateType = isSpareProductCategory(product) ? 5 : 1;
String template = productMapper.selectPrintTemplate(templateType);
product.setTemplateJson(template);
}
@ -517,17 +522,37 @@ public class ErpProductServiceImpl implements ErpProductService {
throw exception(PRODUCT_NOT_EXISTS);
}
private boolean isSpareProductCategory(ErpProductRespVO product) {
Long categoryId = product.getSubCategoryId() != null ? product.getSubCategoryId() : product.getCategoryId();
if (categoryId == null) {
return Objects.equals(product.getCategoryType(), ProductTypeEnum.BEIJIAN.getTypeId());
}
ErpProductCategoryDO category = productCategoryMapper.selectById(categoryId);
return category != null && Objects.equals(category.getType(), ProductTypeEnum.BEIJIAN.getTypeId());
}
@Override
public List<ErpProductRespVO> getProductVOListByStatus(Integer status,Integer categoryId) {
public List<ErpProductRespVO> getProductVOListByStatus(Integer status, Integer categoryId, Integer categoryType) {
List<Integer> categoryList = new ArrayList<>();
if (categoryType != null) {
List<Long> categoryIds = productMapper.selectCategoryIdListByType(categoryType);
if (CollUtil.isEmpty(categoryIds)) {
return new ArrayList<>();
}
if (categoryId != null && !categoryIds.contains(categoryId.longValue())) {
return new ArrayList<>();
}
categoryIds.forEach(item -> categoryList.add(item.intValue()));
}
if(categoryId != null ){
categoryList.clear();
categoryList.add(categoryId);
}
List<ErpProductDO> list = productMapper.selectByCategorys(categoryList);
List<ErpProductDO> list = productMapper.selectByCategorys(categoryList, status);
return buildProductVOList(list);
}
@Override
@ -651,10 +676,14 @@ public class ErpProductServiceImpl implements ErpProductService {
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()));
if (StrUtil.isBlank(product.getUnitName())) {
MapUtils.findAndThen(unitMap, product.getUnitId(),
unit -> product.setUnitName(unit.getName()));
}
if (StrUtil.isBlank(product.getPurchaseUnitName())) {
MapUtils.findAndThen(purchaseUnitMap, product.getPurchaseUnitId(),
unit -> product.setPurchaseUnitName(unit.getName()));
}
product.setPackagingSchemes(packagingSchemeMap.getOrDefault(product.getId(), Collections.emptyList()));
product.setSuppliers(supplierMap.getOrDefault(product.getId(), Collections.emptyList()));
product.setDefaultSupplierId(defaultSupplierMap.get(product.getId()));
@ -825,6 +854,7 @@ public class ErpProductServiceImpl implements ErpProductService {
ErpProductUnitDO unitDO = productUnitService.getProductUnitByName(importProduct.getUnitName());
if (unitDO != null) {
productDO.setUnitId(unitDO.getId());
productDO.setUnitName(unitDO.getName());
}
}

@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheck
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckGenerateByLocationReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckGenerateByProductReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRecordPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSubmitReqVO;
@ -15,6 +16,9 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO;
import javax.validation.Valid;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
/**
* ERP Service
@ -65,6 +69,12 @@ public interface ErpStockCheckService {
*/
ErpStockCheckDO getStockCheck(Long id);
default Map<Long, ErpStockCheckDO> getStockCheckMap(Collection<Long> ids) {
return convertMap(getStockCheckList(ids), ErpStockCheckDO::getId);
}
List<ErpStockCheckDO> getStockCheckList(Collection<Long> ids);
/**
*
*
@ -73,6 +83,8 @@ public interface ErpStockCheckService {
*/
PageResult<ErpStockCheckDO> getStockCheckPage(ErpStockCheckPageReqVO pageReqVO);
PageResult<ErpStockCheckItemDO> getStockCheckRecordPage(ErpStockCheckRecordPageReqVO pageReqVO);
// ==================== 盘点项 ====================
/**

@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheck
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckGenerateByLocationReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckGenerateByProductReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRecordPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSubmitReqVO;
@ -30,9 +31,7 @@ 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.stock.ErpStockCheckApproveActionEnum;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockCheckSourceTypeEnum;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO;
import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
@ -83,7 +82,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
@Resource
private WarehouseAreaService warehouseAreaService;
@Resource
private ErpStockRecordService stockRecordService;
private ErpStockService stockService;
@Resource
private AdminUserApi adminUserApi;
@Resource
@ -119,7 +118,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
ErpStockCheckDO stockCheck = BeanUtils.toBean(createReqVO, ErpStockCheckDO.class, in -> in
.setNo(finalCode)
.setNeedAudit(needAudit())
.setStatus(ErpAuditStatus.DRAFT.getStatus())
.setStatus(ErpAuditStatus.PROCESS.getStatus())
.setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add, BigDecimal.ZERO))
.setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)));
stockCheckMapper.insert(stockCheck);
@ -135,9 +134,9 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockCheck.getStatus())) {
throw exception(STOCK_CHECK_UPDATE_FAIL_APPROVE, stockCheck.getNo());
}
if (ErpAuditStatus.PROCESS.getStatus().equals(stockCheck.getStatus())) {
throw exception(STOCK_CHECK_UPDATE_FAIL_PROCESS, stockCheck.getNo());
}
// if (ErpAuditStatus.PROCESS.getStatus().equals(stockCheck.getStatus())) {
// throw exception(STOCK_CHECK_UPDATE_FAIL_PROCESS, stockCheck.getNo());
// }
validateSourceType(updateReqVO.getSourceType());
List<ErpStockCheckItemDO> stockCheckItems = validateStockCheckItems(updateReqVO.getItems());
@ -182,9 +181,9 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
public void submitStockCheckAudit(ErpStockCheckSubmitReqVO submitReqVO) {
ErpStockCheckDO stockCheck = validateStockCheckExists(submitReqVO.getId());
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
if (!Objects.equals(NumberUtils.parseLong(stockCheck.getCreator()), loginUserId)) {
throw exception(STOCK_CHECK_SUBMIT_FAIL_USER);
}
// if (!Objects.equals(NumberUtils.parseLong(stockCheck.getCreator()), loginUserId)) {
// throw exception(STOCK_CHECK_SUBMIT_FAIL_USER);
// }
if (!ErpAuditStatus.DRAFT.getStatus().equals(stockCheck.getStatus())
&& !ErpAuditStatus.UN_APPROVE.getStatus().equals(stockCheck.getStatus())) {
throw exception(STOCK_CHECK_SUBMIT_FAIL_STATUS);
@ -215,11 +214,12 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
// if (!ErpAuditStatus.PROCESS.getStatus().equals(stockCheck.getStatus())) {
// throw exception(STOCK_CHECK_AUDIT_FAIL_STATUS);
// }
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
Integer fromStatus = stockCheck.getStatus();
if (!needAudit()) {
int updateCount = stockCheckMapper.updateByIdAndStatus(stockCheck.getId(), fromStatus,
new ErpStockCheckDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus()));
new ErpStockCheckDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus()).setAuditUserId(loginUserId));
if (updateCount == 0) {
throw exception(STOCK_CHECK_AUDIT_FAIL_STATUS);
}
@ -231,18 +231,17 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
return;
}
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
boolean adminCanAudit = permissionApi.hasAnyRoles(loginUserId, RoleCodeEnum.SUPER_ADMIN.getCode());
if (!Objects.equals(stockCheck.getAuditUserId(), loginUserId) && !adminCanAudit) {
throw exception(STOCK_CHECK_AUDIT_FAIL_USER);
}
// if (!Objects.equals(stockCheck.getAuditUserId(), loginUserId) && !adminCanAudit) {
// throw exception(STOCK_CHECK_AUDIT_FAIL_USER);
// }
if (!ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus())
&& !ErpAuditStatus.UN_APPROVE.getStatus().equals(auditReqVO.getStatus())) {
throw exception(STOCK_CHECK_AUDIT_FAIL_RESULT);
}
int updateCount = stockCheckMapper.updateByIdAndStatus(stockCheck.getId(), fromStatus,
new ErpStockCheckDO().setNeedAudit(true).setStatus(auditReqVO.getStatus()));
new ErpStockCheckDO().setNeedAudit(true).setStatus(auditReqVO.getStatus()).setAuditUserId(loginUserId));
if (updateCount == 0) {
throw exception(STOCK_CHECK_AUDIT_FAIL_STATUS);
}
@ -269,9 +268,9 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockCheck.getStatus())) {
throw exception(STOCK_CHECK_DELETE_FAIL_APPROVE, stockCheck.getNo());
}
if (ErpAuditStatus.PROCESS.getStatus().equals(stockCheck.getStatus())) {
throw exception(STOCK_CHECK_DELETE_FAIL_PROCESS, stockCheck.getNo());
}
// if (ErpAuditStatus.PROCESS.getStatus().equals(stockCheck.getStatus())) {
// throw exception(STOCK_CHECK_DELETE_FAIL_PROCESS, stockCheck.getNo());
// }
});
stockChecks.forEach(stockCheck -> {
@ -286,11 +285,24 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
return stockCheckMapper.selectById(id);
}
@Override
public List<ErpStockCheckDO> getStockCheckList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return stockCheckMapper.selectBatchIds(ids);
}
@Override
public PageResult<ErpStockCheckDO> getStockCheckPage(ErpStockCheckPageReqVO pageReqVO) {
return stockCheckMapper.selectPage(pageReqVO);
}
@Override
public PageResult<ErpStockCheckItemDO> getStockCheckRecordPage(ErpStockCheckRecordPageReqVO pageReqVO) {
return stockCheckItemMapper.selectRecordPage(pageReqVO);
}
@Override
public List<ErpStockCheckItemDO> getStockCheckItemListByCheckId(Long checkId) {
return stockCheckItemMapper.selectListByCheckId(checkId);
@ -404,25 +416,13 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService {
return;
}
BigDecimal count = approve ? stockCheckItem.getCount() : stockCheckItem.getCount().negate();
Integer bizType;
if (approve) {
bizType = stockCheckItem.getCount().compareTo(BigDecimal.ZERO) > 0
? ErpStockRecordBizTypeEnum.CHECK_MORE_IN.getType()
: ErpStockRecordBizTypeEnum.CHECK_LESS_OUT.getType();
} else {
bizType = stockCheckItem.getCount().compareTo(BigDecimal.ZERO) > 0
? ErpStockRecordBizTypeEnum.CHECK_MORE_IN_CANCEL.getType()
: ErpStockRecordBizTypeEnum.CHECK_LESS_OUT_CANCEL.getType();
}
ErpProductDO productDO = productService.validProductList(Collections.singleton(stockCheckItem.getProductId()))
.stream().findFirst().orElse(null);
if (productDO == null) {
return;
}
stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO(
stockCheckItem.getProductId(), productDO.getCategoryId(), null,
stockCheckItem.getWarehouseId(), stockCheckItem.getAreaId(), stockCheckItem.getAreaName(),
count, bizType, stockCheckItem.getCheckId(), stockCheckItem.getId(), stockCheck.getNo(), stockCheck.getCheckTime()));
stockService.updateStockCountIncrement(productDO.getCategoryId(), stockCheckItem.getProductId(),
stockCheckItem.getWarehouseId(), stockCheckItem.getAreaId(), stockCheckItem.getAreaName(), count);
});
}

@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.StockInTypeEnum;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInApproveRecordDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO;
@ -41,8 +42,6 @@ import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService;
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO;
import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -103,8 +102,6 @@ public class ErpStockInServiceImpl implements ErpStockInService {
@Resource
private AdminUserApi adminUserApi;
@Resource
private PermissionApi permissionApi;
@Resource
private ConfigApi configApi;
@Override
@ -124,7 +121,7 @@ public class ErpStockInServiceImpl implements ErpStockInService {
}
boolean needAudit = needAudit();
Integer status = ErpAuditStatus.DRAFT.getStatus();
Integer status = ErpAuditStatus.PROCESS.getStatus();
ErpStockInDO stockIn = BeanUtils.toBean(createReqVO, ErpStockInDO.class, in -> in
.setNo(no)
.setNeedAudit(needAudit)
@ -158,9 +155,9 @@ public class ErpStockInServiceImpl implements ErpStockInService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockIn.getStatus())) {
throw exception(STOCK_IN_UPDATE_FAIL_APPROVE, stockIn.getNo());
}
if (ErpAuditStatus.PROCESS.getStatus().equals(stockIn.getStatus())) {
throw exception(STOCK_IN_UPDATE_FAIL_PROCESS, stockIn.getNo());
}
// if (ErpAuditStatus.PROCESS.getStatus().equals(stockIn.getStatus())) {
// throw exception(STOCK_IN_UPDATE_FAIL_PROCESS, stockIn.getNo());
// }
if (updateReqVO.getStockUserId() != null) {
adminUserApi.validateUser(updateReqVO.getStockUserId());
}
@ -210,9 +207,9 @@ public class ErpStockInServiceImpl implements ErpStockInService {
public void submitStockInAudit(ErpStockInSubmitReqVO submitReqVO) {
ErpStockInDO stockIn = validateStockInExists(submitReqVO.getId());
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
if (!Objects.equals(NumberUtils.parseLong(stockIn.getCreator()), loginUserId)) {
throw exception(STOCK_IN_SUBMIT_FAIL_USER);
}
// if (!Objects.equals(NumberUtils.parseLong(stockIn.getCreator()), loginUserId)) {
// throw exception(STOCK_IN_SUBMIT_FAIL_USER);
// }
if (!ErpAuditStatus.DRAFT.getStatus().equals(stockIn.getStatus())
&& !ErpAuditStatus.UN_APPROVE.getStatus().equals(stockIn.getStatus())) {
throw exception(STOCK_IN_SUBMIT_FAIL_STATUS);
@ -242,9 +239,11 @@ public class ErpStockInServiceImpl implements ErpStockInService {
// }
Integer fromStatus = stockIn.getStatus();
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
if (!needAudit()) {
int updateCount = stockInMapper.updateByIdAndStatus(stockIn.getId(), fromStatus,
new ErpStockInDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus()));
new ErpStockInDO().setNeedAudit(false).setAuditUserId(loginUserId)
.setStatus(ErpAuditStatus.APPROVE.getStatus()).setAuditUserId(loginUserId));
if (updateCount == 0) {
throw exception(STOCK_IN_AUDIT_FAIL_STATUS);
}
@ -255,18 +254,13 @@ public class ErpStockInServiceImpl implements ErpStockInService {
auditReqVO.getRemark() != null ? auditReqVO.getRemark() : "无需审核,审核时自动入库");
return;
}
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
boolean adminCanAudit = permissionApi.hasAnyRoles(loginUserId, RoleCodeEnum.SUPER_ADMIN.getCode());
if (!Objects.equals(stockIn.getAuditUserId(), loginUserId) && !adminCanAudit) {
throw exception(STOCK_IN_AUDIT_FAIL_USER);
}
if (!ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus())
&& !ErpAuditStatus.UN_APPROVE.getStatus().equals(auditReqVO.getStatus())) {
throw exception(STOCK_IN_AUDIT_FAIL_RESULT);
}
int updateCount = stockInMapper.updateByIdAndStatus(stockIn.getId(), fromStatus,
new ErpStockInDO().setNeedAudit(true).setStatus(auditReqVO.getStatus()));
new ErpStockInDO().setNeedAudit(true).setAuditUserId(loginUserId).setStatus(auditReqVO.getStatus()));
if (updateCount == 0) {
throw exception(STOCK_IN_AUDIT_FAIL_STATUS);
}
@ -292,9 +286,9 @@ public class ErpStockInServiceImpl implements ErpStockInService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockIn.getStatus())) {
throw exception(STOCK_IN_DELETE_FAIL_APPROVE, stockIn.getNo());
}
if (ErpAuditStatus.PROCESS.getStatus().equals(stockIn.getStatus())) {
throw exception(STOCK_IN_DELETE_FAIL_PROCESS, stockIn.getNo());
}
// if (ErpAuditStatus.PROCESS.getStatus().equals(stockIn.getStatus())) {
// throw exception(STOCK_IN_DELETE_FAIL_PROCESS, stockIn.getNo());
// }
});
stockIns.forEach(stockIn -> {
stockInMapper.deleteById(stockIn.getId());
@ -555,14 +549,38 @@ public class ErpStockInServiceImpl implements ErpStockInService {
ErpWarehouseDO::getId);
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(
convertSet(list, ErpStockInSaveReqVO.Item::getAreaId));
Map<Long, ErpSupplierDO> supplierMap = buildStockInItemSupplierMap(list, inType);
return convertList(list, item -> BeanUtils.toBean(item, ErpStockInItemDO.class, target -> target
.setWarehouseName(warehouseMap.containsKey(target.getWarehouseId()) ? warehouseMap.get(target.getWarehouseId()).getName() : null)
.setAreaName(areaMap.containsKey(target.getAreaId()) ? areaMap.get(target.getAreaId()).getAreaName() : null)
.setProductName(productMap.get(target.getProductId()).getName())
.setSupplierName(resolveStockInItemSupplierName(item, supplierMap, inType))
.setProductUnitId(productMap.get(target.getProductId()).getUnitId())
.setTotalPrice(MoneyUtils.priceMultiply(target.getProductPrice(), target.getCount()))));
}
private Map<Long, ErpSupplierDO> buildStockInItemSupplierMap(List<ErpStockInSaveReqVO.Item> list, String inType) {
if (!isSupplierItemStockIn(inType)) {
return Collections.emptyMap();
}
return supplierService.getSupplierMap(convertSet(list, ErpStockInSaveReqVO.Item::getSupplierId));
}
private String resolveStockInItemSupplierName(ErpStockInSaveReqVO.Item item, Map<Long, ErpSupplierDO> supplierMap,
String inType) {
if (!isSupplierItemStockIn(inType) || item.getSupplierId() == null) {
return null;
}
ErpSupplierDO supplier = supplierMap.get(item.getSupplierId());
return supplier != null ? supplier.getName() : item.getSupplierName();
}
private boolean isSupplierItemStockIn(String inType) {
return Objects.equals(inType, StockInTypeEnum..getValue())
|| Objects.equals(inType, StockInTypeEnum..getValue())
|| Objects.equals(inType, "物料入库");
}
private void validatePallets(List<ErpStockInSaveReqVO.Item> list) {
List<Long> palletIds = convertListByFlatMap(list, item -> item.getPallets() == null ? java.util.stream.Stream.empty()
: item.getPallets().stream().map(ErpStockInSaveReqVO.Item.PalletItem::getPalletId));

@ -3,6 +3,9 @@ package cn.iocoder.yudao.module.erp.service.stock;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveAuditReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSubmitReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveApproveRecordDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO;
@ -40,6 +43,12 @@ public interface ErpStockMoveService {
*/
void updateStockMoveStatus(Long id, Integer status);
void submitStockMoveAudit(ErpStockMoveSubmitReqVO submitReqVO);
void auditStockMove(ErpStockMoveAuditReqVO auditReqVO);
List<ErpStockMoveApproveRecordDO> getStockMoveApproveRecordList(Long id);
/**
*
*
@ -81,4 +90,4 @@ public interface ErpStockMoveService {
*/
List<ErpStockMoveItemDO> getStockMoveItemListByMoveIds(Collection<Long> moveIds);
}
}

@ -3,19 +3,33 @@ package cn.iocoder.yudao.module.erp.service.stock;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveAuditReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSubmitReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveApproveRecordDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMoveApproveRecordMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMoveItemMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMoveMapper;
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.stock.ErpStockMoveApproveActionEnum;
import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum;
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO;
import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@ -26,13 +40,14 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
// TODO 芋艿:记录操作日志
// TODO 记录操作日志
/**
* ERP Service
@ -43,10 +58,16 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
@Validated
public class ErpStockMoveServiceImpl implements ErpStockMoveService {
private static final String AUDIT_CONFIG_CATEGORY = "biz";
private static final String AUDIT_CONFIG_KEY = "transferAduit";
private static final String AUDIT_CONFIG_DISABLE_VALUE = "0";
@Resource
private ErpStockMoveMapper stockMoveMapper;
@Resource
private ErpStockMoveItemMapper stockMoveItemMapper;
@Resource
private ErpStockMoveApproveRecordMapper stockMoveApproveRecordMapper;
@Resource
private ErpNoRedisDAO noRedisDAO;
@ -57,11 +78,19 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
private ErpWarehouseService warehouseService;
@Resource
private ErpStockRecordService stockRecordService;
@Resource
private WarehouseAreaService warehouseAreaService;
@Resource
private AdminUserApi adminUserApi;
@Resource
private ConfigApi configApi;
@Resource
private PermissionApi permissionApi;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createStockMove(ErpStockMoveSaveReqVO createReqVO) {
// 1.1 校验出库项的有效性
// 1.1 校验调拨项的有效性
List<ErpStockMoveItemDO> stockMoveItems = validateStockMoveItems(createReqVO.getItems());
// 1.2 生成调拨单号,并校验唯一性
String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_MOVE_NO_PREFIX);
@ -69,13 +98,18 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
throw exception(STOCK_MOVE_NO_EXISTS);
}
// 2.1 插入出库单
if (createReqVO.getAuditUserId() != null) {
adminUserApi.validateUser(createReqVO.getAuditUserId());
}
boolean needAudit = needAudit();
ErpStockMoveDO stockMove = BeanUtils.toBean(createReqVO, ErpStockMoveDO.class, in -> in
.setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())
.setNo(no)
.setNeedAudit(needAudit)
.setStatus(ErpAuditStatus.PROCESS.getStatus())
.setTotalCount(getSumValue(stockMoveItems, ErpStockMoveItemDO::getCount, BigDecimal::add))
.setTotalPrice(getSumValue(stockMoveItems, ErpStockMoveItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)));
stockMoveMapper.insert(stockMove);
// 2.2 插入出库单项
// 2.2 插入调拨单项
stockMoveItems.forEach(o -> o.setMoveId(stockMove.getId()));
stockMoveItemMapper.insertBatch(stockMoveItems);
return stockMove.getId();
@ -89,38 +123,119 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) {
throw exception(STOCK_MOVE_UPDATE_FAIL_APPROVE, stockMove.getNo());
}
// 1.2 校验出库项的有效性
// if (ErpAuditStatus.PROCESS.getStatus().equals(stockMove.getStatus())) {
// throw exception(STOCK_MOVE_UPDATE_FAIL_PROCESS, stockMove.getNo());
// }
List<ErpStockMoveItemDO> stockMoveItems = validateStockMoveItems(updateReqVO.getItems());
if (updateReqVO.getAuditUserId() != null) {
adminUserApi.validateUser(updateReqVO.getAuditUserId());
}
boolean needAudit = needAudit();
// 2.1 更新出库单
ErpStockMoveDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockMoveDO.class, in -> in
.setNeedAudit(needAudit)
.setTotalCount(getSumValue(stockMoveItems, ErpStockMoveItemDO::getCount, BigDecimal::add))
.setTotalPrice(getSumValue(stockMoveItems, ErpStockMoveItemDO::getTotalPrice, BigDecimal::add)));
stockMoveMapper.updateById(updateObj);
// 2.2 更新出库单项
// 2.2 更新调拨单项
updateStockMoveItemList(updateReqVO.getId(), stockMoveItems);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateStockMoveStatus(Long id, Integer status) {
boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
// 1.1 校验存在
ErpStockMoveDO stockMove = validateStockMoveExists(id);
// 1.2 校验状态
if (stockMove.getStatus().equals(status)) {
throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL);
boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
if (approve) {
if (!ErpAuditStatus.PROCESS.getStatus().equals(stockMove.getStatus())) {
throw exception(STOCK_MOVE_APPROVE_FAIL);
}
} else {
if (!ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) {
throw exception(STOCK_MOVE_PROCESS_FAIL);
}
}
// 2. 更新状态
int updateCount = stockMoveMapper.updateByIdAndStatus(id, stockMove.getStatus(),
new ErpStockMoveDO().setStatus(status));
if (updateCount == 0) {
throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL);
}
// 3. 变更库存
List<ErpStockMoveItemDO> stockMoveItems = stockMoveItemMapper.selectListByMoveId(id);
operateStockMoveEffect(stockMove, stockMoveItems, approve);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void submitStockMoveAudit(ErpStockMoveSubmitReqVO submitReqVO) {
ErpStockMoveDO stockMove = validateStockMoveExists(submitReqVO.getId());
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
// if (!Objects.equals(NumberUtils.parseLong(stockMove.getCreator()), loginUserId)) {
// throw exception(STOCK_MOVE_SUBMIT_FAIL_USER);
// }
if (!ErpAuditStatus.DRAFT.getStatus().equals(stockMove.getStatus())
&& !ErpAuditStatus.UN_APPROVE.getStatus().equals(stockMove.getStatus())) {
throw exception(STOCK_MOVE_SUBMIT_FAIL_STATUS);
}
Integer fromStatus = stockMove.getStatus();
Long auditUserId = submitReqVO.getAuditUserId() != null ? submitReqVO.getAuditUserId() : stockMove.getAuditUserId();
if (auditUserId != null) {
adminUserApi.validateUser(auditUserId);
}
int updateCount = stockMoveMapper.updateByIdAndStatus(stockMove.getId(), fromStatus,
new ErpStockMoveDO().setAuditUserId(auditUserId).setStatus(ErpAuditStatus.PROCESS.getStatus()));
if (updateCount == 0) {
throw exception(STOCK_MOVE_SUBMIT_FAIL_STATUS);
}
createApproveRecord(stockMove.getId(), ErpStockMoveApproveActionEnum.SUBMIT, fromStatus,
ErpAuditStatus.PROCESS.getStatus(), auditUserId, submitReqVO.getRemark());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void auditStockMove(ErpStockMoveAuditReqVO auditReqVO) {
ErpStockMoveDO stockMove = validateStockMoveExists(auditReqVO.getId());
Integer fromStatus = stockMove.getStatus();
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
if (!ErpAuditStatus.PROCESS.getStatus().equals(fromStatus) && needAudit()) {
throw exception(STOCK_MOVE_AUDIT_FAIL_STATUS);
}
if (!needAudit()) {
int updateCount = stockMoveMapper.updateByIdAndStatus(stockMove.getId(), fromStatus,
new ErpStockMoveDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus()).setAuditUserId(loginUserId));
if (updateCount == 0) {
throw exception(STOCK_MOVE_AUDIT_FAIL_STATUS);
}
List<ErpStockMoveItemDO> stockMoveItems = stockMoveItemMapper.selectListByMoveId(stockMove.getId());
operateStockMoveEffect(stockMove, stockMoveItems, true);
createApproveRecord(stockMove.getId(), ErpStockMoveApproveActionEnum.AUTO_APPROVE, fromStatus,
ErpAuditStatus.APPROVE.getStatus(), NumberUtils.parseLong(stockMove.getCreator()),
auditReqVO.getRemark() != null ? auditReqVO.getRemark() : "无需审核,审核时自动调拨");
return;
}
boolean adminCanAudit = permissionApi.hasAnyRoles(loginUserId, RoleCodeEnum.SUPER_ADMIN.getCode());
// if (!Objects.equals(stockMove.getAuditUserId(), loginUserId) && !adminCanAudit) {
// throw exception(STOCK_MOVE_AUDIT_FAIL_USER);
// }
if (!ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus())
&& !ErpAuditStatus.UN_APPROVE.getStatus().equals(auditReqVO.getStatus())) {
throw exception(STOCK_MOVE_AUDIT_FAIL_RESULT);
}
int updateCount = stockMoveMapper.updateByIdAndStatus(stockMove.getId(), fromStatus,
new ErpStockMoveDO().setNeedAudit(true).setStatus(auditReqVO.getStatus()).setAuditUserId(loginUserId));
if (updateCount == 0) {
throw exception(STOCK_MOVE_AUDIT_FAIL_STATUS);
}
List<ErpStockMoveItemDO> stockMoveItems = stockMoveItemMapper.selectListByMoveId(stockMove.getId());
if (ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus())) {
operateStockMoveEffect(stockMove, stockMoveItems, true);
}
createApproveRecord(stockMove.getId(), ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus())
? ErpStockMoveApproveActionEnum.APPROVE : ErpStockMoveApproveActionEnum.REJECT,
fromStatus, auditReqVO.getStatus(), NumberUtils.parseLong(stockMove.getCreator()), auditReqVO.getRemark());
}
private void operateStockMoveEffect(ErpStockMoveDO stockMove, List<ErpStockMoveItemDO> stockMoveItems, boolean approve) {
Integer fromBizType = approve ? ErpStockRecordBizTypeEnum.MOVE_OUT.getType()
: ErpStockRecordBizTypeEnum.MOVE_OUT_CANCEL.getType();
Integer toBizType = approve ? ErpStockRecordBizTypeEnum.MOVE_IN.getType()
@ -128,13 +243,15 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
stockMoveItems.forEach(stockMoveItem -> {
BigDecimal fromCount = approve ? stockMoveItem.getCount().negate() : stockMoveItem.getCount();
BigDecimal toCount = approve ? stockMoveItem.getCount() : stockMoveItem.getCount().negate();
ErpProductDO productDO = productService.getProduct(stockMoveItem.getProductId());
ErpProductRespVO productDO = productService.getProduct(stockMoveItem.getProductId());
stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO(
stockMoveItem.getProductId(),productDO.getCategoryId(), stockMoveItem.getFromWarehouseId(), fromCount,
stockMoveItem.getProductId(), productDO.getCategoryId(), productDO.getCategoryType(),
stockMoveItem.getFromWarehouseId(), stockMoveItem.getFromAreaId(), stockMoveItem.getFromAreaName(), fromCount,
fromBizType, stockMoveItem.getMoveId(), stockMoveItem.getId(), stockMove.getNo(),stockMove.getMoveTime()));
stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO(
stockMoveItem.getProductId(),productDO.getCategoryId(), stockMoveItem.getToWarehouseId(), toCount,
stockMoveItem.getProductId(), productDO.getCategoryId(), productDO.getCategoryType(),
stockMoveItem.getToWarehouseId(), stockMoveItem.getToAreaId(), stockMoveItem.getToAreaName(), toCount,
toBizType, stockMoveItem.getMoveId(), stockMoveItem.getId(), stockMove.getNo(),stockMove.getMoveTime()));
});
}
@ -147,12 +264,24 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
// 1.2 校验仓库存在
warehouseService.validWarehouseList(convertSetByFlatMap(list,
item -> Stream.of(item.getFromWarehouseId(), item.getToWarehouseId())));
Map<Long, WarehouseAreaDO> areaMap = warehouseAreaService.getWarehouseAreaMap(convertSetByFlatMap(list,
item -> Stream.of(item.getFromAreaId(), item.getToAreaId())));
// 2. 转化为 ErpStockMoveItemDO 列表
return convertList(list, o -> BeanUtils.toBean(o, ErpStockMoveItemDO.class, item -> item
.setProductUnitId(productMap.get(item.getProductId()).getUnitId())
.setFromAreaName(validateMoveArea(item.getFromWarehouseId(), item.getFromAreaId(), areaMap).getAreaName())
.setToAreaName(validateMoveArea(item.getToWarehouseId(), item.getToAreaId(), areaMap).getAreaName())
.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount()))));
}
private WarehouseAreaDO validateMoveArea(Long warehouseId, Long areaId, Map<Long, WarehouseAreaDO> areaMap) {
WarehouseAreaDO area = areaMap.get(areaId);
if (area == null || !Objects.equals(area.getWarehouseId(), warehouseId)) {
throw exception(WAREHOUSE_AREA_NOT_EXISTS);
}
return area;
}
private void updateStockMoveItemList(Long id, List<ErpStockMoveItemDO> newList) {
// 第一步,对比新老数据,获得添加、修改、删除的列表
List<ErpStockMoveItemDO> oldList = stockMoveItemMapper.selectListByMoveId(id);
@ -184,17 +313,37 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) {
throw exception(STOCK_MOVE_DELETE_FAIL_APPROVE, stockMove.getNo());
}
// if (ErpAuditStatus.PROCESS.getStatus().equals(stockMove.getStatus())) {
// throw exception(STOCK_MOVE_DELETE_FAIL_PROCESS, stockMove.getNo());
// }
});
// 2. 遍历删除,并记录操作日志
stockMoves.forEach(stockMove -> {
// 2.1 删除出库
// 2.1 删除调拨
stockMoveMapper.deleteById(stockMove.getId());
// 2.2 删除出库单项
// 2.2 删除调拨单项
stockMoveItemMapper.deleteByMoveId(stockMove.getId());
stockMoveApproveRecordMapper.deleteByStockMoveId(stockMove.getId());
});
}
private boolean needAudit() {
return !AUDIT_CONFIG_DISABLE_VALUE.equals(configApi.getConfigValueByCategoryAndKey(AUDIT_CONFIG_CATEGORY, AUDIT_CONFIG_KEY));
}
private void createApproveRecord(Long stockMoveId, ErpStockMoveApproveActionEnum action, Integer fromStatus,
Integer toStatus, Long targetUserId, String remark) {
stockMoveApproveRecordMapper.insert(ErpStockMoveApproveRecordDO.builder()
.stockMoveId(stockMoveId)
.actionType(action.getActionType())
.fromStatus(fromStatus)
.toStatus(toStatus)
.targetUserId(targetUserId)
.remark(remark)
.build());
}
private ErpStockMoveDO validateStockMoveExists(Long id) {
ErpStockMoveDO stockMove = stockMoveMapper.selectById(id);
if (stockMove == null) {
@ -213,7 +362,12 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
return stockMoveMapper.selectPage(pageReqVO);
}
// ==================== 出库项 ====================
@Override
public List<ErpStockMoveApproveRecordDO> getStockMoveApproveRecordList(Long id) {
return stockMoveApproveRecordMapper.selectListByStockMoveId(id);
}
// ==================== 调拨项 ====================
@Override
public List<ErpStockMoveItemDO> getStockMoveItemListByMoveId(Long moveId) {
@ -228,4 +382,4 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService {
return stockMoveItemMapper.selectListByMoveIds(moveIds);
}
}
}

@ -144,7 +144,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
}
boolean needAudit = needAudit();
Integer status = ErpAuditStatus.DRAFT.getStatus();
Integer status = ErpAuditStatus.PROCESS.getStatus();
ErpStockOutDO stockOut = BeanUtils.toBean(createReqVO, ErpStockOutDO.class, out -> out
.setNo(no)
.setNeedAudit(needAudit)
@ -180,9 +180,9 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) {
throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockOut.getNo());
}
if (ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) {
throw exception(STOCK_OUT_UPDATE_FAIL_PROCESS, stockOut.getNo());
}
// if (ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) {
// throw exception(STOCK_OUT_UPDATE_FAIL_PROCESS, stockOut.getNo());
// }
if (updateReqVO.getCustomerId() != null) {
customerService.validateCustomer(updateReqVO.getCustomerId());
}
@ -237,9 +237,9 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
public void submitStockOutAudit(ErpStockOutSubmitReqVO submitReqVO) {
ErpStockOutDO stockOut = validateStockOutExists(submitReqVO.getId());
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
if (!Objects.equals(NumberUtils.parseLong(stockOut.getCreator()), loginUserId)) {
throw exception(STOCK_OUT_SUBMIT_FAIL_USER);
}
// if (!Objects.equals(NumberUtils.parseLong(stockOut.getCreator()), loginUserId)) {
// throw exception(STOCK_OUT_SUBMIT_FAIL_USER);
// }
if (!ErpAuditStatus.DRAFT.getStatus().equals(stockOut.getStatus())
&& !ErpAuditStatus.UN_APPROVE.getStatus().equals(stockOut.getStatus())) {
throw exception(STOCK_OUT_SUBMIT_FAIL_STATUS);
@ -267,11 +267,12 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
// if (!ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) {
// throw exception(STOCK_OUT_AUDIT_FAIL_STATUS);
// }
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
Integer fromStatus = stockOut.getStatus();
if (!needAudit()) {
int updateCount = stockOutMapper.updateByIdAndStatus(stockOut.getId(), fromStatus,
new ErpStockOutDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus()));
new ErpStockOutDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus()).setAuditUserId(loginUserId));
if (updateCount == 0) {
throw exception(STOCK_OUT_AUDIT_FAIL_STATUS);
}
@ -283,12 +284,11 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
return;
}
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
boolean adminCanSubmit = permissionApi.hasAnyRoles(loginUserId, RoleCodeEnum.SUPER_ADMIN.getCode());
if (!Objects.equals(stockOut.getAuditUserId(), loginUserId) && !adminCanSubmit) {
throw exception(STOCK_OUT_AUDIT_FAIL_USER);
}
// if (!Objects.equals(stockOut.getAuditUserId(), loginUserId) && !adminCanSubmit) {
// throw exception(STOCK_OUT_AUDIT_FAIL_USER);
// }
if (!ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus())
&& !ErpAuditStatus.UN_APPROVE.getStatus().equals(auditReqVO.getStatus())) {
@ -296,7 +296,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
}
int updateCount = stockOutMapper.updateByIdAndStatus(stockOut.getId(), fromStatus,
new ErpStockOutDO().setNeedAudit(true).setStatus(auditReqVO.getStatus()));
new ErpStockOutDO().setNeedAudit(true).setStatus(auditReqVO.getStatus()).setAuditUserId(loginUserId));
if (updateCount == 0) {
throw exception(STOCK_OUT_AUDIT_FAIL_STATUS);
}
@ -322,9 +322,9 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) {
throw exception(STOCK_OUT_DELETE_FAIL_APPROVE, stockOut.getNo());
}
if (ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) {
throw exception(STOCK_OUT_DELETE_FAIL_PROCESS, stockOut.getNo());
}
// if (ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) {
// throw exception(STOCK_OUT_DELETE_FAIL_PROCESS, stockOut.getNo());
// }
});
stockOuts.forEach(stockOut -> {
stockOutMapper.deleteById(stockOut.getId());

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.erp.service.warehousearea;
import java.util.*;
import java.io.UnsupportedEncodingException;
import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.*;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@ -21,7 +22,7 @@ public interface WarehouseAreaService {
* @param createReqVO
* @return
*/
Long createWarehouseArea(@Valid WarehouseAreaSaveReqVO createReqVO);
Long createWarehouseArea(@Valid WarehouseAreaSaveReqVO createReqVO) throws UnsupportedEncodingException;
/**
* ERP
@ -66,4 +67,8 @@ public interface WarehouseAreaService {
List<WarehouseAreaDO> getWarehouseListByStatus(Integer status);
List<WarehouseAreaDO> getWarehouseListByStatusAndWarehouseId(Integer status, Long warehouseId);
String selectPrintTemplate();
void regenerateCode(Long id, String code) throws UnsupportedEncodingException;
}

@ -2,17 +2,23 @@ package cn.iocoder.yudao.module.erp.service.warehousearea;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.common.enums.CodeTypeEnum;
import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum;
import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.WarehouseAreaPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.warehousearea.vo.WarehouseAreaSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO;
import cn.iocoder.yudao.module.erp.dal.mysql.warehousearea.WarehouseAreaMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.warehouselocation.WarehouseLocationMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.ArrayList;
import java.util.List;
@ -24,8 +30,11 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_ARE
@Service
@Validated
@Slf4j
public class WarehouseAreaServiceImpl implements WarehouseAreaService {
private static final int WAREHOUSE_AREA_PRINT_TEMPLATE_TYPE = 7;
@Resource
private WarehouseAreaMapper warehouseAreaMapper;
@ -35,8 +44,12 @@ public class WarehouseAreaServiceImpl implements WarehouseAreaService {
@Resource
private AutoCodeUtil autoCodeUtil;
@Resource
private QrcodeRecordService qrcodeService;
@Override
public Long createWarehouseArea(WarehouseAreaSaveReqVO createReqVO) {
@Transactional(rollbackFor = Exception.class)
public Long createWarehouseArea(WarehouseAreaSaveReqVO createReqVO) throws UnsupportedEncodingException {
WarehouseAreaDO warehouseArea = BeanUtils.toBean(createReqVO, WarehouseAreaDO.class);
if (StringUtils.isEmpty(warehouseArea.getAreaCode())) {
warehouseArea.setAreaCode(autoCodeUtil.genSerialCode("RESERVOIR_AREA_GENERATE", null));
@ -44,6 +57,17 @@ public class WarehouseAreaServiceImpl implements WarehouseAreaService {
throw exception(WAREHOUSE_AREA_CODE_EXISTS);
}
warehouseAreaMapper.insert(warehouseArea);
CodeTypeEnum codeType = autoCodeUtil.queryCodeType("RESERVOIR_AREA_GENERATE");
if (codeType == null) {
log.warn("[创建库区]未配置码类型跳过生成ruleCode={}", "RESERVOIR_AREA_GENERATE");
return warehouseArea.getId();
}
qrcodeService.generateOrRefresh(
QrcodeBizTypeEnum.WAREHOUSE_AREA,
warehouseArea.getId(),
warehouseArea.getAreaCode(),
"DETAIL",
codeType);
return warehouseArea.getId();
}
@ -106,4 +130,30 @@ public class WarehouseAreaServiceImpl implements WarehouseAreaService {
return result;
}
@Override
public String selectPrintTemplate() {
return warehouseAreaMapper.selectPrintTemplate(WAREHOUSE_AREA_PRINT_TEMPLATE_TYPE);
}
@Override
public void regenerateCode(Long id, String code) throws UnsupportedEncodingException {
if (warehouseAreaMapper.selectById(id) == null) {
throw exception(WAREHOUSE_AREA_NOT_EXISTS);
}
if (StringUtils.isBlank(code)) {
throw exception(WAREHOUSE_AREA_CODE_EXISTS);
}
CodeTypeEnum codeType = autoCodeUtil.queryCodeType("RESERVOIR_AREA_GENERATE");
if (codeType == null) {
log.warn("[重生成库区二维码]未配置码类型跳过生成ruleCode={}", "RESERVOIR_AREA_GENERATE");
return;
}
qrcodeService.regenerateByCodeType(
QrcodeBizTypeEnum.WAREHOUSE_AREA,
id,
code,
"DETAIL",
codeType.getCode());
}
}

@ -9,7 +9,7 @@
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="selectListByIdsWithDeleted" resultType="cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO">
SELECT id, name, bar_code, category_id, sub_category_id, sub_category_name, unit_id,
SELECT id, name, bar_code, category_id, sub_category_id, sub_category_name, unit_id, unit_name,
purchase_unit_id, purchase_unit_name, purchase_unit_convert_quantity,
status, standard, remark, expiry_day, weight, purchase_price, sale_price,
min_price, safety_number, images,

@ -9,4 +9,12 @@
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
</mapper>
<select id="selectPrintTemplate" resultType="java.lang.String">
select template_json
from mes_print_template
where deleted = 0
and template_type = #{templateType}
and template_biz_type = 1
</select>
</mapper>

@ -100,7 +100,8 @@ public class DeviceLedgerPageReqVO extends PageParam {
private Long productId;
@Schema(description = "出厂日期")
private LocalDateTime outgoingTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate[] outgoingTime;
@Schema(description = "序列号")
private String sn;

@ -18,6 +18,9 @@ public class DvRepairPageReqVO extends PageParam {
@Schema(description = "维修单编号")
private String repairCode;
@Schema(description = "关键词,匹配维修单号/设备编号/设备名称")
private String keyword;
@Schema(description = "维修单名称", example = "王五")
private String repairName;
@ -66,6 +69,9 @@ public class DvRepairPageReqVO extends PageParam {
@Schema(description = "单据状态0-待完成 1-已完成", example = "1")
private Integer status;
@Schema(description = "维修状态 0-待完成 1-通过 2-不通过", example = "1")
private Integer repairStatus;
@Schema(description = "备注")
private String remark;
@ -80,6 +86,9 @@ public class DvRepairPageReqVO extends PageParam {
@Schema(description = "设备ID集合", example = "6979")
private List<Long> machineryIds;
@Schema(hidden = true)
private List<Long> keywordMachineryIds;
@Schema(description = "产线")
private String deviceLine;
}

@ -56,6 +56,7 @@ public interface DeviceLedgerMapper extends BaseMapperX<DeviceLedgerDO> {
.eqIfPresent(DeviceLedgerDO::getSort, reqVO.getSort())
.eqIfPresent(DeviceLedgerDO::getIsScheduled, reqVO.getIsScheduled())
.betweenIfPresent(DeviceLedgerDO::getCreateTime, reqVO.getCreateTime())
.betweenIfPresent(DeviceLedgerDO::getOutgoingTime, reqVO.getOutgoingTime())
.orderByDesc(DeviceLedgerDO::getCreateTime);
if (reqVO.getDeviceLineIds() != null && !reqVO.getDeviceLineIds().isEmpty()) {

@ -27,30 +27,22 @@ public interface DvRepairMapper extends BaseMapperX<DvRepairDO> {
LambdaQueryWrapperX<DvRepairDO> dvRepairDOLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
if(StringUtils.isNotBlank(reqVO.getRepairCode())&&StringUtils.isNotBlank(reqVO.getMachineryCode())&&reqVO.getRepairCode().equals(reqVO.getMachineryCode())){
dvRepairDOLambdaQueryWrapperX.and(w -> w
.like(DvRepairDO::getRepairCode, reqVO.getRepairCode())
.or()
.like(DvRepairDO::getMachineryCode, reqVO.getMachineryCode())
.or()
.in(DvRepairDO::getMachineryId,reqVO.getMachineryIds())
);
}else if(CollUtil.isNotEmpty(reqVO.getMachineryIds())){
dvRepairDOLambdaQueryWrapperX.in(DvRepairDO::getMachineryId,reqVO.getMachineryIds());
if(CollUtil.isNotEmpty(reqVO.getMachineryIds())){
dvRepairDOLambdaQueryWrapperX.in(DvRepairDO::getMachineryId, reqVO.getMachineryIds());
}
else{
dvRepairDOLambdaQueryWrapperX.eqIfPresent(DvRepairDO::getRepairCode, reqVO.getRepairCode())
.eqIfPresent(DvRepairDO::getMachineryCode, reqVO.getMachineryCode());
if (StringUtils.isNotBlank(reqVO.getKeyword())) {
dvRepairDOLambdaQueryWrapperX.and(w -> {
w.like(DvRepairDO::getRepairCode, reqVO.getKeyword());
if (CollUtil.isNotEmpty(reqVO.getKeywordMachineryIds())) {
w.or().in(DvRepairDO::getMachineryId, reqVO.getKeywordMachineryIds());
}
});
}
/* if(CollUtil.isNotEmpty(reqVO.getMachineryIds())){
dvRepairDOLambdaQueryWrapperX.in(DvRepairDO::getMachineryId,reqVO.getMachineryIds());
}*/
dvRepairDOLambdaQueryWrapperX
.likeIfPresent(DvRepairDO::getRepairCode, reqVO.getRepairCode())
.likeIfPresent(DvRepairDO::getRepairName, reqVO.getRepairName())
.eqIfPresent(DvRepairDO::getMachineryId, reqVO.getMachineryId())
.likeIfPresent(DvRepairDO::getMachineryName, reqVO.getMachineryName())
.likeIfPresent(DvRepairDO::getMachineryCode, reqVO.getMachineryCode())
.eqIfPresent(DvRepairDO::getMachineryBrand, reqVO.getMachineryBrand())
.eqIfPresent(DvRepairDO::getMachinerySpec, reqVO.getMachinerySpec())
.eqIfPresent(DvRepairDO::getMachineryTypeId, reqVO.getMachineryTypeId())
@ -61,6 +53,7 @@ public interface DvRepairMapper extends BaseMapperX<DvRepairDO> {
.eqIfPresent(DvRepairDO::getAcceptedBy, reqVO.getAcceptedBy())
.eqIfPresent(DvRepairDO::getConfirmBy, reqVO.getConfirmBy())
.eqIfPresent(DvRepairDO::getStatus, reqVO.getStatus())
.eqIfPresent(DvRepairDO::getRepairStatus, reqVO.getRepairStatus())
.eqIfPresent(DvRepairDO::getRemark, reqVO.getRemark())
.betweenIfPresent(DvRepairDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(DvRepairDO::getCreateTime);
@ -78,4 +71,4 @@ public interface DvRepairMapper extends BaseMapperX<DvRepairDO> {
}
void selectDeviceRepair(EventStatisticsVO eventStatisticsVO);
}
}

@ -136,15 +136,15 @@ public class DvRepairServiceImpl implements DvRepairService {
@Override
public PageResult<DvRepairDO> getDvRepairPage(DvRepairPageReqVO pageReqVO) {
if(StringUtils.isNotBlank(pageReqVO.getDeviceLine())|| StringUtils.isNotBlank(pageReqVO.getRepairCode())) {
if(StringUtils.isNotBlank(pageReqVO.getDeviceLine()) || StringUtils.isNotBlank(pageReqVO.getMachineryName())) {
LambdaQueryWrapperX<DeviceLedgerDO> deviceLedgerDOLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
if(StringUtils.isNotBlank(pageReqVO.getDeviceLine()))
deviceLedgerDOLambdaQueryWrapperX.eqIfPresent(DeviceLedgerDO::getDeviceLine, pageReqVO.getDeviceLine());
if(StringUtils.isNotBlank(pageReqVO.getRepairCode())){
if(StringUtils.isNotBlank(pageReqVO.getMachineryName())){
deviceLedgerDOLambdaQueryWrapperX.and(w -> w
.like(DeviceLedgerDO::getDeviceCode, pageReqVO.getRepairCode())
.like(DeviceLedgerDO::getDeviceCode, pageReqVO.getMachineryName())
.or()
.like(DeviceLedgerDO::getDeviceName, pageReqVO.getRepairCode())
.like(DeviceLedgerDO::getDeviceName, pageReqVO.getMachineryName())
);
}
List<DeviceLedgerDO> deviceLedgerDOS = deviceLedgerMapper.selectList(deviceLedgerDOLambdaQueryWrapperX);
@ -158,6 +158,20 @@ public class DvRepairServiceImpl implements DvRepairService {
}
}
if (StringUtils.isNotBlank(pageReqVO.getKeyword())) {
LambdaQueryWrapperX<DeviceLedgerDO> keywordDeviceQuery = new LambdaQueryWrapperX<>();
keywordDeviceQuery.and(w -> w
.like(DeviceLedgerDO::getDeviceCode, pageReqVO.getKeyword())
.or()
.like(DeviceLedgerDO::getDeviceName, pageReqVO.getKeyword())
);
List<DeviceLedgerDO> deviceLedgerDOS = deviceLedgerMapper.selectList(keywordDeviceQuery);
pageReqVO.setKeywordMachineryIds(deviceLedgerDOS.stream()
.map(DeviceLedgerDO::getId)
.distinct()
.collect(Collectors.toList()));
}
return dvRepairMapper.selectPage(pageReqVO);
}

Loading…
Cancel
Save