Commit 93607eb9238f210b5cd3cac5da679f3c621b55b2
1 parent
eba504d0
feat(wms):新增出库管理
Showing
28 changed files
with
1724 additions
and
4 deletions
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/inventory/vo/detail/WmsInventoryDetailPageReqVO.java
| ... | ... | @@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode; |
| 7 | 7 | import lombok.ToString; |
| 8 | 8 | import org.springframework.format.annotation.DateTimeFormat; |
| 9 | 9 | |
| 10 | +import java.math.BigDecimal; | |
| 10 | 11 | import java.time.LocalDateTime; |
| 11 | 12 | |
| 12 | 13 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; |
| ... | ... | @@ -53,6 +54,9 @@ public class WmsInventoryDetailPageReqVO extends PageParam { |
| 53 | 54 | @Schema(description = "批号", example = "BATCH001") |
| 54 | 55 | private String batchNo; |
| 55 | 56 | |
| 57 | + @Schema(description = "最小剩余库存数量", example = "0.01") | |
| 58 | + private BigDecimal minRemainQuantity; | |
| 59 | + | |
| 56 | 60 | @Schema(description = "距离过期天数", example = "30") |
| 57 | 61 | private Integer daysToExpires; |
| 58 | 62 | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/WmsShipmentOrderController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.order.shipment; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.util.NumberUtil; | |
| 5 | +import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; | |
| 6 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 7 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 8 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 9 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | |
| 10 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 11 | +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; | |
| 12 | +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; | |
| 13 | +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; | |
| 14 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailRespVO; | |
| 15 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderPageReqVO; | |
| 16 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderRespVO; | |
| 17 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO; | |
| 18 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO; | |
| 19 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO; | |
| 20 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.merchant.WmsMerchantDO; | |
| 21 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseAreaDO; | |
| 22 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO; | |
| 23 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDO; | |
| 24 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO; | |
| 25 | +import cn.iocoder.yudao.module.wms.framework.config.WmsProperties; | |
| 26 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService; | |
| 27 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 28 | +import cn.iocoder.yudao.module.wms.service.md.merchant.WmsMerchantService; | |
| 29 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseAreaService; | |
| 30 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService; | |
| 31 | +import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderDetailService; | |
| 32 | +import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderService; | |
| 33 | +import io.swagger.v3.oas.annotations.Operation; | |
| 34 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 35 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 36 | +import jakarta.annotation.Resource; | |
| 37 | +import jakarta.servlet.http.HttpServletResponse; | |
| 38 | +import jakarta.validation.Valid; | |
| 39 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 40 | +import org.springframework.validation.annotation.Validated; | |
| 41 | +import org.springframework.web.bind.annotation.*; | |
| 42 | + | |
| 43 | +import java.io.IOException; | |
| 44 | +import java.util.Collections; | |
| 45 | +import java.util.List; | |
| 46 | +import java.util.Map; | |
| 47 | +import java.util.stream.Stream; | |
| 48 | + | |
| 49 | +import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; | |
| 50 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 51 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 52 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; | |
| 53 | + | |
| 54 | +@Tag(name = "管理后台 - WMS 出库单") | |
| 55 | +@RestController | |
| 56 | +@RequestMapping("/wms/shipment-order") | |
| 57 | +@Validated | |
| 58 | +public class WmsShipmentOrderController { | |
| 59 | + | |
| 60 | + @Resource | |
| 61 | + private WmsShipmentOrderService shipmentOrderService; | |
| 62 | + @Resource | |
| 63 | + private WmsShipmentOrderDetailService shipmentOrderDetailService; | |
| 64 | + @Resource | |
| 65 | + private WmsMerchantService merchantService; | |
| 66 | + @Resource | |
| 67 | + private WmsWarehouseService warehouseService; | |
| 68 | + @Resource | |
| 69 | + private WmsWarehouseAreaService warehouseAreaService; | |
| 70 | + @Resource | |
| 71 | + private WmsItemService itemService; | |
| 72 | + @Resource | |
| 73 | + private WmsItemSkuService itemSkuService; | |
| 74 | + | |
| 75 | + @Resource | |
| 76 | + private WmsProperties wmsProperties; | |
| 77 | + | |
| 78 | + @Resource | |
| 79 | + private AdminUserApi adminUserApi; | |
| 80 | + | |
| 81 | + @PostMapping("/create") | |
| 82 | + @Operation(summary = "创建出库单") | |
| 83 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:create')") | |
| 84 | + public CommonResult<Long> createShipmentOrder(@Valid @RequestBody WmsShipmentOrderSaveReqVO createReqVO) { | |
| 85 | + return success(shipmentOrderService.createShipmentOrder(createReqVO)); | |
| 86 | + } | |
| 87 | + | |
| 88 | + @PutMapping("/update") | |
| 89 | + @Operation(summary = "更新出库单") | |
| 90 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:update')") | |
| 91 | + public CommonResult<Boolean> updateShipmentOrder(@Valid @RequestBody WmsShipmentOrderSaveReqVO updateReqVO) { | |
| 92 | + shipmentOrderService.updateShipmentOrder(updateReqVO); | |
| 93 | + return success(true); | |
| 94 | + } | |
| 95 | + | |
| 96 | + @DeleteMapping("/delete") | |
| 97 | + @Operation(summary = "删除出库单") | |
| 98 | + @Parameter(name = "id", description = "编号", required = true) | |
| 99 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:delete')") | |
| 100 | + public CommonResult<Boolean> deleteShipmentOrder(@RequestParam("id") Long id) { | |
| 101 | + shipmentOrderService.deleteShipmentOrder(id); | |
| 102 | + return success(true); | |
| 103 | + } | |
| 104 | + | |
| 105 | + @PutMapping("/complete") | |
| 106 | + @Operation(summary = "完成出库") | |
| 107 | + @Parameter(name = "id", description = "编号", required = true) | |
| 108 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:complete')") | |
| 109 | + public CommonResult<Boolean> completeShipmentOrder(@RequestParam("id") Long id) { | |
| 110 | + shipmentOrderService.completeShipmentOrder(id); | |
| 111 | + return success(true); | |
| 112 | + } | |
| 113 | + | |
| 114 | + @PutMapping("/cancel") | |
| 115 | + @Operation(summary = "作废出库单") | |
| 116 | + @Parameter(name = "id", description = "编号", required = true) | |
| 117 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:cancel')") | |
| 118 | + public CommonResult<Boolean> cancelShipmentOrder(@RequestParam("id") Long id) { | |
| 119 | + shipmentOrderService.cancelShipmentOrder(id); | |
| 120 | + return success(true); | |
| 121 | + } | |
| 122 | + | |
| 123 | + @GetMapping("/get") | |
| 124 | + @Operation(summary = "获得出库单") | |
| 125 | + @Parameter(name = "id", description = "编号", required = true, example = "1024") | |
| 126 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:query')") | |
| 127 | + public CommonResult<WmsShipmentOrderRespVO> getShipmentOrder(@RequestParam("id") Long id) { | |
| 128 | + WmsShipmentOrderDO order = shipmentOrderService.getShipmentOrder(id); | |
| 129 | + if (order == null) { | |
| 130 | + return success(null); | |
| 131 | + } | |
| 132 | + // 获得出库单的明细列表 | |
| 133 | + List<WmsShipmentOrderDetailDO> detailList = shipmentOrderDetailService.getShipmentOrderDetailList(id); | |
| 134 | + // 拼接结果返回 | |
| 135 | + WmsShipmentOrderRespVO respVO = buildShipmentOrderRespVO(order) | |
| 136 | + .setDetails(buildShipmentOrderDetailRespVOList(detailList)); | |
| 137 | + return success(respVO); | |
| 138 | + } | |
| 139 | + | |
| 140 | + @GetMapping("/page") | |
| 141 | + @Operation(summary = "获得出库单分页") | |
| 142 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:query')") | |
| 143 | + public CommonResult<PageResult<WmsShipmentOrderRespVO>> getShipmentOrderPage(@Valid WmsShipmentOrderPageReqVO pageReqVO) { | |
| 144 | + PageResult<WmsShipmentOrderDO> pageResult = shipmentOrderService.getShipmentOrderPage(pageReqVO); | |
| 145 | + return success(new PageResult<>(buildShipmentOrderRespVOList(pageResult.getList()), pageResult.getTotal())); | |
| 146 | + } | |
| 147 | + | |
| 148 | + @GetMapping("/export-excel") | |
| 149 | + @Operation(summary = "导出出库单 Excel") | |
| 150 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:export')") | |
| 151 | + @ApiAccessLog(operateType = EXPORT) | |
| 152 | + public void exportShipmentOrderExcel(@Valid WmsShipmentOrderPageReqVO pageReqVO, | |
| 153 | + HttpServletResponse response) throws IOException { | |
| 154 | + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); | |
| 155 | + List<WmsShipmentOrderDO> list = shipmentOrderService.getShipmentOrderPage(pageReqVO).getList(); | |
| 156 | + ExcelUtils.write(response, "出库单.xls", "数据", WmsShipmentOrderRespVO.class, | |
| 157 | + buildShipmentOrderRespVOList(list)); | |
| 158 | + } | |
| 159 | + | |
| 160 | + // ==================== 拼接 VO ==================== | |
| 161 | + | |
| 162 | + private WmsShipmentOrderRespVO buildShipmentOrderRespVO(WmsShipmentOrderDO order) { | |
| 163 | + if (order == null) { | |
| 164 | + return null; | |
| 165 | + } | |
| 166 | + List<WmsShipmentOrderRespVO> list = buildShipmentOrderRespVOList(List.of(order)); | |
| 167 | + return CollUtil.getFirst(list); | |
| 168 | + } | |
| 169 | + | |
| 170 | + private List<WmsShipmentOrderRespVO> buildShipmentOrderRespVOList(List<WmsShipmentOrderDO> list) { | |
| 171 | + if (CollUtil.isEmpty(list)) { | |
| 172 | + return Collections.emptyList(); | |
| 173 | + } | |
| 174 | + // 获取相关的商户、仓库、库区、用户等数据 | |
| 175 | + Map<Long, WmsMerchantDO> merchantMap = merchantService.getMerchantMap(convertSet(list, WmsShipmentOrderDO::getMerchantId)); | |
| 176 | + Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap(convertSet(list, WmsShipmentOrderDO::getWarehouseId)); | |
| 177 | + Map<Long, WmsWarehouseAreaDO> areaMap = wmsProperties.isAreaEnabled() | |
| 178 | + ? warehouseAreaService.getWarehouseAreaMap(convertSet(list, WmsShipmentOrderDO::getAreaId)) | |
| 179 | + : Collections.emptyMap(); | |
| 180 | + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertSetByFlatMap(list, | |
| 181 | + order -> Stream.of(parseUserId(order.getCreator()), parseUserId(order.getUpdater())))); | |
| 182 | + // 拼接数据 | |
| 183 | + return BeanUtils.toBean(list, WmsShipmentOrderRespVO.class, vo -> { | |
| 184 | + MapUtils.findAndThen(merchantMap, vo.getMerchantId(), merchant -> vo.setMerchantName(merchant.getName())); | |
| 185 | + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName())); | |
| 186 | + MapUtils.findAndThen(areaMap, vo.getAreaId(), area -> vo.setAreaName(area.getName())); | |
| 187 | + MapUtils.findAndThen(userMap, parseUserId(vo.getCreator()), user -> vo.setCreatorName(user.getNickname())); | |
| 188 | + MapUtils.findAndThen(userMap, parseUserId(vo.getUpdater()), user -> vo.setUpdaterName(user.getNickname())); | |
| 189 | + }); | |
| 190 | + } | |
| 191 | + | |
| 192 | + private Long parseUserId(String userId) { | |
| 193 | + return NumberUtil.parseLong(userId, null); | |
| 194 | + } | |
| 195 | + | |
| 196 | + private List<WmsShipmentOrderDetailRespVO> buildShipmentOrderDetailRespVOList(List<WmsShipmentOrderDetailDO> list) { | |
| 197 | + if (CollUtil.isEmpty(list)) { | |
| 198 | + return Collections.emptyList(); | |
| 199 | + } | |
| 200 | + // 获取相关的商品、SKU、仓库、库区等数据 | |
| 201 | + Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsShipmentOrderDetailDO::getSkuId)); | |
| 202 | + Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId)); | |
| 203 | + Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap( | |
| 204 | + convertSet(list, WmsShipmentOrderDetailDO::getWarehouseId)); | |
| 205 | + Map<Long, WmsWarehouseAreaDO> areaMap = wmsProperties.isAreaEnabled() | |
| 206 | + ? warehouseAreaService.getWarehouseAreaMap(convertSet(list, WmsShipmentOrderDetailDO::getAreaId)) | |
| 207 | + : Collections.emptyMap(); | |
| 208 | + // 拼接数据 | |
| 209 | + return BeanUtils.toBean(list, WmsShipmentOrderDetailRespVO.class, vo -> { | |
| 210 | + MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> { | |
| 211 | + vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId()); | |
| 212 | + MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode()) | |
| 213 | + .setItemName(item.getName()).setUnit(item.getUnit())); | |
| 214 | + }); | |
| 215 | + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName())); | |
| 216 | + MapUtils.findAndThen(areaMap, vo.getAreaId(), area -> vo.setAreaName(area.getName())); | |
| 217 | + }); | |
| 218 | + } | |
| 219 | + | |
| 220 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/WmsShipmentOrderDetailController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.order.shipment; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; | |
| 6 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 7 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailRespVO; | |
| 8 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO; | |
| 9 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO; | |
| 10 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseAreaDO; | |
| 11 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO; | |
| 12 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO; | |
| 13 | +import cn.iocoder.yudao.module.wms.framework.config.WmsProperties; | |
| 14 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemService; | |
| 15 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 16 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseAreaService; | |
| 17 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService; | |
| 18 | +import cn.iocoder.yudao.module.wms.service.order.shipment.WmsShipmentOrderDetailService; | |
| 19 | +import io.swagger.v3.oas.annotations.Operation; | |
| 20 | +import io.swagger.v3.oas.annotations.Parameter; | |
| 21 | +import io.swagger.v3.oas.annotations.tags.Tag; | |
| 22 | +import jakarta.annotation.Resource; | |
| 23 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 24 | +import org.springframework.validation.annotation.Validated; | |
| 25 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 26 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 27 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 28 | +import org.springframework.web.bind.annotation.RestController; | |
| 29 | + | |
| 30 | +import java.util.Collections; | |
| 31 | +import java.util.List; | |
| 32 | +import java.util.Map; | |
| 33 | + | |
| 34 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 35 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 36 | + | |
| 37 | +@Tag(name = "管理后台 - WMS 出库单明细") | |
| 38 | +@RestController | |
| 39 | +@RequestMapping("/wms/shipment-order-detail") | |
| 40 | +@Validated | |
| 41 | +public class WmsShipmentOrderDetailController { | |
| 42 | + | |
| 43 | + @Resource | |
| 44 | + private WmsShipmentOrderDetailService shipmentOrderDetailService; | |
| 45 | + @Resource | |
| 46 | + private WmsItemService itemService; | |
| 47 | + @Resource | |
| 48 | + private WmsItemSkuService itemSkuService; | |
| 49 | + @Resource | |
| 50 | + private WmsWarehouseService warehouseService; | |
| 51 | + @Resource | |
| 52 | + private WmsWarehouseAreaService warehouseAreaService; | |
| 53 | + | |
| 54 | + @Resource | |
| 55 | + private WmsProperties wmsProperties; | |
| 56 | + | |
| 57 | + @GetMapping("/list-by-order-id") | |
| 58 | + @Operation(summary = "获得出库单明细列表") | |
| 59 | + @Parameter(name = "orderId", description = "出库单编号", required = true, example = "1024") | |
| 60 | + @PreAuthorize("@ss.hasPermission('wms:shipment-order:query')") | |
| 61 | + public CommonResult<List<WmsShipmentOrderDetailRespVO>> getShipmentOrderDetailListByOrderId( | |
| 62 | + @RequestParam("orderId") Long orderId) { | |
| 63 | + List<WmsShipmentOrderDetailDO> list = shipmentOrderDetailService.getShipmentOrderDetailList(orderId); | |
| 64 | + return success(buildShipmentOrderDetailRespVOList(list)); | |
| 65 | + } | |
| 66 | + | |
| 67 | + // ==================== 拼接 VO ==================== | |
| 68 | + | |
| 69 | + private List<WmsShipmentOrderDetailRespVO> buildShipmentOrderDetailRespVOList(List<WmsShipmentOrderDetailDO> list) { | |
| 70 | + if (CollUtil.isEmpty(list)) { | |
| 71 | + return Collections.emptyList(); | |
| 72 | + } | |
| 73 | + // 查询关联数据 | |
| 74 | + Map<Long, WmsItemSkuDO> skuMap = itemSkuService.getItemSkuMap(convertSet(list, WmsShipmentOrderDetailDO::getSkuId)); | |
| 75 | + Map<Long, WmsItemDO> itemMap = itemService.getItemMap(convertSet(skuMap.values(), WmsItemSkuDO::getItemId)); | |
| 76 | + Map<Long, WmsWarehouseDO> warehouseMap = warehouseService.getWarehouseMap( | |
| 77 | + convertSet(list, WmsShipmentOrderDetailDO::getWarehouseId)); | |
| 78 | + Map<Long, WmsWarehouseAreaDO> areaMap = wmsProperties.isAreaEnabled() | |
| 79 | + ? warehouseAreaService.getWarehouseAreaMap(convertSet(list, WmsShipmentOrderDetailDO::getAreaId)) | |
| 80 | + : Collections.emptyMap(); | |
| 81 | + // 拼接数据 | |
| 82 | + return BeanUtils.toBean(list, WmsShipmentOrderDetailRespVO.class, vo -> { | |
| 83 | + MapUtils.findAndThen(skuMap, vo.getSkuId(), sku -> { | |
| 84 | + vo.setSkuCode(sku.getCode()).setSkuName(sku.getName()).setItemId(sku.getItemId()); | |
| 85 | + MapUtils.findAndThen(itemMap, sku.getItemId(), item -> vo.setItemCode(item.getCode()) | |
| 86 | + .setItemName(item.getName()).setUnit(item.getUnit())); | |
| 87 | + }); | |
| 88 | + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> vo.setWarehouseName(warehouse.getName())); | |
| 89 | + MapUtils.findAndThen(areaMap, vo.getAreaId(), area -> vo.setAreaName(area.getName())); | |
| 90 | + }); | |
| 91 | + } | |
| 92 | + | |
| 93 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/detail/WmsShipmentOrderDetailRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | + | |
| 6 | +import java.math.BigDecimal; | |
| 7 | +import java.time.LocalDateTime; | |
| 8 | + | |
| 9 | +@Schema(description = "管理后台 - WMS 出库单明细 Response VO") | |
| 10 | +@Data | |
| 11 | +public class WmsShipmentOrderDetailRespVO { | |
| 12 | + | |
| 13 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 14 | + private Long id; | |
| 15 | + | |
| 16 | + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 17 | + private Long orderId; | |
| 18 | + | |
| 19 | + @Schema(description = "商品编号", example = "2048") | |
| 20 | + private Long itemId; | |
| 21 | + | |
| 22 | + @Schema(description = "商品编号", example = "SPU-APPLE") | |
| 23 | + private String itemCode; | |
| 24 | + | |
| 25 | + @Schema(description = "商品名称", example = "红富士苹果") | |
| 26 | + private String itemName; | |
| 27 | + | |
| 28 | + @Schema(description = "商品单位", example = "箱") | |
| 29 | + private String unit; | |
| 30 | + | |
| 31 | + @Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | |
| 32 | + private Long skuId; | |
| 33 | + | |
| 34 | + @Schema(description = "规格编号", example = "SKU-APPLE-10KG") | |
| 35 | + private String skuCode; | |
| 36 | + | |
| 37 | + @Schema(description = "规格名称", example = "10kg 箱装") | |
| 38 | + private String skuName; | |
| 39 | + | |
| 40 | + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 41 | + private Long warehouseId; | |
| 42 | + | |
| 43 | + @Schema(description = "仓库名称", example = "北京仓") | |
| 44 | + private String warehouseName; | |
| 45 | + | |
| 46 | + @Schema(description = "库区编号", example = "1024") | |
| 47 | + private Long areaId; | |
| 48 | + | |
| 49 | + @Schema(description = "库区名称", example = "北京库区01") | |
| 50 | + private String areaName; | |
| 51 | + | |
| 52 | + @Schema(description = "库存明细编号", example = "1024") | |
| 53 | + private Long inventoryDetailId; | |
| 54 | + | |
| 55 | + @Schema(description = "批号", example = "B202605110001") | |
| 56 | + private String batchNo; | |
| 57 | + | |
| 58 | + @Schema(description = "生产日期") | |
| 59 | + private LocalDateTime productionDate; | |
| 60 | + | |
| 61 | + @Schema(description = "过期日期") | |
| 62 | + private LocalDateTime expirationDate; | |
| 63 | + | |
| 64 | + @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") | |
| 65 | + private BigDecimal quantity; | |
| 66 | + | |
| 67 | + @Schema(description = "金额", example = "1000.00") | |
| 68 | + private BigDecimal amount; | |
| 69 | + | |
| 70 | + @Schema(description = "备注", example = "备注") | |
| 71 | + private String remark; | |
| 72 | + | |
| 73 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 74 | + private LocalDateTime createTime; | |
| 75 | + | |
| 76 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/detail/WmsShipmentOrderDetailSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import jakarta.validation.constraints.DecimalMin; | |
| 5 | +import jakarta.validation.constraints.NotNull; | |
| 6 | +import jakarta.validation.constraints.Size; | |
| 7 | +import lombok.Data; | |
| 8 | + | |
| 9 | +import java.math.BigDecimal; | |
| 10 | +import java.time.LocalDateTime; | |
| 11 | + | |
| 12 | +@Schema(description = "管理后台 - WMS 出库单明细保存 Request VO") | |
| 13 | +@Data | |
| 14 | +public class WmsShipmentOrderDetailSaveReqVO { | |
| 15 | + | |
| 16 | + @Schema(description = "编号", example = "1024") | |
| 17 | + private Long id; | |
| 18 | + | |
| 19 | + @Schema(description = "SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") | |
| 20 | + @NotNull(message = "SKU 不能为空") | |
| 21 | + private Long skuId; | |
| 22 | + | |
| 23 | + @Schema(description = "库区编号", example = "1024") | |
| 24 | + private Long areaId; | |
| 25 | + | |
| 26 | + @Schema(description = "库存明细编号", example = "1024") | |
| 27 | + private Long inventoryDetailId; | |
| 28 | + | |
| 29 | + @Schema(description = "批号", example = "B202605110001") | |
| 30 | + @Size(max = 64, message = "批号长度不能超过 64 个字符") | |
| 31 | + private String batchNo; | |
| 32 | + | |
| 33 | + @Schema(description = "生产日期") | |
| 34 | + private LocalDateTime productionDate; | |
| 35 | + | |
| 36 | + @Schema(description = "过期日期") | |
| 37 | + private LocalDateTime expirationDate; | |
| 38 | + | |
| 39 | + @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") | |
| 40 | + @NotNull(message = "出库数量不能为空") | |
| 41 | + @DecimalMin(value = "0", inclusive = false, message = "出库数量必须大于 0") | |
| 42 | + private BigDecimal quantity; | |
| 43 | + | |
| 44 | + @Schema(description = "金额", example = "1000.00") | |
| 45 | + @DecimalMin(value = "0", message = "金额不能小于 0") | |
| 46 | + private BigDecimal amount; | |
| 47 | + | |
| 48 | + @Schema(description = "备注", example = "备注") | |
| 49 | + @Size(max = 255, message = "备注长度不能超过 255 个字符") | |
| 50 | + private String remark; | |
| 51 | + | |
| 52 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/order/WmsShipmentOrderPageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageParam; | |
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 5 | +import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum; | |
| 6 | +import cn.iocoder.yudao.module.wms.enums.order.WmsShipmentOrderTypeEnum; | |
| 7 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 8 | +import lombok.Data; | |
| 9 | +import lombok.EqualsAndHashCode; | |
| 10 | +import lombok.ToString; | |
| 11 | +import org.springframework.format.annotation.DateTimeFormat; | |
| 12 | + | |
| 13 | +import java.math.BigDecimal; | |
| 14 | +import java.time.LocalDateTime; | |
| 15 | + | |
| 16 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | |
| 17 | + | |
| 18 | +@Schema(description = "管理后台 - WMS 出库单分页 Request VO") | |
| 19 | +@Data | |
| 20 | +@EqualsAndHashCode(callSuper = true) | |
| 21 | +@ToString(callSuper = true) | |
| 22 | +public class WmsShipmentOrderPageReqVO extends PageParam { | |
| 23 | + | |
| 24 | + @Schema(description = "出库单号", example = "CK202605110001") | |
| 25 | + private String no; | |
| 26 | + | |
| 27 | + @Schema(description = "单据状态", example = "0") | |
| 28 | + @InEnum(WmsOrderStatusEnum.class) | |
| 29 | + private Integer status; | |
| 30 | + | |
| 31 | + @Schema(description = "仓库编号", example = "1024") | |
| 32 | + private Long warehouseId; | |
| 33 | + | |
| 34 | + @Schema(description = "客户编号", example = "1024") | |
| 35 | + private Long merchantId; | |
| 36 | + | |
| 37 | + @Schema(description = "单据日期") | |
| 38 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 39 | + private LocalDateTime[] orderDate; | |
| 40 | + | |
| 41 | + @Schema(description = "最小数量", example = "1.00") | |
| 42 | + private BigDecimal totalQuantityMin; | |
| 43 | + | |
| 44 | + @Schema(description = "最大数量", example = "100.00") | |
| 45 | + private BigDecimal totalQuantityMax; | |
| 46 | + | |
| 47 | + @Schema(description = "最小总金额", example = "1.00") | |
| 48 | + private BigDecimal totalAmountMin; | |
| 49 | + | |
| 50 | + @Schema(description = "最大总金额", example = "1000.00") | |
| 51 | + private BigDecimal totalAmountMax; | |
| 52 | + | |
| 53 | + @Schema(description = "出库类型", example = "201") | |
| 54 | + @InEnum(WmsShipmentOrderTypeEnum.class) | |
| 55 | + private Integer type; | |
| 56 | + | |
| 57 | + @Schema(description = "业务单号", example = "SO202605110001") | |
| 58 | + private String bizOrderNo; | |
| 59 | + | |
| 60 | + @Schema(description = "创建用户", example = "1") | |
| 61 | + private String creator; | |
| 62 | + | |
| 63 | + @Schema(description = "更新用户", example = "1") | |
| 64 | + private String updater; | |
| 65 | + | |
| 66 | + @Schema(description = "创建时间") | |
| 67 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 68 | + private LocalDateTime[] createTime; | |
| 69 | + | |
| 70 | + @Schema(description = "更新时间") | |
| 71 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | |
| 72 | + private LocalDateTime[] updateTime; | |
| 73 | + | |
| 74 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/order/WmsShipmentOrderRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order; | |
| 2 | + | |
| 3 | +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; | |
| 4 | +import cn.idev.excel.annotation.ExcelProperty; | |
| 5 | +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; | |
| 6 | +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; | |
| 7 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailRespVO; | |
| 8 | +import cn.iocoder.yudao.module.wms.enums.DictTypeConstants; | |
| 9 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 10 | +import lombok.Data; | |
| 11 | + | |
| 12 | +import java.math.BigDecimal; | |
| 13 | +import java.time.LocalDateTime; | |
| 14 | +import java.util.List; | |
| 15 | + | |
| 16 | +@Schema(description = "管理后台 - WMS 出库单 Response VO") | |
| 17 | +@Data | |
| 18 | +@ExcelIgnoreUnannotated | |
| 19 | +public class WmsShipmentOrderRespVO { | |
| 20 | + | |
| 21 | + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 22 | + private Long id; | |
| 23 | + | |
| 24 | + @Schema(description = "出库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "CK202605110001") | |
| 25 | + @ExcelProperty("出库单号") | |
| 26 | + private String no; | |
| 27 | + | |
| 28 | + @Schema(description = "出库类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "201") | |
| 29 | + @ExcelProperty(value = "出库类型", converter = DictConvert.class) | |
| 30 | + @DictFormat(DictTypeConstants.SHIPMENT_ORDER_TYPE) | |
| 31 | + private Integer type; | |
| 32 | + | |
| 33 | + @Schema(description = "出库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") | |
| 34 | + @ExcelProperty(value = "出库状态", converter = DictConvert.class) | |
| 35 | + @DictFormat(DictTypeConstants.ORDER_STATUS) | |
| 36 | + private Integer status; | |
| 37 | + | |
| 38 | + @Schema(description = "业务单号", example = "SO202605110001") | |
| 39 | + @ExcelProperty("业务单号") | |
| 40 | + private String bizOrderNo; | |
| 41 | + | |
| 42 | + @Schema(description = "客户编号", example = "1024") | |
| 43 | + private Long merchantId; | |
| 44 | + | |
| 45 | + @Schema(description = "客户名称", example = "某某公司") | |
| 46 | + @ExcelProperty("客户") | |
| 47 | + private String merchantName; | |
| 48 | + | |
| 49 | + @Schema(description = "备注", example = "备注") | |
| 50 | + private String remark; | |
| 51 | + | |
| 52 | + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 53 | + private Long warehouseId; | |
| 54 | + | |
| 55 | + @Schema(description = "仓库名称", example = "北京仓") | |
| 56 | + @ExcelProperty("仓库") | |
| 57 | + private String warehouseName; | |
| 58 | + | |
| 59 | + @Schema(description = "库区编号", example = "1024") | |
| 60 | + private Long areaId; | |
| 61 | + | |
| 62 | + @Schema(description = "库区名称", example = "北京库区01") | |
| 63 | + private String areaName; | |
| 64 | + | |
| 65 | + @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") | |
| 66 | + @ExcelProperty("出库数量") | |
| 67 | + private BigDecimal totalQuantity; | |
| 68 | + | |
| 69 | + @Schema(description = "总金额", example = "1000.00") | |
| 70 | + @ExcelProperty("总金额") | |
| 71 | + private BigDecimal totalAmount; | |
| 72 | + | |
| 73 | + @Schema(description = "出库明细") | |
| 74 | + private List<WmsShipmentOrderDetailRespVO> details; | |
| 75 | + | |
| 76 | + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 77 | + @ExcelProperty("创建时间") | |
| 78 | + private LocalDateTime createTime; | |
| 79 | + | |
| 80 | + @Schema(description = "创建者", example = "1") | |
| 81 | + private String creator; | |
| 82 | + @Schema(description = "创建者名称", example = "芋道") | |
| 83 | + private String creatorName; | |
| 84 | + | |
| 85 | + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 86 | + private LocalDateTime updateTime; | |
| 87 | + | |
| 88 | + @Schema(description = "更新者", example = "1") | |
| 89 | + private String updater; | |
| 90 | + @Schema(description = "更新者名称", example = "芋道") | |
| 91 | + private String updaterName; | |
| 92 | + | |
| 93 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/order/WmsShipmentOrderSaveReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailSaveReqVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.enums.order.WmsShipmentOrderTypeEnum; | |
| 6 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 7 | +import jakarta.validation.Valid; | |
| 8 | +import jakarta.validation.constraints.NotBlank; | |
| 9 | +import jakarta.validation.constraints.NotNull; | |
| 10 | +import jakarta.validation.constraints.Size; | |
| 11 | +import lombok.Data; | |
| 12 | + | |
| 13 | +import java.math.BigDecimal; | |
| 14 | +import java.util.List; | |
| 15 | + | |
| 16 | +@Schema(description = "管理后台 - WMS 出库单保存 Request VO") | |
| 17 | +@Data | |
| 18 | +public class WmsShipmentOrderSaveReqVO { | |
| 19 | + | |
| 20 | + @Schema(description = "编号", example = "1024") | |
| 21 | + private Long id; | |
| 22 | + | |
| 23 | + @Schema(description = "出库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "CK202605110001") | |
| 24 | + @NotBlank(message = "出库单号不能为空") | |
| 25 | + @Size(max = 64, message = "出库单号长度不能超过 64 个字符") | |
| 26 | + private String no; | |
| 27 | + | |
| 28 | + @Schema(description = "出库类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "201") | |
| 29 | + @NotNull(message = "出库类型不能为空") | |
| 30 | + @InEnum(WmsShipmentOrderTypeEnum.class) | |
| 31 | + private Integer type; | |
| 32 | + | |
| 33 | + @Schema(description = "业务单号", example = "SO202605110001") | |
| 34 | + @Size(max = 64, message = "业务单号长度不能超过 64 个字符") | |
| 35 | + private String bizOrderNo; | |
| 36 | + | |
| 37 | + @Schema(description = "客户编号", example = "1024") | |
| 38 | + private Long merchantId; | |
| 39 | + | |
| 40 | + @Schema(description = "备注", example = "备注") | |
| 41 | + @Size(max = 255, message = "备注长度不能超过 255 个字符") | |
| 42 | + private String remark; | |
| 43 | + | |
| 44 | + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 45 | + @NotNull(message = "仓库不能为空") | |
| 46 | + private Long warehouseId; | |
| 47 | + | |
| 48 | + @Schema(description = "库区编号", example = "1024") | |
| 49 | + private Long areaId; | |
| 50 | + | |
| 51 | + @Schema(description = "出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") | |
| 52 | + @NotNull(message = "出库数量不能为空") | |
| 53 | + private BigDecimal totalQuantity; | |
| 54 | + | |
| 55 | + @Schema(description = "总金额", example = "1000.00") | |
| 56 | + private BigDecimal totalAmount; | |
| 57 | + | |
| 58 | + @Schema(description = "出库明细") | |
| 59 | + @Valid | |
| 60 | + private List<WmsShipmentOrderDetailSaveReqVO> details; | |
| 61 | + | |
| 62 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/order/shipment/WmsShipmentOrderDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 4 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.merchant.WmsMerchantDO; | |
| 5 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseAreaDO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO; | |
| 7 | +import cn.iocoder.yudao.module.wms.enums.DictTypeConstants; | |
| 8 | +import cn.iocoder.yudao.module.wms.enums.order.WmsShipmentOrderTypeEnum; | |
| 9 | +import com.baomidou.mybatisplus.annotation.KeySequence; | |
| 10 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 11 | +import com.baomidou.mybatisplus.annotation.TableName; | |
| 12 | +import lombok.*; | |
| 13 | + | |
| 14 | +import java.math.BigDecimal; | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * WMS 出库单 DO | |
| 18 | + * | |
| 19 | + * @author 芋道源码 | |
| 20 | + */ | |
| 21 | +@TableName("wms_shipment_order") | |
| 22 | +@KeySequence("wms_shipment_order_seq") | |
| 23 | +@Data | |
| 24 | +@EqualsAndHashCode(callSuper = true) | |
| 25 | +@ToString(callSuper = true) | |
| 26 | +@Builder | |
| 27 | +@NoArgsConstructor | |
| 28 | +@AllArgsConstructor | |
| 29 | +public class WmsShipmentOrderDO extends BaseDO { | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 主键编号 | |
| 33 | + */ | |
| 34 | + @TableId | |
| 35 | + private Long id; | |
| 36 | + /** | |
| 37 | + * 出库单号 | |
| 38 | + */ | |
| 39 | + private String no; | |
| 40 | + /** | |
| 41 | + * 出库类型 | |
| 42 | + * | |
| 43 | + * 枚举 {@link WmsShipmentOrderTypeEnum} | |
| 44 | + * 字典 {@link DictTypeConstants#SHIPMENT_ORDER_TYPE} | |
| 45 | + */ | |
| 46 | + private Integer type; | |
| 47 | + /** | |
| 48 | + * 出库状态 | |
| 49 | + * | |
| 50 | + * 字典 {@link DictTypeConstants#ORDER_STATUS} | |
| 51 | + */ | |
| 52 | + private Integer status; | |
| 53 | + /** | |
| 54 | + * 业务订单号 | |
| 55 | + */ | |
| 56 | + private String bizOrderNo; | |
| 57 | + /** | |
| 58 | + * 客户编号 | |
| 59 | + * | |
| 60 | + * 关联 {@link WmsMerchantDO#getId()} | |
| 61 | + */ | |
| 62 | + private Long merchantId; | |
| 63 | + /** | |
| 64 | + * 备注 | |
| 65 | + */ | |
| 66 | + private String remark; | |
| 67 | + | |
| 68 | + // ========= 仓库库区字段 ========= | |
| 69 | + | |
| 70 | + /** | |
| 71 | + * 仓库编号 | |
| 72 | + * | |
| 73 | + * 关联 {@link WmsWarehouseDO#getId()} | |
| 74 | + */ | |
| 75 | + private Long warehouseId; | |
| 76 | + /** | |
| 77 | + * 库区编号 | |
| 78 | + * | |
| 79 | + * 关联 {@link WmsWarehouseAreaDO#getId()} | |
| 80 | + */ | |
| 81 | + private Long areaId; | |
| 82 | + | |
| 83 | + // ========= 汇总金额字段 ========= | |
| 84 | + | |
| 85 | + /** | |
| 86 | + * 总数量 | |
| 87 | + */ | |
| 88 | + private BigDecimal totalQuantity; | |
| 89 | + /** | |
| 90 | + * 总金额 | |
| 91 | + */ | |
| 92 | + private BigDecimal totalAmount; | |
| 93 | + | |
| 94 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/dataobject/order/shipment/WmsShipmentOrderDetailDO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 4 | +import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDetailDO; | |
| 5 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseAreaDO; | |
| 7 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseDO; | |
| 8 | +import com.baomidou.mybatisplus.annotation.KeySequence; | |
| 9 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 10 | +import com.baomidou.mybatisplus.annotation.TableName; | |
| 11 | +import lombok.*; | |
| 12 | + | |
| 13 | +import java.math.BigDecimal; | |
| 14 | +import java.time.LocalDateTime; | |
| 15 | + | |
| 16 | +/** | |
| 17 | + * WMS 出库单明细 DO | |
| 18 | + * | |
| 19 | + * @author 芋道源码 | |
| 20 | + */ | |
| 21 | +@TableName("wms_shipment_order_detail") | |
| 22 | +@KeySequence("wms_shipment_order_detail_seq") | |
| 23 | +@Data | |
| 24 | +@EqualsAndHashCode(callSuper = true) | |
| 25 | +@ToString(callSuper = true) | |
| 26 | +@Builder | |
| 27 | +@NoArgsConstructor | |
| 28 | +@AllArgsConstructor | |
| 29 | +public class WmsShipmentOrderDetailDO extends BaseDO { | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 主键编号 | |
| 33 | + */ | |
| 34 | + @TableId | |
| 35 | + private Long id; | |
| 36 | + /** | |
| 37 | + * 备注 | |
| 38 | + */ | |
| 39 | + private String remark; | |
| 40 | + | |
| 41 | + // ========= 单据商品字段 ========= | |
| 42 | + | |
| 43 | + /** | |
| 44 | + * 出库单编号 | |
| 45 | + * | |
| 46 | + * 关联 {@link WmsShipmentOrderDO#getId()} | |
| 47 | + */ | |
| 48 | + private Long orderId; | |
| 49 | + /** | |
| 50 | + * 商品 SKU 编号 | |
| 51 | + * | |
| 52 | + * 关联 {@link WmsItemSkuDO#getId()} | |
| 53 | + */ | |
| 54 | + private Long skuId; | |
| 55 | + | |
| 56 | + // ========= 仓库库区字段 ========= | |
| 57 | + | |
| 58 | + /** | |
| 59 | + * 仓库编号 | |
| 60 | + * | |
| 61 | + * 关联 {@link WmsWarehouseDO#getId()} | |
| 62 | + */ | |
| 63 | + private Long warehouseId; | |
| 64 | + /** | |
| 65 | + * 库区编号 | |
| 66 | + * | |
| 67 | + * 关联 {@link WmsWarehouseAreaDO#getId()} | |
| 68 | + */ | |
| 69 | + private Long areaId; | |
| 70 | + /** | |
| 71 | + * 库存明细编号 | |
| 72 | + * | |
| 73 | + * 关联 {@link WmsInventoryDetailDO#getId()} | |
| 74 | + */ | |
| 75 | + private Long inventoryDetailId; | |
| 76 | + | |
| 77 | + // ========= 批次效期字段 ========= | |
| 78 | + | |
| 79 | + /** | |
| 80 | + * 批号 | |
| 81 | + */ | |
| 82 | + private String batchNo; | |
| 83 | + /** | |
| 84 | + * 生产日期 | |
| 85 | + */ | |
| 86 | + private LocalDateTime productionDate; | |
| 87 | + /** | |
| 88 | + * 过期日期 | |
| 89 | + */ | |
| 90 | + private LocalDateTime expirationDate; | |
| 91 | + | |
| 92 | + // ========= 汇总金额字段 ========= | |
| 93 | + | |
| 94 | + /** | |
| 95 | + * 出库数量 | |
| 96 | + */ | |
| 97 | + private BigDecimal quantity; | |
| 98 | + /** | |
| 99 | + * 金额(小计、非单价) | |
| 100 | + */ | |
| 101 | + private BigDecimal amount; | |
| 102 | + | |
| 103 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/inventory/WmsInventoryDetailMapper.java
| ... | ... | @@ -8,8 +8,10 @@ import cn.iocoder.yudao.module.wms.controller.admin.inventory.vo.detail.WmsInven |
| 8 | 8 | import cn.iocoder.yudao.module.wms.dal.dataobject.inventory.WmsInventoryDetailDO; |
| 9 | 9 | import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemDO; |
| 10 | 10 | import cn.iocoder.yudao.module.wms.dal.dataobject.md.item.WmsItemSkuDO; |
| 11 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | |
| 11 | 12 | import org.apache.ibatis.annotations.Mapper; |
| 12 | 13 | |
| 14 | +import java.math.BigDecimal; | |
| 13 | 15 | import java.time.LocalDate; |
| 14 | 16 | import java.time.LocalDateTime; |
| 15 | 17 | import java.time.LocalTime; |
| ... | ... | @@ -35,6 +37,7 @@ public interface WmsInventoryDetailMapper extends BaseMapperX<WmsInventoryDetail |
| 35 | 37 | .eqIfPresent(WmsInventoryDetailDO::getWarehouseId, reqVO.getWarehouseId()) |
| 36 | 38 | .eqIfPresent(WmsInventoryDetailDO::getAreaId, reqVO.getAreaId()) |
| 37 | 39 | .likeIfPresent(WmsInventoryDetailDO::getBatchNo, reqVO.getBatchNo()) |
| 40 | + .geIfPresent(WmsInventoryDetailDO::getRemainQuantity, reqVO.getMinRemainQuantity()) | |
| 38 | 41 | .betweenIfPresent(WmsInventoryDetailDO::getCreateTime, reqVO.getCreateTime()); |
| 39 | 42 | appendDaysToExpiresQuery(query, reqVO.getDaysToExpires()); |
| 40 | 43 | appendDimensionOrder(query, reqVO.getType()); | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/shipment/WmsShipmentOrderDetailMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.dal.mysql.order.shipment; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 5 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO; | |
| 6 | +import org.apache.ibatis.annotations.Mapper; | |
| 7 | + | |
| 8 | +import java.util.Collection; | |
| 9 | +import java.util.List; | |
| 10 | + | |
| 11 | +/** | |
| 12 | + * WMS 出库单明细 Mapper | |
| 13 | + * | |
| 14 | + * @author 芋道源码 | |
| 15 | + */ | |
| 16 | +@Mapper | |
| 17 | +public interface WmsShipmentOrderDetailMapper extends BaseMapperX<WmsShipmentOrderDetailDO> { | |
| 18 | + | |
| 19 | + default List<WmsShipmentOrderDetailDO> selectListByOrderId(Long orderId) { | |
| 20 | + return selectList(WmsShipmentOrderDetailDO::getOrderId, orderId); | |
| 21 | + } | |
| 22 | + | |
| 23 | + default List<WmsShipmentOrderDetailDO> selectListByOrderIds(Collection<Long> orderIds) { | |
| 24 | + return selectList(new LambdaQueryWrapperX<WmsShipmentOrderDetailDO>() | |
| 25 | + .inIfPresent(WmsShipmentOrderDetailDO::getOrderId, orderIds) | |
| 26 | + .orderByAsc(WmsShipmentOrderDetailDO::getOrderId) | |
| 27 | + .orderByAsc(WmsShipmentOrderDetailDO::getId)); | |
| 28 | + } | |
| 29 | + | |
| 30 | + default void deleteByOrderId(Long orderId) { | |
| 31 | + delete(WmsShipmentOrderDetailDO::getOrderId, orderId); | |
| 32 | + } | |
| 33 | + | |
| 34 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/dal/mysql/order/shipment/WmsShipmentOrderMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.dal.mysql.order.shipment; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderPageReqVO; | |
| 7 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDO; | |
| 8 | +import org.apache.ibatis.annotations.Mapper; | |
| 9 | + | |
| 10 | +/** | |
| 11 | + * WMS 出库单 Mapper | |
| 12 | + * | |
| 13 | + * @author 芋道源码 | |
| 14 | + */ | |
| 15 | +@Mapper | |
| 16 | +public interface WmsShipmentOrderMapper extends BaseMapperX<WmsShipmentOrderDO> { | |
| 17 | + | |
| 18 | + default PageResult<WmsShipmentOrderDO> selectPage(WmsShipmentOrderPageReqVO reqVO) { | |
| 19 | + return selectPage(reqVO, new LambdaQueryWrapperX<WmsShipmentOrderDO>() | |
| 20 | + .likeIfPresent(WmsShipmentOrderDO::getNo, reqVO.getNo()) | |
| 21 | + .eqIfPresent(WmsShipmentOrderDO::getStatus, reqVO.getStatus()) | |
| 22 | + .eqIfPresent(WmsShipmentOrderDO::getWarehouseId, reqVO.getWarehouseId()) | |
| 23 | + .eqIfPresent(WmsShipmentOrderDO::getMerchantId, reqVO.getMerchantId()) | |
| 24 | + .betweenIfPresent(WmsShipmentOrderDO::getCreateTime, reqVO.getOrderDate()) | |
| 25 | + .geIfPresent(WmsShipmentOrderDO::getTotalQuantity, reqVO.getTotalQuantityMin()) | |
| 26 | + .leIfPresent(WmsShipmentOrderDO::getTotalQuantity, reqVO.getTotalQuantityMax()) | |
| 27 | + .geIfPresent(WmsShipmentOrderDO::getTotalAmount, reqVO.getTotalAmountMin()) | |
| 28 | + .leIfPresent(WmsShipmentOrderDO::getTotalAmount, reqVO.getTotalAmountMax()) | |
| 29 | + .eqIfPresent(WmsShipmentOrderDO::getType, reqVO.getType()) | |
| 30 | + .likeIfPresent(WmsShipmentOrderDO::getBizOrderNo, reqVO.getBizOrderNo()) | |
| 31 | + .eqIfPresent(WmsShipmentOrderDO::getCreator, reqVO.getCreator()) | |
| 32 | + .eqIfPresent(WmsShipmentOrderDO::getUpdater, reqVO.getUpdater()) | |
| 33 | + .betweenIfPresent(WmsShipmentOrderDO::getCreateTime, reqVO.getCreateTime()) | |
| 34 | + .betweenIfPresent(WmsShipmentOrderDO::getUpdateTime, reqVO.getUpdateTime()) | |
| 35 | + .orderByDesc(WmsShipmentOrderDO::getId)); | |
| 36 | + } | |
| 37 | + | |
| 38 | + default WmsShipmentOrderDO selectByNo(String no) { | |
| 39 | + return selectOne(WmsShipmentOrderDO::getNo, no); | |
| 40 | + } | |
| 41 | + | |
| 42 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/enums/DictTypeConstants.java
| ... | ... | @@ -10,8 +10,7 @@ public interface DictTypeConstants { |
| 10 | 10 | String MERCHANT_TYPE = "merchant_type"; |
| 11 | 11 | String ORDER_STATUS = "wms_order_status"; |
| 12 | 12 | String RECEIPT_ORDER_TYPE = "wms_receipt_order_type"; |
| 13 | - String SHIPMENT_STATUS = "wms_shipment_status"; | |
| 14 | - String SHIPMENT_TYPE = "wms_shipment_type"; | |
| 13 | + String SHIPMENT_ORDER_TYPE = "wms_shipment_order_type"; | |
| 15 | 14 | String INVENTORY_HISTORY_TYPE = "wms_inventory_history_type"; |
| 16 | 15 | String MOVEMENT_STATUS = "wms_movement_status"; |
| 17 | 16 | String CHECK_STATUS = "wms_check_status"; | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/enums/ErrorCodeConstants.java
| ... | ... | @@ -48,6 +48,7 @@ public interface ErrorCodeConstants { |
| 48 | 48 | // ========== WMS 基础数据-往来企业 1-060-105-000 ========== |
| 49 | 49 | ErrorCode MERCHANT_NOT_EXISTS = new ErrorCode(1_060_105_000, "往来企业不存在"); |
| 50 | 50 | ErrorCode MERCHANT_NOT_SUPPLIER = new ErrorCode(1_060_105_001, "往来企业必须是供应商或客户/供应商类型"); |
| 51 | + ErrorCode MERCHANT_NOT_CUSTOMER = new ErrorCode(1_060_105_002, "往来企业必须是客户或客户/供应商类型"); | |
| 51 | 52 | |
| 52 | 53 | // ========== WMS 入库单 1-060-200-000 ========== |
| 53 | 54 | ErrorCode RECEIPT_ORDER_NOT_EXISTS = new ErrorCode(1_060_200_000, "入库单不存在"); |
| ... | ... | @@ -58,4 +59,18 @@ public interface ErrorCodeConstants { |
| 58 | 59 | ErrorCode RECEIPT_ORDER_STATUS_NOT_DELETABLE = new ErrorCode(1_060_200_005, "入库单状态不是草稿或已作废,不能删除"); |
| 59 | 60 | ErrorCode RECEIPT_ORDER_DETAIL_NOT_EXISTS = new ErrorCode(1_060_200_007, "入库单明细不存在"); |
| 60 | 61 | |
| 62 | + // ========== WMS 出库单 1-060-201-000 ========== | |
| 63 | + ErrorCode SHIPMENT_ORDER_NOT_EXISTS = new ErrorCode(1_060_201_000, "出库单不存在"); | |
| 64 | + ErrorCode SHIPMENT_ORDER_NO_DUPLICATE = new ErrorCode(1_060_201_001, "出库单号重复"); | |
| 65 | + ErrorCode SHIPMENT_ORDER_STATUS_NOT_PREPARE = new ErrorCode(1_060_201_002, "出库单状态不是草稿,不能操作"); | |
| 66 | + ErrorCode SHIPMENT_ORDER_DETAIL_REQUIRED = new ErrorCode(1_060_201_003, "出库单至少包含一条明细"); | |
| 67 | + ErrorCode SHIPMENT_ORDER_AREA_REQUIRED = new ErrorCode(1_060_201_004, "库区模式下,出库单库区不能为空"); | |
| 68 | + ErrorCode SHIPMENT_ORDER_STATUS_NOT_DELETABLE = new ErrorCode(1_060_201_005, "出库单状态不是草稿或已作废,不能删除"); | |
| 69 | + ErrorCode SHIPMENT_ORDER_DETAIL_NOT_EXISTS = new ErrorCode(1_060_201_007, "出库单明细不存在"); | |
| 70 | + | |
| 71 | + // ========== WMS 库存 1-060-300-000 ========== | |
| 72 | + ErrorCode INVENTORY_QUANTITY_NOT_ENOUGH = new ErrorCode(1_060_300_000, "库存不足,当前库存:{},变更数量:{}"); | |
| 73 | + ErrorCode INVENTORY_DETAIL_NOT_EXISTS = new ErrorCode(1_060_300_001, "库存明细不存在"); | |
| 74 | + ErrorCode INVENTORY_DETAIL_REMAIN_QUANTITY_NOT_ENOUGH = new ErrorCode(1_060_300_002, "库存明细剩余数量不足,当前剩余:{},出库数量:{}"); | |
| 75 | + | |
| 61 | 76 | } | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/enums/order/WmsOrderTypeConstants.java
| ... | ... | @@ -19,4 +19,10 @@ public final class WmsOrderTypeConstants { |
| 19 | 19 | public static final int RECEIPT_RETURN = 102; // 退货入库:WmsReceiptOrderDO |
| 20 | 20 | public static final int RECEIPT_GIVE_BACK = 103; // 归还入库:WmsReceiptOrderDO |
| 21 | 21 | |
| 22 | + // ========== 出库单类型 [200, 300) ========== | |
| 23 | + | |
| 24 | + public static final int SHIPMENT_RETURN = 200; // 退货出库:WmsShipmentOrderDO | |
| 25 | + public static final int SHIPMENT_SALE = 201; // 销售出库:WmsShipmentOrderDO | |
| 26 | + public static final int SHIPMENT_PRODUCTION = 202; // 生产出库:WmsShipmentOrderDO | |
| 27 | + | |
| 22 | 28 | } | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/enums/order/WmsShipmentOrderTypeEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.enums.order; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.core.ArrayValuable; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Getter; | |
| 6 | + | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * WMS 出库单类型枚举 | |
| 11 | + * | |
| 12 | + * @author 芋道源码 | |
| 13 | + */ | |
| 14 | +@Getter | |
| 15 | +@AllArgsConstructor | |
| 16 | +public enum WmsShipmentOrderTypeEnum implements ArrayValuable<Integer> { | |
| 17 | + | |
| 18 | + RETURN(WmsOrderTypeConstants.SHIPMENT_RETURN, "退货出库"), | |
| 19 | + SALE(WmsOrderTypeConstants.SHIPMENT_SALE, "销售出库"), | |
| 20 | + PRODUCTION(WmsOrderTypeConstants.SHIPMENT_PRODUCTION, "生产出库"); | |
| 21 | + | |
| 22 | + public static final Integer[] ARRAYS = Arrays.stream(values()).map(WmsShipmentOrderTypeEnum::getType).toArray(Integer[]::new); | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * 类型 | |
| 26 | + */ | |
| 27 | + private final Integer type; | |
| 28 | + /** | |
| 29 | + * 名称 | |
| 30 | + */ | |
| 31 | + private final String name; | |
| 32 | + | |
| 33 | + @Override | |
| 34 | + public Integer[] array() { | |
| 35 | + return ARRAYS; | |
| 36 | + } | |
| 37 | + | |
| 38 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/inventory/dto/WmsInventoryChangeReqDTO.java
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/merchant/WmsMerchantService.java
| ... | ... | @@ -55,9 +55,19 @@ public interface WmsMerchantService { |
| 55 | 55 | * @param id 编号 |
| 56 | 56 | * @return 往来企业 |
| 57 | 57 | */ |
| 58 | + @SuppressWarnings("UnusedReturnValue") | |
| 58 | 59 | WmsMerchantDO validateSupplierMerchantExists(Long id); |
| 59 | 60 | |
| 60 | 61 | /** |
| 62 | + * 校验客户存在 | |
| 63 | + * | |
| 64 | + * @param id 编号 | |
| 65 | + * @return 往来企业 | |
| 66 | + */ | |
| 67 | + @SuppressWarnings("UnusedReturnValue") | |
| 68 | + WmsMerchantDO validateCustomerMerchantExists(Long id); | |
| 69 | + | |
| 70 | + /** | |
| 61 | 71 | * 获得往来企业 |
| 62 | 72 | * |
| 63 | 73 | * @param id 编号 | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/md/merchant/WmsMerchantServiceImpl.java
| ... | ... | @@ -79,6 +79,16 @@ public class WmsMerchantServiceImpl implements WmsMerchantService { |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | 81 | @Override |
| 82 | + public WmsMerchantDO validateCustomerMerchantExists(Long id) { | |
| 83 | + WmsMerchantDO merchant = validateMerchantExists(id); | |
| 84 | + if (ObjectUtil.notEqual(merchant.getType(), WmsMerchantTypeEnum.CUSTOMER.getType()) | |
| 85 | + && ObjectUtil.notEqual(merchant.getType(), WmsMerchantTypeEnum.CUSTOMER_SUPPLIER.getType())) { | |
| 86 | + throw exception(MERCHANT_NOT_CUSTOMER); | |
| 87 | + } | |
| 88 | + return merchant; | |
| 89 | + } | |
| 90 | + | |
| 91 | + @Override | |
| 82 | 92 | public WmsMerchantDO getMerchant(Long id) { |
| 83 | 93 | return merchantMapper.selectById(id); |
| 84 | 94 | } | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/receipt/WmsReceiptOrderServiceImpl.java
| ... | ... | @@ -171,6 +171,14 @@ public class WmsReceiptOrderServiceImpl implements WmsReceiptOrderService { |
| 171 | 171 | return order; |
| 172 | 172 | } |
| 173 | 173 | |
| 174 | + /** | |
| 175 | + * 增加入库单对应库存。 | |
| 176 | + * | |
| 177 | + * 入库在库存变更模型中使用正数数量;批次模式下,会根据入库明细生成新的库存明细。 | |
| 178 | + * | |
| 179 | + * @param order 入库单 | |
| 180 | + * @param details 入库单明细列表 | |
| 181 | + */ | |
| 174 | 182 | private void createInventory(WmsReceiptOrderDO order, List<WmsReceiptOrderDetailDO> details) { |
| 175 | 183 | List<WmsInventoryChangeReqDTO.Item> items = convertList(details, |
| 176 | 184 | detail -> BeanUtils.toBean(detail, WmsInventoryChangeReqDTO.Item.class)); | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderDetailService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.shipment; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO; | |
| 4 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO; | |
| 5 | + | |
| 6 | +import java.util.Collection; | |
| 7 | +import java.util.List; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * WMS 出库单明细 Service 接口 | |
| 11 | + * | |
| 12 | + * @author 芋道源码 | |
| 13 | + */ | |
| 14 | +public interface WmsShipmentOrderDetailService { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 创建出库单明细列表 | |
| 18 | + * | |
| 19 | + * @param orderId 出库单编号 | |
| 20 | + * @param reqVO 出库单保存信息 | |
| 21 | + */ | |
| 22 | + void createShipmentOrderDetailList(Long orderId, WmsShipmentOrderSaveReqVO reqVO); | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * 更新出库单明细列表 | |
| 26 | + * | |
| 27 | + * @param orderId 出库单编号 | |
| 28 | + * @param reqVO 出库单保存信息 | |
| 29 | + */ | |
| 30 | + void updateShipmentOrderDetailList(Long orderId, WmsShipmentOrderSaveReqVO reqVO); | |
| 31 | + | |
| 32 | + /** | |
| 33 | + * 按出库单编号删除明细列表 | |
| 34 | + * | |
| 35 | + * @param orderId 出库单编号 | |
| 36 | + */ | |
| 37 | + void deleteShipmentOrderDetailListByOrderId(Long orderId); | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * 按出库单编号获得明细列表 | |
| 41 | + * | |
| 42 | + * @param orderId 出库单编号 | |
| 43 | + * @return 明细列表 | |
| 44 | + */ | |
| 45 | + List<WmsShipmentOrderDetailDO> getShipmentOrderDetailList(Long orderId); | |
| 46 | + | |
| 47 | + /** | |
| 48 | + * 按出库单编号集合获得明细列表 | |
| 49 | + * | |
| 50 | + * @param orderIds 出库单编号集合 | |
| 51 | + * @return 明细列表 | |
| 52 | + */ | |
| 53 | + List<WmsShipmentOrderDetailDO> getShipmentOrderDetailList(Collection<Long> orderIds); | |
| 54 | + | |
| 55 | + /** | |
| 56 | + * 校验出库单明细列表存在 | |
| 57 | + * | |
| 58 | + * @param orderId 出库单编号 | |
| 59 | + * @return 明细列表 | |
| 60 | + */ | |
| 61 | + List<WmsShipmentOrderDetailDO> validateShipmentOrderDetailListExists(Long orderId); | |
| 62 | + | |
| 63 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderDetailServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.shipment; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.hutool.core.collection.ListUtil; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 6 | +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | |
| 7 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO; | |
| 8 | +import cn.iocoder.yudao.module.wms.dal.dataobject.md.warehouse.WmsWarehouseAreaDO; | |
| 9 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO; | |
| 10 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.shipment.WmsShipmentOrderDetailMapper; | |
| 11 | +import cn.iocoder.yudao.module.wms.framework.config.WmsProperties; | |
| 12 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 13 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseAreaService; | |
| 14 | +import jakarta.annotation.Resource; | |
| 15 | +import org.springframework.stereotype.Service; | |
| 16 | +import org.springframework.transaction.annotation.Transactional; | |
| 17 | +import org.springframework.validation.annotation.Validated; | |
| 18 | + | |
| 19 | +import java.util.Collection; | |
| 20 | +import java.util.List; | |
| 21 | + | |
| 22 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 23 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 24 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; | |
| 25 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.*; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * WMS 出库单明细 Service 实现类 | |
| 29 | + * | |
| 30 | + * @author 芋道源码 | |
| 31 | + */ | |
| 32 | +@Service | |
| 33 | +@Validated | |
| 34 | +public class WmsShipmentOrderDetailServiceImpl implements WmsShipmentOrderDetailService { | |
| 35 | + | |
| 36 | + @Resource | |
| 37 | + private WmsShipmentOrderDetailMapper shipmentOrderDetailMapper; | |
| 38 | + @Resource | |
| 39 | + private WmsItemSkuService itemSkuService; | |
| 40 | + @Resource | |
| 41 | + private WmsWarehouseAreaService warehouseAreaService; | |
| 42 | + @Resource | |
| 43 | + private WmsProperties wmsProperties; | |
| 44 | + | |
| 45 | + @Override | |
| 46 | + @Transactional(rollbackFor = Exception.class) | |
| 47 | + public void createShipmentOrderDetailList(Long orderId, WmsShipmentOrderSaveReqVO reqVO) { | |
| 48 | + List<WmsShipmentOrderDetailDO> list = buildShipmentOrderDetailList(reqVO); | |
| 49 | + if (CollUtil.isEmpty(list)) { | |
| 50 | + return; | |
| 51 | + } | |
| 52 | + list.forEach(detail -> detail.setId(null).setOrderId(orderId)); | |
| 53 | + shipmentOrderDetailMapper.insertBatch(list); | |
| 54 | + } | |
| 55 | + | |
| 56 | + @Override | |
| 57 | + @Transactional(rollbackFor = Exception.class) | |
| 58 | + public void updateShipmentOrderDetailList(Long orderId, WmsShipmentOrderSaveReqVO reqVO) { | |
| 59 | + // 第一步,对比新老数据,获得添加、修改、删除的列表 | |
| 60 | + List<WmsShipmentOrderDetailDO> oldList = shipmentOrderDetailMapper.selectListByOrderId(orderId); | |
| 61 | + List<WmsShipmentOrderDetailDO> list = buildShipmentOrderDetailList(reqVO); | |
| 62 | + List<WmsShipmentOrderDetailDO> newList = CollUtil.isEmpty(list) ? ListUtil.of() : list; | |
| 63 | + List<List<WmsShipmentOrderDetailDO>> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 | |
| 64 | + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); | |
| 65 | + | |
| 66 | + // 第二步,批量添加、修改、删除 | |
| 67 | + if (CollUtil.isNotEmpty(diffList.get(0))) { | |
| 68 | + if (CollUtil.isNotEmpty(convertList(diffList.get(0), WmsShipmentOrderDetailDO::getId))) { | |
| 69 | + throw exception(SHIPMENT_ORDER_DETAIL_NOT_EXISTS); | |
| 70 | + } | |
| 71 | + diffList.get(0).forEach(detail -> detail.setOrderId(orderId)); | |
| 72 | + shipmentOrderDetailMapper.insertBatch(diffList.get(0)); | |
| 73 | + } | |
| 74 | + if (CollUtil.isNotEmpty(diffList.get(1))) { | |
| 75 | + diffList.get(1).forEach(detail -> detail.setOrderId(orderId)); | |
| 76 | + shipmentOrderDetailMapper.updateBatch(diffList.get(1)); | |
| 77 | + } | |
| 78 | + if (CollUtil.isNotEmpty(diffList.get(2))) { | |
| 79 | + shipmentOrderDetailMapper.deleteByIds(convertList(diffList.get(2), WmsShipmentOrderDetailDO::getId)); | |
| 80 | + } | |
| 81 | + } | |
| 82 | + | |
| 83 | + @Override | |
| 84 | + public void deleteShipmentOrderDetailListByOrderId(Long orderId) { | |
| 85 | + shipmentOrderDetailMapper.deleteByOrderId(orderId); | |
| 86 | + } | |
| 87 | + | |
| 88 | + @Override | |
| 89 | + public List<WmsShipmentOrderDetailDO> getShipmentOrderDetailList(Long orderId) { | |
| 90 | + return shipmentOrderDetailMapper.selectListByOrderId(orderId); | |
| 91 | + } | |
| 92 | + | |
| 93 | + @Override | |
| 94 | + public List<WmsShipmentOrderDetailDO> getShipmentOrderDetailList(Collection<Long> orderIds) { | |
| 95 | + if (CollUtil.isEmpty(orderIds)) { | |
| 96 | + return ListUtil.of(); | |
| 97 | + } | |
| 98 | + return shipmentOrderDetailMapper.selectListByOrderIds(orderIds); | |
| 99 | + } | |
| 100 | + | |
| 101 | + @Override | |
| 102 | + public List<WmsShipmentOrderDetailDO> validateShipmentOrderDetailListExists(Long orderId) { | |
| 103 | + List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailMapper.selectListByOrderId(orderId); | |
| 104 | + if (CollUtil.isEmpty(details)) { | |
| 105 | + throw exception(SHIPMENT_ORDER_DETAIL_REQUIRED); | |
| 106 | + } | |
| 107 | + if (wmsProperties.isAreaEnabled() && details.stream() | |
| 108 | + .anyMatch(detail -> ObjectUtils.equalsAny(detail.getAreaId(), null, WmsWarehouseAreaDO.ID_EMPTY))) { | |
| 109 | + throw exception(SHIPMENT_ORDER_AREA_REQUIRED); | |
| 110 | + } | |
| 111 | + return details; | |
| 112 | + } | |
| 113 | + | |
| 114 | + private List<WmsShipmentOrderDetailDO> buildShipmentOrderDetailList(WmsShipmentOrderSaveReqVO reqVO) { | |
| 115 | + if (CollUtil.isEmpty(reqVO.getDetails())) { | |
| 116 | + return ListUtil.of(); | |
| 117 | + } | |
| 118 | + return convertList(reqVO.getDetails(), detail -> { | |
| 119 | + // 校验 SKU 存在 | |
| 120 | + itemSkuService.validateItemSkuExists(detail.getSkuId()); | |
| 121 | + // 校验仓库区域存在,并且属于当前仓库 | |
| 122 | + Long areaId = warehouseAreaService.validateAndNormalizeWarehouseAreaId( | |
| 123 | + detail.getAreaId() == null ? reqVO.getAreaId() : detail.getAreaId(), reqVO.getWarehouseId()); | |
| 124 | + // 构建对象 | |
| 125 | + return BeanUtils.toBean(detail, WmsShipmentOrderDetailDO.class) | |
| 126 | + .setWarehouseId(reqVO.getWarehouseId()).setAreaId(areaId); | |
| 127 | + }); | |
| 128 | + } | |
| 129 | + | |
| 130 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderService.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.shipment; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderPageReqVO; | |
| 5 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDO; | |
| 7 | +import jakarta.validation.Valid; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * WMS 出库单 Service 接口 | |
| 11 | + * | |
| 12 | + * @author 芋道源码 | |
| 13 | + */ | |
| 14 | +public interface WmsShipmentOrderService { | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * 创建出库单 | |
| 18 | + * | |
| 19 | + * @param createReqVO 创建信息 | |
| 20 | + * @return 编号 | |
| 21 | + */ | |
| 22 | + Long createShipmentOrder(@Valid WmsShipmentOrderSaveReqVO createReqVO); | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * 更新出库单 | |
| 26 | + * | |
| 27 | + * @param updateReqVO 更新信息 | |
| 28 | + */ | |
| 29 | + void updateShipmentOrder(@Valid WmsShipmentOrderSaveReqVO updateReqVO); | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * 删除出库单 | |
| 33 | + * | |
| 34 | + * @param id 编号 | |
| 35 | + */ | |
| 36 | + void deleteShipmentOrder(Long id); | |
| 37 | + | |
| 38 | + /** | |
| 39 | + * 完成出库 | |
| 40 | + * | |
| 41 | + * @param id 编号 | |
| 42 | + */ | |
| 43 | + void completeShipmentOrder(Long id); | |
| 44 | + | |
| 45 | + /** | |
| 46 | + * 作废出库单 | |
| 47 | + * | |
| 48 | + * @param id 编号 | |
| 49 | + */ | |
| 50 | + void cancelShipmentOrder(Long id); | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * 获得出库单 | |
| 54 | + * | |
| 55 | + * @param id 编号 | |
| 56 | + * @return 出库单 | |
| 57 | + */ | |
| 58 | + WmsShipmentOrderDO getShipmentOrder(Long id); | |
| 59 | + | |
| 60 | + /** | |
| 61 | + * 获得出库单分页 | |
| 62 | + * | |
| 63 | + * @param pageReqVO 分页查询 | |
| 64 | + * @return 出库单分页 | |
| 65 | + */ | |
| 66 | + PageResult<WmsShipmentOrderDO> getShipmentOrderPage(WmsShipmentOrderPageReqVO pageReqVO); | |
| 67 | + | |
| 68 | +} | ... | ... |
yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImpl.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.shipment; | |
| 2 | + | |
| 3 | +import cn.hutool.core.util.ObjectUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 5 | +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | |
| 6 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderPageReqVO; | |
| 7 | +import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order.WmsShipmentOrderSaveReqVO; | |
| 8 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDO; | |
| 9 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO; | |
| 10 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.shipment.WmsShipmentOrderMapper; | |
| 11 | +import cn.iocoder.yudao.module.wms.enums.inventory.WmsInventoryOrderTypeEnum; | |
| 12 | +import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum; | |
| 13 | +import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService; | |
| 14 | +import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO; | |
| 15 | +import cn.iocoder.yudao.module.wms.service.md.merchant.WmsMerchantService; | |
| 16 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService; | |
| 17 | +import jakarta.annotation.Resource; | |
| 18 | +import org.springframework.stereotype.Service; | |
| 19 | +import org.springframework.transaction.annotation.Transactional; | |
| 20 | +import org.springframework.validation.annotation.Validated; | |
| 21 | + | |
| 22 | +import java.math.BigDecimal; | |
| 23 | +import java.util.List; | |
| 24 | + | |
| 25 | +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | |
| 26 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | |
| 27 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.*; | |
| 28 | + | |
| 29 | +/** | |
| 30 | + * WMS 出库单 Service 实现类 | |
| 31 | + * | |
| 32 | + * @author 芋道源码 | |
| 33 | + */ | |
| 34 | +@Service | |
| 35 | +@Validated | |
| 36 | +public class WmsShipmentOrderServiceImpl implements WmsShipmentOrderService { | |
| 37 | + | |
| 38 | + @Resource | |
| 39 | + private WmsShipmentOrderMapper shipmentOrderMapper; | |
| 40 | + @Resource | |
| 41 | + private WmsShipmentOrderDetailService shipmentOrderDetailService; | |
| 42 | + @Resource | |
| 43 | + private WmsWarehouseService warehouseService; | |
| 44 | + @Resource | |
| 45 | + private WmsMerchantService merchantService; | |
| 46 | + @Resource | |
| 47 | + private WmsInventoryService inventoryService; | |
| 48 | + | |
| 49 | + @Override | |
| 50 | + @Transactional(rollbackFor = Exception.class) | |
| 51 | + public Long createShipmentOrder(WmsShipmentOrderSaveReqVO createReqVO) { | |
| 52 | + // 1. 校验出库单保存数据 | |
| 53 | + validateShipmentOrderSaveData(createReqVO); | |
| 54 | + | |
| 55 | + // 2.1 插入出库单 | |
| 56 | + WmsShipmentOrderDO order = BeanUtils.toBean(createReqVO, WmsShipmentOrderDO.class); | |
| 57 | + order.setStatus(WmsOrderStatusEnum.PREPARE.getStatus()); | |
| 58 | + shipmentOrderMapper.insert(order); | |
| 59 | + // 2.2 插入出库单明细 | |
| 60 | + shipmentOrderDetailService.createShipmentOrderDetailList(order.getId(), createReqVO); | |
| 61 | + return order.getId(); | |
| 62 | + } | |
| 63 | + | |
| 64 | + @Override | |
| 65 | + @Transactional(rollbackFor = Exception.class) | |
| 66 | + public void updateShipmentOrder(WmsShipmentOrderSaveReqVO updateReqVO) { | |
| 67 | + // 1. 校验出库单保存数据 | |
| 68 | + validateShipmentOrderPrepare(updateReqVO.getId()); | |
| 69 | + validateShipmentOrderSaveData(updateReqVO); | |
| 70 | + | |
| 71 | + // 2.1 更新出库单 | |
| 72 | + WmsShipmentOrderDO updateObj = BeanUtils.toBean(updateReqVO, WmsShipmentOrderDO.class) | |
| 73 | + .setStatus(WmsOrderStatusEnum.PREPARE.getStatus()); | |
| 74 | + shipmentOrderMapper.updateById(updateObj); | |
| 75 | + // 2.2 更新出库单明细 | |
| 76 | + shipmentOrderDetailService.updateShipmentOrderDetailList(updateReqVO.getId(), updateReqVO); | |
| 77 | + } | |
| 78 | + | |
| 79 | + @Override | |
| 80 | + @Transactional(rollbackFor = Exception.class) | |
| 81 | + public void deleteShipmentOrder(Long id) { | |
| 82 | + // 1. 校验存在,且可删除 | |
| 83 | + WmsShipmentOrderDO order = validateShipmentOrderExists(id); | |
| 84 | + if (ObjectUtil.notEqual(order.getStatus(), WmsOrderStatusEnum.PREPARE.getStatus()) | |
| 85 | + && ObjectUtil.notEqual(order.getStatus(), WmsOrderStatusEnum.CANCELED.getStatus())) { | |
| 86 | + throw exception(SHIPMENT_ORDER_STATUS_NOT_DELETABLE); | |
| 87 | + } | |
| 88 | + | |
| 89 | + // 2.1 删除出库单 | |
| 90 | + shipmentOrderMapper.deleteById(id); | |
| 91 | + // 2.2 删除出库单明细 | |
| 92 | + shipmentOrderDetailService.deleteShipmentOrderDetailListByOrderId(id); | |
| 93 | + } | |
| 94 | + | |
| 95 | + @Override | |
| 96 | + @Transactional(rollbackFor = Exception.class) | |
| 97 | + public void completeShipmentOrder(Long id) { | |
| 98 | + // 1.1 校验存在,且草稿 | |
| 99 | + WmsShipmentOrderDO order = validateShipmentOrderPrepare(id); | |
| 100 | + // 1.2 校验出库单明细存在 | |
| 101 | + List<WmsShipmentOrderDetailDO> details = shipmentOrderDetailService.validateShipmentOrderDetailListExists(id); | |
| 102 | + | |
| 103 | + // 2. 完成出库单 | |
| 104 | + shipmentOrderMapper.updateById(new WmsShipmentOrderDO().setId(id) | |
| 105 | + .setStatus(WmsOrderStatusEnum.FINISHED.getStatus())); | |
| 106 | + | |
| 107 | + // 3. 扣减库存 | |
| 108 | + changeInventory(order, details); | |
| 109 | + } | |
| 110 | + | |
| 111 | + @Override | |
| 112 | + @Transactional(rollbackFor = Exception.class) | |
| 113 | + public void cancelShipmentOrder(Long id) { | |
| 114 | + // 1. 校验存在,且草稿 | |
| 115 | + validateShipmentOrderPrepare(id); | |
| 116 | + | |
| 117 | + // 2. 作废出库单 | |
| 118 | + shipmentOrderMapper.updateById(new WmsShipmentOrderDO().setId(id) | |
| 119 | + .setStatus(WmsOrderStatusEnum.CANCELED.getStatus())); | |
| 120 | + } | |
| 121 | + | |
| 122 | + @Override | |
| 123 | + public WmsShipmentOrderDO getShipmentOrder(Long id) { | |
| 124 | + return shipmentOrderMapper.selectById(id); | |
| 125 | + } | |
| 126 | + | |
| 127 | + @Override | |
| 128 | + public PageResult<WmsShipmentOrderDO> getShipmentOrderPage(WmsShipmentOrderPageReqVO pageReqVO) { | |
| 129 | + return shipmentOrderMapper.selectPage(pageReqVO); | |
| 130 | + } | |
| 131 | + | |
| 132 | + private void validateShipmentOrderSaveData(WmsShipmentOrderSaveReqVO reqVO) { | |
| 133 | + // 校验出库单号唯一 | |
| 134 | + validateShipmentOrderNoUnique(reqVO.getId(), reqVO.getNo()); | |
| 135 | + // 校验仓库存在 | |
| 136 | + warehouseService.validateWarehouseExists(reqVO.getWarehouseId()); | |
| 137 | + // 校验客户类型 | |
| 138 | + if (reqVO.getMerchantId() != null) { | |
| 139 | + merchantService.validateCustomerMerchantExists(reqVO.getMerchantId()); | |
| 140 | + } | |
| 141 | + } | |
| 142 | + | |
| 143 | + private void validateShipmentOrderNoUnique(Long id, String no) { | |
| 144 | + WmsShipmentOrderDO order = shipmentOrderMapper.selectByNo(no); | |
| 145 | + if (order == null) { | |
| 146 | + return; | |
| 147 | + } | |
| 148 | + if (id == null || ObjectUtil.notEqual(order.getId(), id)) { | |
| 149 | + throw exception(SHIPMENT_ORDER_NO_DUPLICATE); | |
| 150 | + } | |
| 151 | + } | |
| 152 | + | |
| 153 | + private WmsShipmentOrderDO validateShipmentOrderExists(Long id) { | |
| 154 | + WmsShipmentOrderDO order = id == null ? null : shipmentOrderMapper.selectById(id); | |
| 155 | + if (order == null) { | |
| 156 | + throw exception(SHIPMENT_ORDER_NOT_EXISTS); | |
| 157 | + } | |
| 158 | + return order; | |
| 159 | + } | |
| 160 | + | |
| 161 | + /** | |
| 162 | + * 校验出库单存在且为草稿状态 | |
| 163 | + * | |
| 164 | + * @param id 出库单编号 | |
| 165 | + * @return 出库单 | |
| 166 | + */ | |
| 167 | + private WmsShipmentOrderDO validateShipmentOrderPrepare(Long id) { | |
| 168 | + WmsShipmentOrderDO order = validateShipmentOrderExists(id); | |
| 169 | + if (ObjectUtil.notEqual(order.getStatus(), WmsOrderStatusEnum.PREPARE.getStatus())) { | |
| 170 | + throw exception(SHIPMENT_ORDER_STATUS_NOT_PREPARE); | |
| 171 | + } | |
| 172 | + return order; | |
| 173 | + } | |
| 174 | + | |
| 175 | + /** | |
| 176 | + * 扣减出库单对应库存。 | |
| 177 | + * | |
| 178 | + * 出库在库存变更模型中使用负数数量;批次模式下,明细里的 inventoryDetailId 会用于扣减对应库存明细的剩余数量。 | |
| 179 | + * | |
| 180 | + * @param order 出库单 | |
| 181 | + * @param details 出库单明细列表 | |
| 182 | + */ | |
| 183 | + private void changeInventory(WmsShipmentOrderDO order, List<WmsShipmentOrderDetailDO> details) { | |
| 184 | + List<WmsInventoryChangeReqDTO.Item> items = convertList(details, | |
| 185 | + detail -> BeanUtils.toBean(detail, WmsInventoryChangeReqDTO.Item.class) | |
| 186 | + .setQuantity(detail.getQuantity().multiply(BigDecimal.valueOf(-1L)))); | |
| 187 | + inventoryService.changeInventory(new WmsInventoryChangeReqDTO() | |
| 188 | + .setOrderId(order.getId()).setOrderNo(order.getNo()) | |
| 189 | + .setOrderType(WmsInventoryOrderTypeEnum.SHIPMENT.getType()).setItems(items)); | |
| 190 | + } | |
| 191 | + | |
| 192 | +} | ... | ... |
yudao-module-wms/src/test/java/cn/iocoder/yudao/module/wms/service/order/shipment/WmsShipmentOrderServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.wms.service.order.shipment; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 4 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDO; | |
| 5 | +import cn.iocoder.yudao.module.wms.dal.dataobject.order.shipment.WmsShipmentOrderDetailDO; | |
| 6 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.shipment.WmsShipmentOrderDetailMapper; | |
| 7 | +import cn.iocoder.yudao.module.wms.dal.mysql.order.shipment.WmsShipmentOrderMapper; | |
| 8 | +import cn.iocoder.yudao.module.wms.enums.inventory.WmsInventoryOrderTypeEnum; | |
| 9 | +import cn.iocoder.yudao.module.wms.enums.order.WmsOrderStatusEnum; | |
| 10 | +import cn.iocoder.yudao.module.wms.enums.order.WmsShipmentOrderTypeEnum; | |
| 11 | +import cn.iocoder.yudao.module.wms.framework.config.WmsProperties; | |
| 12 | +import cn.iocoder.yudao.module.wms.service.inventory.WmsInventoryService; | |
| 13 | +import cn.iocoder.yudao.module.wms.service.inventory.dto.WmsInventoryChangeReqDTO; | |
| 14 | +import cn.iocoder.yudao.module.wms.service.md.item.WmsItemSkuService; | |
| 15 | +import cn.iocoder.yudao.module.wms.service.md.merchant.WmsMerchantService; | |
| 16 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseAreaService; | |
| 17 | +import cn.iocoder.yudao.module.wms.service.md.warehouse.WmsWarehouseService; | |
| 18 | +import jakarta.annotation.Resource; | |
| 19 | +import org.junit.jupiter.api.Test; | |
| 20 | +import org.mockito.ArgumentCaptor; | |
| 21 | +import org.springframework.context.annotation.Import; | |
| 22 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | |
| 23 | + | |
| 24 | +import java.math.BigDecimal; | |
| 25 | + | |
| 26 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 27 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.SHIPMENT_ORDER_AREA_REQUIRED; | |
| 28 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.SHIPMENT_ORDER_DETAIL_REQUIRED; | |
| 29 | +import static cn.iocoder.yudao.module.wms.enums.ErrorCodeConstants.SHIPMENT_ORDER_STATUS_NOT_DELETABLE; | |
| 30 | +import static org.junit.jupiter.api.Assertions.assertEquals; | |
| 31 | +import static org.junit.jupiter.api.Assertions.assertNotNull; | |
| 32 | +import static org.junit.jupiter.api.Assertions.assertNull; | |
| 33 | +import static org.mockito.ArgumentMatchers.any; | |
| 34 | +import static org.mockito.Mockito.never; | |
| 35 | +import static org.mockito.Mockito.verify; | |
| 36 | + | |
| 37 | +@Import({WmsShipmentOrderServiceImpl.class, WmsShipmentOrderDetailServiceImpl.class, WmsProperties.class}) | |
| 38 | +public class WmsShipmentOrderServiceImplTest extends BaseDbUnitTest { | |
| 39 | + | |
| 40 | + @Resource | |
| 41 | + private WmsShipmentOrderServiceImpl shipmentOrderService; | |
| 42 | + | |
| 43 | + @Resource | |
| 44 | + private WmsShipmentOrderMapper shipmentOrderMapper; | |
| 45 | + @Resource | |
| 46 | + private WmsShipmentOrderDetailMapper shipmentOrderDetailMapper; | |
| 47 | + | |
| 48 | + @MockitoBean | |
| 49 | + private WmsWarehouseService warehouseService; | |
| 50 | + @MockitoBean | |
| 51 | + private WmsWarehouseAreaService warehouseAreaService; | |
| 52 | + @MockitoBean | |
| 53 | + private WmsMerchantService merchantService; | |
| 54 | + @MockitoBean | |
| 55 | + private WmsItemSkuService itemSkuService; | |
| 56 | + @MockitoBean | |
| 57 | + private WmsInventoryService inventoryService; | |
| 58 | + | |
| 59 | + @Test | |
| 60 | + public void testCompleteShipmentOrder_success() { | |
| 61 | + // mock 数据 | |
| 62 | + Long warehouseId = 100L; | |
| 63 | + Long skuId = 200L; | |
| 64 | + Long inventoryDetailId = 300L; | |
| 65 | + WmsShipmentOrderDO order = createShipmentOrder(warehouseId); | |
| 66 | + shipmentOrderMapper.insert(order); | |
| 67 | + shipmentOrderDetailMapper.insert(createShipmentOrderDetail(order.getId(), skuId, warehouseId, 400L, | |
| 68 | + inventoryDetailId)); | |
| 69 | + | |
| 70 | + // 调用 | |
| 71 | + shipmentOrderService.completeShipmentOrder(order.getId()); | |
| 72 | + | |
| 73 | + // 断言:出库单 | |
| 74 | + WmsShipmentOrderDO dbOrder = shipmentOrderMapper.selectById(order.getId()); | |
| 75 | + assertNotNull(dbOrder); | |
| 76 | + assertEquals(WmsOrderStatusEnum.FINISHED.getStatus(), dbOrder.getStatus()); | |
| 77 | + // 断言:库存变更 | |
| 78 | + ArgumentCaptor<WmsInventoryChangeReqDTO> captor = ArgumentCaptor.forClass(WmsInventoryChangeReqDTO.class); | |
| 79 | + verify(inventoryService).changeInventory(captor.capture()); | |
| 80 | + WmsInventoryChangeReqDTO inventoryReqDTO = captor.getValue(); | |
| 81 | + assertEquals(order.getId(), inventoryReqDTO.getOrderId()); | |
| 82 | + assertEquals(order.getNo(), inventoryReqDTO.getOrderNo()); | |
| 83 | + assertEquals(WmsInventoryOrderTypeEnum.SHIPMENT.getType(), inventoryReqDTO.getOrderType()); | |
| 84 | + assertEquals(1, inventoryReqDTO.getItems().size()); | |
| 85 | + assertEquals(skuId, inventoryReqDTO.getItems().get(0).getSkuId()); | |
| 86 | + assertEquals(warehouseId, inventoryReqDTO.getItems().get(0).getWarehouseId()); | |
| 87 | + assertEquals(inventoryDetailId, inventoryReqDTO.getItems().get(0).getInventoryDetailId()); | |
| 88 | + assertEquals(0, new BigDecimal("-2.00").compareTo(inventoryReqDTO.getItems().get(0).getQuantity())); | |
| 89 | + } | |
| 90 | + | |
| 91 | + @Test | |
| 92 | + public void testCompleteShipmentOrder_detailRequired() { | |
| 93 | + // mock 数据 | |
| 94 | + WmsShipmentOrderDO order = createShipmentOrder(100L); | |
| 95 | + shipmentOrderMapper.insert(order); | |
| 96 | + | |
| 97 | + // 调用,并断言 | |
| 98 | + assertServiceException(() -> shipmentOrderService.completeShipmentOrder(order.getId()), | |
| 99 | + SHIPMENT_ORDER_DETAIL_REQUIRED); | |
| 100 | + verify(inventoryService, never()).changeInventory(any()); | |
| 101 | + } | |
| 102 | + | |
| 103 | + @Test | |
| 104 | + public void testCompleteShipmentOrder_areaRequired() { | |
| 105 | + // mock 数据 | |
| 106 | + WmsShipmentOrderDO order = createShipmentOrder(100L); | |
| 107 | + shipmentOrderMapper.insert(order); | |
| 108 | + shipmentOrderDetailMapper.insert(createShipmentOrderDetail(order.getId(), 200L, 100L, 0L, null)); | |
| 109 | + | |
| 110 | + // 调用,并断言 | |
| 111 | + assertServiceException(() -> shipmentOrderService.completeShipmentOrder(order.getId()), | |
| 112 | + SHIPMENT_ORDER_AREA_REQUIRED); | |
| 113 | + verify(inventoryService, never()).changeInventory(any()); | |
| 114 | + } | |
| 115 | + | |
| 116 | + @Test | |
| 117 | + public void testCancelShipmentOrder_success() { | |
| 118 | + // mock 数据 | |
| 119 | + WmsShipmentOrderDO order = createShipmentOrder(100L); | |
| 120 | + shipmentOrderMapper.insert(order); | |
| 121 | + | |
| 122 | + // 调用 | |
| 123 | + shipmentOrderService.cancelShipmentOrder(order.getId()); | |
| 124 | + | |
| 125 | + // 断言 | |
| 126 | + WmsShipmentOrderDO dbOrder = shipmentOrderMapper.selectById(order.getId()); | |
| 127 | + assertNotNull(dbOrder); | |
| 128 | + assertEquals(WmsOrderStatusEnum.CANCELED.getStatus(), dbOrder.getStatus()); | |
| 129 | + verify(inventoryService, never()).changeInventory(any()); | |
| 130 | + } | |
| 131 | + | |
| 132 | + @Test | |
| 133 | + public void testDeleteShipmentOrder_canceled() { | |
| 134 | + // mock 数据 | |
| 135 | + WmsShipmentOrderDO order = createShipmentOrder(100L).setStatus(WmsOrderStatusEnum.CANCELED.getStatus()); | |
| 136 | + shipmentOrderMapper.insert(order); | |
| 137 | + shipmentOrderDetailMapper.insert(createShipmentOrderDetail(order.getId(), 200L, 100L, 300L, null)); | |
| 138 | + | |
| 139 | + // 调用 | |
| 140 | + shipmentOrderService.deleteShipmentOrder(order.getId()); | |
| 141 | + | |
| 142 | + // 断言 | |
| 143 | + assertNull(shipmentOrderMapper.selectById(order.getId())); | |
| 144 | + assertEquals(0, shipmentOrderDetailMapper.selectListByOrderId(order.getId()).size()); | |
| 145 | + } | |
| 146 | + | |
| 147 | + @Test | |
| 148 | + public void testDeleteShipmentOrder_finished() { | |
| 149 | + // mock 数据 | |
| 150 | + WmsShipmentOrderDO order = createShipmentOrder(100L).setStatus(WmsOrderStatusEnum.FINISHED.getStatus()); | |
| 151 | + shipmentOrderMapper.insert(order); | |
| 152 | + | |
| 153 | + // 调用,并断言 | |
| 154 | + assertServiceException(() -> shipmentOrderService.deleteShipmentOrder(order.getId()), | |
| 155 | + SHIPMENT_ORDER_STATUS_NOT_DELETABLE); | |
| 156 | + } | |
| 157 | + | |
| 158 | + private static WmsShipmentOrderDO createShipmentOrder(Long warehouseId) { | |
| 159 | + return new WmsShipmentOrderDO() | |
| 160 | + .setNo("CK202605120001") | |
| 161 | + .setType(WmsShipmentOrderTypeEnum.SALE.getType()) | |
| 162 | + .setStatus(WmsOrderStatusEnum.PREPARE.getStatus()) | |
| 163 | + .setWarehouseId(warehouseId) | |
| 164 | + .setAreaId(0L) | |
| 165 | + .setTotalQuantity(new BigDecimal("2.00")) | |
| 166 | + .setTotalAmount(new BigDecimal("20.00")); | |
| 167 | + } | |
| 168 | + | |
| 169 | + private static WmsShipmentOrderDetailDO createShipmentOrderDetail(Long orderId, Long skuId, Long warehouseId, | |
| 170 | + Long areaId, Long inventoryDetailId) { | |
| 171 | + return WmsShipmentOrderDetailDO.builder() | |
| 172 | + .orderId(orderId) | |
| 173 | + .skuId(skuId) | |
| 174 | + .warehouseId(warehouseId) | |
| 175 | + .areaId(areaId) | |
| 176 | + .inventoryDetailId(inventoryDetailId) | |
| 177 | + .quantity(new BigDecimal("2.00")) | |
| 178 | + .amount(new BigDecimal("20.00")) | |
| 179 | + .build(); | |
| 180 | + } | |
| 181 | + | |
| 182 | +} | ... | ... |
yudao-module-wms/src/test/resources/sql/clean.sql
yudao-module-wms/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -106,8 +106,8 @@ CREATE TABLE IF NOT EXISTS "wms_inventory_history" ( |
| 106 | 106 | CREATE TABLE IF NOT EXISTS "wms_receipt_order" ( |
| 107 | 107 | "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, |
| 108 | 108 | "no" varchar(64) NOT NULL, |
| 109 | - "type" tinyint NOT NULL, | |
| 110 | - "status" tinyint NOT NULL DEFAULT '0', | |
| 109 | + "type" int NOT NULL, | |
| 110 | + "status" int NOT NULL DEFAULT '0', | |
| 111 | 111 | "biz_order_no" varchar(64) DEFAULT NULL, |
| 112 | 112 | "merchant_id" bigint DEFAULT NULL, |
| 113 | 113 | "remark" varchar(255) DEFAULT NULL, |
| ... | ... | @@ -144,3 +144,46 @@ CREATE TABLE IF NOT EXISTS "wms_receipt_order_detail" ( |
| 144 | 144 | "tenant_id" bigint NOT NULL DEFAULT '0', |
| 145 | 145 | PRIMARY KEY ("id") |
| 146 | 146 | ) COMMENT 'WMS 入库单明细表'; |
| 147 | + | |
| 148 | +CREATE TABLE IF NOT EXISTS "wms_shipment_order" ( | |
| 149 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 150 | + "no" varchar(64) NOT NULL, | |
| 151 | + "type" int NOT NULL, | |
| 152 | + "status" int NOT NULL DEFAULT '0', | |
| 153 | + "biz_order_no" varchar(64) DEFAULT NULL, | |
| 154 | + "merchant_id" bigint DEFAULT NULL, | |
| 155 | + "remark" varchar(255) DEFAULT NULL, | |
| 156 | + "warehouse_id" bigint NOT NULL, | |
| 157 | + "area_id" bigint NOT NULL DEFAULT '0', | |
| 158 | + "total_quantity" decimal(20, 2) NOT NULL DEFAULT '0', | |
| 159 | + "total_amount" decimal(10, 2) DEFAULT NULL, | |
| 160 | + "creator" varchar(64) DEFAULT '', | |
| 161 | + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 162 | + "updater" varchar(64) DEFAULT '', | |
| 163 | + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 164 | + "deleted" bit NOT NULL DEFAULT FALSE, | |
| 165 | + "tenant_id" bigint NOT NULL DEFAULT '0', | |
| 166 | + PRIMARY KEY ("id") | |
| 167 | +) COMMENT 'WMS 出库单表'; | |
| 168 | + | |
| 169 | +CREATE TABLE IF NOT EXISTS "wms_shipment_order_detail" ( | |
| 170 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 171 | + "remark" varchar(255) DEFAULT NULL, | |
| 172 | + "order_id" bigint NOT NULL, | |
| 173 | + "sku_id" bigint NOT NULL, | |
| 174 | + "warehouse_id" bigint NOT NULL, | |
| 175 | + "area_id" bigint NOT NULL DEFAULT '0', | |
| 176 | + "inventory_detail_id" bigint DEFAULT NULL, | |
| 177 | + "batch_no" varchar(64) DEFAULT NULL, | |
| 178 | + "production_date" timestamp DEFAULT NULL, | |
| 179 | + "expiration_date" timestamp DEFAULT NULL, | |
| 180 | + "quantity" decimal(20, 2) NOT NULL DEFAULT '0', | |
| 181 | + "amount" decimal(10, 2) DEFAULT NULL, | |
| 182 | + "creator" varchar(64) DEFAULT '', | |
| 183 | + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 184 | + "updater" varchar(64) DEFAULT '', | |
| 185 | + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 186 | + "deleted" bit NOT NULL DEFAULT FALSE, | |
| 187 | + "tenant_id" bigint NOT NULL DEFAULT '0', | |
| 188 | + PRIMARY KEY ("id") | |
| 189 | +) COMMENT 'WMS 出库单明细表'; | ... | ... |