完成采购调拨单,入库单,部分库存盘点。

This commit is contained in:
c
2026-03-10 09:55:02 +08:00
parent 263902969d
commit c15c5c9a09
9 changed files with 183 additions and 246 deletions

View File

@@ -23,6 +23,7 @@ public class CustomerTenantHandler implements TenantLineHandler {
customerTables.add("storage_list"); customerTables.add("storage_list");
customerTables.add("bom_list"); customerTables.add("bom_list");
customerTables.add("vendor"); customerTables.add("vendor");
customerTables.add("productionform");
} }
@Override @Override

View File

@@ -24,6 +24,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
@Tag(name = "InventoryCount") @Tag(name = "InventoryCount")
@@ -41,15 +43,15 @@ public class InventoryCountController {
public BaseResult<IPage<InventoryCountDto>> getInventoryCountPage(@Validated BasePageReqParams pageParams, public BaseResult<IPage<InventoryCountDto>> getInventoryCountPage(@Validated BasePageReqParams pageParams,
@Validated(Get.class) InventoryCountDto searchParams) { @Validated(Get.class) InventoryCountDto searchParams) {
var wrapper = new LambdaQueryWrapper<Document>(); var wrapper = new LambdaQueryWrapper<Document>();
if (searchParams != null) { if (searchParams != null) {
if (StringUtils.hasText(searchParams.searchCode())) { if (StringUtils.hasText(searchParams.searchCode())) {
wrapper.like(Document::getFormCode, searchParams.searchCode()); wrapper.like(Document::getFormCode, searchParams.searchCode());
}
} }
}
wrapper.orderByDesc(Document::getCreateDate);
return BaseResult.successWithData(inventoryCountService.getInventoryCountPage(pageParams, wrapper)); return BaseResult.successWithData(inventoryCountService.getInventoryCountPage(pageParams, wrapper));
} }
@ApiLog(type = OperationType.ADD, remark = "新增一条InventoryCount记录") @ApiLog(type = OperationType.ADD, remark = "新增一条InventoryCount记录")
@Operation(summary = "新增InventoryCount", operationId = "addInventoryCount") @Operation(summary = "新增InventoryCount", operationId = "addInventoryCount")
@PostMapping("/addInventoryCount") @PostMapping("/addInventoryCount")
@@ -59,66 +61,20 @@ public class InventoryCountController {
return BaseResult.success(); return BaseResult.success();
} }
@ApiLog(type = OperationType.UPDATE, remark = "更新一条InventoryCount记录")
@Operation(summary = "更新InventoryCount", operationId = "updateInventoryCount")
@PostMapping("/updateInventoryCount")
@PreAuthorize("hasAuthority('inventory_count:update')")
public BaseResult<?> updateInventoryCount(@Validated(Update.class) @RequestBody InventoryCountDto dto) {
inventoryCountService.updateInventoryCount(dto);
return BaseResult.success();
}
@ApiLog(type = OperationType.DELETE, remark = "删除一条InventoryCount记录") @ApiLog(type = OperationType.DELETE, remark = "删除一条InventoryCount记录")
@Operation(summary = "删除InventoryCount", operationId = "deleteInventoryCount") @Operation(summary = "删除InventoryCount", operationId = "deleteInventoryCount")
@PostMapping("/deleteInventoryCount") @PostMapping("/deleteInventoryCount")
@PreAuthorize("hasAuthority('inventory_count:delete')") @PreAuthorize("hasAuthority('inventory_count:remove')")
public BaseResult<?> deleteInventoryCount(@Validated(DeleteOne.class) @RequestBody BaseDeleteBody req) { public BaseResult<?> deleteInventoryCount(@Validated(DeleteOne.class) @RequestBody BaseDeleteBody req) {
inventoryCountService.deleteInventoryCount(req.id()); inventoryCountService.deleteInventoryCount(req.id());
return BaseResult.success(); return BaseResult.success();
} }
@ApiLog(type = OperationType.DELETE, remark = "批量删除InventoryCount记录")
@Operation(summary = "批量删除InventoryCount", operationId = "deleteInventoryCountBatch")
@PostMapping("/deleteInventoryCountBatch")
@PreAuthorize("hasAuthority('inventory_count:deleteBatch')")
public BaseResult<?> deleteInventoryCountBatch(@Validated(DeleteBatch.class) @RequestBody BaseDeleteBody req) {
inventoryCountService.deleteBatch(req.ids());
return BaseResult.success();
}
@ApiLog(type = OperationType.UPDATE, remark = "审核InventoryCount")
@Operation(summary = "审核InventoryCount", operationId = "approveInventoryCount")
@PostMapping("/approveInventoryCount")
@PreAuthorize("hasAuthority('inventory_count:approve')")
public BaseResult<?> approveInventoryCount(
@Parameter(description = "盘点单ID") @RequestParam Long id) {
inventoryCountService.approve(id);
return BaseResult.success();
}
@ApiLog(type = OperationType.UPDATE, remark = "反审核InventoryCount")
@Operation(summary = "反审核InventoryCount", operationId = "unapproveInventoryCount")
@PostMapping("/unapproveInventoryCount")
@PreAuthorize("hasAuthority('inventory_count:unapprove')")
public BaseResult<?> unapproveInventoryCount(
@Parameter(description = "盘点单ID") @RequestParam Long id) {
inventoryCountService.unapprove(id);
return BaseResult.success();
}
@Operation(summary = "获取InventoryCount明细", operationId = "getInventoryCountDetail") @Operation(summary = "获取InventoryCount明细", operationId = "getInventoryCountDetail")
@GetMapping("/getInventoryCountDetail") @GetMapping("/getInventoryCountDetail")
@PreAuthorize("hasAuthority('inventorycount:index')") @PreAuthorize("hasAuthority('inventory_count:index')")
public BaseResult<List<InventoryCountItemDto>> getInventoryCountDetail( public BaseResult<List<InventoryCountItemDto>> getInventoryCountDetail(
@Parameter(description = "盘点单ID") @RequestParam Long id) { @Parameter(description = "盘点单ID") @RequestParam Long id) {
return BaseResult.successWithData(inventoryCountService.getDetail(id)); return BaseResult.successWithData(inventoryCountService.getDetail(id));
} }
@Operation(summary = "导入InventoryCount明细", operationId = "importInventoryCountItems")
@PostMapping("/importInventoryCountItems")
@PreAuthorize("hasAuthority('inventory_count:import')")
public BaseResult<List<InventoryCountItemDto>> importInventoryCountItems(
@Parameter(description = "Excel文件") @RequestParam("file") MultipartFile file) {
return BaseResult.successWithData(inventoryCountService.importItems(file));
}
} }

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.niuan.erp.common.annotation.ApiLog; import com.niuan.erp.common.annotation.ApiLog;
import com.niuan.erp.common.annotation.ModuleLog; import com.niuan.erp.common.annotation.ModuleLog;
import com.niuan.erp.common.base.BaseApproveAndRejectDto;
import com.niuan.erp.common.base.BaseDeleteBody; import com.niuan.erp.common.base.BaseDeleteBody;
import com.niuan.erp.common.base.BasePageReqParams; import com.niuan.erp.common.base.BasePageReqParams;
import com.niuan.erp.common.base.BaseResult; import com.niuan.erp.common.base.BaseResult;
@@ -41,11 +42,14 @@ public class WarehouseReceiptController {
public BaseResult<IPage<WarehouseReceiptDto>> getWarehouseReceiptPage(@Validated BasePageReqParams pageParams, public BaseResult<IPage<WarehouseReceiptDto>> getWarehouseReceiptPage(@Validated BasePageReqParams pageParams,
@Validated(Get.class) WarehouseReceiptDto searchParams) { @Validated(Get.class) WarehouseReceiptDto searchParams) {
var wrapper = new LambdaQueryWrapper<Document>(); var wrapper = new LambdaQueryWrapper<Document>();
if (searchParams != null) { if (searchParams != null && StringUtils.hasText(searchParams.searchCode())) {
if (StringUtils.hasText(searchParams.searchCode())) { String searchCode = searchParams.searchCode();
wrapper.like(Document::getFormCode, searchParams.searchCode()); wrapper.and(w -> w.like(Document::getFormCode, searchCode)
} .or()
} .like(Document::getFormName, searchCode)
.or()
.like(Document::getFormMark, searchCode));
}
return BaseResult.successWithData(warehouseReceiptService.getWarehouseReceiptPage(pageParams, wrapper)); return BaseResult.successWithData(warehouseReceiptService.getWarehouseReceiptPage(pageParams, wrapper));
} }
@@ -71,7 +75,7 @@ public class WarehouseReceiptController {
@ApiLog(type = OperationType.DELETE, remark = "删除一条WarehouseReceipt记录") @ApiLog(type = OperationType.DELETE, remark = "删除一条WarehouseReceipt记录")
@Operation(summary = "删除WarehouseReceipt", operationId = "deleteWarehouseReceipt") @Operation(summary = "删除WarehouseReceipt", operationId = "deleteWarehouseReceipt")
@PostMapping("/deleteWarehouseReceipt") @PostMapping("/deleteWarehouseReceipt")
@PreAuthorize("hasAuthority('warehouse_receipt:delete')") @PreAuthorize("hasAuthority('warehouse_receipt:remove')")
public BaseResult<?> deleteWarehouseReceipt(@Validated(DeleteOne.class) @RequestBody BaseDeleteBody req) { public BaseResult<?> deleteWarehouseReceipt(@Validated(DeleteOne.class) @RequestBody BaseDeleteBody req) {
warehouseReceiptService.deleteWarehouseReceipt(req.id()); warehouseReceiptService.deleteWarehouseReceipt(req.id());
return BaseResult.success(); return BaseResult.success();
@@ -91,34 +95,26 @@ public class WarehouseReceiptController {
@PostMapping("/approveWarehouseReceipt") @PostMapping("/approveWarehouseReceipt")
@PreAuthorize("hasAuthority('warehouse_receipt:approve')") @PreAuthorize("hasAuthority('warehouse_receipt:approve')")
public BaseResult<?> approveWarehouseReceipt( public BaseResult<?> approveWarehouseReceipt(
@Parameter(description = "入库单ID") @RequestParam Long id) { @Validated @RequestBody BaseApproveAndRejectDto dto) {
warehouseReceiptService.approve(id); warehouseReceiptService.approve(dto.id());
return BaseResult.success(); return BaseResult.success();
} }
@ApiLog(type = OperationType.UPDATE, remark = "反审核WarehouseReceipt") @ApiLog(type = OperationType.UPDATE, remark = "反审核WarehouseReceipt")
@Operation(summary = "反审核WarehouseReceipt", operationId = "unapproveWarehouseReceipt") @Operation(summary = "反审核WarehouseReceipt", operationId = "rejectWarehouseReceipt")
@PostMapping("/unapproveWarehouseReceipt") @PostMapping("/rejectWarehouseReceipt")
@PreAuthorize("hasAuthority('warehouse_receipt:unapprove')") @PreAuthorize("hasAuthority('warehouse_receipt:reject')")
public BaseResult<?> unapproveWarehouseReceipt( public BaseResult<?> rejectWarehouseReceipt(
@Parameter(description = "入库单ID") @RequestParam Long id) { @Validated @RequestBody BaseApproveAndRejectDto dto) {
warehouseReceiptService.unapprove(id); warehouseReceiptService.reject(dto.id());
return BaseResult.success(); return BaseResult.success();
} }
@Operation(summary = "获取WarehouseReceipt明细", operationId = "getWarehouseReceiptDetail") @Operation(summary = "获取WarehouseReceipt明细", operationId = "getWarehouseReceiptDetail")
@GetMapping("/getWarehouseReceiptDetail") @GetMapping("/getWarehouseReceiptDetail")
@PreAuthorize("hasAuthority('warehousereceipt:index')") @PreAuthorize("hasAuthority('warehouse_receipt:index')")
public BaseResult<List<WarehouseReceiptItemDto>> getWarehouseReceiptDetail( public BaseResult<List<WarehouseReceiptItemDto>> getWarehouseReceiptDetail(
@Parameter(description = "入库单ID") @RequestParam Long id) { @Parameter(description = "入库单ID") @RequestParam Long id) {
return BaseResult.successWithData(warehouseReceiptService.getDetail(id)); return BaseResult.successWithData(warehouseReceiptService.getDetail(id));
} }
@Operation(summary = "导入WarehouseReceipt明细", operationId = "importWarehouseReceiptItems")
@PostMapping("/importWarehouseReceiptItems")
@PreAuthorize("hasAuthority('warehouse_receipt:add')")
public BaseResult<List<WarehouseReceiptItemDto>> importWarehouseReceiptItems(
@Parameter(description = "Excel文件") @RequestParam("file") MultipartFile file) {
return BaseResult.successWithData(warehouseReceiptService.importItems(file));
}
} }

View File

@@ -1,6 +1,7 @@
package com.niuan.erp.module.warehouse.controller.dto; package com.niuan.erp.module.warehouse.controller.dto;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
public record WarehouseReceiptDto( public record WarehouseReceiptDto(
Long id, Long id,
@@ -20,11 +21,6 @@ public record WarehouseReceiptDto(
String formMark, String formMark,
Integer reserve1, Integer reserve1,
String reserve2, String reserve2,
Integer vendorNo,
String vendorName,
Double totalValue,
Integer outStoreNo,
String outStoreName,
Integer groupId,
Integer customerId, Integer customerId,
String searchCode) {} String searchCode,
List<WarehouseReceiptItemAddDto> receiptItems) {}

View File

@@ -22,7 +22,6 @@ public interface InventoryCountConverter {
InventoryCountItem toEntity(InventoryCountItemAddDto dto); InventoryCountItem toEntity(InventoryCountItemAddDto dto);
List<InventoryCountItem> toEntityList(List<InventoryCountItemAddDto> dtoList); List<InventoryCountItem> toEntityList(List<InventoryCountItemAddDto> dtoList);
@Mapping(target = "productSpec", ignore = true)
InventoryCountItemDto toItemDto(InventoryCountItem entity); InventoryCountItemDto toItemDto(InventoryCountItem entity);
List<InventoryCountItemDto> toItemDtoList(List<InventoryCountItem> entities); List<InventoryCountItemDto> toItemDtoList(List<InventoryCountItem> entities);
} }

View File

@@ -25,9 +25,7 @@ public interface WarehouseReceiptService {
void approve(long id); void approve(long id);
void unapprove(long id); void reject(long id);
List<WarehouseReceiptItemDto> getDetail(long id); List<WarehouseReceiptItemDto> getDetail(long id);
List<WarehouseReceiptItemDto> importItems(MultipartFile file);
} }

View File

@@ -18,9 +18,9 @@ import com.niuan.erp.module.warehouse.controller.dto.InventoryCountItemAddDto;
import com.niuan.erp.module.warehouse.controller.dto.InventoryCountItemDto; import com.niuan.erp.module.warehouse.controller.dto.InventoryCountItemDto;
import com.niuan.erp.module.warehouse.converter.InventoryCountConverter; import com.niuan.erp.module.warehouse.converter.InventoryCountConverter;
import com.niuan.erp.module.warehouse.entity.InventoryCountItem; import com.niuan.erp.module.warehouse.entity.InventoryCountItem;
import com.niuan.erp.module.warehouse.entity.Stock; import com.niuan.erp.module.warehouse.entity.WarehouseItem;
import com.niuan.erp.module.warehouse.mapper.InventoryCountItemMapper; import com.niuan.erp.module.warehouse.mapper.InventoryCountItemMapper;
import com.niuan.erp.module.warehouse.mapper.StockMapper; import com.niuan.erp.module.warehouse.mapper.WarehouseItemMapper;
import com.niuan.erp.module.warehouse.service.InventoryCountService; import com.niuan.erp.module.warehouse.service.InventoryCountService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
@@ -45,7 +45,7 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
private final InventoryCountItemMapper inventoryCountItemMapper; private final InventoryCountItemMapper inventoryCountItemMapper;
private final StockMapper stockMapper; private final WarehouseItemMapper warehouseItemMapper;
@Override @Override
public IPage<InventoryCountDto> getInventoryCountPage(BasePageReqParams pageParams, LambdaQueryWrapper<Document> wrapper) { public IPage<InventoryCountDto> getInventoryCountPage(BasePageReqParams pageParams, LambdaQueryWrapper<Document> wrapper) {
@@ -87,20 +87,16 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
.map(InventoryCountItem::getPartNumber) .map(InventoryCountItem::getPartNumber)
.toList(); .toList();
LambdaQueryWrapper<Stock> stockWrapper = new LambdaQueryWrapper<>(); Map<String, Map<String, Object>> stockMaps = warehouseItemMapper.getWarehouseItemStockListByPartNumbers(partNumbers);
stockWrapper.eq(Stock::getStoreNo, dto.storeNo()) Map<String, Integer> stockMap = new HashMap<>();
.in(Stock::getPartNumber, partNumbers); for (Map.Entry<String, Map<String, Object>> entry : stockMaps.entrySet()) {
List<Stock> stockList = stockMapper.selectList(stockWrapper); stockMap.put(entry.getKey(), ((Number) entry.getValue().get("productCount")).intValue());
Map<String, Stock> stockMap = stockList.stream() }
.collect(Collectors.toMap(Stock::getPartNumber, s -> s));
for (InventoryCountItem item : items) { for (InventoryCountItem item : items) {
Stock stock = stockMap.get(item.getPartNumber()); Integer originalCount = stockMap.get(item.getPartNumber());
if (stock == null) { item.setOriginalProductCount(originalCount != null ? originalCount : 0);
throw new BusinessException("warehouse.inventory_count.exception.stock_not_found"); item.setDiffCount(item.getProductCount() - item.getOriginalProductCount());
}
item.setOriginalProductCount(stock.getProductCount());
item.setDiffCount(item.getProductCount() - stock.getProductCount());
} }
} else { } else {
for (InventoryCountItem item : items) { for (InventoryCountItem item : items) {
@@ -121,25 +117,6 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
} }
inventoryCountItemMapper.insert(items); inventoryCountItemMapper.insert(items);
if (isInit == 1) {
List<Stock> newStocks = new ArrayList<>();
for (InventoryCountItem item : items) {
Stock stock = new Stock();
stock.setPartNumber(item.getPartNumber());
stock.setProductCount(item.getProductCount());
stock.setStoreNo(dto.storeNo());
stock.setStoreName(dto.storeName());
stock.setCreateDate(LocalDateTime.now());
stock.setCreateUserId(SecurityUtils.getUserId());
stock.setCreateUserName(SecurityUtils.getUserName());
stock.setStatus(0);
newStocks.add(stock);
}
for (Stock stock : newStocks) {
stockMapper.insert(stock);
}
}
} }
@Override @Override
@@ -214,47 +191,6 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
throw new BusinessException("warehouse.inventory_count.exception.no_items"); throw new BusinessException("warehouse.inventory_count.exception.no_items");
} }
Integer storeNo = entity.getStoreNo();
List<String> partNumbers = items.stream()
.map(InventoryCountItem::getPartNumber)
.toList();
LambdaQueryWrapper<Stock> stockWrapper = new LambdaQueryWrapper<>();
stockWrapper.eq(Stock::getStoreNo, storeNo)
.in(Stock::getPartNumber, partNumbers);
List<Stock> existingStockList = stockMapper.selectList(stockWrapper);
Map<String, Stock> existingStockMap = existingStockList.stream()
.collect(Collectors.toMap(Stock::getPartNumber, s -> s));
List<Stock> newStocks = new ArrayList<>();
for (InventoryCountItem item : items) {
Stock existingStock = existingStockMap.get(item.getPartNumber());
if (existingStock == null) {
Stock newStock = new Stock();
newStock.setPartNumber(item.getPartNumber());
newStock.setProductCount(item.getProductCount());
newStock.setStoreNo(storeNo);
newStock.setStoreName(entity.getStoreName());
newStock.setCreateDate(LocalDateTime.now());
newStock.setCreateUserId(SecurityUtils.getUserId());
newStock.setCreateUserName(SecurityUtils.getUserName());
newStock.setStatus(0);
newStocks.add(newStock);
} else {
existingStock.setProductCount(item.getProductCount());
existingStock.setUpdateDate(LocalDateTime.now());
existingStock.setUpdateUserId(SecurityUtils.getUserId());
existingStock.setUpdateUserName(SecurityUtils.getUserName());
stockMapper.updateById(existingStock);
}
}
if (!newStocks.isEmpty()) {
for (Stock newStock : newStocks) {
stockMapper.insert(newStock);
}
}
entity.setFormStatus(FormStatus.APPROVE); entity.setFormStatus(FormStatus.APPROVE);
entity.setUpdateDate(LocalDateTime.now()); entity.setUpdateDate(LocalDateTime.now());
entity.setUpdateUserId(SecurityUtils.getUserId()); entity.setUpdateUserId(SecurityUtils.getUserId());
@@ -281,31 +217,7 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
LambdaQueryWrapper<InventoryCountItem> itemWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<InventoryCountItem> itemWrapper = new LambdaQueryWrapper<>();
itemWrapper.eq(InventoryCountItem::getDocumentNo, id); itemWrapper.eq(InventoryCountItem::getDocumentNo, id);
List<InventoryCountItem> items = inventoryCountItemMapper.selectList(itemWrapper); inventoryCountItemMapper.selectList(itemWrapper);
Integer storeNo = entity.getStoreNo();
List<String> partNumbers = items.stream()
.map(InventoryCountItem::getPartNumber)
.toList();
LambdaQueryWrapper<Stock> stockWrapper = new LambdaQueryWrapper<>();
stockWrapper.eq(Stock::getStoreNo, storeNo)
.in(Stock::getPartNumber, partNumbers);
List<Stock> existingStockList = stockMapper.selectList(stockWrapper);
Map<String, Stock> existingStockMap = existingStockList.stream()
.collect(Collectors.toMap(Stock::getPartNumber, s -> s));
for (InventoryCountItem item : items) {
Stock existingStock = existingStockMap.get(item.getPartNumber());
if (existingStock == null) {
throw new BusinessException("warehouse.inventory_count.exception.stock_not_found_for_unapprove");
}
existingStock.setProductCount(item.getOriginalProductCount());
existingStock.setUpdateDate(LocalDateTime.now());
existingStock.setUpdateUserId(SecurityUtils.getUserId());
existingStock.setUpdateUserName(SecurityUtils.getUserName());
stockMapper.updateById(existingStock);
}
entity.setFormStatus(FormStatus.NO_APPROVE); entity.setFormStatus(FormStatus.NO_APPROVE);
entity.setUpdateDate(LocalDateTime.now()); entity.setUpdateDate(LocalDateTime.now());
@@ -326,7 +238,47 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
LambdaQueryWrapper<InventoryCountItem> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<InventoryCountItem> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(InventoryCountItem::getDocumentNo, id); wrapper.eq(InventoryCountItem::getDocumentNo, id);
List<InventoryCountItem> items = inventoryCountItemMapper.selectList(wrapper); List<InventoryCountItem> items = inventoryCountItemMapper.selectList(wrapper);
return inventoryCountConverter.toItemDtoList(items);
List<String> partNumbers = items.stream()
.map(InventoryCountItem::getPartNumber)
.filter(Objects::nonNull)
.distinct()
.toList();
Map<String, String> partNumberToSpecs = new HashMap<>();
if (!partNumbers.isEmpty()) {
LambdaQueryWrapper<WarehouseItem> itemWrapper = new LambdaQueryWrapper<>();
itemWrapper.in(WarehouseItem::getPartNumber, partNumbers);
List<WarehouseItem> warehouseItems = warehouseItemMapper.selectList(itemWrapper);
partNumberToSpecs = warehouseItems.stream()
.collect(Collectors.toMap(WarehouseItem::getPartNumber, WarehouseItem::getProductSpecs, (v1, v2) -> v1));
}
List<InventoryCountItemDto> dtoList = inventoryCountConverter.toItemDtoList(items);
Map<String, String> finalPartNumberToSpecs = partNumberToSpecs;
return dtoList.stream()
.map(dto -> new InventoryCountItemDto(
dto.id(),
dto.status(),
dto.createDate(),
dto.createUserId(),
dto.createUserName(),
dto.updateDate(),
dto.updateUserId(),
dto.updateUserName(),
dto.storeNo(),
dto.storeName(),
dto.partNumber(),
dto.productCount(),
dto.diffCount(),
dto.stockTakingMark(),
dto.reserve1(),
dto.reserve2(),
dto.documentNo(),
dto.originalProductCount(),
finalPartNumberToSpecs.get(dto.partNumber())
))
.toList();
} }
@Override @Override

