Add Excel sheet extraction logic to mappers and services

Implemented methods to extract and map data from Excel sheets for various entities such as rates, nodes, and packaging. Enhanced header validation and added support for parsing Excel inputs in the `BulkFileProcessingService`.
This commit is contained in:
Jan 2025-04-16 15:58:32 +02:00
parent 1a57d7dc3d
commit c0fc174510
12 changed files with 606 additions and 32 deletions

View file

@ -0,0 +1,176 @@
package de.avatic.lcc.excelmodel;
import de.avatic.lcc.model.country.IsoCode;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Map;
public class ExcelNode {
private Integer id;
@NotNull
@Size(max = 255)
private String name;
@NotNull
@Size(max = 500)
private String address;
@Size(max = 32)
private String externalMappingId;
@NotNull
private Boolean predecessorRequired;
private Boolean isDestination;
private Boolean isSource;
private Boolean isIntermediate;
@Digits(integer = 7, fraction = 4)
@DecimalMin("-90.0000")
@DecimalMax("90.0000")
private BigDecimal geoLat;
@Digits(integer = 7, fraction = 4)
@DecimalMin("-180.0000")
@DecimalMax("180.0000")
private BigDecimal geoLng;
private OffsetDateTime updatedAt;
private Boolean isDeprecated;
private IsoCode country;
private List<List<String>> nodePredecessors;
private List<String> outboundCountries;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getExternalMappingId() {
return externalMappingId;
}
public void setExternalMappingId(String externalMappingId) {
this.externalMappingId = externalMappingId;
}
public Boolean getPredecessorRequired() {
return predecessorRequired;
}
public void setPredecessorRequired(Boolean predecessorRequired) {
this.predecessorRequired = predecessorRequired;
}
public Boolean getDestination() {
return isDestination;
}
public void setDestination(Boolean destination) {
isDestination = destination;
}
public Boolean getSource() {
return isSource;
}
public void setSource(Boolean source) {
isSource = source;
}
public Boolean getIntermediate() {
return isIntermediate;
}
public void setIntermediate(Boolean intermediate) {
isIntermediate = intermediate;
}
public BigDecimal getGeoLat() {
return geoLat;
}
public void setGeoLat(BigDecimal geoLat) {
this.geoLat = geoLat;
}
public BigDecimal getGeoLng() {
return geoLng;
}
public void setGeoLng(BigDecimal geoLng) {
this.geoLng = geoLng;
}
public OffsetDateTime getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(OffsetDateTime updatedAt) {
this.updatedAt = updatedAt;
}
public Boolean getDeprecated() {
return isDeprecated;
}
public void setDeprecated(Boolean deprecated) {
isDeprecated = deprecated;
}
public IsoCode getCountryId() {
return country;
}
public void setCountryId(IsoCode country) {
this.country = country;
}
public List<List<String>> getNodePredecessors() {
return nodePredecessors;
}
public void setNodePredecessors(List<List<String>> nodePredecessors) {
this.nodePredecessors = nodePredecessors;
}
public List<String> getOutboundCountries() {
return outboundCountries;
}
public void setOutboundCountries(List<String> outboundCountries) {
this.outboundCountries = outboundCountries;
}
}

View file

