diff --git a/yudao-module-common/yudao-module-common-biz/src/main/java/cn/iocoder/yudao/module/common/enums/QrcodeBizTypeEnum.java b/yudao-module-common/yudao-module-common-biz/src/main/java/cn/iocoder/yudao/module/common/enums/QrcodeBizTypeEnum.java index 51aff4a27..2a87cb0a0 100644 --- a/yudao-module-common/yudao-module-common-biz/src/main/java/cn/iocoder/yudao/module/common/enums/QrcodeBizTypeEnum.java +++ b/yudao-module-common/yudao-module-common-biz/src/main/java/cn/iocoder/yudao/module/common/enums/QrcodeBizTypeEnum.java @@ -12,6 +12,7 @@ public enum QrcodeBizTypeEnum { DEVICE_LINE("DEVICE_LINE", "设备产线"), KEY_PART("KEY_PART", "关键件"), MOLD("MOLD", "模具"), + PALLET("PALLET", "托盘"), SPARE("SPARE", "备件"); private final String code; 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 33af6e76a..a8f30708b 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,9 @@ 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, "托盘编码已存在"); + ErrorCode PALLET_CODE_EMPTY = new ErrorCode(1_030_400_010, "托盘编码不能为空"); // ========== ERP 其它入库单 1-030-401-000 ========== ErrorCode STOCK_IN_NOT_EXISTS = new ErrorCode(1_030_401_000, "其它入库单不存在"); @@ -160,6 +163,9 @@ public interface ErrorCodeConstants { ErrorCode STOCK_CHECK_AUDIT_FAIL_STATUS = new ErrorCode(1_030_403_011, "审核失败,只有审核中的盘点单才能审核"); 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-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockCheckApproveActionEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockCheckApproveActionEnum.java index b9b3392b4..f72c31705 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockCheckApproveActionEnum.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockCheckApproveActionEnum.java @@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor; public enum ErpStockCheckApproveActionEnum { SUBMIT("SUBMIT"), + AUTO_APPROVE("AUTO_APPROVE"), APPROVE("APPROVE"), REJECT("REJECT"); diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockCheckSourceTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockCheckSourceTypeEnum.java new file mode 100644 index 000000000..06dcd5982 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockCheckSourceTypeEnum.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.erp.enums.stock; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +@RequiredArgsConstructor +@Getter +public enum ErpStockCheckSourceTypeEnum implements IntArrayValuable { + + BY_LOCATION(1, "按库存"), + BY_PRODUCT(2, "按产品"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockCheckSourceTypeEnum::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-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockOutModeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockOutModeEnum.java new file mode 100644 index 000000000..62629f077 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockOutModeEnum.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.erp.enums.stock; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum ErpStockOutModeEnum implements IntArrayValuable { + + BY_PALLET(1, "按托出库"), + SPLIT_PALLET(2, "拆托出库"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockOutModeEnum::getMode).toArray(); + + private final Integer mode; + 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/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..3fc4d7966 --- /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,141 @@ +package cn.iocoder.yudao.module.erp.controller.admin.pallet; + +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum; +import cn.iocoder.yudao.module.common.service.qrcordrecord.QrcodeRecordService; +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.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +@Tag(name = "管理后台 - ERP 托盘") +@RestController +@RequestMapping("/erp/pallet") +@Validated +public class ErpPalletController { + + @Resource + private ErpPalletService palletService; + @Resource + private QrcodeRecordService qrcodeService; + + @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(buildPalletRespVO(pallet)); + } + + @GetMapping("/page") + @Operation(summary = "获得托盘分页") + @PreAuthorize("@ss.hasPermission('erp:pallet:query')") + public CommonResult> getPalletPage(@Valid ErpPalletPageReqVO pageReqVO) { + PageResult pageResult = palletService.getPalletPage(pageReqVO); + Map qrcodeMap = qrcodeService.selectQrcodeUrlMapByBizTypeAndIds(QrcodeBizTypeEnum.PALLET.getCode(), + convertList(pageResult.getList(), ErpPalletDO::getId)); + List list = convertList(pageResult.getList(), pallet -> buildPalletRespVO(pallet, qrcodeMap)); + return success(new PageResult<>(list, pageResult.getTotal())); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出托盘 Excel") + @PreAuthorize("@ss.hasPermission('erp:pallet:export')") + @ApiAccessLog(operateType = EXPORT) + public void exportPalletExcel(@Valid ErpPalletPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + PageResult pageResult = palletService.getPalletPage(pageReqVO); + Map qrcodeMap = qrcodeService.selectQrcodeUrlMapByBizTypeAndIds(QrcodeBizTypeEnum.PALLET.getCode(), + convertList(pageResult.getList(), ErpPalletDO::getId)); + List list = convertList(pageResult.getList(), pallet -> buildPalletRespVO(pallet, qrcodeMap)); + ExcelUtils.write(response, "托盘.xls", "数据", ErpPalletRespVO.class, list); + } + + @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); + Map qrcodeMap = qrcodeService.selectQrcodeUrlMapByBizTypeAndIds(QrcodeBizTypeEnum.PALLET.getCode(), + convertList(list, ErpPalletDO::getId)); + return success(convertList(list, item -> buildPalletRespVO(item, qrcodeMap))); + } + + @PostMapping("/regenerate-code") + public CommonResult regenerateCode(@RequestParam("id") Long id, + @RequestParam("code") String code) throws UnsupportedEncodingException { + palletService.regenerateCode(id, code); + return success(true); + } + + private ErpPalletRespVO buildPalletRespVO(ErpPalletDO pallet) { + if (pallet == null) { + return null; + } + ErpPalletRespVO respVO = BeanUtils.toBean(pallet, ErpPalletRespVO.class); + String qrcode = qrcodeService.selectQrcodeUrlByIdAndCode(QrcodeBizTypeEnum.PALLET.getCode(), pallet.getId(), pallet.getCode()); + if (qrcode != null) { + respVO.setQrcode(qrcode); + } + return respVO; + } + + private ErpPalletRespVO buildPalletRespVO(ErpPalletDO pallet, Map qrcodeMap) { + ErpPalletRespVO respVO = BeanUtils.toBean(pallet, ErpPalletRespVO.class); + String qrcode = qrcodeMap.get(pallet.getId()); + if (qrcode != null) { + respVO.setQrcode(qrcode); + } + return respVO; + } +} 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..f14d657af 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; @@ -94,7 +98,7 @@ public class ErpStockCheckController { @PutMapping("/update-status") @Operation(summary = "更新库存盘点单状态") - @PreAuthorize("@ss.hasPermission('erp:stock-check:update-status')") + @PreAuthorize("@ss.hasPermission('erp:stock-check:update')") @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) public CommonResult updateStockCheckStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { @@ -104,7 +108,7 @@ public class ErpStockCheckController { @PutMapping("/submit") @Operation(summary = "提交库存盘点单审核") - @PreAuthorize("@ss.hasPermission('erp:stock-check:update')") + @PreAuthorize("@ss.hasPermission('erp:stock-check:submit')") @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) public CommonResult submitStockCheckAudit(@Valid @RequestBody ErpStockCheckSubmitReqVO submitReqVO) { stockCheckService.submitStockCheckAudit(submitReqVO); @@ -113,7 +117,7 @@ public class ErpStockCheckController { @PutMapping("/audit") @Operation(summary = "审核库存盘点单") - @PreAuthorize("@ss.hasPermission('erp:stock-check:update-status')") + @PreAuthorize("@ss.hasPermission('erp:stock-check:audit')") @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) public CommonResult auditStockCheck(@Valid @RequestBody ErpStockCheckAuditReqVO auditReqVO) { stockCheckService.auditStockCheck(auditReqVO); @@ -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/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java index eb47ffc3f..0139d80a9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java @@ -12,9 +12,11 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProduc import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; 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.pallet.ErpPalletService; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; @@ -36,8 +38,12 @@ 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.List; import java.util.Map; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -59,6 +65,8 @@ public class ErpStockController { private WarehouseAreaService warehouseAreaService; @Resource private ErpStockRecordService stockRecordService; + @Resource + private ErpPalletService palletService; @GetMapping("/get") @Operation(summary = "获得产品库存") @@ -112,6 +120,7 @@ public class ErpStockController { convertSet(pageResult.getList(), ErpStockDO::getWarehouseId)); Map areaMap = warehouseAreaService.getWarehouseAreaMap( convertSet(pageResult.getList(), ErpStockDO::getAreaId)); + Map palletCountMap = buildPalletCountMap(pageResult.getList()); return BeanUtils.toBean(pageResult, ErpStockRespVO.class, stock -> { MapUtils.findAndThen(productMap, stock.getProductId(), product -> { stock.setProductName(product.getName()).setBarCode(product.getBarCode()) @@ -120,6 +129,7 @@ public class ErpStockController { fillProductExtraInfo(stock, product); fillPackagingSnapshot(stock, product); }); + stock.setPalletCount(palletCountMap.getOrDefault(buildStockKey(stock.getProductId(), stock.getWarehouseId(), stock.getAreaId()), 0L)); stock.setPackagingRule(buildPackagingRule(stock)); stock.setStockDisplay(buildStockDisplay(stock)); MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> stock.setWarehouseName(warehouse.getName())); @@ -150,6 +160,7 @@ public class ErpStockController { fillPackagingSnapshot(respVO, product); } fillDerivedFields(respVO); + respVO.setPalletCount(getPalletCount(respVO)); respVO.setPackagingRule(buildPackagingRule(respVO)); respVO.setStockDisplay(buildStockDisplay(respVO)); ErpWarehouseDO warehouse = warehouseService.getWarehouse(stock.getWarehouseId()); @@ -259,11 +270,12 @@ public class ErpStockController { return null; } if (isProductType(stock.getCategoryType())) { - if (stock.getPalletTotalQuantity() == null || stock.getPalletTotalQuantity().compareTo(BigDecimal.ZERO) <= 0) { + if (stock.getPackageQuantity() == null || stock.getPackageQuantity().compareTo(BigDecimal.ZERO) <= 0) { return formatNumber(stock.getCount()) + stock.getUnitName(); } - BigDecimal palletCount = stock.getCount().divideToIntegralValue(stock.getPalletTotalQuantity()); - return formatNumber(palletCount) + "托,0包,0个"; + BigDecimal packageCount = stock.getCount().divide(stock.getPackageQuantity(), 0, RoundingMode.CEILING); + return formatNumber(BigDecimal.valueOf(stock.getPalletCount() != null ? stock.getPalletCount() : 0L)) + "\u6258" + + formatNumber(packageCount) + "\u5305" + formatNumber(stock.getCount()) + stock.getUnitName(); } if (stock.getPurchaseUnitConvertQuantity() == null || stock.getPurchaseUnitConvertQuantity().compareTo(BigDecimal.ZERO) <= 0 || stock.getPurchaseUnitName() == null || stock.getUnitName() == null) { @@ -298,6 +310,28 @@ public class ErpStockController { return Integer.valueOf(1).equals(categoryType); } + private Map buildPalletCountMap(List stockList) { + if (CollUtil.isEmpty(stockList)) { + return new HashMap<>(); + } + return palletService.getOccupiedPalletList(convertSet(stockList, ErpStockDO::getProductId), + convertSet(stockList, ErpStockDO::getWarehouseId), convertSet(stockList, ErpStockDO::getAreaId)).stream() + .collect(Collectors.groupingBy(pallet -> buildStockKey(pallet.getProductId(), pallet.getWarehouseId(), pallet.getAreaId()), + Collectors.counting())); + } + + private Long getPalletCount(ErpStockRespVO stock) { + return palletService.getOccupiedPalletList(Collections.singleton(stock.getProductId()), + Collections.singleton(stock.getWarehouseId()), Collections.singleton(stock.getAreaId())).stream() + .filter(pallet -> buildStockKey(stock.getProductId(), stock.getWarehouseId(), stock.getAreaId()) + .equals(buildStockKey(pallet.getProductId(), pallet.getWarehouseId(), pallet.getAreaId()))) + .count(); + } + + private String buildStockKey(Long productId, Long warehouseId, Long areaId) { + return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId); + } + private String formatNumber(BigDecimal value) { return value == null ? "0" : value.stripTrailingZeros().toPlainString(); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java index 2120c9b96..02b9e4296 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -19,16 +19,19 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInRespVO import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSubmitReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.StockInTypeEnum; +import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; 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; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import cn.iocoder.yudao.module.erp.dal.dataobject.warehousearea.WarehouseAreaDO; import cn.iocoder.yudao.module.erp.enums.ErpStockInStatusEnum; import cn.iocoder.yudao.module.erp.service.mold.MoldBrandService; import cn.iocoder.yudao.module.erp.service.mold.MoldService; +import cn.iocoder.yudao.module.erp.service.pallet.ErpPalletService; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockInService; @@ -92,6 +95,8 @@ public class ErpStockInController { @Resource private MoldService moldService; @Resource + private ErpPalletService palletService; + @Resource private AdminUserApi adminUserApi; @PostMapping("/create") @@ -121,8 +126,8 @@ public class ErpStockInController { } @PutMapping("/submit") - @Operation(summary = "提交其它入库单审核") - @PreAuthorize("@ss.hasPermission('erp:stock-in:update')") + @Operation(summary = "提交入库单审核") + @PreAuthorize("@ss.hasPermission('erp:stock-in:submit')") @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) public CommonResult submitStockInAudit(@Valid @RequestBody ErpStockInSubmitReqVO submitReqVO) { stockInService.submitStockInAudit(submitReqVO); @@ -130,8 +135,8 @@ public class ErpStockInController { } @PutMapping("/audit") - @Operation(summary = "审核其它入库单") - @PreAuthorize("@ss.hasPermission('erp:stock-in:update-status')") + @Operation(summary = "审核入库单") + @PreAuthorize("@ss.hasPermission('erp:stock-in:audit')") @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) public CommonResult auditStockIn(@Valid @RequestBody ErpStockInAuditReqVO auditReqVO) { stockInService.auditStockIn(auditReqVO); @@ -246,17 +251,23 @@ public class ErpStockInController { convertSet(allItems, ErpStockInItemDO::getMoldSetId)); Map> moldListMap = moldService.getMoldListMapByBrandIds( convertSet(allItems, ErpStockInItemDO::getMoldSetId)); + Map> itemPalletMap = stockInService.getStockInItemPalletListByInIds( + convertSet(stockIns, ErpStockInDO::getId)).stream() + .collect(Collectors.groupingBy(ErpStockInItemPalletDO::getInItemId)); + Map palletMap = palletService.getPalletMap( + convertSet(convertListByFlatMap(itemPalletMap.values(), Collection::stream), ErpStockInItemPalletDO::getPalletId)); Map stockMap = buildStockMap(allItems); List list = convertList(stockIns, stockIn -> buildStockInRespVO( stockIn, itemMap.getOrDefault(stockIn.getId(), Collections.emptyList()), Collections.emptyList(), - userMap, supplierMap, stockMap, warehouseMap, areaMap, productMap, moldMap, moldListMap)); + userMap, supplierMap, stockMap, warehouseMap, areaMap, productMap, moldMap, moldListMap, + itemPalletMap, palletMap)); return new PageResult<>(list, pageResult.getTotal()); } private ErpStockInRespVO buildStockInRespVO(ErpStockInDO stockIn, List stockInItemList, List approveRecords) { return buildStockInRespVO(stockIn, stockInItemList, approveRecords, - null, null, null, null, null, null, null, null); + null, null, null, null, null, null, null, null, null, null); } private ErpStockInRespVO buildStockInRespVO(ErpStockInDO stockIn, List stockInItemList, @@ -268,7 +279,9 @@ public class ErpStockInController { Map pageAreaMap, Map pageProductMap, Map pageMoldMap, - Map> pageMoldListMap) { + Map> pageMoldListMap, + Map> pageItemPalletMap, + Map pagePalletMap) { ErpStockInRespVO stockInVO = BeanUtils.toBean(stockIn, ErpStockInRespVO.class); stockInVO.setStatusName(getStockInStatusName(stockIn.getStatus())); Map warehouseMap = pageWarehouseMap != null ? pageWarehouseMap : warehouseService.getWarehouseMap( @@ -278,6 +291,11 @@ public class ErpStockInController { Map userMap = pageUserMap != null ? pageUserMap : adminUserApi.getUserMap(convertListByFlatMap( Collections.singletonList(stockIn), item -> Stream.of(NumberUtils.parseLong(item.getCreator()), item.getStockUserId(), item.getAuditUserId()))); + Map> itemPalletMap = pageItemPalletMap != null ? pageItemPalletMap + : stockInService.getStockInItemPalletListByInId(stockIn.getId()).stream() + .collect(Collectors.groupingBy(ErpStockInItemPalletDO::getInItemId)); + Map palletMap = pagePalletMap != null ? pagePalletMap : palletService.getPalletMap( + convertSet(convertListByFlatMap(itemPalletMap.values(), Collection::stream), ErpStockInItemPalletDO::getPalletId)); MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockIn.getCreator()), user -> stockInVO.setCreatorName(user.getNickname())); MapUtils.findAndThen(userMap, stockIn.getStockUserId(), user -> stockInVO.setStockUserName(user.getNickname())); MapUtils.findAndThen(userMap, stockIn.getAuditUserId(), user -> stockInVO.setAuditUserName(user.getNickname())); @@ -294,6 +312,7 @@ public class ErpStockInController { item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>())); fillWarehouseInfo(item, source, warehouseMap, areaMap); + item.setPallets(buildStockInPalletRespList(itemPalletMap.get(source.getId()), palletMap)); MapUtils.findAndThen(moldMap, source.getMoldSetId(), mold -> { item.setMoldSetName(mold.getName()); item.setProductName(mold.getName()); @@ -316,6 +335,7 @@ public class ErpStockInController { if (StringUtils.isBlank(item.getAreaName())) { MapUtils.findAndThen(areaMap, item.getAreaId(), area -> item.setAreaName(area.getAreaName())); } + item.setPallets(buildStockInPalletRespList(itemPalletMap.get(item.getId()), palletMap)); MapUtils.findAndThen(productMap, item.getProductId(), product -> { item.setProductName(product.getName()); item.setProductBarCode(product.getBarCode()); @@ -359,6 +379,20 @@ public class ErpStockInController { return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId); } + private List buildStockInPalletRespList(List itemPallets, + Map palletMap) { + if (CollUtil.isEmpty(itemPallets)) { + return Collections.emptyList(); + } + return convertList(itemPallets, itemPallet -> { + ErpStockInRespVO.Item.PalletItem palletItem = new ErpStockInRespVO.Item.PalletItem(); + palletItem.setPalletId(itemPallet.getPalletId()); + palletItem.setPackageCount(itemPallet.getPackageCount()); + MapUtils.findAndThen(palletMap, itemPallet.getPalletId(), pallet -> palletItem.setPalletCode(pallet.getCode())); + return palletItem; + }); + } + private List buildApproveRecordRespList(List records) { if (CollUtil.isEmpty(records)) { return new ArrayList<>(); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java index 07ae4baad..191df5a74 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java @@ -19,14 +19,17 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutResp import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSubmitReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.StockOutTypeEnum; +import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemPalletDO; import cn.iocoder.yudao.module.erp.enums.ErpStockOutStatusEnum; import cn.iocoder.yudao.module.erp.service.mold.MoldBrandService; import cn.iocoder.yudao.module.erp.service.mold.MoldService; +import cn.iocoder.yudao.module.erp.service.pallet.ErpPalletService; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockOutService; @@ -90,6 +93,8 @@ public class ErpStockOutController { @Resource private MoldService moldService; @Resource + private ErpPalletService palletService; + @Resource private AdminUserApi adminUserApi; @PostMapping("/create") @@ -119,8 +124,8 @@ public class ErpStockOutController { } @PutMapping("/submit") - @Operation(summary = "提交其它出库单审核") - @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + @Operation(summary = "提交出库单审核") + @PreAuthorize("@ss.hasPermission('erp:stock-out:submit')") @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) public CommonResult submitStockOutAudit(@Valid @RequestBody ErpStockOutSubmitReqVO submitReqVO) { stockOutService.submitStockOutAudit(submitReqVO); @@ -128,8 +133,8 @@ public class ErpStockOutController { } @PutMapping("/audit") - @Operation(summary = "审核其它出库单") - @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") + @Operation(summary = "审核出库单") + @PreAuthorize("@ss.hasPermission('erp:stock-out:audit')") @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) public CommonResult auditStockOut(@Valid @RequestBody ErpStockOutAuditReqVO auditReqVO) { stockOutService.auditStockOut(auditReqVO); @@ -250,17 +255,22 @@ public class ErpStockOutController { convertSet(allItems, ErpStockOutItemDO::getMoldSetId)); Map> moldListMap = moldService.getMoldListMapByBrandIds( convertSet(allItems, ErpStockOutItemDO::getMoldSetId)); + Map> itemPalletMap = stockOutService.getStockOutItemPalletListByOutIds( + convertSet(stockOuts, ErpStockOutDO::getId)).stream() + .collect(Collectors.groupingBy(ErpStockOutItemPalletDO::getOutItemId)); + Map palletMap = palletService.getPalletMap( + convertSet(convertListByFlatMap(itemPalletMap.values(), Collection::stream), ErpStockOutItemPalletDO::getPalletId)); Map stockMap = buildStockMap(allItems); List list = convertList(stockOuts, stockOut -> buildStockOutRespVO( stockOut, itemMap.getOrDefault(stockOut.getId(), Collections.emptyList()), Collections.emptyList(), - userMap, customerMap, stockMap, productMap, moldMap, moldListMap)); + userMap, customerMap, stockMap, productMap, moldMap, moldListMap, itemPalletMap, palletMap)); return new PageResult<>(list, pageResult.getTotal()); } private ErpStockOutRespVO buildStockOutRespVO(ErpStockOutDO stockOut, List stockOutItemList, List approveRecords) { return buildStockOutRespVO(stockOut, stockOutItemList, approveRecords, - null, null, null, null, null, null); + null, null, null, null, null, null, null, null); } private ErpStockOutRespVO buildStockOutRespVO(ErpStockOutDO stockOut, List stockOutItemList, @@ -270,12 +280,19 @@ public class ErpStockOutController { Map pageStockMap, Map pageProductMap, Map pageMoldMap, - Map> pageMoldListMap) { + Map> pageMoldListMap, + Map> pageItemPalletMap, + Map pagePalletMap) { ErpStockOutRespVO stockOutVO = BeanUtils.toBean(stockOut, ErpStockOutRespVO.class); stockOutVO.setStatusName(getStockOutStatusName(stockOut.getStatus())); Map userMap = pageUserMap != null ? pageUserMap : adminUserApi.getUserMap(convertListByFlatMap( Collections.singletonList(stockOut), item -> Stream.of(NumberUtils.parseLong(item.getCreator()), item.getResponserId(), item.getAuditUserId()))); + Map> itemPalletMap = pageItemPalletMap != null ? pageItemPalletMap + : stockOutService.getStockOutItemPalletListByOutId(stockOut.getId()).stream() + .collect(Collectors.groupingBy(ErpStockOutItemPalletDO::getOutItemId)); + Map palletMap = pagePalletMap != null ? pagePalletMap : palletService.getPalletMap( + convertSet(convertListByFlatMap(itemPalletMap.values(), Collection::stream), ErpStockOutItemPalletDO::getPalletId)); MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockOut.getCreator()), user -> stockOutVO.setCreatorName(user.getNickname())); MapUtils.findAndThen(userMap, stockOut.getResponserId(), user -> stockOutVO.setResponserName(user.getNickname())); MapUtils.findAndThen(userMap, stockOut.getAuditUserId(), user -> stockOutVO.setAuditUserName(user.getNickname())); @@ -291,6 +308,7 @@ public class ErpStockOutController { : stockService.getStock(source.getMoldSetId(), source.getWarehouseId(), source.getAreaId()); item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>())); + item.setPallets(buildStockOutPalletRespList(itemPalletMap.get(source.getId()), palletMap)); MapUtils.findAndThen(moldMap, source.getMoldSetId(), mold -> { item.setMoldSetName(mold.getName()); item.setProductName(mold.getName()); @@ -307,6 +325,7 @@ public class ErpStockOutController { ErpStockDO stock = pageStockMap != null ? pageStockMap.get(buildStockKey(item.getProductId(), item.getWarehouseId(), item.getAreaId())) : stockService.getStock(item.getProductId(), item.getWarehouseId(), item.getAreaId()); item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + item.setPallets(buildStockOutPalletRespList(itemPalletMap.get(item.getId()), palletMap)); MapUtils.findAndThen(productMap, item.getProductId(), product -> { item.setProductName(product.getName()); item.setProductBarCode(product.getBarCode()); @@ -369,6 +388,20 @@ public class ErpStockOutController { return String.valueOf(productId) + "_" + String.valueOf(warehouseId) + "_" + String.valueOf(areaId); } + private List buildStockOutPalletRespList(List itemPallets, + Map palletMap) { + if (CollUtil.isEmpty(itemPallets)) { + return Collections.emptyList(); + } + return convertList(itemPallets, itemPallet -> { + ErpStockOutRespVO.Item.PalletItem palletItem = new ErpStockOutRespVO.Item.PalletItem(); + palletItem.setPalletId(itemPallet.getPalletId()); + palletItem.setPackageCount(itemPallet.getPackageCount()); + MapUtils.findAndThen(palletMap, itemPallet.getPalletId(), pallet -> palletItem.setPalletCode(pallet.getCode())); + return palletItem; + }); + } + private List buildApproveRecordRespList(List records) { if (CollUtil.isEmpty(records)) { return new ArrayList<>(); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java index f25a6b627..d87830a28 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java @@ -5,13 +5,17 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 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.validation.InEnum; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.enums.ErpWarehouseCategoryEnum; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSummaryRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseSummaryService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; @@ -38,6 +42,8 @@ public class ErpWarehouseController { @Resource private ErpWarehouseService warehouseService; + @Resource + private ErpWarehouseSummaryService warehouseSummaryService; @PostMapping("/create") @Operation(summary = "创建仓库") @@ -93,10 +99,21 @@ public class ErpWarehouseController { @GetMapping("/simple-list") @Operation(summary = "获得仓库精简列表", description = "只包含被开启的仓库,主要用于前端的下拉选项") - public CommonResult> getWarehouseSimpleList() { - List list = warehouseService.getWarehouseListByStatus(CommonStatusEnum.ENABLE.getStatus()); + @Parameter(name = "categoryType", description = "仓库分类", example = "1") + public CommonResult> getWarehouseSimpleList( + @RequestParam(value = "categoryType", required = false) Integer categoryType) { + List list = warehouseService.getWarehouseListByStatus(CommonStatusEnum.ENABLE.getStatus(), categoryType); return success(convertList(list, warehouse -> new ErpWarehouseRespVO().setId(warehouse.getId()) - .setName(warehouse.getName()).setDefaultStatus(warehouse.getDefaultStatus()))); + .setName(warehouse.getName()).setCategoryType(warehouse.getCategoryType()) + .setDefaultStatus(warehouse.getDefaultStatus()))); + } + + @GetMapping("/summary") + @Operation(summary = "获得仓库总览") + @Parameter(name = "warehouseId", description = "仓库编号", required = true, example = "1") + @PreAuthorize("@ss.hasPermission('erp:warehouse:query')") + public CommonResult getWarehouseSummary(@RequestParam("warehouseId") Long warehouseId) { + return success(warehouseSummaryService.getWarehouseSummary(warehouseId)); } @GetMapping("/export-excel") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/enums/ErpWarehouseCategoryEnum.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/enums/ErpWarehouseCategoryEnum.java new file mode 100644 index 000000000..96e0c7423 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/enums/ErpWarehouseCategoryEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.enums; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +@Getter +@AllArgsConstructor +public enum ErpWarehouseCategoryEnum implements IntArrayValuable { + + PRODUCT(1, "产品"), + MATERIAL(2, "物料"), + SPARE_PART(3, "备件"), + OTHER(4, "其他"); + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpWarehouseCategoryEnum::getCategory).toArray(); + + private final Integer category; + 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/stock/vo/check/ErpStockCheckGenerateByLocationReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckGenerateByLocationReqVO.java index f7ff71bd0..35c83946e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckGenerateByLocationReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckGenerateByLocationReqVO.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import javax.validation.constraints.NotEmpty; import java.util.List; @Schema(description = "管理后台 - ERP 库存盘点按仓库/库区生成盘点项 Request VO") @@ -16,8 +15,11 @@ public class ErpStockCheckGenerateByLocationReqVO { @Schema(description = "库区编号列表", example = "[11,12]") private List areaIds; - @Schema(description = "是否允许为空,默认 false", example = "false") - private Boolean allowEmpty; + @Schema(description = "是否允许为空库存,默认 true", example = "true") + private Boolean allowEmpty = Boolean.TRUE; + + @Schema(description = "选择分类", example = "1") + private Integer categoryType; public boolean validSelection() { return (warehouseIds != null && !warehouseIds.isEmpty()) || (areaIds != null && !areaIds.isEmpty()); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckGenerateByProductReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckGenerateByProductReqVO.java index 76564c842..420a7a385 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckGenerateByProductReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckGenerateByProductReqVO.java @@ -14,4 +14,10 @@ public class ErpStockCheckGenerateByProductReqVO { @NotEmpty(message = "产品编号列表不能为空") private List productIds; + @Schema(description = "是否允许为空库存,默认 true", example = "true") + private Boolean allowEmpty = Boolean.TRUE; + + @Schema(description = "选择分类", example = "1") + private Integer categoryType; + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java index 41c23bc9d..5a072e4cd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java @@ -42,6 +42,12 @@ public class ErpStockCheckPageReqVO extends PageParam { @Schema(description = "产品编号", example = "1") private Long productId; + @Schema(description = "选择分类", example = "1") + private Integer categoryType; + + @Schema(description = "盘点状态:0-未盘点,1-已盘点", example = "1") + private Integer checkStatus; + @Schema(description = "id集合导出用") private String ids; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/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 ee93dfa40..f55779fd9 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 @@ -2,8 +2,14 @@ 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 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; @@ -29,8 +35,28 @@ 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") + @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 = "true") + private Boolean needAudit; + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") @ExcelProperty("合计数量") private BigDecimal totalCount; @@ -104,8 +130,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 cf04eca64..301f94917 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,6 +1,13 @@ 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; import lombok.Data; import javax.validation.Valid; @@ -17,17 +24,34 @@ 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") + @NotNull(message = "生成来源类型不能为空") + @InEnum(ErpStockCheckSourceTypeEnum.class) + private Integer sourceType; + + @Schema(description = "选择分类", example = "1") + private Integer categoryType; + + @Schema(description = "盘点状态:0-未盘点,1-已盘点", example = "1") + private Integer checkStatus; + @Schema(description = "备注", example = "随便") private String remark; @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") private String fileUrl; - @Schema(description = "盘点项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @Schema(description = "盘点项列表", implementation = Item.class) @NotEmpty(message = "盘点项列表不能为空") @Valid private List items; @@ -56,8 +80,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/controller/admin/stock/vo/in/ErpStockInPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java index e744085a8..508b5b5a0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java @@ -31,7 +31,7 @@ public class ErpStockInPageReqVO extends PageParam { private LocalDateTime[] inTime; @Schema(description = "状态", example = "10") - @InEnum(ErpStockInStatusEnum.class) +// @InEnum(ErpStockInStatusEnum.class) private List statusList; @Schema(description = "入库类型", example = "其它入库") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java index 57551db70..4f4578fd9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -141,9 +141,36 @@ public class ErpStockInRespVO { @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") private BigDecimal count; + @Schema(description = "是否关联任务单", example = "true") + private Boolean relateTask; + + @Schema(description = "任务单 ID", example = "10001") + private Long taskId; + @Schema(description = "包装方案 ID", example = "1") private Long packagingSchemeId; + @Schema(description = "包装方案名称", example = "标准包装") + private String packagingSchemeName; + + @Schema(description = "每包数量", example = "10.00") + private BigDecimal packageQuantity; + + @Schema(description = "每托包数", example = "20.00") + private BigDecimal palletPackageQuantity; + + @Schema(description = "每托总数量", example = "200.00") + private BigDecimal palletTotalQuantity; + + @Schema(description = "托数", example = "2.00") + private BigDecimal palletCount; + + @Schema(description = "包数", example = "40.00") + private BigDecimal packageCount; + + @Schema(description = "个数", example = "400.00") + private BigDecimal pieceCount; + @Schema(description = "单位输入方式", example = "包") private String inputUnitType; @@ -177,7 +204,23 @@ public class ErpStockInRespVO { @Schema(description = "库存数量", example = "100.00") private BigDecimal stockCount; + @Schema(description = "托盘列表") + private List pallets; + @Schema(description = "子模具详情") private List moldList; + + @Data + public static class PalletItem { + + @Schema(description = "托盘 ID", example = "1") + private Long palletId; + + @Schema(description = "托盘编码", example = "TP20240601001") + private String palletCode; + + @Schema(description = "包数", example = "10") + private BigDecimal packageCount; + } } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java index 6bd847d09..72b155291 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java @@ -76,16 +76,58 @@ public class ErpStockInSaveReqVO { @Schema(description = "包装方案 ID", example = "1") private Long packagingSchemeId; + @Schema(description = "包装方案名称", example = "标准包装") + private String packagingSchemeName; + + @Schema(description = "每包数量", example = "10") + private BigDecimal packageQuantity; + + @Schema(description = "每托包数", example = "20") + private BigDecimal palletPackageQuantity; + + @Schema(description = "每托总数量", example = "200") + private BigDecimal palletTotalQuantity; + + @Schema(description = "托数", example = "1") + private BigDecimal palletCount; + + @Schema(description = "包数", example = "10") + private BigDecimal packageCount; + + @Schema(description = "个数", example = "100") + private BigDecimal pieceCount; + @Schema(description = "单位输入方式", example = "包") private String inputUnitType; @Schema(description = "录入数量", example = "10.00") private BigDecimal inputCount; + @Schema(description = "是否关联任务单", example = "true") + private Boolean relateTask; + + @Schema(description = "任务单ID", example = "10001") + private Long taskId; + + @Schema(description = "托盘列表") + @Valid + private List pallets; + @Schema(description = "备注", example = "随便") private String remark; @Schema(description = "设备 id", example = "100") private Long deviceId; + + @Data + public static class PalletItem { + + @Schema(description = "托盘ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "托盘ID不能为空") + private Long palletId; + + @Schema(description = "包数", example = "10") + private BigDecimal packageCount; + } } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java index 1679296bf..6173ab455 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java @@ -40,7 +40,7 @@ public class ErpStockOutPageReqVO extends PageParam { private LocalDateTime[] outTime; @Schema(description = "状态", example = "10") - @InEnum(ErpStockOutStatusEnum.class) +// @InEnum(ErpStockOutStatusEnum.class) private List statusList; @Schema(description = "审核人编号", example = "1") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java index 84a95cd8b..00d7ad76b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -181,6 +181,39 @@ public class ErpStockOutRespVO { @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") private BigDecimal count; + @Schema(description = "包装方案 ID", example = "1") + private Long packagingSchemeId; + + @Schema(description = "包装方案名称", example = "标准包装") + private String packagingSchemeName; + + @Schema(description = "每包数量", example = "10.00") + private BigDecimal packageQuantity; + + @Schema(description = "每托包数", example = "20.00") + private BigDecimal palletPackageQuantity; + + @Schema(description = "每托总数量", example = "200.00") + private BigDecimal palletTotalQuantity; + + @Schema(description = "托数", example = "2.00") + private BigDecimal palletCount; + + @Schema(description = "包数", example = "40.00") + private BigDecimal packageCount; + + @Schema(description = "个数", example = "400.00") + private BigDecimal pieceCount; + + @Schema(description = "单位输入方式", example = "包") + private String inputUnitType; + + @Schema(description = "录入数量", example = "10.00") + private BigDecimal inputCount; + + @Schema(description = "出库方式:1-按托出库 2-拆托出库", example = "1") + private Integer outMode; + @Schema(description = "出库用途", example = "1") private Integer outUsageType; @@ -226,8 +259,24 @@ public class ErpStockOutRespVO { @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") private BigDecimal stockCount; + @Schema(description = "托盘列表") + private List pallets; + @Schema(description = "子模具列表") private List moldList; + + @Data + public static class PalletItem { + + @Schema(description = "托盘 ID", example = "1") + private Long palletId; + + @Schema(description = "托盘编码", example = "TP20240601001") + private String palletCode; + + @Schema(description = "包数", example = "10") + private BigDecimal packageCount; + } } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVOItem.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVOItem.java index eb83335ad..28f8122cc 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVOItem.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVOItem.java @@ -5,8 +5,12 @@ import cn.iocoder.yudao.module.erp.enums.ErpStockOutUsageTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import javax.validation.Valid; import javax.validation.constraints.NotNull; import java.math.BigDecimal; +import java.util.List; + +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockOutModeEnum; @Schema(description = "ERP 其它出库单明细项") @Data @@ -33,9 +37,43 @@ public class ErpStockOutSaveReqVOItem { @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") private BigDecimal count; + @Schema(description = "包装方案 ID", example = "1") + private Long packagingSchemeId; + + @Schema(description = "包装方案名称", example = "标准包装") + private String packagingSchemeName; + + @Schema(description = "每包数量", example = "10.00") + private BigDecimal packageQuantity; + + @Schema(description = "每托包数", example = "20.00") + private BigDecimal palletPackageQuantity; + + @Schema(description = "每托总数量", example = "200.00") + private BigDecimal palletTotalQuantity; + + @Schema(description = "托数", example = "2.00") + private BigDecimal palletCount; + + @Schema(description = "包数", example = "40.00") + private BigDecimal packageCount; + + @Schema(description = "个数", example = "400.00") + private BigDecimal pieceCount; + + @Schema(description = "单位输入方式", example = "包") + private String inputUnitType; + + @Schema(description = "录入数量", example = "10.00") + private BigDecimal inputCount; + + @Schema(description = "出库方式:1-按托出库 2-拆托出库", example = "1") + @InEnum(ErpStockOutModeEnum.class) + private Integer outMode; + @Schema(description = "出库用途", example = "1") @InEnum(ErpStockOutUsageTypeEnum.class) - @NotNull(message = "出库用途不能为空") +// @NotNull(message = "出库用途不能为空") private Integer outUsageType; @Schema(description = "维修单编号", example = "1001") @@ -49,4 +87,19 @@ public class ErpStockOutSaveReqVOItem { @Schema(description = "备注", example = "备注信息") private String remark; + + @Schema(description = "托盘列表") + @Valid + private List pallets; + + @Data + public static class PalletItem { + + @Schema(description = "托盘ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "托盘ID不能为空") + private Long palletId; + + @Schema(description = "包数", example = "10") + private BigDecimal packageCount; + } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java index ffb58ab76..723135e6f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java @@ -95,6 +95,9 @@ public class ErpStockRespVO { @ExcelProperty("库存展示") private String stockDisplay; + @Schema(description = "托盘数量", example = "2") + private Long palletCount; + // ========== 仓库信息 ========== @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java index 11f97e4fc..e6da3112a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.controller.admin.stock.enums.ErpWarehouseCategoryEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -17,10 +18,14 @@ public class ErpWarehousePageReqVO extends PageParam { @Schema(description = "仓库名称", example = "李四") private String name; + @Schema(description = "仓库分类", example = "1") + @InEnum(ErpWarehouseCategoryEnum.class) + private Integer categoryType; + @Schema(description = "开启状态", example = "1") @InEnum(CommonStatusEnum.class) private Integer status; @Schema(description = "id集合导出用") private String ids; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java index e51086788..ba0509e2d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java @@ -27,6 +27,10 @@ public class ErpWarehouseRespVO { @ExcelProperty("仓库名称") private String name; + @Schema(description = "仓库分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("仓库分类") + private Integer categoryType; + @Schema(description = "仓库地址", example = "上海陆家嘴") @ExcelProperty("仓库地址") private String address; @@ -78,5 +82,4 @@ public class ErpWarehouseRespVO { @Schema(description = "库位列表") private List locationList; - } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java index 96e843979..ce3e200d4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.controller.admin.stock.enums.ErpWarehouseCategoryEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -20,6 +21,11 @@ public class ErpWarehouseSaveReqVO { @NotEmpty(message = "仓库名称不能为空") private String name; + @Schema(description = "仓库分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "仓库分类不能为空") + @InEnum(ErpWarehouseCategoryEnum.class) + private Integer categoryType; + @Schema(description = "仓库地址", example = "上海陆家嘴") private String address; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSummaryRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSummaryRespVO.java new file mode 100644 index 000000000..b78704822 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSummaryRespVO.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 仓库总览 Response VO") +@Data +public class ErpWarehouseSummaryRespVO { + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "仓库名称", example = "A仓") + private String warehouseName; + + @Schema(description = "产品库存量", example = "1000") + private BigDecimal productStockCount; + + @Schema(description = "产品库存展示", example = "2托3包4个") + private String productStockDisplay; + + @Schema(description = "物料库存量", example = "1000") + private BigDecimal materialStockCount; + + @Schema(description = "物料库存展示", example = "10采购单位20库存单位") + private String materialStockDisplay; + + @Schema(description = "备件库存量", example = "1000") + private BigDecimal sparePartStockCount; + + @Schema(description = "备件库存展示", example = "10采购单位20库存单位") + private String sparePartStockDisplay; + + @Schema(description = "今日入库单数量", example = "5") + private Long todayStockInOrderCount; + + @Schema(description = "今日入库明细行数量", example = "18") + private Long todayStockInItemCount; + + @Schema(description = "今日入库产成品展示", example = "2托3包4个") + private String todayProductStockInDisplay; + + @Schema(description = "今日入库物料展示", example = "100个") + private String todayMaterialStockInDisplay; + + @Schema(description = "今日入库备件展示", example = "100个") + private String todaySparePartStockInDisplay; + + @Schema(description = "今日出库单数量", example = "3") + private Long todayStockOutOrderCount; + + @Schema(description = "今日出库明细行数量", example = "10") + private Long todayStockOutItemCount; + + @Schema(description = "今日出库产成品展示", example = "2托3包4个") + private String todayProductStockOutDisplay; + + @Schema(description = "今日出库物料展示", example = "100个") + private String todayMaterialStockOutDisplay; + + @Schema(description = "今日出库备件展示", example = "100个") + private String todaySparePartStockOutDisplay; + +} 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/dataobject/stock/ErpStockCheckDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java index 54130f443..ce7c82229 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java @@ -37,6 +37,22 @@ public class ErpStockCheckDO extends BaseDO { * 盘点时间 */ private LocalDateTime checkTime; + /** + * 生成来源类型:1-按库存,2-按产品 + */ + private Integer sourceType; + /** + * 产品分类类型 + */ + private Integer categoryType; + /** + * 盘点状态:0-未盘点,1-已盘点 + */ + private Integer checkStatus; + /** + * 是否需要审核 + */ + private Boolean needAudit; /** * 合计数量 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java index b1f859d48..54bacfa42 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java @@ -70,6 +70,34 @@ public class ErpStockInItemDO extends BaseDO { * 包装方案 ID */ private Long packagingSchemeId; + /** + * 包装方案名称 + */ + private String packagingSchemeName; + /** + * 每包数量 + */ + private BigDecimal packageQuantity; + /** + * 每托包数 + */ + private BigDecimal palletPackageQuantity; + /** + * 每托总数量 + */ + private BigDecimal palletTotalQuantity; + /** + * 托数 + */ + private BigDecimal palletCount; + /** + * 包数 + */ + private BigDecimal packageCount; + /** + * 个数 + */ + private BigDecimal pieceCount; /** * 单位输入方式(托/包/个) */ @@ -78,6 +106,8 @@ public class ErpStockInItemDO extends BaseDO { * 录入数量 */ private BigDecimal inputCount; + private Boolean relateTask; + private Long taskId; /** * 合计金额,单位:元 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemPalletDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemPalletDO.java new file mode 100644 index 000000000..9e5b07401 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemPalletDO.java @@ -0,0 +1,32 @@ +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; + +import java.math.BigDecimal; + +@TableName("erp_stock_in_item_pallet") +@KeySequence("erp_stock_in_item_pallet_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockInItemPalletDO extends BaseDO { + + @TableId + private Long id; + private Long inId; + private Long inItemId; + private Long palletId; + private BigDecimal packageCount; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java index 472c16901..6cadaf609 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java @@ -105,6 +105,47 @@ public class ErpStockOutItemDO extends BaseDO { * 产品数量 */ private BigDecimal count; + /** + * 包装方案 ID + */ + private Long packagingSchemeId; + /** + * 包装方案名称 + */ + private String packagingSchemeName; + /** + * 每包数量 + */ + private BigDecimal packageQuantity; + /** + * 每托包数 + */ + private BigDecimal palletPackageQuantity; + /** + * 每托总数量 + */ + private BigDecimal palletTotalQuantity; + /** + * 托数 + */ + private BigDecimal palletCount; + /** + * 包数 + */ + private BigDecimal packageCount; + /** + * 个数 + */ + private BigDecimal pieceCount; + /** + * 单位输入方式(托/包/个) + */ + private String inputUnitType; + /** + * 录入数量 + */ + private BigDecimal inputCount; + private Integer outMode; /** * 合计金额,单位:元 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemPalletDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemPalletDO.java new file mode 100644 index 000000000..953de013d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemPalletDO.java @@ -0,0 +1,32 @@ +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; + +import java.math.BigDecimal; + +@TableName("erp_stock_out_item_pallet") +@KeySequence("erp_stock_out_item_pallet_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockOutItemPalletDO extends BaseDO { + + @TableId + private Long id; + private Long outId; + private Long outItemId; + private Long palletId; + private BigDecimal packageCount; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java index 4f206173f..ffe8a45db 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java @@ -32,6 +32,10 @@ public class ErpWarehouseDO extends BaseDO { * 仓库名称 */ private String name; + /** + * 仓库分类 + */ + private Integer categoryType; /** * 仓库地址 */ @@ -67,4 +71,4 @@ public class ErpWarehouseDO extends BaseDO { */ private Boolean defaultStatus; -} \ 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/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..86f8d573d --- /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,52 @@ +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.math.BigDecimal; +import java.util.Collection; +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); + } + + default List selectOccupiedList(Collection productIds, Collection warehouseIds, + Collection areaIds) { + boolean containsNullArea = areaIds != null && areaIds.stream().anyMatch(java.util.Objects::isNull); + return selectList(new LambdaQueryWrapperX() + .inIfPresent(ErpPalletDO::getProductId, productIds) + .inIfPresent(ErpPalletDO::getWarehouseId, warehouseIds) + .inIfPresent(ErpPalletDO::getAreaId, containsNullArea ? null : areaIds) + .gt(ErpPalletDO::getProductCount, BigDecimal.ZERO)); + } +} 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..3c0fb5ec2 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; @@ -27,15 +25,21 @@ public interface ErpStockCheckMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX() .likeIfPresent(ErpStockCheckDO::getNo, reqVO.getNo()) .betweenIfPresent(ErpStockCheckDO::getCheckTime, reqVO.getCheckTime()) + .eqIfPresent(ErpStockCheckDO::getCategoryType, reqVO.getCategoryType()) + .eqIfPresent(ErpStockCheckDO::getCheckStatus, reqVO.getCheckStatus()) .eqIfPresent(ErpStockCheckDO::getStatus, reqVO.getStatus()) .likeIfPresent(ErpStockCheckDO::getRemark, reqVO.getRemark()) .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 +65,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/ErpStockInItemPalletMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemPalletMapper.java new file mode 100644 index 000000000..ce7243223 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemPalletMapper.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemPalletDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface ErpStockInItemPalletMapper extends BaseMapperX { + + default List selectListByInId(Long inId) { + return selectList(ErpStockInItemPalletDO::getInId, inId); + } + + default List selectListByInIds(Collection inIds) { + return selectList(ErpStockInItemPalletDO::getInId, inIds); + } + + default int deleteByInId(Long inId) { + return delete(ErpStockInItemPalletDO::getInId, inId); + } +} 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..b353be054 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,42 @@ public interface ErpStockMapper extends BaseMapperX { return selectList(query); } + default List selectListByWarehouseIdsAndAreaIds(List warehouseIds, List areaIds, + boolean nonZeroOnly) { + return selectListByWarehouseIdsAndAreaIds(warehouseIds, areaIds, nonZeroOnly, null); + } + + default List selectListByWarehouseIdsAndAreaIds(List warehouseIds, List areaIds, + boolean nonZeroOnly, Integer categoryType) { + LambdaQueryWrapperX query = new LambdaQueryWrapperX() + .inIfPresent(ErpStockDO::getWarehouseId, warehouseIds) + .inIfPresent(ErpStockDO::getAreaId, areaIds) + .eqIfPresent(ErpStockDO::getCategoryType, categoryType); + 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) { + return selectListByProductIds(productIds, nonZeroOnly, null); + } + + default List selectListByProductIds(List productIds, boolean nonZeroOnly, Integer categoryType) { + LambdaQueryWrapperX query = new LambdaQueryWrapperX() + .inIfPresent(ErpStockDO::getProductId, productIds) + .eqIfPresent(ErpStockDO::getCategoryType, categoryType); + 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/dal/mysql/stock/ErpStockOutItemPalletMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemPalletMapper.java new file mode 100644 index 000000000..a87bd9e26 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemPalletMapper.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemPalletDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +@Mapper +public interface ErpStockOutItemPalletMapper extends BaseMapperX { + + default List selectListByOutId(Long outId) { + return selectList(ErpStockOutItemPalletDO::getOutId, outId); + } + + default List selectListByOutIds(Collection outIds) { + return selectList(ErpStockOutItemPalletDO::getOutId, outIds); + } + + default int deleteByOutId(Long outId) { + return delete(ErpStockOutItemPalletDO::getOutId, outId); + } +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java index 792610dd4..d12c0c32f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java @@ -24,6 +24,7 @@ public interface ErpWarehouseMapper extends BaseMapperX { LambdaQueryWrapperX erpWarehouseDOLambdaQueryWrapperX = new LambdaQueryWrapperX() .likeIfPresent(ErpWarehouseDO::getName, reqVO.getName()) + .eqIfPresent(ErpWarehouseDO::getCategoryType, reqVO.getCategoryType()) .eqIfPresent(ErpWarehouseDO::getStatus, reqVO.getStatus()) .orderByDesc(ErpWarehouseDO::getId); @@ -43,8 +44,11 @@ public interface ErpWarehouseMapper extends BaseMapperX { return selectOne(ErpWarehouseDO::getDefaultStatus, true); } - default List selectListByStatus(Integer status) { - return selectList(ErpWarehouseDO::getStatus, status); + default List selectListByStatus(Integer status, Integer categoryType) { + return selectList(new LambdaQueryWrapperX() + .eqIfPresent(ErpWarehouseDO::getStatus, status) + .eqIfPresent(ErpWarehouseDO::getCategoryType, categoryType) + .orderByDesc(ErpWarehouseDO::getId)); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/handler/PalletQrcodeBizHandler.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/handler/PalletQrcodeBizHandler.java new file mode 100644 index 000000000..2079a2d7c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/handler/PalletQrcodeBizHandler.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.erp.handler; + +import cn.iocoder.yudao.module.common.enums.QrcodeBizTypeEnum; +import cn.iocoder.yudao.module.common.handler.QrcodeBizHandler; +import cn.iocoder.yudao.module.erp.dal.mysql.pallet.ErpPalletMapper; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +@Component +public class PalletQrcodeBizHandler implements QrcodeBizHandler { + + @Resource + private ErpPalletMapper palletMapper; + + @Override + public String getBizType() { + return QrcodeBizTypeEnum.PALLET.getCode(); + } + + @Override + public boolean exists(Long id) { + return palletMapper.selectById(id) != null; + } + + @Override + public String buildDeepLink(Long id) { + return "https://www.baidu.com"; + } + + @Override + public String buildH5Path(Long id) { + return "https://baike.baidu.com/item/%E6%98%9F%E5%BA%A7/8072715?fr=aladdin"; + } +} 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..39cf20904 --- /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,35 @@ +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.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public interface ErpPalletService { + + Long createPallet(@Valid ErpPalletSaveReqVO createReqVO); + + void updatePallet(@Valid ErpPalletSaveReqVO updateReqVO); + + void deletePallet(Long id); + + ErpPalletDO getPallet(Long id); + + List getPalletList(Collection ids); + + Map getPalletMap(Collection ids); + + PageResult getPalletPage(ErpPalletPageReqVO pageReqVO); + + List getPalletListByStatus(Integer status); + + List getOccupiedPalletList(Collection productIds, Collection warehouseIds, Collection areaIds); + + void regenerateCode(Long id, String code) throws UnsupportedEncodingException; +} 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..0137928b9 --- /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,205 @@ +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.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.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.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PALLET_CODE_EMPTY; +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; + @Resource + private QrcodeRecordService qrcodeService; + + @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); + generatePalletQrcode(pallet.getId(), pallet.getCode()); + 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 List getPalletList(Collection ids) { + return ids == null || ids.isEmpty() ? Collections.emptyList() : palletMapper.selectBatchIds(ids); + } + + @Override + public Map getPalletMap(Collection ids) { + return convertMap(getPalletList(ids), ErpPalletDO::getId); + } + + @Override + public PageResult getPalletPage(ErpPalletPageReqVO pageReqVO) { + return palletMapper.selectPage(pageReqVO); + } + + @Override + public List getPalletListByStatus(Integer status) { + return palletMapper.selectListByStatus(status); + } + + @Override + public List getOccupiedPalletList(Collection productIds, Collection warehouseIds, + Collection areaIds) { + return palletMapper.selectOccupiedList(productIds, warehouseIds, areaIds); + } + + @Override + public void regenerateCode(Long id, String code) throws UnsupportedEncodingException { + validatePalletExists(id); + if (StringUtils.isBlank(code)) { + throw exception(PALLET_CODE_EMPTY); + } + CodeTypeEnum codeType = autoCodeUtil.queryCodeType("PALLET_CODE_GENERATE"); + qrcodeService.regenerateByCodeType( + QrcodeBizTypeEnum.PALLET, + id, + code, + "DETAIL", + codeType.getCode() + ); + } + + 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); + } + } + + private void generatePalletQrcode(Long id, String code) { + CodeTypeEnum codeType = autoCodeUtil.queryCodeType("PALLET_CODE_GENERATE"); + if (codeType == null) { + return; + } + try { + qrcodeService.generateOrRefresh( + QrcodeBizTypeEnum.PALLET, + id, + code, + "DETAIL", + codeType + ); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } +} 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 53badaa8d..4d70b6ba6 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; @@ -29,13 +29,18 @@ import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; 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; 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; @@ -55,22 +60,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_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 @@ -98,18 +88,37 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { private AdminUserApi adminUserApi; @Resource private PermissionApi permissionApi; + @Autowired + private AutoCodeUtil autoCodeUtil; + @Resource + private ConfigApi configApi; @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) + .setNeedAudit(needAudit()) .setStatus(ErpAuditStatus.DRAFT.getStatus()) .setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add, BigDecimal.ZERO)) .setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); @@ -130,8 +139,10 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { throw exception(STOCK_CHECK_UPDATE_FAIL_PROCESS, stockCheck.getNo()); } + validateSourceType(updateReqVO.getSourceType()); List stockCheckItems = validateStockCheckItems(updateReqVO.getItems()); ErpStockCheckDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockCheckDO.class, in -> in + .setNeedAudit(needAudit()) .setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add, BigDecimal.ZERO)) .setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); stockCheckMapper.updateById(updateObj); @@ -179,15 +190,16 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { throw exception(STOCK_CHECK_SUBMIT_FAIL_STATUS); } + Integer fromStatus = stockCheck.getStatus(); Long auditUserId = submitReqVO.getAuditUserId() != null ? submitReqVO.getAuditUserId() : stockCheck.getAuditUserId(); - if (auditUserId == null) { - throw exception(STOCK_CHECK_SUBMIT_FAIL_AUDIT_USER_EMPTY); + if (auditUserId != null) { + adminUserApi.validateUser(auditUserId); } - adminUserApi.validateUser(auditUserId); - Integer fromStatus = stockCheck.getStatus(); - int updateCount = stockCheckMapper.updateByIdAndStatus(stockCheck.getId(), fromStatus, - new ErpStockCheckDO().setAuditUserId(auditUserId).setStatus(ErpAuditStatus.PROCESS.getStatus())); + ErpStockCheckDO updateObj = new ErpStockCheckDO() + .setAuditUserId(auditUserId) + .setStatus(ErpAuditStatus.PROCESS.getStatus()); + int updateCount = stockCheckMapper.updateByIdAndStatus(stockCheck.getId(), fromStatus, updateObj); if (updateCount == 0) { throw exception(STOCK_CHECK_SUBMIT_FAIL_STATUS); } @@ -200,8 +212,23 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { @Transactional(rollbackFor = Exception.class) public void auditStockCheck(ErpStockCheckAuditReqVO auditReqVO) { ErpStockCheckDO stockCheck = validateStockCheckExists(auditReqVO.getId()); - if (!ErpAuditStatus.PROCESS.getStatus().equals(stockCheck.getStatus())) { - throw exception(STOCK_CHECK_AUDIT_FAIL_STATUS); +// if (!ErpAuditStatus.PROCESS.getStatus().equals(stockCheck.getStatus())) { +// throw exception(STOCK_CHECK_AUDIT_FAIL_STATUS); +// } + + Integer fromStatus = stockCheck.getStatus(); + if (!needAudit()) { + int updateCount = stockCheckMapper.updateByIdAndStatus(stockCheck.getId(), fromStatus, + new ErpStockCheckDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus())); + if (updateCount == 0) { + throw exception(STOCK_CHECK_AUDIT_FAIL_STATUS); + } + List stockCheckItems = stockCheckItemMapper.selectListByCheckId(stockCheck.getId()); + applyStockCheckEffect(stockCheck, stockCheckItems); + createApproveRecord(stockCheck.getId(), ErpStockCheckApproveActionEnum.AUTO_APPROVE, + fromStatus, ErpAuditStatus.APPROVE.getStatus(), NumberUtils.parseLong(stockCheck.getCreator()), + auditReqVO.getRemark() != null ? auditReqVO.getRemark() : "无需审核,审核时自动盘点"); + return; } Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); @@ -214,9 +241,8 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { throw exception(STOCK_CHECK_AUDIT_FAIL_RESULT); } - Integer fromStatus = stockCheck.getStatus(); int updateCount = stockCheckMapper.updateByIdAndStatus(stockCheck.getId(), fromStatus, - new ErpStockCheckDO().setStatus(auditReqVO.getStatus())); + new ErpStockCheckDO().setNeedAudit(true).setStatus(auditReqVO.getStatus())); if (updateCount == 0) { throw exception(STOCK_CHECK_AUDIT_FAIL_STATUS); } @@ -288,10 +314,9 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { if (reqVO == null || !reqVO.validSelection()) { return Collections.emptyList(); } - List stockList = stockMapper.selectListByWarehouseIdsAndAreaIds(reqVO.getWarehouseIds(), reqVO.getAreaIds()); - if (!Boolean.TRUE.equals(reqVO.getAllowEmpty())) { - stockList = filterNonZeroStocks(stockList); - } + boolean nonZeroOnly = Boolean.FALSE.equals(reqVO.getAllowEmpty()); + List stockList = stockMapper.selectListByWarehouseIdsAndAreaIds( + reqVO.getWarehouseIds(), reqVO.getAreaIds(), nonZeroOnly, reqVO.getCategoryType()); return buildPreviewItems(stockList); } @@ -300,7 +325,9 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { if (reqVO == null || CollUtil.isEmpty(reqVO.getProductIds())) { return Collections.emptyList(); } - return buildPreviewItems(filterNonZeroStocks(stockMapper.selectListByProductIds(reqVO.getProductIds()))); + boolean nonZeroOnly = Boolean.FALSE.equals(reqVO.getAllowEmpty()); + List stockList = stockMapper.selectListByProductIds(reqVO.getProductIds(), nonZeroOnly, reqVO.getCategoryType()); + return buildPreviewItems(stockList); } private List filterNonZeroStocks(List stockList) { @@ -320,7 +347,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<>(); @@ -331,7 +359,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) { @@ -339,13 +367,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); } @@ -426,8 +451,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()) @@ -440,7 +465,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(); }); @@ -476,6 +501,10 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { .build()); } + private boolean needAudit() { + return !"0".equals(configApi.getConfigValueByCategoryAndKey("biz", "inventoryAudit")); + } + private ErpStockCheckDO validateStockCheckExists(Long id) { ErpStockCheckDO stockCheck = stockCheckMapper.selectById(id); if (stockCheck == null) { @@ -484,4 +513,11 @@ public class ErpStockCheckServiceImpl implements ErpStockCheckService { return stockCheck; } + private void validateSourceType(Integer sourceType) { + if (!ErpStockCheckSourceTypeEnum.BY_LOCATION.getType().equals(sourceType) + && !ErpStockCheckSourceTypeEnum.BY_PRODUCT.getType().equals(sourceType)) { + throw exception(STOCK_CHECK_SOURCE_TYPE_NOT_EXISTS); + } + } + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java index b040af898..2f57ce7bd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSubmit 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; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemPalletDO; import javax.validation.Valid; import java.util.Collection; @@ -37,6 +38,10 @@ public interface ErpStockInService { List getStockInItemListByInIds(Collection inIds); + List getStockInItemPalletListByInId(Long inId); + + List getStockInItemPalletListByInIds(Collection inIds); + List getStockInApproveRecordList(Long stockInId); void updateMoldStatus(Long id, Integer status); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index f17cec123..34f8feb6c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -10,19 +10,24 @@ import cn.iocoder.yudao.module.common.controller.admin.mold.vo.MoldBrandSaveReqV import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO; import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldBrandMapper; import cn.iocoder.yudao.module.common.enums.MoldBrandStatusEnum; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletStatusEnum; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInAuditReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSubmitReqVO; 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.stock.ErpStockInApproveRecordDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemPalletDO; 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.dal.mysql.pallet.ErpPalletMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInApproveRecordMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemPalletMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; @@ -49,9 +54,11 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; @@ -71,6 +78,7 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_SUBM import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_SUBMIT_FAIL_USER; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_UPDATE_FAIL_APPROVE; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_UPDATE_FAIL_PROCESS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PALLET_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; @@ -85,10 +93,14 @@ public class ErpStockInServiceImpl implements ErpStockInService { @Resource private ErpStockInItemMapper stockInItemMapper; @Resource + private ErpStockInItemPalletMapper stockInItemPalletMapper; + @Resource private ErpStockInApproveRecordMapper stockInApproveRecordMapper; @Resource private ErpStockMapper erpStockMapper; @Resource + private ErpPalletMapper palletMapper; + @Resource private ErpNoRedisDAO noRedisDAO; @Resource private ErpProductService productService; @@ -135,6 +147,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { stockInMapper.insert(stockIn); stockInItems.forEach(item -> item.setInId(stockIn.getId())); stockInItemMapper.insertBatch(stockInItems); + saveStockInItemPallets(stockIn.getId(), stockInItems, createReqVO.getItems()); if (createReqVO.getInType().equals("模具入库")){ //修改模具组状态 @@ -174,6 +187,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); stockInMapper.updateById(updateObj); updateStockInItemList(updateReqVO.getId(), stockInItems); + saveStockInItemPallets(updateReqVO.getId(), stockInItems, updateReqVO.getItems()); } @Override @@ -215,27 +229,12 @@ public class ErpStockInServiceImpl implements ErpStockInService { throw exception(STOCK_IN_SUBMIT_FAIL_STATUS); } Integer fromStatus = stockIn.getStatus(); - if (!Boolean.TRUE.equals(stockIn.getNeedAudit())) { - int updateCount = stockInMapper.updateByIdAndStatus(stockIn.getId(), fromStatus, - new ErpStockInDO().setStatus(ErpAuditStatus.APPROVE.getStatus())); - if (updateCount == 0) { - throw exception(STOCK_IN_SUBMIT_FAIL_STATUS); - } - List stockInItems = stockInItemMapper.selectListByInId(stockIn.getId()); - applyStockInEffect(stockIn, stockInItems, null); - createApproveRecord(stockIn.getId(), ErpStockInApproveActionEnum.AUTO_APPROVE, fromStatus, - ErpAuditStatus.APPROVE.getStatus(), null, - submitReqVO.getRemark() != null ? submitReqVO.getRemark() : "无需审核,提交后自动入库"); - return; - } Long auditUserId = submitReqVO.getAuditUserId() != null ? submitReqVO.getAuditUserId() : stockIn.getAuditUserId(); - if (auditUserId == null) { - throw exception(STOCK_IN_SUBMIT_FAIL_AUDIT_USER_EMPTY); + if (auditUserId != null) { + adminUserApi.validateUser(auditUserId); } - adminUserApi.validateUser(auditUserId); ErpStockInDO updateObj = new ErpStockInDO() .setAuditUserId(auditUserId) - .setNeedAudit(true) .setStatus(ErpAuditStatus.PROCESS.getStatus()); int updateCount = stockInMapper.updateByIdAndStatus(stockIn.getId(), fromStatus, updateObj); if (updateCount == 0) { @@ -249,8 +248,23 @@ public class ErpStockInServiceImpl implements ErpStockInService { @Transactional(rollbackFor = Exception.class) public void auditStockIn(ErpStockInAuditReqVO auditReqVO) { ErpStockInDO stockIn = validateStockInExists(auditReqVO.getId()); - if (!ErpAuditStatus.PROCESS.getStatus().equals(stockIn.getStatus())) { - throw exception(STOCK_IN_AUDIT_FAIL_STATUS); +// if (!ErpAuditStatus.PROCESS.getStatus().equals(stockIn.getStatus())) { +// throw exception(STOCK_IN_AUDIT_FAIL_STATUS); +// } + + Integer fromStatus = stockIn.getStatus(); + if (!needAudit()) { + int updateCount = stockInMapper.updateByIdAndStatus(stockIn.getId(), fromStatus, + new ErpStockInDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus())); + if (updateCount == 0) { + throw exception(STOCK_IN_AUDIT_FAIL_STATUS); + } + List stockInItems = stockInItemMapper.selectListByInId(stockIn.getId()); + applyStockInEffect(stockIn, stockInItems, null); + createApproveRecord(stockIn.getId(), ErpStockInApproveActionEnum.AUTO_APPROVE, fromStatus, + ErpAuditStatus.APPROVE.getStatus(), NumberUtils.parseLong(stockIn.getCreator()), + auditReqVO.getRemark() != null ? auditReqVO.getRemark() : "无需审核,审核时自动入库"); + return; } Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); boolean adminCanAudit = permissionApi.hasAnyRoles(loginUserId, RoleCodeEnum.SUPER_ADMIN.getCode()); @@ -262,9 +276,8 @@ public class ErpStockInServiceImpl implements ErpStockInService { throw exception(STOCK_IN_AUDIT_FAIL_RESULT); } - Integer fromStatus = stockIn.getStatus(); int updateCount = stockInMapper.updateByIdAndStatus(stockIn.getId(), fromStatus, - new ErpStockInDO().setStatus(auditReqVO.getStatus())); + new ErpStockInDO().setNeedAudit(true).setStatus(auditReqVO.getStatus())); if (updateCount == 0) { throw exception(STOCK_IN_AUDIT_FAIL_STATUS); } @@ -297,6 +310,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { stockIns.forEach(stockIn -> { stockInMapper.deleteById(stockIn.getId()); stockInItemMapper.deleteByInId(stockIn.getId()); + stockInItemPalletMapper.deleteByInId(stockIn.getId()); stockInApproveRecordMapper.deleteByStockInId(stockIn.getId()); }); } @@ -340,6 +354,19 @@ public class ErpStockInServiceImpl implements ErpStockInService { return stockInItemMapper.selectListByInIds(inIds); } + @Override + public List getStockInItemPalletListByInId(Long inId) { + return stockInItemPalletMapper.selectListByInId(inId); + } + + @Override + public List getStockInItemPalletListByInIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyList(); + } + return stockInItemPalletMapper.selectListByInIds(inIds); + } + @Override public List getStockInApproveRecordList(Long stockInId) { return stockInApproveRecordMapper.selectListByStockInId(stockInId); @@ -386,6 +413,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { recordBizType, stockInItem.getInId(), stockInItem.getId(), stockIn.getNo(), stockIn.getInTime())); } }); + operateStockInPalletEffect(stockIn.getId(), stockInItems, approve); } private Integer resolveRecordBizType(String inType, boolean approve, Integer bizType) { @@ -445,6 +473,8 @@ public class ErpStockInServiceImpl implements ErpStockInService { .packagingSchemeId(item.getPackagingSchemeId()) .inputUnitType(item.getInputUnitType()) .inputCount(item.getInputCount()) + .relateTask(item.getRelateTask()) + .taskId(item.getTaskId()) .totalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())) .remark(item.getRemark()) .deviceId(item.getDeviceId()) @@ -452,6 +482,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { }); } validateWarehouseAreas(list); + validatePallets(list); List productList = productService.validProductList(convertSet(list, ErpStockInSaveReqVO.Item::getProductId)); @@ -468,6 +499,20 @@ public class ErpStockInServiceImpl implements ErpStockInService { .setTotalPrice(MoneyUtils.priceMultiply(target.getProductPrice(), target.getCount())))); } + private void validatePallets(List list) { + List palletIds = convertListByFlatMap(list, item -> item.getPallets() == null ? java.util.stream.Stream.empty() + : item.getPallets().stream().map(ErpStockInSaveReqVO.Item.PalletItem::getPalletId)); + if (CollUtil.isEmpty(palletIds)) { + return; + } + Map palletMap = convertMap(palletMapper.selectBatchIds(palletIds), ErpPalletDO::getId); + palletIds.forEach(palletId -> { + if (!palletMap.containsKey(palletId)) { + throw exception(PALLET_NOT_EXISTS); + } + }); + } + private void validateWarehouseAreas(List list) { Map warehouseMap = convertMap( warehouseService.validWarehouseList(convertSet(list, ErpStockInSaveReqVO.Item::getWarehouseId)), @@ -513,4 +558,72 @@ public class ErpStockInServiceImpl implements ErpStockInService { stockInItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockInItemDO::getId)); } } + + private void saveStockInItemPallets(Long inId, List stockInItems, + List reqItems) { + stockInItemPalletMapper.deleteByInId(inId); + if (CollUtil.isEmpty(stockInItems) || CollUtil.isEmpty(reqItems)) { + return; + } + List palletRelations = CollUtil.newArrayList(); + for (int i = 0; i < Math.min(stockInItems.size(), reqItems.size()); i++) { + ErpStockInItemDO stockInItem = stockInItems.get(i); + ErpStockInSaveReqVO.Item reqItem = reqItems.get(i); + if (stockInItem.getId() == null || CollUtil.isEmpty(reqItem.getPallets())) { + continue; + } + reqItem.getPallets().forEach(pallet -> palletRelations.add(ErpStockInItemPalletDO.builder() + .inId(inId) + .inItemId(stockInItem.getId()) + .palletId(pallet.getPalletId()) + .packageCount(defaultPackageCount(pallet.getPackageCount(), stockInItem.getCount())) + .build())); + } + if (CollUtil.isNotEmpty(palletRelations)) { + stockInItemPalletMapper.insertBatch(palletRelations); + } + } + + private void operateStockInPalletEffect(Long inId, List stockInItems, boolean approve) { + List palletRelations = stockInItemPalletMapper.selectListByInId(inId); + if (CollUtil.isEmpty(palletRelations)) { + return; + } + Map itemMap = convertMap(stockInItems, ErpStockInItemDO::getId); + Map palletMap = convertMap(palletMapper.selectBatchIds( + convertSet(palletRelations, ErpStockInItemPalletDO::getPalletId)), ErpPalletDO::getId); + palletRelations.forEach(relation -> { + ErpStockInItemDO item = itemMap.get(relation.getInItemId()); + ErpPalletDO pallet = palletMap.get(relation.getPalletId()); + if (item == null || pallet == null) { + return; + } + BigDecimal packageCount = defaultZero(relation.getPackageCount()); + if (approve) { + pallet.setStatus(ErpPalletStatusEnum.OCCUPIED.getStatus()); + pallet.setProductId(item.getProductId()); + pallet.setProductCount(defaultZero(pallet.getProductCount()).add(packageCount)); + pallet.setWarehouseId(item.getWarehouseId()); + pallet.setAreaId(item.getAreaId()); + } else { + BigDecimal remainCount = defaultZero(pallet.getProductCount()).subtract(packageCount); + if (remainCount.compareTo(BigDecimal.ZERO) <= 0) { + pallet.setStatus(ErpPalletStatusEnum.IDLE.getStatus()); + pallet.setProductId(null); + pallet.setProductCount(BigDecimal.ZERO); + } else { + pallet.setProductCount(remainCount); + } + } + palletMapper.updateById(pallet); + }); + } + + private BigDecimal defaultPackageCount(BigDecimal packageCount, BigDecimal itemCount) { + return packageCount != null ? packageCount : defaultZero(itemCount); + } + + private BigDecimal defaultZero(BigDecimal value) { + return value != null ? value : BigDecimal.ZERO; + } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java index da07fd9ad..4aba89c84 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSave import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemPalletDO; import javax.validation.Valid; import java.util.Collection; @@ -90,6 +91,10 @@ public interface ErpStockOutService { */ List getStockOutItemListByOutIds(Collection outIds); + List getStockOutItemPalletListByOutId(Long outId); + + List getStockOutItemPalletListByOutIds(Collection outIds); + List getStockOutApproveRecordList(Long stockOutId); List selectByOutType(List outTypes); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java index 415b7d583..2b097c11d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -10,20 +10,25 @@ import cn.iocoder.yudao.module.common.controller.admin.mold.vo.MoldBrandSaveReqV import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO; import cn.iocoder.yudao.module.common.dal.mysql.mold.MoldBrandMapper; import cn.iocoder.yudao.module.common.enums.MoldBrandStatusEnum; +import cn.iocoder.yudao.module.erp.controller.admin.pallet.enums.ErpPalletStatusEnum; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutAuditReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVOItem; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSubmitReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.pallet.ErpPalletDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemPalletDO; 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.dal.mysql.pallet.ErpPalletMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutApproveRecordMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemPalletMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutMapper; import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; @@ -58,6 +63,7 @@ import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; @@ -79,8 +85,12 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { @Resource private ErpStockOutItemMapper stockOutItemMapper; @Resource + private ErpStockOutItemPalletMapper stockOutItemPalletMapper; + @Resource private ErpStockOutApproveRecordMapper stockOutApproveRecordMapper; @Resource + private ErpPalletMapper palletMapper; + @Resource private ErpNoRedisDAO noRedisDAO; @Resource private ErpProductService productService; @@ -137,6 +147,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { stockOutMapper.insert(stockOut); stockOutItems.forEach(item -> item.setOutId(stockOut.getId())); stockOutItemMapper.insertBatch(stockOutItems); + saveStockOutItemPallets(stockOut.getId(), stockOutItems, createReqVO.getItems()); if (createReqVO.getOutType().equals("模具出库")) { //修改模具组状态 @@ -179,6 +190,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { fillUsageSnapshot(stockOutItems, updateReqVO.getItems()); stockOutMapper.updateById(updateObj); updateStockOutItemList(updateReqVO.getId(), stockOutItems); + saveStockOutItemPallets(updateReqVO.getId(), stockOutItems, updateReqVO.getItems()); } @Override @@ -220,27 +232,12 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { throw exception(STOCK_OUT_SUBMIT_FAIL_STATUS); } Integer fromStatus = stockOut.getStatus(); - if (!Boolean.TRUE.equals(stockOut.getNeedAudit())) { - int updateCount = stockOutMapper.updateByIdAndStatus(stockOut.getId(), fromStatus, - new ErpStockOutDO().setStatus(ErpAuditStatus.APPROVE.getStatus())); - if (updateCount == 0) { - throw exception(STOCK_OUT_SUBMIT_FAIL_STATUS); - } - List stockOutItems = stockOutItemMapper.selectListByOutId(stockOut.getId()); - applyStockOutEffect(stockOut, stockOutItems, null); - createApproveRecord(stockOut.getId(), ErpStockOutApproveActionEnum.AUTO_APPROVE, fromStatus, - ErpAuditStatus.APPROVE.getStatus(), null, - submitReqVO.getRemark() != null ? submitReqVO.getRemark() : "无需审核,提交后自动出库"); - return; - } Long auditUserId = submitReqVO.getAuditUserId() != null ? submitReqVO.getAuditUserId() : stockOut.getAuditUserId(); - if (auditUserId == null) { - throw exception(STOCK_OUT_SUBMIT_FAIL_AUDIT_USER_EMPTY); + if (auditUserId != null) { + adminUserApi.validateUser(auditUserId); } - adminUserApi.validateUser(auditUserId); ErpStockOutDO updateObj = new ErpStockOutDO() .setAuditUserId(auditUserId) - .setNeedAudit(true) .setStatus(ErpAuditStatus.PROCESS.getStatus()); int updateCount = stockOutMapper.updateByIdAndStatus(stockOut.getId(), fromStatus, updateObj); if (updateCount == 0) { @@ -254,8 +251,23 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { @Transactional(rollbackFor = Exception.class) public void auditStockOut(ErpStockOutAuditReqVO auditReqVO) { ErpStockOutDO stockOut = validateStockOutExists(auditReqVO.getId()); - if (!ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) { - throw exception(STOCK_OUT_AUDIT_FAIL_STATUS); +// if (!ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) { +// throw exception(STOCK_OUT_AUDIT_FAIL_STATUS); +// } + + Integer fromStatus = stockOut.getStatus(); + if (!needAudit()) { + int updateCount = stockOutMapper.updateByIdAndStatus(stockOut.getId(), fromStatus, + new ErpStockOutDO().setNeedAudit(false).setStatus(ErpAuditStatus.APPROVE.getStatus())); + if (updateCount == 0) { + throw exception(STOCK_OUT_AUDIT_FAIL_STATUS); + } + List stockOutItems = stockOutItemMapper.selectListByOutId(stockOut.getId()); + applyStockOutEffect(stockOut, stockOutItems, null); + createApproveRecord(stockOut.getId(), ErpStockOutApproveActionEnum.AUTO_APPROVE, fromStatus, + ErpAuditStatus.APPROVE.getStatus(), NumberUtils.parseLong(stockOut.getCreator()), + auditReqVO.getRemark() != null ? auditReqVO.getRemark() : "无需审核,审核时自动出库"); + return; } Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); @@ -270,9 +282,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { throw exception(STOCK_OUT_AUDIT_FAIL_RESULT); } - Integer fromStatus = stockOut.getStatus(); int updateCount = stockOutMapper.updateByIdAndStatus(stockOut.getId(), fromStatus, - new ErpStockOutDO().setStatus(auditReqVO.getStatus())); + new ErpStockOutDO().setNeedAudit(true).setStatus(auditReqVO.getStatus())); if (updateCount == 0) { throw exception(STOCK_OUT_AUDIT_FAIL_STATUS); } @@ -305,6 +316,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { stockOuts.forEach(stockOut -> { stockOutMapper.deleteById(stockOut.getId()); stockOutItemMapper.deleteByOutId(stockOut.getId()); + stockOutItemPalletMapper.deleteByOutId(stockOut.getId()); stockOutApproveRecordMapper.deleteByStockOutId(stockOut.getId()); }); } @@ -340,6 +352,19 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { return stockOutItemMapper.selectListByOutIds(outIds); } + @Override + public List getStockOutItemPalletListByOutId(Long outId) { + return stockOutItemPalletMapper.selectListByOutId(outId); + } + + @Override + public List getStockOutItemPalletListByOutIds(Collection outIds) { + if (CollUtil.isEmpty(outIds)) { + return Collections.emptyList(); + } + return stockOutItemPalletMapper.selectListByOutIds(outIds); + } + @Override public List getStockOutApproveRecordList(Long stockOutId) { return stockOutApproveRecordMapper.selectListByStockOutId(stockOutId); @@ -401,6 +426,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { recordBizType, stockOutItem.getOutId(), stockOutItem.getId(), stockOut.getNo(), stockOut.getOutTime())); } }); + operateStockOutPalletEffect(stockOut.getId(), stockOutItems, approve); } private boolean itemNeedUpdateMoldStatus(MoldBrandDO moldDO) { @@ -477,6 +503,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { .productUnitId(null) .productPrice(item.getProductPrice()) .count(item.getCount()) + .outMode(item.getOutMode()) .totalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())) .outUsageType(item.getOutUsageType()) .outUsageTypeName(ErpStockOutUsageTypeEnum.getNameByType(item.getOutUsageType())) @@ -487,6 +514,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { .build(); }); } + validatePallets(list); List productList = productService.validProductList(convertSet(list, ErpStockOutSaveReqVOItem::getProductId)); Map productMap = convertMap(productList, ErpProductDO::getId); Map areaMap = warehouseAreaService.getWarehouseAreaMap( @@ -505,6 +533,20 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { .setMaintenanceName(null))); } + private void validatePallets(List list) { + List palletIds = convertListByFlatMap(list, item -> item.getPallets() == null ? java.util.stream.Stream.empty() + : item.getPallets().stream().map(ErpStockOutSaveReqVOItem.PalletItem::getPalletId)); + if (CollUtil.isEmpty(palletIds)) { + return; + } + Map palletMap = convertMap(palletMapper.selectBatchIds(palletIds), ErpPalletDO::getId); + palletIds.forEach(palletId -> { + if (!palletMap.containsKey(palletId)) { + throw exception(PALLET_NOT_EXISTS); + } + }); + } + private void validateWarehouseAreas(List list) { Map warehouseMap = convertMap( warehouseService.validWarehouseList(convertSet(list, ErpStockOutSaveReqVOItem::getWarehouseId)), @@ -553,4 +595,72 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { } } + private void saveStockOutItemPallets(Long outId, List stockOutItems, + List reqItems) { + stockOutItemPalletMapper.deleteByOutId(outId); + if (CollUtil.isEmpty(stockOutItems) || CollUtil.isEmpty(reqItems)) { + return; + } + List palletRelations = CollUtil.newArrayList(); + for (int i = 0; i < Math.min(stockOutItems.size(), reqItems.size()); i++) { + ErpStockOutItemDO stockOutItem = stockOutItems.get(i); + ErpStockOutSaveReqVOItem reqItem = reqItems.get(i); + if (stockOutItem.getId() == null || CollUtil.isEmpty(reqItem.getPallets())) { + continue; + } + reqItem.getPallets().forEach(pallet -> palletRelations.add(ErpStockOutItemPalletDO.builder() + .outId(outId) + .outItemId(stockOutItem.getId()) + .palletId(pallet.getPalletId()) + .packageCount(defaultPackageCount(pallet.getPackageCount(), stockOutItem.getCount())) + .build())); + } + if (CollUtil.isNotEmpty(palletRelations)) { + stockOutItemPalletMapper.insertBatch(palletRelations); + } + } + + private void operateStockOutPalletEffect(Long outId, List stockOutItems, boolean approve) { + List palletRelations = stockOutItemPalletMapper.selectListByOutId(outId); + if (CollUtil.isEmpty(palletRelations)) { + return; + } + Map itemMap = convertMap(stockOutItems, ErpStockOutItemDO::getId); + Map palletMap = convertMap(palletMapper.selectBatchIds( + convertSet(palletRelations, ErpStockOutItemPalletDO::getPalletId)), ErpPalletDO::getId); + palletRelations.forEach(relation -> { + ErpStockOutItemDO item = itemMap.get(relation.getOutItemId()); + ErpPalletDO pallet = palletMap.get(relation.getPalletId()); + if (item == null || pallet == null) { + return; + } + BigDecimal packageCount = defaultZero(relation.getPackageCount()); + if (approve) { + BigDecimal remainCount = defaultZero(pallet.getProductCount()).subtract(packageCount); + if (remainCount.compareTo(BigDecimal.ZERO) <= 0) { + pallet.setStatus(ErpPalletStatusEnum.IDLE.getStatus()); + pallet.setProductId(null); + pallet.setProductCount(BigDecimal.ZERO); + } else { + pallet.setProductCount(remainCount); + } + } else { + pallet.setStatus(ErpPalletStatusEnum.OCCUPIED.getStatus()); + pallet.setProductId(item.getProductId()); + pallet.setProductCount(defaultZero(pallet.getProductCount()).add(packageCount)); + pallet.setWarehouseId(item.getWarehouseId()); + pallet.setAreaId(item.getAreaId()); + } + palletMapper.updateById(pallet); + }); + } + + private BigDecimal defaultPackageCount(BigDecimal packageCount, BigDecimal itemCount) { + return packageCount != null ? packageCount : defaultZero(itemCount); + } + + private BigDecimal defaultZero(BigDecimal value) { + return value != null ? value : BigDecimal.ZERO; + } + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java index 0d514cabb..5271a804b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java @@ -75,7 +75,7 @@ public interface ErpWarehouseService { * @param status 状态 * @return 仓库列表 */ - List getWarehouseListByStatus(Integer status); + List getWarehouseListByStatus(Integer status, Integer categoryType); /** * 获得仓库列表 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java index 10eade2f5..38e377f63 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java @@ -128,8 +128,8 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService { } @Override - public List getWarehouseListByStatus(Integer status) { - return warehouseMapper.selectListByStatus(status); + public List getWarehouseListByStatus(Integer status, Integer categoryType) { + return warehouseMapper.selectListByStatus(status, categoryType); } @Override diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseSummaryService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseSummaryService.java new file mode 100644 index 000000000..fc0bde160 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseSummaryService.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSummaryRespVO; + +public interface ErpWarehouseSummaryService { + + ErpWarehouseSummaryRespVO getWarehouseSummary(Long warehouseId); + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseSummaryServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseSummaryServiceImpl.java new file mode 100644 index 000000000..c9ac20c6d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseSummaryServiceImpl.java @@ -0,0 +1,261 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSummaryRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutMapper; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@Service +@Validated +public class ErpWarehouseSummaryServiceImpl implements ErpWarehouseSummaryService { + + @Resource + private ErpWarehouseService warehouseService; + @Resource + private ErpStockMapper stockMapper; + @Resource + private ErpStockInMapper stockInMapper; + @Resource + private ErpStockInItemMapper stockInItemMapper; + @Resource + private ErpStockOutMapper stockOutMapper; + @Resource + private ErpStockOutItemMapper stockOutItemMapper; + @Resource + private ErpProductService productService; + + @Override + public ErpWarehouseSummaryRespVO getWarehouseSummary(Long warehouseId) { + ErpWarehouseDO warehouse = warehouseService.getWarehouse(warehouseId); + ErpWarehouseSummaryRespVO respVO = new ErpWarehouseSummaryRespVO(); + respVO.setWarehouseId(warehouseId); + respVO.setWarehouseName(warehouse != null ? warehouse.getName() : null); + + List stockList = stockMapper.selectListByWarehouseIdsAndAreaIds(Collections.singletonList(warehouseId), null); + fillStockSummary(respVO, stockList); + + LocalDateTime beginTime = LocalDate.now().atStartOfDay(); + LocalDateTime endTime = beginTime.plusDays(1); + fillTodayInSummary(respVO, warehouseId, beginTime, endTime); + fillTodayOutSummary(respVO, warehouseId, beginTime, endTime); + return respVO; + } + + private void fillStockSummary(ErpWarehouseSummaryRespVO respVO, List stockList) { + if (CollUtil.isEmpty(stockList)) { + respVO.setProductStockCount(BigDecimal.ZERO); + respVO.setMaterialStockCount(BigDecimal.ZERO); + respVO.setSparePartStockCount(BigDecimal.ZERO); + respVO.setProductStockDisplay(formatProductDisplay(BigDecimal.ZERO, null, null, null)); + respVO.setMaterialStockDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null)); + respVO.setSparePartStockDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null)); + return; + } + + Map> categoryMap = stockList.stream().collect(Collectors.groupingBy(this::resolveCategoryType)); + BigDecimal productCount = sumCount(categoryMap.get(1)); + BigDecimal materialCount = sumCount(categoryMap.get(2)); + BigDecimal sparePartCount = sumCount(categoryMap.get(3)); + + respVO.setProductStockCount(productCount); + respVO.setMaterialStockCount(materialCount); + respVO.setSparePartStockCount(sparePartCount); + + ErpStockDO productStock = firstStock(categoryMap.get(1)); + ErpStockDO materialStock = firstStock(categoryMap.get(2)); + ErpStockDO sparePartStock = firstStock(categoryMap.get(3)); + respVO.setProductStockDisplay(formatProductDisplay(productCount, + productStock != null ? productStock.getPalletTotalQuantity() : null, + productStock != null ? productStock.getPalletPackageQuantity() : null, + productStock != null ? productStock.getPackageQuantity() : null)); + respVO.setMaterialStockDisplay(formatUnitDisplay(materialCount, + materialStock != null ? materialStock.getPurchaseUnitConvertQuantity() : null, + materialStock != null ? materialStock.getPurchaseUnitName() : null, + materialStock != null ? materialStock.getUnitName() : null)); + respVO.setSparePartStockDisplay(formatUnitDisplay(sparePartCount, + sparePartStock != null ? sparePartStock.getPurchaseUnitConvertQuantity() : null, + sparePartStock != null ? sparePartStock.getPurchaseUnitName() : null, + sparePartStock != null ? sparePartStock.getUnitName() : null)); + } + + private void fillTodayInSummary(ErpWarehouseSummaryRespVO respVO, Long warehouseId, LocalDateTime beginTime, LocalDateTime endTime) { + List stockInList = stockInMapper.selectList(new LambdaQueryWrapper() + .eq(ErpStockInDO::getStatus, 20) + .between(ErpStockInDO::getInTime, beginTime, endTime)); + List inIds = stockInList.stream() + .filter(stockIn -> hasWarehouseIn(stockIn.getId(), warehouseId)) + .map(ErpStockInDO::getId) + .collect(Collectors.toList()); + respVO.setTodayStockInOrderCount((long) inIds.size()); + + List itemList = stockInItemMapper.selectListByInIds(inIds); + respVO.setTodayStockInItemCount((long) itemList.size()); + fillInOutDisplay(respVO, true, itemList); + } + + private void fillTodayOutSummary(ErpWarehouseSummaryRespVO respVO, Long warehouseId, LocalDateTime beginTime, LocalDateTime endTime) { + List stockOutList = stockOutMapper.selectList(new LambdaQueryWrapper() + .eq(ErpStockOutDO::getStatus, 20) + .between(ErpStockOutDO::getOutTime, beginTime, endTime)); + List outIds = stockOutList.stream() + .filter(stockOut -> hasWarehouseOut(stockOut.getId(), warehouseId)) + .map(ErpStockOutDO::getId) + .collect(Collectors.toList()); + respVO.setTodayStockOutOrderCount((long) outIds.size()); + + List itemList = stockOutItemMapper.selectListByOutIds(outIds); + respVO.setTodayStockOutItemCount((long) itemList.size()); + fillInOutDisplay(respVO, false, itemList); + } + + private void fillInOutDisplay(ErpWarehouseSummaryRespVO respVO, boolean inbound, List itemList) { + if (CollUtil.isEmpty(itemList)) { + if (inbound) { + respVO.setTodayProductStockInDisplay(formatProductDisplay(BigDecimal.ZERO, null, null, null)); + respVO.setTodayMaterialStockInDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null)); + respVO.setTodaySparePartStockInDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null)); + } else { + respVO.setTodayProductStockOutDisplay(formatProductDisplay(BigDecimal.ZERO, null, null, null)); + respVO.setTodayMaterialStockOutDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null)); + respVO.setTodaySparePartStockOutDisplay(formatUnitDisplay(BigDecimal.ZERO, null, null, null)); + } + return; + } + + Set productIds = itemList.stream() + .map(item -> item instanceof ErpStockInItemDO ? ((ErpStockInItemDO) item).getProductId() : ((ErpStockOutItemDO) item).getProductId()) + .collect(Collectors.toSet()); + Map productMap = productService.getProductVOMap(productIds); + + BigDecimal productCount = BigDecimal.ZERO; + BigDecimal materialCount = BigDecimal.ZERO; + BigDecimal sparePartCount = BigDecimal.ZERO; + + for (Object item : itemList) { + Long productId = item instanceof ErpStockInItemDO ? ((ErpStockInItemDO) item).getProductId() : ((ErpStockOutItemDO) item).getProductId(); + BigDecimal count = item instanceof ErpStockInItemDO ? ((ErpStockInItemDO) item).getCount() : ((ErpStockOutItemDO) item).getCount(); + ErpProductRespVO product = productMap.get(productId); + Integer categoryType = product != null ? product.getCategoryType() : null; + if (Integer.valueOf(1).equals(categoryType)) { + productCount = productCount.add(safeCount(count)); + } else if (Integer.valueOf(2).equals(categoryType)) { + materialCount = materialCount.add(safeCount(count)); + } else if (Integer.valueOf(3).equals(categoryType)) { + sparePartCount = sparePartCount.add(safeCount(count)); + } + } + + if (inbound) { + respVO.setTodayProductStockInDisplay(formatProductDisplay(productCount, null, null, null)); + respVO.setTodayMaterialStockInDisplay(formatUnitDisplay(materialCount, null, null, null)); + respVO.setTodaySparePartStockInDisplay(formatUnitDisplay(sparePartCount, null, null, null)); + } else { + respVO.setTodayProductStockOutDisplay(formatProductDisplay(productCount, null, null, null)); + respVO.setTodayMaterialStockOutDisplay(formatUnitDisplay(materialCount, null, null, null)); + respVO.setTodaySparePartStockOutDisplay(formatUnitDisplay(sparePartCount, null, null, null)); + } + } + + private boolean hasWarehouseIn(Long inId, Long warehouseId) { + return stockInItemMapper.selectListByInId(inId).stream().anyMatch(item -> warehouseId.equals(item.getWarehouseId())); + } + + private boolean hasWarehouseOut(Long outId, Long warehouseId) { + return stockOutItemMapper.selectListByOutId(outId).stream().anyMatch(item -> warehouseId.equals(item.getWarehouseId())); + } + + private Integer resolveCategoryType(ErpStockDO stock) { + if (stock.getCategoryType() != null) { + return stock.getCategoryType(); + } + ErpProductRespVO product = productService.getProductVOMap(Collections.singleton(stock.getProductId())).get(stock.getProductId()); + return product != null ? product.getCategoryType() : null; + } + + private ErpStockDO firstStock(List list) { + return CollUtil.isEmpty(list) ? null : list.get(0); + } + + private BigDecimal sumCount(List list) { + if (CollUtil.isEmpty(list)) { + return BigDecimal.ZERO; + } + BigDecimal total = BigDecimal.ZERO; + for (ErpStockDO stock : list) { + total = total.add(safeCount(stock.getCount())); + } + return total; + } + + private BigDecimal safeCount(BigDecimal count) { + return count == null ? BigDecimal.ZERO : count; + } + + private String formatProductDisplay(BigDecimal count, BigDecimal palletTotalQuantity, BigDecimal palletPackageQuantity, + BigDecimal packageQuantity) { + BigDecimal safeCount = safeCount(count); + if (palletTotalQuantity == null || palletTotalQuantity.compareTo(BigDecimal.ZERO) <= 0) { + return formatNumber(safeCount) + "个"; + } + BigDecimal palletCount = safeCount.divideToIntegralValue(palletTotalQuantity); + BigDecimal remainAfterPallet = safeCount.remainder(palletTotalQuantity); + if (palletPackageQuantity == null || palletPackageQuantity.compareTo(BigDecimal.ZERO) <= 0) { + return formatNumber(palletCount) + "托" + formatNumber(remainAfterPallet) + "个"; + } + BigDecimal packageCount = remainAfterPallet.divideToIntegralValue(palletPackageQuantity); + BigDecimal remainAfterPackage = remainAfterPallet.remainder(palletPackageQuantity); + if (packageQuantity == null || packageQuantity.compareTo(BigDecimal.ZERO) <= 0) { + return formatNumber(palletCount) + "托" + formatNumber(packageCount) + "包" + formatNumber(remainAfterPackage) + "个"; + } + BigDecimal unitCount = remainAfterPackage.divideToIntegralValue(packageQuantity); + return formatNumber(palletCount) + "托" + formatNumber(packageCount) + "包" + formatNumber(unitCount) + "个"; + } + + private String formatUnitDisplay(BigDecimal count, BigDecimal purchaseUnitConvertQuantity, String purchaseUnitName, String unitName) { + BigDecimal safeCount = safeCount(count); + if (purchaseUnitConvertQuantity == null || purchaseUnitConvertQuantity.compareTo(BigDecimal.ZERO) <= 0 + || purchaseUnitName == null || unitName == null) { + return formatNumber(safeCount) + (unitName != null ? unitName : "个"); + } + BigDecimal purchaseCount = safeCount.divideToIntegralValue(purchaseUnitConvertQuantity); + BigDecimal unitCount = safeCount.remainder(purchaseUnitConvertQuantity); + StringBuilder display = new StringBuilder(); + if (purchaseCount.compareTo(BigDecimal.ZERO) > 0) { + display.append(formatNumber(purchaseCount)).append(purchaseUnitName); + } + if (unitCount.compareTo(BigDecimal.ZERO) > 0 || display.length() == 0) { + display.append(formatNumber(unitCount)).append(unitName); + } + return display.toString(); + } + + private String formatNumber(BigDecimal value) { + return value == null ? "0" : value.stripTrailingZeros().toPlainString(); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/TaskController.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/TaskController.java index 3a305589a..cf9674a11 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/TaskController.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/TaskController.java @@ -216,6 +216,16 @@ public class TaskController { public CommonResult> getTaskDetailListByTaskId(@RequestParam("taskId") Long taskId) { return success(taskService.buildDetailVOList(taskService.getTaskDetailListByTaskId(taskId))); } + + @GetMapping("/task-detail/default-packaging-schemes") + @Operation(summary = "获得生产任务单明细产品默认包装方案列表") + @Parameter(name = "taskId", description = "task ID", required = true) + @PreAuthorize("@ss.hasPermission('mes:task:query')") + public CommonResult getTaskProductDefaultPackagingSchemes( + @RequestParam("taskId") Long taskId) { + return success(taskService.getTaskProductDefaultPackagingSchemes(taskId)); + } + // ==================== 子表(生产任务单明细) ==================== @GetMapping("/task-detail/page") @@ -266,4 +276,4 @@ public class TaskController { public CommonResult> getTaskDetailSummary(@RequestParam("taskId") Long taskId) { return success(taskService.getTaskProductSummaryList(taskId)); } -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskPackagingSchemeRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskPackagingSchemeRespVO.java new file mode 100644 index 000000000..16b2346bf --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskPackagingSchemeRespVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.mes.controller.admin.task.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - 生产任务单默认包装方案 Response VO") +@Data +public class TaskPackagingSchemeRespVO { + + @Schema(description = "任务单 ID", example = "1") + private Long taskId; + + @Schema(description = "任务单名称", example = "RW20240618001") + private String taskName; + + @Schema(description = "产品默认包装方案列表") + private List products; + +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskProductPackagingSchemeRespVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskProductPackagingSchemeRespVO.java new file mode 100644 index 000000000..da5647607 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/task/vo/TaskProductPackagingSchemeRespVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.mes.controller.admin.task.vo; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +@Schema(description = "管理后台 - 生产任务单产品默认包装方案 Response VO") +@Data +public class TaskProductPackagingSchemeRespVO { + + @Schema(description = "产品 ID", example = "1") + private Long productId; + + @Schema(description = "产品编码", example = "CP001") + private String productCode; + + @Schema(description = "产品名称", example = "产品A") + private String productName; + + @Schema(description = "任务明细 ID 列表") + private List taskDetailIds; + + @Schema(description = "默认包装方案列表") + private List packagingSchemes; + +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/vo/TicketManagementPageReqVO.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/vo/TicketManagementPageReqVO.java index 230f2db2f..741a1eead 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/vo/TicketManagementPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/ticketmanagement/vo/TicketManagementPageReqVO.java @@ -65,6 +65,9 @@ public class TicketManagementPageReqVO extends PageParam { @Schema(description = "设备集合", example = "6979") private List machineryNames; + @Schema(description = "设备 ID", example = "6979") + private Long deviceId; + @Schema(description = "产线") private String deviceLineId; -} \ No newline at end of file +} diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskService.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskService.java index a13f4e298..40b39d2c0 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskService.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskService.java @@ -96,6 +96,7 @@ public interface TaskService { */ List getTaskDetailListByTaskId(Long taskId); List buildDetailVOList(List list); + TaskPackagingSchemeRespVO getTaskProductDefaultPackagingSchemes(Long taskId); /** * 获得生产任务单明细分页 * diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java index 83c66d602..713bf103e 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/task/TaskServiceImpl.java @@ -6,12 +6,15 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPackagingSchemeRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductRelationRespVO; 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.dal.dataobject.productdevicerel.ProductDeviceRelDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.productpackagingschemerel.ProductPackagingSchemeRelDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; import cn.iocoder.yudao.module.erp.dal.mysql.productdevicerel.ProductDeviceRelMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.productpackagingschemerel.ProductPackagingSchemeRelMapper; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; import cn.iocoder.yudao.module.iot.dal.dataobject.device.DeviceDO; @@ -97,6 +100,8 @@ public class TaskServiceImpl implements TaskService { @Resource private ProductDeviceRelMapper productDeviceRelMapper; + @Resource + private ProductPackagingSchemeRelMapper productPackagingSchemeRelMapper; @Resource private DeviceLedgerService deviceLedgerService; @@ -258,6 +263,42 @@ public class TaskServiceImpl implements TaskService { return taskDetailMapper.selectListByTaskId(taskId); } + @Override + public TaskPackagingSchemeRespVO getTaskProductDefaultPackagingSchemes(Long taskId) { + TaskDO task = getTask(taskId); + TaskPackagingSchemeRespVO result = new TaskPackagingSchemeRespVO(); + result.setTaskId(taskId); + result.setTaskName(task == null ? null : task.getCode()); + List details = getTaskDetailListByTaskId(taskId); + if (CollUtil.isEmpty(details)) { + result.setProducts(Collections.emptyList()); + return result; + } + Set productIds = convertSet(details, TaskDetailDO::getProductId); + Map productMap = productService.getProductMap(productIds); + Map> taskDetailIdMap = details.stream() + .filter(item -> item.getProductId() != null) + .collect(Collectors.groupingBy(TaskDetailDO::getProductId, + Collectors.mapping(TaskDetailDO::getId, Collectors.toList()))); + Map> packagingSchemeMap = productPackagingSchemeRelMapper + .selectListByProductIds(productIds).stream() + .filter(item -> Integer.valueOf(1).equals(item.getDefaultStatus())) + .collect(Collectors.groupingBy(ProductPackagingSchemeRelDO::getProductId, + Collectors.mapping(item -> BeanUtils.toBean(item, ProductPackagingSchemeRespVO.class), + Collectors.toList()))); + result.setProducts(productIds.stream().map(productId -> { + ErpProductDO product = productMap.get(productId); + TaskProductPackagingSchemeRespVO respVO = new TaskProductPackagingSchemeRespVO(); + respVO.setProductId(productId); + respVO.setProductCode(product == null ? null : product.getBarCode()); + respVO.setProductName(product == null ? null : product.getName()); + respVO.setTaskDetailIds(taskDetailIdMap.getOrDefault(productId, Collections.emptyList())); + respVO.setPackagingSchemes(packagingSchemeMap.getOrDefault(productId, Collections.emptyList())); + return respVO; + }).collect(Collectors.toList())); + return result; + } + private void createTaskDetailList(Long taskId, List list) { list.forEach(o -> o.setTaskId(taskId)); taskDetailMapper.insertBatch(list); diff --git a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementServiceImpl.java b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementServiceImpl.java index 49526878e..7fcbfc5c3 100644 --- a/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-biz/src/main/java/cn/iocoder/yudao/module/mes/service/ticketmanagement/TicketManagementServiceImpl.java @@ -93,7 +93,17 @@ public class TicketManagementServiceImpl implements TicketManagementService { @Override public PageResult getTicketManagementPage(TicketManagementPageReqVO pageReqVO) { - if(StringUtils.isNotBlank(pageReqVO.getDeviceLineId())||StringUtils.isNotBlank(pageReqVO.getPlanNo())) { + if (pageReqVO.getDeviceId() != null) { + pageReqVO.setPlanNo(null); + DeviceLedgerDO deviceLedgerDO = deviceLedgerMapper.selectById(pageReqVO.getDeviceId()); + if (deviceLedgerDO != null + && StringUtils.isNotBlank(deviceLedgerDO.getDeviceName()) + && matchesDeviceLine(deviceLedgerDO, pageReqVO.getDeviceLineId())) { + pageReqVO.setMachineryNames(Collections.singletonList(deviceLedgerDO.getDeviceName())); + } else { + pageReqVO.setMachineryNames(emptyResultMachineryNames()); + } + } else if(StringUtils.isNotBlank(pageReqVO.getDeviceLineId())||StringUtils.isNotBlank(pageReqVO.getPlanNo())) { LambdaQueryWrapperX deviceLedgerDOLambdaQueryWrapperX = new LambdaQueryWrapperX<>(); if(StringUtils.isNotBlank(pageReqVO.getDeviceLineId())) deviceLedgerDOLambdaQueryWrapperX.eqIfPresent(DeviceLedgerDO::getDeviceLine, pageReqVO.getDeviceLineId()); @@ -109,15 +119,23 @@ public class TicketManagementServiceImpl implements TicketManagementService { if(CollUtil.isNotEmpty(machineryNames)){ pageReqVO.setMachineryNames(machineryNames); }else { - List objects = new ArrayList<>(); - objects.add("adsaf"); - pageReqVO.setMachineryNames(objects); + pageReqVO.setMachineryNames(emptyResultMachineryNames()); } } return ticketManagementMapper.selectPage(pageReqVO); } + private boolean matchesDeviceLine(DeviceLedgerDO deviceLedgerDO, String deviceLineId) { + return StringUtils.isBlank(deviceLineId) + || (deviceLedgerDO.getDeviceLine() != null + && Objects.equals(String.valueOf(deviceLedgerDO.getDeviceLine()), deviceLineId)); + } + + private List emptyResultMachineryNames() { + return Collections.singletonList("adsaf"); + } + @Override @Transactional(rollbackFor = Exception.class) public void batchUpdateJobStatus(TicketManagementBatchUpdateReqVO reqVO) {