View File

@@ -20,7 +20,9 @@ import com.niuan.erp.module.warehouse.controller.dto.WarehouseReceiptItemAddDto;
import com.niuan.erp.module.warehouse.controller.dto.WarehouseReceiptItemDto; import com.niuan.erp.module.warehouse.controller.dto.WarehouseReceiptItemDto;
import com.niuan.erp.module.warehouse.converter.WarehouseReceiptConverter; import com.niuan.erp.module.warehouse.converter.WarehouseReceiptConverter;
import com.niuan.erp.module.warehouse.entity.Stock; import com.niuan.erp.module.warehouse.entity.Stock;
import com.niuan.erp.module.warehouse.entity.WarehouseItem;
import com.niuan.erp.module.warehouse.mapper.StockMapper; import com.niuan.erp.module.warehouse.mapper.StockMapper;
import com.niuan.erp.module.warehouse.mapper.WarehouseItemMapper;
import com.niuan.erp.module.warehouse.service.WarehouseReceiptService; import com.niuan.erp.module.warehouse.service.WarehouseReceiptService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.*;
@@ -47,9 +49,12 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
private final StockMapper stockMapper; private final StockMapper stockMapper;
private final WarehouseItemMapper warehouseItemMapper;
@Override @Override
public IPage<WarehouseReceiptDto> getWarehouseReceiptPage(BasePageReqParams pageParams, LambdaQueryWrapper<Document> wrapper) { public IPage<WarehouseReceiptDto> getWarehouseReceiptPage(BasePageReqParams pageParams, LambdaQueryWrapper<Document> wrapper) {
wrapper.eq(Document::getFormType, DocumentType.WAREHOUSE_RECEIPT); wrapper.eq(Document::getFormType, DocumentType.WAREHOUSE_RECEIPT)
.orderByDesc(Document::getCreateDate);
IPage<Document> result = this.baseMapper.selectPage(new Page<>(pageParams.page(), pageParams.pageSize()), wrapper); IPage<Document> result = this.baseMapper.selectPage(new Page<>(pageParams.page(), pageParams.pageSize()), wrapper);
return result.convert(warehouseReceiptConverter::toDto); return result.convert(warehouseReceiptConverter::toDto);
} }
@@ -93,6 +98,24 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
entity.setUpdateUserName(SecurityUtils.getUserName()); entity.setUpdateUserName(SecurityUtils.getUserName());
entity.setUpdateDate(LocalDateTime.now()); entity.setUpdateDate(LocalDateTime.now());
this.baseMapper.updateById(entity); this.baseMapper.updateById(entity);
// 删除旧明细
LambdaQueryWrapper<DocumentMaterial> materialWrapper = new LambdaQueryWrapper<>();
materialWrapper.eq(DocumentMaterial::getDocumentNo, dto.id());
documentMaterialMapper.delete(materialWrapper);
// 插入新明细
if (dto.receiptItems() != null && !dto.receiptItems().isEmpty()) {
List<DocumentMaterial> materials = warehouseReceiptConverter.toEntityList(dto.receiptItems());
materials.forEach(m -> {
m.setDocumentNo(dto.id().intValue());
m.setCreateUserId(SecurityUtils.getUserId());
m.setCreateUserName(SecurityUtils.getUserName());
m.setCreateDate(LocalDateTime.now());
m.setStatus(0);
});
documentMaterialMapper.insert(materials);
}
} }
@Override @Override
@@ -162,6 +185,7 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
Map<String, Stock> existingStockMap = existingStockList.stream() Map<String, Stock> existingStockMap = existingStockList.stream()
.collect(Collectors.toMap(Stock::getPartNumber, s -> s)); .collect(Collectors.toMap(Stock::getPartNumber, s -> s));
String storeName = entity.getStoreName();
List<Stock> newStocks = new ArrayList<>(); List<Stock> newStocks = new ArrayList<>();
for (DocumentMaterial material : materialList) { for (DocumentMaterial material : materialList) {
Stock existingStock = existingStockMap.get(material.getPartNumber()); Stock existingStock = existingStockMap.get(material.getPartNumber());
@@ -170,6 +194,7 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
newStock.setPartNumber(material.getPartNumber()); newStock.setPartNumber(material.getPartNumber());
newStock.setProductCount(material.getProductCount()); newStock.setProductCount(material.getProductCount());
newStock.setStoreNo(storeNo); newStock.setStoreNo(storeNo);
newStock.setStoreName(storeName);
newStock.setCreateDate(LocalDateTime.now()); newStock.setCreateDate(LocalDateTime.now());
newStock.setCreateUserId(SecurityUtils.getUserId()); newStock.setCreateUserId(SecurityUtils.getUserId());
newStock.setCreateUserName(SecurityUtils.getUserName()); newStock.setCreateUserName(SecurityUtils.getUserName());
@@ -205,7 +230,7 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
} }
@Override @Override
public void unapprove(long id) { public void reject(long id) {
Document entity = this.baseMapper.selectById(id); Document entity = this.baseMapper.selectById(id);
if (entity == null) { if (entity == null) {
throw new BusinessException("warehouse.warehouse_receipt.exception.not_found"); throw new BusinessException("warehouse.warehouse_receipt.exception.not_found");
@@ -264,60 +289,52 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
LambdaQueryWrapper<DocumentMaterial> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<DocumentMaterial> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(DocumentMaterial::getDocumentNo, id); wrapper.eq(DocumentMaterial::getDocumentNo, id);
List<DocumentMaterial> materials = documentMaterialMapper.selectList(wrapper); List<DocumentMaterial> materials = documentMaterialMapper.selectList(wrapper);
return warehouseReceiptConverter.toItemDtoList(materials);
}
@Override // 获取所有物料编号
public List<WarehouseReceiptItemDto> importItems(MultipartFile file) { List<String> partNumbers = materials.stream()
if (file == null || file.isEmpty()) { .map(DocumentMaterial::getPartNumber)
throw new BusinessException("warehouse.warehouse_receipt.exception.file_empty"); .filter(Objects::nonNull)
.distinct()
.toList();
// 查询物料规格信息
Map<String, String> partNumberToSpecs = new HashMap<>();
if (!partNumbers.isEmpty()) {
LambdaQueryWrapper<WarehouseItem> itemWrapper = new LambdaQueryWrapper<>();
itemWrapper.in(WarehouseItem::getPartNumber, partNumbers);
List<WarehouseItem> items = warehouseItemMapper.selectList(itemWrapper);
partNumberToSpecs = items.stream()
.collect(Collectors.toMap(WarehouseItem::getPartNumber, WarehouseItem::getProductSpecs, (v1, v2) -> v1));
} }
try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) { // 转换并填充 productSpec
Sheet sheet = workbook.getSheetAt(0); List<WarehouseReceiptItemDto> dtoList = warehouseReceiptConverter.toItemDtoList(materials);
List<WarehouseReceiptItemDto> items = new ArrayList<>(); Map<String, String> finalPartNumberToSpecs = partNumberToSpecs;
return dtoList.stream()
for (int i = 1; i <= sheet.getLastRowNum(); i++) { .map(dto -> {
Row row = sheet.getRow(i); String specs = finalPartNumberToSpecs.get(dto.partNumber());
if (row == null) continue; return new WarehouseReceiptItemDto(
dto.id(),
String partNumber = getCellValueAsString(row.getCell(0)); dto.status(),
String productSpec = getCellValueAsString(row.getCell(1)); dto.createDate(),
String countStr = getCellValueAsString(row.getCell(2)); dto.createUserId(),
dto.createUserName(),
if (!StringUtils.hasText(partNumber)) continue; dto.updateDate(),
dto.updateUserId(),
int productCount = 0; dto.updateUserName(),
if (StringUtils.hasText(countStr)) { dto.documentNo(),
try { dto.partNumber(),
productCount = Integer.parseInt(countStr); dto.originalCount(),
} catch (NumberFormatException e) { dto.productCount(),
productCount = 0; dto.productMark(),
} dto.reserve1(),
} dto.reserve2(),
dto.storeNo(),
WarehouseReceiptItemDto item = new WarehouseReceiptItemDto( dto.demandCount(),
null, null, null, null, null, null, null, null, dto.partId(),
null, partNumber, null, productCount, null, null, null, null, null, null, productSpec specs
); );
items.add(item); })
} .toList();
return items;
} catch (IOException e) {
throw new BusinessException("warehouse.warehouse_receipt.exception.import_failed");
}
}
private String getCellValueAsString(Cell cell) {
if (cell == null) {
return "";
}
return switch (cell.getCellType()) {
case STRING -> cell.getStringCellValue().trim();
case NUMERIC -> String.valueOf((long) cell.getNumericCellValue());
case BOOLEAN -> String.valueOf(cell.getBooleanCellValue());
default -> "";
};
} }
} }