@ -0,0 +1,149 @@
package de.avatic.lcc.excelmodel;
import de.avatic.lcc.model.utils.DimensionUnit;
import de.avatic.lcc.model.utils.WeightUnit;
public class ExcelPackaging {
private Integer id;
private String supplierMappingId;
private String partNumber;
private Double shuLength;
private Double shuWidth;
private Double shuHeight;
private Double shuWeight;
private DimensionUnit shuDimensionUnit;
private WeightUnit shuWeightUnit;
private Double huLength;
private Double huWidth;
private Double huHeight;
private Double huWeight;
private DimensionUnit huDimensionUnit;
private WeightUnit huWeightUnit;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getSupplierMappingId() {
return supplierMappingId;
}
public void setSupplierMappingId(String supplierMappingId) {
this.supplierMappingId = supplierMappingId;
}
public String getPartNumber() {
return partNumber;
}
public void setPartNumber(String partNumber) {
this.partNumber = partNumber;
}
public Double getShuLength() {
return shuLength;
}
public void setShuLength(Double shuLength) {
this.shuLength = shuLength;
}
public Double getShuWidth() {
return shuWidth;
}
public void setShuWidth(Double shuWidth) {
this.shuWidth = shuWidth;
}
public Double getShuHeight() {
return shuHeight;
}
public void setShuHeight(Double shuHeight) {
this.shuHeight = shuHeight;
}
public Double getShuWeight() {
return shuWeight;
}
public void setShuWeight(Double shuWeight) {
this.shuWeight = shuWeight;
}
public DimensionUnit getShuDimensionUnit() {
return shuDimensionUnit;
}
public void setShuDimensionUnit(DimensionUnit shuDimensionUnit) {
this.shuDimensionUnit = shuDimensionUnit;
}
public WeightUnit getShuWeightUnit() {
return shuWeightUnit;
}
public void setShuWeightUnit(WeightUnit shuWeightUnit) {
this.shuWeightUnit = shuWeightUnit;
}
public Double getHuLength() {
return huLength;
}
public void setHuLength(Double huLength) {
this.huLength = huLength;
}
public Double getHuWidth() {
return huWidth;
}
public void setHuWidth(Double huWidth) {
this.huWidth = huWidth;
}
public Double getHuHeight() {
return huHeight;
}
public void setHuHeight(Double huHeight) {
this.huHeight = huHeight;
}
public Double getHuWeight() {
return huWeight;
}
public void setHuWeight(Double huWeight) {
this.huWeight = huWeight;
}
public DimensionUnit getHuDimensionUnit() {
return huDimensionUnit;
}
public void setHuDimensionUnit(DimensionUnit huDimensionUnit) {
this.huDimensionUnit = huDimensionUnit;
}
public WeightUnit getHuWeightUnit() {
return huWeightUnit;
}
public void setHuWeightUnit(WeightUnit huWeightUnit) {
this.huWeightUnit = huWeightUnit;
}
}

View file

