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

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("bom_list");
customerTables.add("vendor");
customerTables.add("productionform");
}
@Override

View File

@@ -24,6 +24,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
@Tag(name = "InventoryCount")
@@ -41,15 +43,15 @@ public class InventoryCountController {
public BaseResult<IPage<InventoryCountDto>> getInventoryCountPage(@Validated BasePageReqParams pageParams,
@Validated(Get.class) InventoryCountDto searchParams) {
var wrapper = new LambdaQueryWrapper<Document>();
if (searchParams != null) {
if (StringUtils.hasText(searchParams.searchCode())) {
wrapper.like(Document::getFormCode, searchParams.searchCode());
}
if (searchParams != null) {
if (StringUtils.hasText(searchParams.searchCode())) {
wrapper.like(Document::getFormCode, searchParams.searchCode());
}
}
wrapper.orderByDesc(Document::getCreateDate);
return BaseResult.successWithData(inventoryCountService.getInventoryCountPage(pageParams, wrapper));
}
@ApiLog(type = OperationType.ADD, remark = "新增一条InventoryCount记录")
@Operation(summary = "新增InventoryCount", operationId = "addInventoryCount")
@PostMapping("/addInventoryCount")
@@ -59,66 +61,20 @@ public class InventoryCountController {
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记录")
@Operation(summary = "删除InventoryCount", operationId = "deleteInventoryCount")
@PostMapping("/deleteInventoryCount")
@PreAuthorize("hasAuthority('inventory_count:delete')")
@PreAuthorize("hasAuthority('inventory_count:remove')")
public BaseResult<?> deleteInventoryCount(@Validated(DeleteOne.class) @RequestBody BaseDeleteBody req) {
inventoryCountService.deleteInventoryCount(req.id());
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")
@GetMapping("/getInventoryCountDetail")
@PreAuthorize("hasAuthority('inventorycount:index')")
@PreAuthorize("hasAuthority('inventory_count:index')")
public BaseResult<List<InventoryCountItemDto>> getInventoryCountDetail(
@Parameter(description = "盘点单ID") @RequestParam Long 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.niuan.erp.common.annotation.ApiLog;
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.BasePageReqParams;
import com.niuan.erp.common.base.BaseResult;
@@ -41,11 +42,14 @@ public class WarehouseReceiptController {
public BaseResult<IPage<WarehouseReceiptDto>> getWarehouseReceiptPage(@Validated BasePageReqParams pageParams,
@Validated(Get.class) WarehouseReceiptDto searchParams) {
var wrapper = new LambdaQueryWrapper<Document>();
if (searchParams != null) {
if (StringUtils.hasText(searchParams.searchCode())) {
wrapper.like(Document::getFormCode, searchParams.searchCode());
}
}
if (searchParams != null && StringUtils.hasText(searchParams.searchCode())) {
String searchCode = 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));
}
@@ -71,7 +75,7 @@ public class WarehouseReceiptController {
@ApiLog(type = OperationType.DELETE, remark = "删除一条WarehouseReceipt记录")
@Operation(summary = "删除WarehouseReceipt", operationId = "deleteWarehouseReceipt")
@PostMapping("/deleteWarehouseReceipt")
@PreAuthorize("hasAuthority('warehouse_receipt:delete')")
@PreAuthorize("hasAuthority('warehouse_receipt:remove')")
public BaseResult<?> deleteWarehouseReceipt(@Validated(DeleteOne.class) @RequestBody BaseDeleteBody req) {
warehouseReceiptService.deleteWarehouseReceipt(req.id());
return BaseResult.success();
@@ -91,34 +95,26 @@ public class WarehouseReceiptController {
@PostMapping("/approveWarehouseReceipt")
@PreAuthorize("hasAuthority('warehouse_receipt:approve')")
public BaseResult<?> approveWarehouseReceipt(
@Parameter(description = "入库单ID") @RequestParam Long id) {
warehouseReceiptService.approve(id);
@Validated @RequestBody BaseApproveAndRejectDto dto) {
warehouseReceiptService.approve(dto.id());
return BaseResult.success();
}
@ApiLog(type = OperationType.UPDATE, remark = "反审核WarehouseReceipt")
@Operation(summary = "反审核WarehouseReceipt", operationId = "unapproveWarehouseReceipt")
@PostMapping("/unapproveWarehouseReceipt")
@PreAuthorize("hasAuthority('warehouse_receipt:unapprove')")
public BaseResult<?> unapproveWarehouseReceipt(
@Parameter(description = "入库单ID") @RequestParam Long id) {
warehouseReceiptService.unapprove(id);
@Operation(summary = "反审核WarehouseReceipt", operationId = "rejectWarehouseReceipt")
@PostMapping("/rejectWarehouseReceipt")
@PreAuthorize("hasAuthority('warehouse_receipt:reject')")
public BaseResult<?> rejectWarehouseReceipt(
@Validated @RequestBody BaseApproveAndRejectDto dto) {
warehouseReceiptService.reject(dto.id());
return BaseResult.success();
}
@Operation(summary = "获取WarehouseReceipt明细", operationId = "getWarehouseReceiptDetail")
@GetMapping("/getWarehouseReceiptDetail")
@PreAuthorize("hasAuthority('warehousereceipt:index')")
@PreAuthorize("hasAuthority('warehouse_receipt:index')")
public BaseResult<List<WarehouseReceiptItemDto>> getWarehouseReceiptDetail(
@Parameter(description = "入库单ID") @RequestParam Long 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;
import java.time.LocalDateTime;
import java.util.List;
public record WarehouseReceiptDto(
Long id,
@@ -20,11 +21,6 @@ public record WarehouseReceiptDto(
String formMark,
Integer reserve1,
String reserve2,
Integer vendorNo,
String vendorName,
Double totalValue,
Integer outStoreNo,
String outStoreName,
Integer groupId,
Integer customerId,
String searchCode) {}
String searchCode,
List<WarehouseReceiptItemAddDto> receiptItems) {}

View File

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

View File

@@ -25,9 +25,7 @@ public interface WarehouseReceiptService {
void approve(long id);
void unapprove(long id);
void reject(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.converter.InventoryCountConverter;
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.StockMapper;
import com.niuan.erp.module.warehouse.mapper.WarehouseItemMapper;
import com.niuan.erp.module.warehouse.service.InventoryCountService;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.*;
@@ -45,7 +45,7 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
private final InventoryCountItemMapper inventoryCountItemMapper;
private final StockMapper stockMapper;
private final WarehouseItemMapper warehouseItemMapper;
@Override
public IPage<InventoryCountDto> getInventoryCountPage(BasePageReqParams pageParams, LambdaQueryWrapper<Document> wrapper) {
@@ -87,20 +87,16 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
.map(InventoryCountItem::getPartNumber)
.toList();
LambdaQueryWrapper<Stock> stockWrapper = new LambdaQueryWrapper<>();
stockWrapper.eq(Stock::getStoreNo, dto.storeNo())
.in(Stock::getPartNumber, partNumbers);
List<Stock> stockList = stockMapper.selectList(stockWrapper);
Map<String, Stock> stockMap = stockList.stream()
.collect(Collectors.toMap(Stock::getPartNumber, s -> s));
Map<String, Map<String, Object>> stockMaps = warehouseItemMapper.getWarehouseItemStockListByPartNumbers(partNumbers);
Map<String, Integer> stockMap = new HashMap<>();
for (Map.Entry<String, Map<String, Object>> entry : stockMaps.entrySet()) {
stockMap.put(entry.getKey(), ((Number) entry.getValue().get("productCount")).intValue());
}
for (InventoryCountItem item : items) {
Stock stock = stockMap.get(item.getPartNumber());
if (stock == null) {
throw new BusinessException("warehouse.inventory_count.exception.stock_not_found");
}
item.setOriginalProductCount(stock.getProductCount());
item.setDiffCount(item.getProductCount() - stock.getProductCount());
Integer originalCount = stockMap.get(item.getPartNumber());
item.setOriginalProductCount(originalCount != null ? originalCount : 0);
item.setDiffCount(item.getProductCount() - item.getOriginalProductCount());
}
} else {
for (InventoryCountItem item : items) {
@@ -121,25 +117,6 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
}
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
@@ -214,47 +191,6 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
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.setUpdateDate(LocalDateTime.now());
entity.setUpdateUserId(SecurityUtils.getUserId());
@@ -281,31 +217,7 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
LambdaQueryWrapper<InventoryCountItem> itemWrapper = new LambdaQueryWrapper<>();
itemWrapper.eq(InventoryCountItem::getDocumentNo, id);
List<InventoryCountItem> items = 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);
}
inventoryCountItemMapper.selectList(itemWrapper);
entity.setFormStatus(FormStatus.NO_APPROVE);
entity.setUpdateDate(LocalDateTime.now());
@@ -326,7 +238,47 @@ public class InventoryCountServiceImpl extends ServiceImpl<DocumentMapper, Docum
LambdaQueryWrapper<InventoryCountItem> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(InventoryCountItem::getDocumentNo, id);
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

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.converter.WarehouseReceiptConverter;
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.WarehouseItemMapper;
import com.niuan.erp.module.warehouse.service.WarehouseReceiptService;
import lombok.RequiredArgsConstructor;
import org.apache.poi.ss.usermodel.*;
@@ -47,9 +49,12 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
private final StockMapper stockMapper;
private final WarehouseItemMapper warehouseItemMapper;
@Override
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);
return result.convert(warehouseReceiptConverter::toDto);
}
@@ -93,6 +98,24 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
entity.setUpdateUserName(SecurityUtils.getUserName());
entity.setUpdateDate(LocalDateTime.now());
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
@@ -162,6 +185,7 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
Map<String, Stock> existingStockMap = existingStockList.stream()
.collect(Collectors.toMap(Stock::getPartNumber, s -> s));
String storeName = entity.getStoreName();
List<Stock> newStocks = new ArrayList<>();
for (DocumentMaterial material : materialList) {
Stock existingStock = existingStockMap.get(material.getPartNumber());
@@ -170,6 +194,7 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
newStock.setPartNumber(material.getPartNumber());
newStock.setProductCount(material.getProductCount());
newStock.setStoreNo(storeNo);
newStock.setStoreName(storeName);
newStock.setCreateDate(LocalDateTime.now());
newStock.setCreateUserId(SecurityUtils.getUserId());
newStock.setCreateUserName(SecurityUtils.getUserName());
@@ -205,7 +230,7 @@ public class WarehouseReceiptServiceImpl extends ServiceImpl<DocumentMapper, Doc
}
@Override
public void unapprove(long id) {
public void reject(long id) {
Document entity = this.baseMapper.selectById(id);
if (entity == null) {
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<>();
wrapper.eq(DocumentMaterial::getDocumentNo, id);
List<DocumentMaterial> materials = documentMaterialMapper.selectList(wrapper);
return warehouseReceiptConverter.toItemDtoList(materials);
}
@Override
public List<WarehouseReceiptItemDto> importItems(MultipartFile file) {
if (file == null || file.isEmpty()) {
throw new BusinessException("warehouse.warehouse_receipt.exception.file_empty");
// 获取所有物料编号
List<String> partNumbers = materials.stream()
.map(DocumentMaterial::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> items = warehouseItemMapper.selectList(itemWrapper);
partNumberToSpecs = items.stream()
.collect(Collectors.toMap(WarehouseItem::getPartNumber, WarehouseItem::getProductSpecs, (v1, v2) -> v1));
}
try (Workbook workbook = WorkbookFactory.create(file.getInputStream())) {
Sheet sheet = workbook.getSheetAt(0);
List<WarehouseReceiptItemDto> items = new ArrayList<>();
for (int i = 1; i <= sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
if (row == null) continue;
String partNumber = getCellValueAsString(row.getCell(0));
String productSpec = getCellValueAsString(row.getCell(1));
String countStr = getCellValueAsString(row.getCell(2));
if (!StringUtils.hasText(partNumber)) continue;
int productCount = 0;
if (StringUtils.hasText(countStr)) {
try {
productCount = Integer.parseInt(countStr);
} catch (NumberFormatException e) {
productCount = 0;
}
}
WarehouseReceiptItemDto item = new WarehouseReceiptItemDto(
null, null, null, null, null, null, null, null,
null, partNumber, null, productCount, null, null, null, null, null, null, productSpec
);
items.add(item);
}
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 -> "";
};
// 转换并填充 productSpec
List<WarehouseReceiptItemDto> dtoList = warehouseReceiptConverter.toItemDtoList(materials);
Map<String, String> finalPartNumberToSpecs = partNumberToSpecs;
return dtoList.stream()
.map(dto -> {
String specs = finalPartNumberToSpecs.get(dto.partNumber());
return new WarehouseReceiptItemDto(
dto.id(),
dto.status(),
dto.createDate(),
dto.createUserId(),
dto.createUserName(),
dto.updateDate(),
dto.updateUserId(),
dto.updateUserName(),
dto.documentNo(),
dto.partNumber(),
dto.originalCount(),
dto.productCount(),
dto.productMark(),
dto.reserve1(),
dto.reserve2(),
dto.storeNo(),
dto.demandCount(),
dto.partId(),
specs
);
})
.toList();
}
}

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.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=参数不能为空
validated.error=参数错误
#jakarta.validation.constraints.NotNull.message={0}不能为空
#jakarta.validation.constraints.NotBlank.message={0}不能为空
#jakarta.validation.constraints.Size.message={0}长度必须在{min}到{max}之间
#jakarta.validation.constraints.Pattern.message={0}格式不正确
#jakarta.validation.constraints.NotNull.message="{0}"不能为空
#jakarta.validation.constraints.NotBlank.message="{0}"不能为空
#jakarta.validation.constraints.Size.message="{0}"长度必须在{min}到{max}之间
#jakarta.validation.constraints.Pattern.message="{0}"格式不正确