Bugfixes for #72, #73, #75, #68

This commit is contained in:
Jan 2025-12-14 10:39:15 +01:00
parent b75fe9bb99
commit bce745e458
5 changed files with 55 additions and 20 deletions

View file

@ -24,7 +24,6 @@ public class BulkExportService {
private final HeaderCellStyleProvider headerCellStyleProvider;
private final ContainerRateExcelMapper containerRateExcelMapper;
private final MatrixRateExcelMapper matrixRateExcelMapper;
private final MaterialExcelMapper materialExcelMapper;
private final PackagingExcelMapper packagingExcelMapper;
private final NodeExcelMapper nodeExcelMapper;
private final HiddenNodeExcelMapper hiddenNodeExcelMapper;
@ -32,11 +31,10 @@ public class BulkExportService {
private final String sheetPassword;
private final MaterialFastExcelMapper materialFastExcelMapper;
public BulkExportService(@Value("${lcc.bulk.sheet_password}") String sheetPassword, HeaderCellStyleProvider headerCellStyleProvider, ContainerRateExcelMapper containerRateExcelMapper, MatrixRateExcelMapper matrixRateExcelMapper, MaterialExcelMapper materialExcelMapper, PackagingExcelMapper packagingExcelMapper, NodeExcelMapper nodeExcelMapper, HiddenNodeExcelMapper hiddenNodeExcelMapper, HiddenCountryExcelMapper hiddenCountryExcelMapper, MaterialFastExcelMapper materialFastExcelMapper) {
public BulkExportService(@Value("${lcc.bulk.sheet_password}") String sheetPassword, HeaderCellStyleProvider headerCellStyleProvider, ContainerRateExcelMapper containerRateExcelMapper, MatrixRateExcelMapper matrixRateExcelMapper, PackagingExcelMapper packagingExcelMapper, NodeExcelMapper nodeExcelMapper, HiddenNodeExcelMapper hiddenNodeExcelMapper, HiddenCountryExcelMapper hiddenCountryExcelMapper, MaterialFastExcelMapper materialFastExcelMapper) {
this.headerCellStyleProvider = headerCellStyleProvider;
this.containerRateExcelMapper = containerRateExcelMapper;
this.matrixRateExcelMapper = matrixRateExcelMapper;
this.materialExcelMapper = materialExcelMapper;
this.packagingExcelMapper = packagingExcelMapper;
this.nodeExcelMapper = nodeExcelMapper;
this.hiddenNodeExcelMapper = hiddenNodeExcelMapper;
@ -93,10 +91,6 @@ public class BulkExportService {
matrixRateExcelMapper.fillSheet(worksheet, style, periodId);
matrixRateExcelMapper.createConstraints(workbook, worksheet);
break;
// case MATERIAL:
// materialExcelMapper.fillSheet(worksheet, style);
// materialExcelMapper.createConstraints(worksheet);
// break;
case PACKAGING:
packagingExcelMapper.fillSheet(worksheet, style);
packagingExcelMapper.createConstraints(workbook, worksheet);

View file

@ -96,10 +96,6 @@ public class BulkImportService {
var matrixRates = matrixRateExcelMapper.extractSheet(sheet);
matrixRateImportService.processMatrixRates(matrixRates);
break;
// case MATERIAL:
// var materials = materialExcelMapper.extractSheet(sheet);
// materials.forEach(materialBulkImportService::processMaterialInstructions);
// break;
case PACKAGING:
var packaging = packagingExcelMapper.extractSheet(sheet);
packaging.forEach(packagingBulkImportService::processPackagingInstructions);

View file

@ -4,9 +4,12 @@ import de.avatic.lcc.dto.generic.TransportType;
import de.avatic.lcc.model.bulk.HiddenTableType;
import de.avatic.lcc.model.bulk.header.ContainerRateHeader;
import de.avatic.lcc.model.bulk.header.HiddenNodeHeader;
import de.avatic.lcc.model.db.nodes.Node;
import de.avatic.lcc.model.db.properties.SystemPropertyMappingId;
import de.avatic.lcc.model.db.rates.ContainerRate;
import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.rates.ContainerRateRepository;
import de.avatic.lcc.service.access.PropertyService;
import de.avatic.lcc.service.bulk.helper.ConstraintGenerator;
import de.avatic.lcc.service.bulk.helper.HeaderGenerator;
import de.avatic.lcc.util.exception.internalerror.ExcelValidationError;
@ -16,6 +19,7 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Service
public class ContainerRateExcelMapper {
@ -24,12 +28,14 @@ public class ContainerRateExcelMapper {
private final ContainerRateRepository containerRateRepository;
private final NodeRepository nodeRepository;
private final ConstraintGenerator constraintGenerator;
private final PropertyService propertyService;
public ContainerRateExcelMapper(HeaderGenerator headerGenerator, ContainerRateRepository containerRateRepository, NodeRepository nodeRepository, ConstraintGenerator constraintGenerator) {
public ContainerRateExcelMapper(HeaderGenerator headerGenerator, ContainerRateRepository containerRateRepository, NodeRepository nodeRepository, ConstraintGenerator constraintGenerator, PropertyService propertyService) {
this.headerGenerator = headerGenerator;
this.containerRateRepository = containerRateRepository;
this.nodeRepository = nodeRepository;
this.constraintGenerator = constraintGenerator;
this.propertyService = propertyService;
}
public void fillSheet(Sheet sheet, CellStyle headerStyle, Integer periodId) {
@ -73,10 +79,20 @@ public class ContainerRateExcelMapper {
return true;
}
private String getRefStart() {
Optional<String> ref = propertyService.getProperty(SystemPropertyMappingId.START_REF);
return ref.orElseThrow(() -> new InternalError("Unable to get start reference from properties"));
}
private String getRefEnd() {
Optional<String> ref = propertyService.getProperty(SystemPropertyMappingId.END_REF);
return ref.orElseThrow(() -> new InternalError("Unable to get end reference from properties"));
}
public List<ContainerRate> extractSheet(Sheet sheet) {
headerGenerator.validateHeader(sheet, ContainerRateHeader.class);
var rates = new ArrayList<ContainerRate>();
var rates = new ArrayList<ExcelContainerRate>();
sheet.forEach(row -> {
if (row.getRowNum() == 0) return;
@ -84,7 +100,18 @@ public class ContainerRateExcelMapper {
rates.add(mapToEntity(row));
});
return rates;
validateReferenceRoute(rates);
return rates.stream().map(ExcelContainerRate::rate).toList();
}
private void validateReferenceRoute(List<ExcelContainerRate> rates) {
var startRef = getRefStart();
var endRef = getRefEnd();
if(rates.stream().noneMatch(rate -> rate.fromNode().getExternalMappingId().equals(startRef) || rate.toNode().getExternalMappingId().equals(endRef)))
throw new ExcelValidationError(String.format("Container rates must reference route (%s - %s) not found in container rates", startRef, endRef));
}
private boolean isEmpty(Row row) {
@ -109,7 +136,7 @@ public class ContainerRateExcelMapper {
return result.toString();
}
private ContainerRate mapToEntity(Row row) {
private ExcelContainerRate mapToEntity(Row row) {
ContainerRate entity = new ContainerRate();
validateConstraints(row);
@ -134,7 +161,7 @@ public class ContainerRateExcelMapper {
entity.setRateTeu(BigDecimal.valueOf(row.getCell(ContainerRateHeader.RATE_TEU.ordinal()).getNumericCellValue()));
entity.setRateHc(BigDecimal.valueOf(row.getCell(ContainerRateHeader.RATE_HC.ordinal()).getNumericCellValue()));
return entity;
return new ExcelContainerRate(entity, fromNode.orElseThrow(), toNode.orElseThrow());
}
private void validateConstraints(Row row) {
@ -142,10 +169,12 @@ public class ContainerRateExcelMapper {
constraintGenerator.validateStringCell(row, ContainerRateHeader.FROM_NODE.ordinal());
constraintGenerator.validateStringCell(row, ContainerRateHeader.TO_NODE.ordinal());
constraintGenerator.validateEnumConstraint(row, ContainerRateHeader.CONTAINER_RATE_TYPE.ordinal(), TransportType.class);
constraintGenerator.validateDecimalConstraint(row, ContainerRateHeader.RATE_FEU.ordinal(), 0.0, 1000000.0);
constraintGenerator.validateDecimalConstraint(row, ContainerRateHeader.RATE_TEU.ordinal(), 0.0, 1000000.0);
constraintGenerator.validateDecimalConstraint(row, ContainerRateHeader.RATE_HC.ordinal(), 0.0, 1000000.0);
constraintGenerator.validateDecimalConstraint(row, ContainerRateHeader.RATE_FEU.ordinal(), 1.0, 1000000.0);
constraintGenerator.validateDecimalConstraint(row, ContainerRateHeader.RATE_TEU.ordinal(), 1.0, 1000000.0);
constraintGenerator.validateDecimalConstraint(row, ContainerRateHeader.RATE_HC.ordinal(), 1.0, 1000000.0);
constraintGenerator.validateIntegerConstraint(row, ContainerRateHeader.LEAD_TIME.ordinal(), 0, 365);
}
private record ExcelContainerRate(ContainerRate rate, Node fromNode, Node toNode) {}
}

View file

@ -1,5 +1,6 @@
package de.avatic.lcc.service.excelMapper;
import de.avatic.lcc.model.bulk.header.ContainerRateHeader;
import de.avatic.lcc.model.excel.ExcelNode;
import de.avatic.lcc.model.bulk.BulkInstruction;
import de.avatic.lcc.model.bulk.BulkInstructionType;
@ -150,6 +151,11 @@ public class NodeExcelMapper {
entity.setSource(Boolean.valueOf(row.getCell(NodeHeader.IS_SOURCE.ordinal()).getStringCellValue()));
entity.setIntermediate(Boolean.valueOf(row.getCell(NodeHeader.IS_INTERMEDIATE.ordinal()).getStringCellValue()));
entity.setDestination(Boolean.valueOf(row.getCell(NodeHeader.IS_DESTINATION.ordinal()).getStringCellValue()));
if(!entity.getSource() && !entity.getDestination() && !entity.getIntermediate())
throw new ExcelValidationError("Unable to validate row " + (row.getRowNum() + 1) + " column " + toExcelLetter(ContainerRateHeader.FROM_NODE.ordinal()) + ": Node with mapping id " + row.getCell(NodeHeader.MAPPING_ID.ordinal()).getStringCellValue() + " must be either source, destination or intermediate");
entity.setPredecessorRequired(Boolean.valueOf(row.getCell(NodeHeader.IS_PREDECESSOR_MANDATORY.ordinal()).getStringCellValue()));
entity.setNodePredecessors(mapChainsFromCell(CellUtil.getCell(row, NodeHeader.PREDECESSOR_NODES.ordinal()).getStringCellValue()));
entity.setOutboundCountries(mapOutboundCountriesFromCell(CellUtil.getCell(row, NodeHeader.OUTBOUND_COUNTRIES.ordinal()).getStringCellValue()));
@ -199,4 +205,14 @@ public class NodeExcelMapper {
return Arrays.stream(chain.split(",")).map(String::trim).toList();
}
private String toExcelLetter(int columnIdx) {
StringBuilder result = new StringBuilder();
columnIdx++; // Convert from 0-based to 1-based for the algorithm
while (columnIdx > 0) {
columnIdx--; // Adjust for 1-based indexing
result.insert(0, (char) ('A' + columnIdx % 26));
columnIdx /= 26;
}
return result.toString();
}
}

View file

@ -60,7 +60,7 @@ public class PackagingExcelMapper {
private void mapToRow(Packaging packaging, ArrayList<String> headers, Row row) {
Optional<PackagingDimension> shu = packagingDimensionRepository.getById(packaging.getShuId());
Optional<PackagingDimension> hu = packagingDimensionRepository.getById(packaging.getShuId());
Optional<PackagingDimension> hu = packagingDimensionRepository.getById(packaging.getHuId());
row.createCell(PackagingHeader.OPERATION.ordinal()).setCellValue(BulkInstructionType.UPDATE.name());