@ -1,18 +1,11 @@
package de.avatic.lcc.model.rates;
import de.avatic.lcc.model.nodes.Node;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotNull;
import jdk.jfr.Unsigned;
import org.springframework.data.annotation.Id;
import org.springframework.data.jdbc.core.mapping.AggregateReference;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.math.BigDecimal;
@Table(name = "container_rate")
public class ContainerRate {
private Integer id;

View file

@ -132,7 +132,7 @@ public class NodeRepository {
@Transactional
public Optional<Integer> update(Node node) {
//TODO update predecessors and outbound_countries too
String query = "UPDATE node SET";
String query = "UPDATE node SET name = ?, address = ?, country_id = ?, is_source = ?, is_destination = ?, is_intermediate = ?, predecessor_required = ? WHERE id = ?";
return Optional.ofNullable(jdbcTemplate.update(query, node.getId()) == 0 ? null : node.getId());
}
@ -166,6 +166,18 @@ public class NodeRepository {
return jdbcTemplate.query(queryBuilder.toString(), new NodeMapper());
}
public Optional<Node> getByExternalMappingId(String mappingId) {
String query = """
SELECT node.id AS id, node.name AS name, node.address as address, node.is_source as is_source,
node.is_destination as is_destination, node.is_intermediate as is_intermediate, node.country_id as country_id, node.predecessor_required as predecessor_required
FROM node
WHERE node.external_mapping_id = ?""";
var node = jdbcTemplate.queryForObject(query, new NodeMapper(), mappingId);
return Optional.ofNullable(node);
}
private class NodeMapper implements RowMapper<Node> {
@Override

View file

@ -52,6 +52,9 @@ public class BulkExportService {
CellStyle style = headerCellStyleProvider.createHeaderCellStyle(workbook);
//TODO: check if a parallel task is needed.
if(bulkFileType.equals(BulkFileType.COUNTRY_MATRIX) || bulkFileType.equals(BulkFileType.NODE))
{

View file

@ -3,21 +3,76 @@ package de.avatic.lcc.service.bulk;
import de.avatic.lcc.dto.bulk.BulkFileType;
import de.avatic.lcc.dto.bulk.BulkProcessingType;
import de.avatic.lcc.dto.bulk.BulkStatus;
import de.avatic.lcc.model.bulk.BulkFileTypes;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.model.rates.ContainerRate;
import de.avatic.lcc.model.rates.MatrixRate;
import de.avatic.lcc.service.bulk.mapper.*;
import de.avatic.lcc.util.exception.clienterror.FileFormatNotSupportedException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
@Service
public class BulkFileProcessingService {
private final MatrixRateExcelMapper matrixRateExcelMapper;
private final ContainerRateExcelMapper containerRateExcelMapper;
private final MaterialExcelMapper materialExcelMapper;
private final PackagingExcelMapper packagingExcelMapper;
private final NodeExcelMapper nodeExcelMapper;
public BulkFileProcessingService(MatrixRateExcelMapper matrixRateExcelMapper, ContainerRateExcelMapper containerRateExcelMapper, MaterialExcelMapper materialExcelMapper, PackagingExcelMapper packagingExcelMapper, NodeExcelMapper nodeExcelMapper) {
this.matrixRateExcelMapper = matrixRateExcelMapper;
this.containerRateExcelMapper = containerRateExcelMapper;
this.materialExcelMapper = materialExcelMapper;
this.packagingExcelMapper = packagingExcelMapper;
this.nodeExcelMapper = nodeExcelMapper;
}
public Integer processFile(BulkFileType type, BulkProcessingType processingType, MultipartFile file) {
//TODO: launch parallel task
String contentType = file.getContentType();
if (!"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(contentType) &&
!"application/vnd.ms-excel".equals(contentType)) {
throw new FileFormatNotSupportedException(contentType);
}
try (InputStream in = file.getInputStream()) {
Workbook workbook = new XSSFWorkbook(in);
Sheet sheet = workbook.getSheet(BulkFileTypes.valueOf(type.name()).getSheetName());
switch (type) {
case CONTAINER_RATE:
var containerRates = containerRateExcelMapper.extractSheet(sheet);
break;
case COUNTRY_MATRIX:
var matrixRates = matrixRateExcelMapper.extractSheet(sheet);
break;
case MATERIAL:
var materials = materialExcelMapper.extractSheet(sheet);
break;
case PACKAGING:
var packaging = packagingExcelMapper.extractSheet(sheet);
break;
case NODE:
var nodes = nodeExcelMapper.extractSheet(sheet);
break;
default:
}
} catch (Exception e) {
}
return null;
}

View file

@ -12,12 +12,32 @@ import java.util.EnumSet;
@Service
public class HeaderGenerator {
public <H extends Enum<H> & HeaderProvider> boolean validateHeader(Sheet sheet, Class<H> headers) {
Row row = sheet.getRow(0);
for(H header : EnumSet.allOf(headers)){
Cell cell = row.getCell(header.ordinal());
if(cell == null || !cell.getStringCellValue().equals(header.getHeader())){
return false;
}
}
return true;
}
public boolean validateHeader(Sheet sheet, String[] headers) {
Row row = sheet.getRow(0);
int idx = 0;
for(String header : headers){
Cell cell = row.getCell(idx++);
if(cell == null || !cell.getStringCellValue().equals(header)){
return false;
}
}
return true;
}
public <T extends Enum<T> & HeaderProvider> void generateHeader(Sheet worksheet, Class<T> headers, CellStyle style) {
public <H extends Enum<H> & HeaderProvider> void generateHeader(Sheet worksheet, Class<H> headers, CellStyle style) {
Row row = worksheet.createRow(0);
for (T header : EnumSet.allOf(headers)) {
for (H header : EnumSet.allOf(headers)) {
Cell cell = row.createCell(header.ordinal());
cell.setCellValue(header.getHeader());
cell.setCellStyle(style);

View file

@ -15,6 +15,10 @@ import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Service
public class ContainerRateExcelMapper {
@ -60,4 +64,27 @@ public class ContainerRateExcelMapper {
constraintGenerator.createIntegerConstraint(sheet, ContainerRateHeader.LEAD_TIME.ordinal(), 0, 365);
}
public List<ContainerRate> extractSheet(Sheet sheet) {
if(!headerGenerator.validateHeader(sheet, ContainerRateHeader.class)) return null;
var rates = new ArrayList<ContainerRate>();
sheet.forEach(row -> rates.add(mapToEntity(row)));
return rates;
}
private ContainerRate mapToEntity(Row row) {
ContainerRate entity = new ContainerRate();
entity.setFromNodeId(nodeRepository.getByExternalMappingId(row.getCell(ContainerRateHeader.FROM_NODE.ordinal()).getStringCellValue()).orElseThrow().getId());
entity.setFromNodeId(nodeRepository.getByExternalMappingId(row.getCell(ContainerRateHeader.TO_NODE.ordinal()).getStringCellValue()).orElseThrow().getId());
entity.setType(ContainerRateType.valueOf(row.getCell(ContainerRateHeader.CONTAINER_RATE_TYPE.ordinal()).getStringCellValue()));
entity.setLeadTime(Double.valueOf(row.getCell(ContainerRateHeader.LEAD_TIME.ordinal()).getNumericCellValue()).intValue());
entity.setType(ContainerRateType.valueOf(row.getCell(ContainerRateHeader.CONTAINER_RATE_TYPE.ordinal()).getStringCellValue()));
entity.setRateFeu(BigDecimal.valueOf(row.getCell(ContainerRateHeader.RATE_FEU.ordinal()).getNumericCellValue()));
entity.setRateTeu(BigDecimal.valueOf(row.getCell(ContainerRateHeader.RATE_TEU.ordinal()).getNumericCellValue()));
entity.setRateHc(BigDecimal.valueOf(row.getCell(ContainerRateHeader.RATE_HC.ordinal()).getNumericCellValue()));
return entity;
}
}

View file

@ -1,9 +1,7 @@
package de.avatic.lcc.service.bulk.mapper;
import de.avatic.lcc.model.bulk.HiddenCountryHeader;
import de.avatic.lcc.model.bulk.HiddenTableType;
import de.avatic.lcc.model.bulk.ContainerRateHeader;
import de.avatic.lcc.model.bulk.MaterialHeader;
import de.avatic.lcc.model.bulk.MatrixRateHeader;
import de.avatic.lcc.model.materials.Material;
import de.avatic.lcc.repositories.MaterialRepository;
import de.avatic.lcc.service.bulk.helper.ConstraintGenerator;
@ -11,9 +9,11 @@ import de.avatic.lcc.service.bulk.helper.HeaderGenerator;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class MaterialExcelMapper {
@ -43,4 +43,38 @@ public class MaterialExcelMapper {
constraintGenerator.createLengthConstraint(sheet, MaterialHeader.HS_CODE.ordinal(), 0, 8);
constraintGenerator.createLengthConstraint(sheet, MaterialHeader.DESCRIPTION.ordinal(), 1, 500);
}
public List<Material> extractSheet(Sheet sheet) {
if(!headerGenerator.validateHeader(sheet, MaterialHeader.class)) return null;
var materials = new ArrayList<Material>();
sheet.forEach(row -> materials.add(mapToEntity(row)));
return materials;
}
private Material mapToEntity(Row row) {
Material entity = new Material();
entity.setPartNumber(row.getCell(MaterialHeader.PART_NUMBER.ordinal()).getStringCellValue());
entity.setName(row.getCell(MaterialHeader.DESCRIPTION.ordinal()).getStringCellValue());
entity.setHsCode(row.getCell(MaterialHeader.HS_CODE.ordinal()).getStringCellValue());
entity.setNormalizedPartNumber(normalizePartNumber(entity.getPartNumber()));
entity.setDeprecated(false);
if(!validateHsCode(entity.getHsCode())) throw new IllegalArgumentException("Invalid HS Code");
return entity;
}
private String normalizePartNumber(String partNumber) {
if (partNumber.length() > 12) throw new IllegalArgumentException("Part number must be less than 12 characters");
return "000000000000".concat(partNumber).substring(partNumber.length());
}
private boolean validateHsCode(String hsCode) {
//TODO check via api?!
return true;
}
}

View file

@ -1,6 +1,7 @@
package de.avatic.lcc.service.bulk.mapper;
import de.avatic.lcc.model.bulk.*;
import de.avatic.lcc.model.country.IsoCode;
import de.avatic.lcc.model.rates.ContainerRateType;
import de.avatic.lcc.model.rates.MatrixRate;
import de.avatic.lcc.repositories.country.CountryRepository;
@ -13,6 +14,10 @@ import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Service
public class MatrixRateExcelMapper {
@ -33,6 +38,24 @@ public class MatrixRateExcelMapper {
matrixRateRepository.listAllRatesByPeriodId(periodId).forEach(rate -> mapToRow(rate, sheet.createRow(sheet.getLastRowNum()+1)));
}
public List<MatrixRate> extractSheet(Sheet sheet) {
if(!headerGenerator.validateHeader(sheet, MatrixRateHeader.class)) return null;
List<MatrixRate> rates = new ArrayList<>();
sheet.forEach(row -> rates.add(mapToEntity(row)));
return rates;
}
private MatrixRate mapToEntity(Row row) {
MatrixRate entity = new MatrixRate();
entity.setToCountry(countryRepository.getByIsoCode(IsoCode.valueOf(row.getCell(MatrixRateHeader.TO_COUNTRY.ordinal()).getStringCellValue())).orElseThrow().getId());
entity.setFromCountry(countryRepository.getByIsoCode(IsoCode.valueOf(row.getCell(MatrixRateHeader.FROM_COUNTRY.ordinal()).getStringCellValue())).orElseThrow().getId());
entity.setRate(BigDecimal.valueOf(row.getCell(MatrixRateHeader.RATE.ordinal()).getNumericCellValue()));
return entity;
}
private void mapToRow(MatrixRate rate, Row row) {
row.createCell(MatrixRateHeader.FROM_COUNTRY.ordinal()).setCellValue(countryRepository.getById(rate.getFromCountry()).orElseThrow().getIsoCode().getCode());
row.createCell(MatrixRateHeader.TO_COUNTRY.ordinal()).setCellValue(countryRepository.getById(rate.getToCountry()).orElseThrow().getIsoCode().getCode());

View file

@ -1,8 +1,8 @@
package de.avatic.lcc.service.bulk.mapper;
import de.avatic.lcc.excelmodel.ExcelNode;
import de.avatic.lcc.model.bulk.HiddenCountryHeader;
import de.avatic.lcc.model.bulk.HiddenTableType;
import de.avatic.lcc.model.bulk.MatrixRateHeader;
import de.avatic.lcc.model.bulk.NodeHeader;
import de.avatic.lcc.model.country.Country;
import de.avatic.lcc.model.country.IsoCode;
@ -17,6 +17,7 @@ import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@ -52,7 +53,7 @@ public class NodeExcelMapper {
row.createCell(NodeHeader.IS_ORIGIN.ordinal()).setCellValue(node.getSource());
row.createCell(NodeHeader.IS_INTERMEDIATE.ordinal()).setCellValue(node.getIntermediate());
row.createCell(NodeHeader.IS_DESTINATION.ordinal()).setCellValue(node.getDestination());
row.createCell(NodeHeader.OUTBOUND_COUNTRIES.ordinal()).setCellValue(mapOutboundCountries(node.getOutboundCountries()));
row.createCell(NodeHeader.OUTBOUND_COUNTRIES.ordinal()).setCellValue(mapOutboundCountriesToCell(node.getOutboundCountries()));
row.createCell(NodeHeader.PREDECESSOR_NODES.ordinal()).setCellValue(mapChains(node.getNodePredecessors()));
row.createCell(NodeHeader.IS_PREDECESSOR_MANDATORY.ordinal()).setCellValue(node.getPredecessorRequired());
}
@ -67,7 +68,7 @@ public class NodeExcelMapper {
return seq.stream().map(s -> nodeRepository.getById(chain.get(s)).orElseThrow().getExternalMappingId()).collect(Collectors.joining(", "));
}
private String mapOutboundCountries(Collection<Integer> outboundCountryIds) {
private String mapOutboundCountriesToCell(Collection<Integer> outboundCountryIds) {
return outboundCountryIds.stream().map(countryRepository::getById).filter(Optional::isPresent).map(Optional::get).map(Country::getIsoCode).map(IsoCode::getCode).collect(Collectors.joining(", "));
}
@ -85,4 +86,46 @@ public class NodeExcelMapper {
constraintGenerator.createLengthConstraint(sheet, NodeHeader.NAME.ordinal(), 1, 255);
}
public List<ExcelNode> extractSheet(Sheet sheet) {
if(!headerGenerator.validateHeader(sheet, NodeHeader.class)) return null;
var nodes = new ArrayList<ExcelNode>();
sheet.forEach(row -> nodes.add(mapToEntity(row)));
return nodes;
}
private ExcelNode mapToEntity(Row row) {
ExcelNode entity = new ExcelNode();
entity.setExternalMappingId(row.getCell(NodeHeader.MAPPING_ID.ordinal()).getStringCellValue());
entity.setName(row.getCell(NodeHeader.NAME.ordinal()).getStringCellValue());
entity.setAddress(row.getCell(NodeHeader.ADDRESS.ordinal()).getStringCellValue());
entity.setCountryId(IsoCode.valueOf(row.getCell(NodeHeader.COUNTRY.ordinal()).getStringCellValue()));
entity.setGeoLat(BigDecimal.valueOf(row.getCell(NodeHeader.GEO_LATITUDE.ordinal()).getNumericCellValue()));
entity.setGeoLng(BigDecimal.valueOf(row.getCell(NodeHeader.GEO_LONGITUDE.ordinal()).getNumericCellValue()));
entity.setSource(row.getCell(NodeHeader.IS_ORIGIN.ordinal()).getBooleanCellValue());
entity.setIntermediate(row.getCell(NodeHeader.IS_INTERMEDIATE.ordinal()).getBooleanCellValue());
entity.setDestination(row.getCell(NodeHeader.IS_DESTINATION.ordinal()).getBooleanCellValue());
entity.setPredecessorRequired(row.getCell(NodeHeader.IS_PREDECESSOR_MANDATORY.ordinal()).getBooleanCellValue());
entity.setNodePredecessors(mapChainsFromCell(row.getCell(NodeHeader.PREDECESSOR_NODES.ordinal()).getStringCellValue()));
entity.setOutboundCountries(mapOutboundCountriesFromCell(row.getCell(NodeHeader.OUTBOUND_COUNTRIES.ordinal()).getStringCellValue()));
return entity;
}
private List<String> mapOutboundCountriesFromCell(String outboundCountryIds) {
if(outboundCountryIds == null || outboundCountryIds.isBlank()) return Collections.emptyList();
return Arrays.stream(outboundCountryIds.split(",")).map(String::trim).toList();
}
private List<List<String>> mapChainsFromCell(String cell) {
if(cell == null || cell.isBlank()) return Collections.emptyList();
return Arrays.stream(cell.split(";")).map(String::trim).map(this::mapChainFromCell).toList();
}
private List<String> mapChainFromCell(String chain) {
return Arrays.stream(chain.split(",")).map(String::trim).toList();
}
}

View file

@ -1,11 +1,15 @@
package de.avatic.lcc.service.bulk.mapper;
import de.avatic.lcc.model.bulk.*;
import de.avatic.lcc.excelmodel.ExcelPackaging;
import de.avatic.lcc.model.bulk.HiddenNodeHeader;
import de.avatic.lcc.model.bulk.HiddenTableType;
import de.avatic.lcc.model.bulk.PackagingHeader;
import de.avatic.lcc.model.packaging.Packaging;
import de.avatic.lcc.model.packaging.PackagingDimension;
import de.avatic.lcc.model.properties.PropertyType;
import de.avatic.lcc.model.utils.DimensionUnit;
import de.avatic.lcc.model.utils.WeightUnit;
import de.avatic.lcc.repositories.MaterialRepository;
import de.avatic.lcc.repositories.NodeRepository;
import de.avatic.lcc.repositories.packaging.PackagingDimensionRepository;
@ -18,6 +22,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
@ -48,7 +53,7 @@ public class PackagingExcelMapper {
headers.addAll(packagingPropertiesRepository.listTypes().stream().map(PropertyType::getExternalMappingId).toList());
headerGenerator.generateHeader(sheet, headers.toArray(String[]::new), headerStyle);
packagingRepository.listAllPackaging().forEach(p -> mapToRow(p,headers, sheet.createRow(sheet.getLastRowNum()+1)));
packagingRepository.listAllPackaging().forEach(p -> mapToRow(p, headers, sheet.createRow(sheet.getLastRowNum() + 1)));
}
private void mapToRow(Packaging packaging, ArrayList<String> headers, Row row) {
@ -79,28 +84,62 @@ public class PackagingExcelMapper {
}
private <T, R> void mapToCell(Cell cell, Optional<T> dimension, Function<T,R> resolver){
if(dimension.isPresent()) {
if(resolver.apply(dimension.get()) instanceof Integer)
cell.setCellValue((Integer) resolver.apply(dimension.get()));
if(resolver.apply(dimension.get()) instanceof String)
cell.setCellValue((String) resolver.apply(dimension.get()));
if(resolver.apply(dimension.get()) instanceof DimensionUnit)
cell.setCellValue(((DimensionUnit) resolver.apply(dimension.get())).name());
}
else cell.setBlank();
private <T, R> void mapToCell(Cell cell, Optional<T> dimension, Function<T, R> resolver) {
if (dimension.isPresent()) {
if (resolver.apply(dimension.get()) instanceof Integer)
cell.setCellValue((Integer) resolver.apply(dimension.get()));
if (resolver.apply(dimension.get()) instanceof String)
cell.setCellValue((String) resolver.apply(dimension.get()));
if (resolver.apply(dimension.get()) instanceof DimensionUnit)
cell.setCellValue(((DimensionUnit) resolver.apply(dimension.get())).name());
} else cell.setBlank();
}
public void createConstraints(Workbook workbook, Sheet sheet) {
var namedRange = constraintGenerator.createReference(workbook, HiddenNodeHeader.MAPPING_ID.ordinal(), HiddenTableType.ORIGIN_HIDDEN_TABLE);
constraintGenerator.createFormulaListConstraint(sheet, PackagingHeader.SUPPLIER.ordinal(), namedRange.getNameName());
constraintGenerator.createLengthConstraint(sheet, PackagingHeader.PART_NUMBER.ordinal(), 0,12);
constraintGenerator.createLengthConstraint(sheet, PackagingHeader.PART_NUMBER.ordinal(), 0, 12);
//TODO: check hu dimensions...
//todo check propeties?
//todo check properties?
}
public List<ExcelPackaging> extractSheet(Sheet sheet) {
if (!headerGenerator.validateHeader(sheet, PackagingHeader.class)) return null;
var packaging = new ArrayList<ExcelPackaging>();
sheet.forEach(row -> packaging.add(mapToEntity(row)));
return packaging;
}
private ExcelPackaging mapToEntity(Row row) {
ExcelPackaging entity = new ExcelPackaging();
entity.setSupplierMappingId(row.getCell(PackagingHeader.SUPPLIER.ordinal()).getStringCellValue());
entity.setPartNumber(row.getCell(PackagingHeader.PART_NUMBER.ordinal()).getStringCellValue());
entity.setHuHeight(row.getCell(PackagingHeader.HU_HEIGHT.ordinal()).getNumericCellValue());
entity.setHuWidth(row.getCell(PackagingHeader.HU_WIDTH.ordinal()).getNumericCellValue());
entity.setHuLength(row.getCell(PackagingHeader.HU_LENGTH.ordinal()).getNumericCellValue());
entity.setHuWeight(row.getCell(PackagingHeader.HU_WEIGHT.ordinal()).getNumericCellValue());
entity.setHuDimensionUnit(DimensionUnit.valueOf(row.getCell(PackagingHeader.HU_DIMENSION_UNIT.ordinal()).getStringCellValue()));
entity.setHuWeightUnit(WeightUnit.valueOf(row.getCell(PackagingHeader.HU_WEIGHT_UNIT.ordinal()).getStringCellValue()));
entity.setShuHeight(row.getCell(PackagingHeader.SHU_HEIGHT.ordinal()).getNumericCellValue());
entity.setShuWidth(row.getCell(PackagingHeader.SHU_WIDTH.ordinal()).getNumericCellValue());
entity.setShuLength(row.getCell(PackagingHeader.SHU_LENGTH.ordinal()).getNumericCellValue());
entity.setShuWeight(row.getCell(PackagingHeader.SHU_WEIGHT.ordinal()).getNumericCellValue());
entity.setShuDimensionUnit(DimensionUnit.valueOf(row.getCell(PackagingHeader.SHU_DIMENSION_UNIT.ordinal()).getStringCellValue()));
entity.setShuWeightUnit(WeightUnit.valueOf(row.getCell(PackagingHeader.SHU_WEIGHT_UNIT.ordinal()).getStringCellValue()));
return entity;
}
}