diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index d80d25dc4..e09a78361 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -101,6 +101,8 @@ public interface ErrorCodeConstants { ErrorCode WAREHOUSE_LOCATION_CODE_EXISTS = new ErrorCode(1_030_400_005, "库位编码不存在"); ErrorCode WAREHOUSE_LOCATION_NOT_EXISTS = new ErrorCode(1_030_400_006, "库位不存在"); ErrorCode WAREHOUSE_LOCATION_WAREHOUSE_AREA_NOT_MATCH = new ErrorCode(1_030_400_007, "暂无匹配库位信息"); + ErrorCode PALLET_NOT_EXISTS = new ErrorCode(1_030_400_008, "托盘不存在"); + ErrorCode PALLET_CODE_EXISTS = new ErrorCode(1_030_400_009, "托盘编码已存在"); // ========== ERP 其它入库单 1-030-401-000 ========== ErrorCode STOCK_IN_NOT_EXISTS = new ErrorCode(1_030_401_000, "其它入库单不存在"); @@ -161,6 +163,8 @@ public interface ErrorCodeConstants { ErrorCode STOCK_CHECK_AUDIT_FAIL_USER = new ErrorCode(1_030_403_012, "审核失败,当前用户不是指定审核人"); ErrorCode STOCK_CHECK_AUDIT_FAIL_RESULT = new ErrorCode(1_030_403_013, "审核失败,审核结果只支持通过或驳回"); ErrorCode STOCK_CHECK_SOURCE_TYPE_NOT_EXISTS = new ErrorCode(1_030_403_014, "盘点单生成来源类型不存在"); + ErrorCode STOCK_CODE_EXISTS = new ErrorCode(1_030_403_014, "盘点单编码已存在"); + // ========== ERP 产品库存 1-030-404-000 ========== ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_404_000, "操作失败,产品({})所在仓库({})的库存:{},小于变更数量:{}"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java new file mode 100644 index 000000000..cbf0d2bc6 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/ErpPalletController.java @@ -0,0 +1,82 @@ +package cn.iocoder.yudao.module.erp.controller.admin.pallet; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; +import cn.iocoder.yudao.module.erp.service.pallet.ErpPalletService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.validation.Valid; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - ERP 托盘") +@RestController +@RequestMapping("/erp/pallet") +@Validated +public class ErpPalletController { + + @Resource + private ErpPalletService palletService; + + @PostMapping("/create") + @Operation(summary = "创建托盘") + @PreAuthorize("@ss.hasPermission('erp:pallet:create')") + public CommonResult createPallet(@Valid @RequestBody ErpPalletSaveReqVO createReqVO) { + return success(palletService.createPallet(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新托盘") + @PreAuthorize("@ss.hasPermission('erp:pallet:update')") + public CommonResult updatePallet(@Valid @RequestBody ErpPalletSaveReqVO updateReqVO) { + palletService.updatePallet(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除托盘") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:pallet:delete')") + public CommonResult deletePallet(@RequestParam("id") Long id) { + palletService.deletePallet(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得托盘") + @Parameter(name = "id", description = "编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('erp:pallet:query')") + public CommonResult getPallet(@RequestParam("id") Long id) { + ErpPalletDO pallet = palletService.getPallet(id); + return success(BeanUtils.toBean(pallet, ErpPalletRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得托盘分页") + @PreAuthorize("@ss.hasPermission('erp:pallet:query')") + public CommonResult> getPalletPage(@Valid ErpPalletPageReqVO pageReqVO) { + PageResult pageResult = palletService.getPalletPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpPalletRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得托盘精简列表") + @Parameter(name = "status", description = "托盘状态", example = "1") + public CommonResult> getPalletSimpleList(@RequestParam(value = "status", required = false) Integer status) { + List list = palletService.getPalletListByStatus(status); + return success(convertList(list, item -> BeanUtils.toBean(item, ErpPalletRespVO.class))); + } +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/enums/ErpPalletStatusEnum.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/enums/ErpPalletStatusEnum.java new file mode 100644 index 000000000..a08e3447d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/enums/ErpPalletStatusEnum.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.erp.controller.admin.pallet.enums; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum ErpPalletStatusEnum implements IntArrayValuable { + + IDLE(1, "空闲"), + OCCUPIED(2, "占用"), + SCRAPPED(3, "报废"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpPalletStatusEnum::getStatus).toArray(); + + private final Integer status; + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/enums/ErpPalletTypeEnum.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/enums/ErpPalletTypeEnum.java new file mode 100644 index 000000000..cea997b7b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/enums/ErpPalletTypeEnum.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.erp.controller.admin.pallet.enums; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum ErpPalletTypeEnum implements IntArrayValuable { + + PLASTIC(1, "塑料"), + STEEL(2, "钢质"), + WOOD(3, "木托盘"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpPalletTypeEnum::getType).toArray(); + + private final Integer type; + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletPageReqVO.java new file mode 100644 index 000000000..fa05fb24d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletPageReqVO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.erp.controller.admin.pallet.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletStatusEnum; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletTypeEnum; +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.LocalDate; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; +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 ErpPalletPageReqVO extends PageParam { + + @Schema(description = "托盘编码", example = "TP202506100001") + private String code; + + @Schema(description = "托盘类型", example = "1") + @InEnum(ErpPalletTypeEnum.class) + private Integer palletType; + + @Schema(description = "托盘状态", example = "1") + @InEnum(ErpPalletStatusEnum.class) + private Integer status; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "11") + private Long areaId; + + @Schema(description = "生产任务单号", example = "PLAN20250610001") + private String planCode; + + @Schema(description = "产品编号", example = "1001") + private Long productId; + + @Schema(description = "采购日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDate[] purchaseDate; + + @Schema(description = "投入使用日期") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDate[] useDate; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java new file mode 100644 index 000000000..0144a353b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletRespVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.controller.admin.pallet.vo; + +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.LocalDate; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 托盘 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpPalletRespVO { + + @Schema(description = "托盘编号", example = "1") + @ExcelProperty("托盘编号") + private Long id; + + @Schema(description = "托盘编码", example = "TP202506100001") + @ExcelProperty("托盘编码") + private String code; + + @Schema(description = "托盘类型", example = "1") + @ExcelProperty("托盘类型") + private Integer palletType; + + @Schema(description = "托盘规格", example = "1200×1000×150") + @ExcelProperty("托盘规格") + private String specification; + + @Schema(description = "额定承载重量", example = "1000") + @ExcelProperty("额定承载重量") + private BigDecimal ratedLoadWeight; + + @Schema(description = "单位", example = "kg") + @ExcelProperty("单位") + private String unit; + + @Schema(description = "托盘状态", example = "1") + @ExcelProperty("托盘状态") + private Integer status; + + @Schema(description = "仓库编号", example = "1") + @ExcelProperty("仓库编号") + private Long warehouseId; + + @Schema(description = "库区编号", example = "11") + @ExcelProperty("库区编号") + private Long areaId; + + @Schema(description = "生产任务单号", example = "PLAN20250610001") + @ExcelProperty("生产任务单号") + private String planCode; + + @Schema(description = "产品编号", example = "1001") + @ExcelProperty("产品编号") + private Long productId; + + @Schema(description = "产品数量", example = "120") + @ExcelProperty("产品数量") + private BigDecimal productCount; + + @Schema(description = "二维码", example = "https://xxx.com/qrcode/pallet/1") + @ExcelProperty("二维码") + private String qrcode; + + @Schema(description = "采购日期", example = "2025-06-10") + @ExcelProperty("采购日期") + private LocalDate purchaseDate; + + @Schema(description = "投入使用日期", example = "2025-06-11") + @ExcelProperty("投入使用日期") + private LocalDate useDate; + + @Schema(description = "备注", example = "用于成品周转") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建时间") + @ExcelProperty("创建时间") + private LocalDateTime createTime; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletSaveReqVO.java new file mode 100644 index 000000000..09155b306 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/pallet/vo/ErpPalletSaveReqVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.erp.controller.admin.pallet.vo; + +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletStatusEnum; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import javax.validation.constraints.NotNull; +import java.math.BigDecimal; +import java.time.LocalDate; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; + +@Schema(description = "管理后台 - ERP 托盘新增/修改 Request VO") +@Data +public class ErpPalletSaveReqVO { + + @Schema(description = "托盘编号", example = "1") + private Long id; + + @Schema(description = "托盘编码", example = "TP202506100001") + private String code; + + @Schema(description = "托盘类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "托盘类型不能为空") + @InEnum(ErpPalletTypeEnum.class) + private Integer palletType; + + @Schema(description = "托盘规格(长×宽×高)", example = "1200×1000×150") + private String specification; + + @Schema(description = "额定承载重量", example = "1000") + private BigDecimal ratedLoadWeight; + + @Schema(description = "单位", example = "kg") + private String unit; + + @Schema(description = "托盘状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "托盘状态不能为空") + @InEnum(ErpPalletStatusEnum.class) + private Integer status; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "库区编号", example = "11") + private Long areaId; + + @Schema(description = "生产任务单号", example = "PLAN20250610001") + private String planCode; + + @Schema(description = "产品编号", example = "1001") + private Long productId; + + @Schema(description = "产品数量", example = "120") + private BigDecimal productCount; + + @Schema(description = "二维码", example = "https://xxx.com/qrcode/pallet/1") + private String qrcode; + + @Schema(description = "采购日期", example = "2025-06-10") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDate purchaseDate; + + @Schema(description = "投入使用日期", example = "2025-06-11") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY) + private LocalDate useDate; + + @Schema(description = "备注", example = "用于成品周转") + private String remark; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java index 72370a12f..ac138d679 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java @@ -10,7 +10,8 @@ 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; @@ -25,6 +26,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; 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.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockCheckService; import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService; @@ -71,6 +73,8 @@ public class ErpStockCheckController { @Resource private ErpProductService productService; @Resource + private ErpProductUnitService productUnitService; + @Resource private ErpWarehouseService warehouseService; @Resource private WarehouseAreaService warehouseAreaService; @@ -189,10 +193,12 @@ public class ErpStockCheckController { List stockCheckItemList = stockCheckService.getStockCheckItemListByCheckIds( convertSet(pageResult.getList(), ErpStockCheckDO::getId)); Map> stockCheckItemMap = convertMultiMap(stockCheckItemList, ErpStockCheckItemDO::getCheckId); + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), + stockCheck -> Stream.of(NumberUtils.parseLong(stockCheck.getCreator()), stockCheck.getAuditUserId()))); return BeanUtils.toBean(pageResult, ErpStockCheckRespVO.class, stockCheck -> { stockCheck.setItems(buildItemRespList(stockCheckItemMap.get(stockCheck.getId()))); stockCheck.setProductNames(CollUtil.join(stockCheck.getItems(), ",", ErpStockCheckRespVO.Item::getProductName)); - fillUserInfo(stockCheck); + fillUserInfo(stockCheck, userMap); }); } @@ -210,12 +216,18 @@ public class ErpStockCheckController { if (CollUtil.isEmpty(itemList)) { return new ArrayList<>(); } - Map productMap = productService.getProductVOMap(convertSet(itemList, ErpStockCheckItemDO::getProductId)); + Map productMap = productService.getProductMap(convertSet(itemList, ErpStockCheckItemDO::getProductId)); + Map unitMap = productUnitService.getProductUnitMap(convertSet(itemList, item -> { + ErpProductDO product = productMap.get(item.getProductId()); + return product != null ? product.getUnitId() : null; + })); Map warehouseMap = warehouseService.getWarehouseMap(convertSet(itemList, ErpStockCheckItemDO::getWarehouseId)); Map areaMap = warehouseAreaService.getWarehouseAreaMap(convertSet(itemList, ErpStockCheckItemDO::getAreaId)); return BeanUtils.toBean(itemList, ErpStockCheckRespVO.Item.class, item -> { MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) - .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + .setProductBarCode(product.getBarCode())); + MapUtils.findAndThen(productMap, item.getProductId(), product -> + MapUtils.findAndThen(unitMap, product.getUnitId(), unit -> item.setProductUnitName(unit.getName()))); MapUtils.findAndThen(warehouseMap, item.getWarehouseId(), warehouse -> item.setWarehouseName(warehouse.getName())); if (item.getAreaName() == null) { MapUtils.findAndThen(areaMap, item.getAreaId(), area -> item.setAreaName(area.getAreaName())); @@ -228,6 +240,10 @@ public class ErpStockCheckController { userIds.add(NumberUtils.parseLong(stockCheck.getCreator())); userIds.add(stockCheck.getAuditUserId()); Map userMap = adminUserApi.getUserMap(userIds); + fillUserInfo(stockCheck, userMap); + } + + private void fillUserInfo(ErpStockCheckRespVO stockCheck, Map userMap) { MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockCheck.getCreator()), user -> stockCheck.setCreatorName(user.getNickname())); MapUtils.findAndThen(userMap, stockCheck.getAuditUserId(), user -> stockCheck.setAuditUserName(user.getNickname())); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java index 633b73157..339471138 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java @@ -5,6 +5,11 @@ import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.PRODUCT_CATEGORY_TYPE; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import io.swagger.v3.oas.annotations.media.Schema; import javax.validation.constraints.NotNull; import lombok.Data; @@ -30,6 +35,9 @@ public class ErpStockCheckRespVO { @Schema(description = "盘点时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("盘点时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime checkTime; @Schema(description = "生成来源类型:1-按库存,2-按产品", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @@ -110,8 +118,7 @@ public class ErpStockCheckRespVO { @NotNull(message = "账面数量不能为空") private BigDecimal stockCount; - @Schema(description = "实际数量(实际库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") - @NotNull(message = "实际数量不能为空") + @Schema(description = "实际数量(实际库存)", example = "100.00") private BigDecimal actualCount; @Schema(description = "盈亏数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java index fc6e77997..48125b098 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java @@ -1,5 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; import io.swagger.v3.oas.annotations.media.Schema; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.erp.enums.stock.ErpStockCheckSourceTypeEnum; @@ -19,8 +24,14 @@ public class ErpStockCheckSaveReqVO { @Schema(description = "盘点编号", example = "11756") private Long id; + @Schema(description = "盘点编码", example = "11756") + private String code; + @Schema(description = "盘点时间", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "盘点时间不能为空") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime checkTime; @Schema(description = "生成来源类型:1-按库存,2-按产品", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @@ -63,8 +74,7 @@ public class ErpStockCheckSaveReqVO { @NotNull(message = "账面数量不能为空") private BigDecimal stockCount; - @Schema(description = "实际数量(实际库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") - @NotNull(message = "实际数量不能为空") + @Schema(description = "实际数量(实际库存)", example = "100.00") private BigDecimal actualCount; @Schema(description = "盈亏数量,服务端自动按 实际数量 - 账面数量 计算", example = "100.00") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/pallet/ErpPalletDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/pallet/ErpPalletDO.java new file mode 100644 index 000000000..726c9bf19 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/pallet/ErpPalletDO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.pallet; + +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; + +import java.math.BigDecimal; +import java.time.LocalDate; + +@TableName("erp_pallet") +@KeySequence("erp_pallet_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPalletDO extends BaseDO { + + @TableId + private Long id; + private String code; + private Integer palletType; + private String specification; + private BigDecimal ratedLoadWeight; + private String unit; + private Integer status; + private Long warehouseId; + private Long areaId; + private String planCode; + private Long productId; + private BigDecimal productCount; + private String qrcode; + private LocalDate purchaseDate; + private LocalDate useDate; + private String remark; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java new file mode 100644 index 000000000..f353dc732 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/pallet/ErpPalletMapper.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.pallet; + +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.pallet.vo.ErpPalletPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface ErpPalletMapper extends BaseMapperX { + + default PageResult selectPage(ErpPalletPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpPalletDO::getCode, reqVO.getCode()) + .eqIfPresent(ErpPalletDO::getPalletType, reqVO.getPalletType()) + .eqIfPresent(ErpPalletDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ErpPalletDO::getWarehouseId, reqVO.getWarehouseId()) + .eqIfPresent(ErpPalletDO::getAreaId, reqVO.getAreaId()) + .likeIfPresent(ErpPalletDO::getPlanCode, reqVO.getPlanCode()) + .eqIfPresent(ErpPalletDO::getProductId, reqVO.getProductId()) + .betweenIfPresent(ErpPalletDO::getPurchaseDate, reqVO.getPurchaseDate()) + .betweenIfPresent(ErpPalletDO::getUseDate, reqVO.getUseDate()) + .betweenIfPresent(ErpPalletDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ErpPalletDO::getId)); + } + + default ErpPalletDO selectByCode(String code) { + return selectOne(ErpPalletDO::getCode, code); + } + + default List selectListByStatus(Integer status) { + if (status == null) { + return selectList(); + } + return selectList(ErpPalletDO::getStatus, status); + } +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java index 6db811513..e57f430e0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java @@ -5,8 +5,6 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; -import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; -import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import com.alibaba.excel.util.StringUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -32,10 +30,14 @@ public interface ErpStockCheckMapper extends BaseMapperX { .eqIfPresent(ErpStockCheckDO::getCreator, reqVO.getCreator()) .orderByDesc(ErpStockCheckDO::getId); if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { - query.leftJoin(ErpStockCheckItemDO.class, ErpStockCheckItemDO::getCheckId, ErpStockCheckDO::getId) - .eq(reqVO.getWarehouseId() != null, ErpStockCheckItemDO::getWarehouseId, reqVO.getWarehouseId()) - .eq(reqVO.getProductId() != null, ErpStockCheckItemDO::getProductId, reqVO.getProductId()) - .groupBy(ErpStockCheckDO::getId); // 避免 1 对多查询,产生相同的 1 + StringBuilder itemFilterSql = new StringBuilder("select distinct check_id from erp_stock_check_item where deleted = 0"); + if (reqVO.getWarehouseId() != null) { + itemFilterSql.append(" and warehouse_id = ").append(reqVO.getWarehouseId()); + } + if (reqVO.getProductId() != null) { + itemFilterSql.append(" and product_id = ").append(reqVO.getProductId()); + } + query.inSql(ErpStockCheckDO::getId, itemFilterSql.toString()); } @@ -61,4 +63,4 @@ public interface ErpStockCheckMapper extends BaseMapperX { return selectOne(ErpStockCheckDO::getNo, no); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java index f16283cf4..d30d61f4c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java @@ -83,11 +83,31 @@ public interface ErpStockMapper extends BaseMapperX { return selectList(query); } + default List selectListByWarehouseIdsAndAreaIds(List warehouseIds, List areaIds, + boolean nonZeroOnly) { + LambdaQueryWrapperX query = new LambdaQueryWrapperX() + .inIfPresent(ErpStockDO::getWarehouseId, warehouseIds) + .inIfPresent(ErpStockDO::getAreaId, areaIds); + if (nonZeroOnly) { + query.ne(ErpStockDO::getCount, BigDecimal.ZERO); + } + return selectList(query); + } + default List selectListByProductIds(List productIds) { return selectList(new LambdaQueryWrapperX() .inIfPresent(ErpStockDO::getProductId, productIds)); } + default List selectListByProductIds(List productIds, boolean nonZeroOnly) { + LambdaQueryWrapperX query = new LambdaQueryWrapperX() + .inIfPresent(ErpStockDO::getProductId, productIds); + if (nonZeroOnly) { + query.ne(ErpStockDO::getCount, BigDecimal.ZERO); + } + return selectList(query); + } + default List selectListByProductIdsAndWarehouseIdsAndAreaIds(Collection productIds, Collection warehouseIds, Collection areaIds) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletService.java new file mode 100644 index 000000000..6d13decd8 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletService.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.service.pallet; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; + +import javax.validation.Valid; +import java.util.List; + +public interface ErpPalletService { + + Long createPallet(@Valid ErpPalletSaveReqVO createReqVO); + + void updatePallet(@Valid ErpPalletSaveReqVO updateReqVO); + + void deletePallet(Long id); + + ErpPalletDO getPallet(Long id); + + PageResult getPalletPage(ErpPalletPageReqVO pageReqVO); + + List getPalletListByStatus(Integer status); +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java new file mode 100644 index 000000000..296a77c35 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/pallet/ErpPalletServiceImpl.java @@ -0,0 +1,144 @@ +package cn.iocoder.yudao.module.erp.service.pallet; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.vo.ErpPalletSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; +import cn.iocoder.yudao.module.erp.dal.mysql.pallet.ErpPalletMapper; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; +import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.Collections; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PALLET_CODE_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PALLET_NOT_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_AREA_NOT_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_LOCATION_WAREHOUSE_AREA_NOT_MATCH; + +@Service +@Validated +public class ErpPalletServiceImpl implements ErpPalletService { + + @Resource + private ErpPalletMapper palletMapper; + @Resource + private AutoCodeUtil autoCodeUtil; + @Resource + private ErpWarehouseService warehouseService; + @Resource + private WarehouseAreaService warehouseAreaService; + @Resource + private ErpProductService productService; + + @Override + public Long createPallet(ErpPalletSaveReqVO createReqVO) { + validateWarehouseAreaMatch(createReqVO.getWarehouseId(), createReqVO.getAreaId()); + validateProductExists(createReqVO.getProductId()); + ErpPalletDO pallet = BeanUtils.toBean(createReqVO, ErpPalletDO.class); + if (StringUtils.isBlank(pallet.getCode())) { + pallet.setCode(autoCodeUtil.genSerialCode("PALLET_CODE_GENERATE", null)); + } else { + validateCodeUnique(null, pallet.getCode()); + } + if (StringUtils.isBlank(pallet.getQrcode())) { + pallet.setQrcode(pallet.getCode()); + } + palletMapper.insert(pallet); + return pallet.getId(); + } + + @Override + public void updatePallet(ErpPalletSaveReqVO updateReqVO) { + ErpPalletDO pallet = validatePalletExists(updateReqVO.getId()); + validateWarehouseAreaMatch(updateReqVO.getWarehouseId(), updateReqVO.getAreaId()); + validateProductExists(updateReqVO.getProductId()); + ErpPalletDO updateObj = BeanUtils.toBean(updateReqVO, ErpPalletDO.class); + if (StringUtils.isBlank(updateObj.getCode())) { + updateObj.setCode(pallet.getCode()); + } else { + validateCodeUnique(updateObj.getId(), updateObj.getCode()); + } + if (StringUtils.isBlank(updateObj.getQrcode())) { + updateObj.setQrcode(updateObj.getCode()); + } + palletMapper.updateById(updateObj); + } + + @Override + public void deletePallet(Long id) { + validatePalletExists(id); + palletMapper.deleteById(id); + } + + @Override + public ErpPalletDO getPallet(Long id) { + return palletMapper.selectById(id); + } + + @Override + public PageResult getPalletPage(ErpPalletPageReqVO pageReqVO) { + return palletMapper.selectPage(pageReqVO); + } + + @Override + public List getPalletListByStatus(Integer status) { + return palletMapper.selectListByStatus(status); + } + + private ErpPalletDO validatePalletExists(Long id) { + ErpPalletDO pallet = palletMapper.selectById(id); + if (pallet == null) { + throw exception(PALLET_NOT_EXISTS); + } + return pallet; + } + + private void validateCodeUnique(Long id, String code) { + ErpPalletDO pallet = palletMapper.selectByCode(code); + if (pallet == null) { + return; + } + if (id == null || !pallet.getId().equals(id)) { + throw exception(PALLET_CODE_EXISTS); + } + } + + private void validateWarehouseAreaMatch(Long warehouseId, Long areaId) { + if (warehouseId == null && areaId == null) { + return; + } + if (warehouseId != null && warehouseService.validWarehouseList(Collections.singleton(warehouseId)).isEmpty()) { + throw exception(cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS); + } + if (areaId == null) { + return; + } + WarehouseAreaDO area = warehouseAreaService.getWarehouseArea(areaId); + if (area == null) { + throw exception(WAREHOUSE_AREA_NOT_EXISTS); + } + if (warehouseId == null || !warehouseId.equals(area.getWarehouseId())) { + throw exception(WAREHOUSE_LOCATION_WAREHOUSE_AREA_NOT_MATCH); + } + } + + private void validateProductExists(Long productId) { + if (productId == null) { + return; + } + if (productService.validProductList(Collections.singleton(productId)).isEmpty()) { + throw exception(PRODUCT_NOT_EXISTS); + } + } +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java index 06c6130c5..22339826a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java @@ -7,7 +7,7 @@ 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.autocode.util.AutoCodeUtil; 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; @@ -37,6 +37,9 @@ import cn.iocoder.yudao.module.erp.service.warehousearea.WarehouseAreaService; 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 com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -56,23 +59,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_APPROVE_FAIL; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_AUDIT_FAIL_RESULT; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_AUDIT_FAIL_STATUS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_AUDIT_FAIL_USER; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_DELETE_FAIL_APPROVE; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_DELETE_FAIL_PROCESS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_NOT_EXISTS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_NO_EXISTS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_SOURCE_TYPE_NOT_EXISTS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_PROCESS_FAIL; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_SUBMIT_FAIL_AUDIT_USER_EMPTY; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_SUBMIT_FAIL_STATUS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_SUBMIT_FAIL_USER; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_UPDATE_FAIL_APPROVE; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_CHECK_UPDATE_FAIL_PROCESS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_AREA_NOT_EXISTS; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_LOCATION_WAREHOUSE_AREA_NOT_MATCH; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; @Service @Validated @@ -100,19 +87,34 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { private AdminUserApi adminUserApi; @Resource private PermissionApi permissionApi; + @Autowired + private AutoCodeUtil autoCodeUtil; @Override @Transactional(rollbackFor = Exception.class) public Long createStockCheck(ErpStockCheckSaveReqVO createReqVO) { + String code = createReqVO.getCode(); + validateSourceType(createReqVO.getSourceType()); List stockCheckItems = validateStockCheckItems(createReqVO.getItems()); - String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_CHECK_NO_PREFIX); - if (stockCheckMapper.selectByNo(no) != null) { - throw exception(STOCK_CHECK_NO_EXISTS); +// String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_CHECK_NO_PREFIX); +// if (stockCheckMapper.selectByNo(no) != null) { +// throw exception(STOCK_CHECK_NO_EXISTS); +// } + boolean autoGeneratedCode = StringUtils.isBlank(code); + + if (autoGeneratedCode) { + code = autoCodeUtil.genSerialCode("INVENTORY_EXECUTION_CODE", null); + } else { + if (stockCheckMapper.selectOne(Wrappers.lambdaQuery() + .eq(ErpStockCheckDO::getNo, code)) != null) { + throw exception(STOCK_CODE_EXISTS); + } } + String finalCode = code; ErpStockCheckDO stockCheck = BeanUtils.toBean(createReqVO, ErpStockCheckDO.class, in -> in - .setNo(no) + .setNo(finalCode) .setStatus(ErpAuditStatus.DRAFT.getStatus()) .setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add, BigDecimal.ZERO)) .setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); @@ -292,10 +294,9 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { if (reqVO == null || !reqVO.validSelection()) { return Collections.emptyList(); } - List stockList = stockMapper.selectListByWarehouseIdsAndAreaIds(reqVO.getWarehouseIds(), reqVO.getAreaIds()); - if (Boolean.FALSE.equals(reqVO.getAllowEmpty())) { - stockList = filterNonZeroStocks(stockList); - } + boolean nonZeroOnly = Boolean.FALSE.equals(reqVO.getAllowEmpty()); + List stockList = stockMapper.selectListByWarehouseIdsAndAreaIds( + reqVO.getWarehouseIds(), reqVO.getAreaIds(), nonZeroOnly); return buildPreviewItems(stockList); } @@ -304,10 +305,8 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { if (reqVO == null || CollUtil.isEmpty(reqVO.getProductIds())) { return Collections.emptyList(); } - List stockList = stockMapper.selectListByProductIds(reqVO.getProductIds()); - if (Boolean.FALSE.equals(reqVO.getAllowEmpty())) { - stockList = filterNonZeroStocks(stockList); - } + boolean nonZeroOnly = Boolean.FALSE.equals(reqVO.getAllowEmpty()); + List stockList = stockMapper.selectListByProductIds(reqVO.getProductIds(), nonZeroOnly); return buildPreviewItems(stockList); } @@ -328,7 +327,8 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { if (CollUtil.isEmpty(stockList)) { return Collections.emptyList(); } - Map productMap = productService.getProductMap(convertSet(stockList, ErpStockDO::getProductId)); + Collection productIds = convertSet(stockList, ErpStockDO::getProductId); + Map productMap = productService.getProductMap(productIds); Map warehouseMap = warehouseService.getWarehouseMap(convertSet(stockList, ErpStockDO::getWarehouseId)); Map areaMap = warehouseAreaService.getWarehouseAreaMap(convertSet(stockList, ErpStockDO::getAreaId)); List result = new ArrayList<>(); @@ -339,7 +339,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { item.setAreaName(stock.getAreaName()); item.setProductId(stock.getProductId()); item.setStockCount(stock.getCount() != null ? stock.getCount() : BigDecimal.ZERO); - item.setActualCount(stock.getCount() != null ? stock.getCount() : BigDecimal.ZERO); + item.setActualCount(null); item.setCount(BigDecimal.ZERO); MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> item.setWarehouseName(warehouse.getName())); if (item.getAreaName() == null) { @@ -347,13 +347,10 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { } ErpProductDO productDO = productMap.get(stock.getProductId()); item.setProductPrice(resolveProductPrice(productDO)); + item.setProductUnitName(stock.getUnitName()); if (productDO != null) { item.setProductName(productDO.getName()); item.setProductBarCode(productDO.getBarCode()); - ErpProductRespVO productVO = productService.getProduct(productDO.getId()); - if (productVO != null) { - item.setProductUnitName(productVO.getUnitName()); - } } result.add(item); } @@ -434,8 +431,8 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { ErpProductDO productDO = productMap.get(item.getProductId()); WarehouseAreaDO area = item.getAreaId() != null ? areaMap.get(item.getAreaId()) : null; BigDecimal stockCount = item.getStockCount() != null ? item.getStockCount() : BigDecimal.ZERO; - BigDecimal actualCount = item.getActualCount() != null ? item.getActualCount() : BigDecimal.ZERO; - BigDecimal count = actualCount.subtract(stockCount); + BigDecimal actualCount = item.getActualCount(); + BigDecimal count = actualCount != null ? actualCount.subtract(stockCount) : null; BigDecimal productPrice = item.getProductPrice() != null ? item.getProductPrice() : resolveProductPrice(productDO); return ErpStockCheckItemDO.builder() .id(item.getId()) @@ -448,7 +445,7 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { .stockCount(stockCount) .actualCount(actualCount) .count(count) - .totalPrice(MoneyUtils.priceMultiply(productPrice, count)) + .totalPrice(count != null ? MoneyUtils.priceMultiply(productPrice, count) : null) .remark(item.getRemark()) .build(); });