View File

@@ -31,6 +31,28 @@ warehouse.stock_transfer_order.validate.product_count.min=调拨数量不能小
warehouse.stock_transfer_order.validate.part_id.not_null=物料 ID 不能为空 warehouse.stock_transfer_order.validate.part_id.not_null=物料 ID 不能为空
warehouse.stock_transfer_order.validate.order_id.not_null=调拨单 ID 不能为空 warehouse.stock_transfer_order.validate.order_id.not_null=调拨单 ID 不能为空
warehouse.inventory_count.validate.form_code.not_null=盘点单编号不能为空
warehouse.inventory_count.validate.form_name.not_null=盘点单名称不能为空
warehouse.inventory_count.validate.store_no.not_null=仓库 ID 不能为空
warehouse.inventory_count.validate.store_name.not_null=仓库名称不能为空
warehouse.inventory_count.validate.count_items.not_null=盘点明细不能为空
warehouse.inventory_count.validate.part_number.not_null=物料编号不能为空
warehouse.inventory_count.validate.product_count.not_null=盘点数量不能为空
warehouse.inventory_count.validate.product_count.min=盘点数量不能小于 0
warehouse.inventory_count.exception.init_already_exists=当前仓库已有初始库存单
warehouse.inventory_count.exception.stock_not_found=物料库存不存在
warehouse.inventory_count.exception.not_found=盘点单不存在
warehouse.inventory_count.exception.cannot_update_approved=已审核的盘点单不能修改
warehouse.inventory_count.exception.cannot_delete_approved=已审核的盘点单不能删除
warehouse.inventory_count.exception.cannot_delete_approved_batch=选中的盘点单中包含已审核的单据,不能删除
warehouse.inventory_count.exception.ids_empty=请选择要删除的记录
warehouse.inventory_count.exception.already_approved=盘点单已经审核
warehouse.inventory_count.exception.not_approved=盘点单不是已审核状态,不能反审
warehouse.inventory_count.exception.no_items=盘点单没有明细
warehouse.inventory_count.exception.file_empty=文件不能为空
warehouse.inventory_count.exception.import_failed=导入失败
warehouse.inventory_count.exception.stock_not_found_for_unapprove=反审核时找不到对应库存记录
# ==========>> 生产管理 # ==========>> 生产管理
@@ -86,7 +108,7 @@ password.notNull=密码不能为空
httpMessage.notNull=参数不能为空 httpMessage.notNull=参数不能为空
validated.error=参数错误 validated.error=参数错误
#jakarta.validation.constraints.NotNull.message={0}不能为空 #jakarta.validation.constraints.NotNull.message="{0}"不能为空
#jakarta.validation.constraints.NotBlank.message={0}不能为空 #jakarta.validation.constraints.NotBlank.message="{0}"不能为空
#jakarta.validation.constraints.Size.message={0}长度必须在{min}到{max}之间 #jakarta.validation.constraints.Size.message="{0}"长度必须在{min}到{max}之间
#jakarta.validation.constraints.Pattern.message={0}格式不正确 #jakarta.validation.constraints.Pattern.message="{0}"格式不正确