Bugfixing

This commit is contained in:
Jan 2025-07-28 13:36:04 +02:00
parent eab6ed2e1b
commit 259b46ec84
31 changed files with 673 additions and 295 deletions

View file

@ -215,7 +215,7 @@ public class ContainerCalculationResult {
* @return The total utilization value for the container.
*/
public double getTotalUtilizationByVolume() {
return getHuUtilizationByVolume() * huUnitCount;
return getHuUtilizationByVolume() * huUnitCount * layer;
}
/**

View file

@ -7,6 +7,10 @@ import jakarta.validation.constraints.Min;
public class DestinationUpdateDTO {
@JsonProperty("annual_amount")
@Min(1)
private Integer annualAmount;
@JsonProperty("repacking_cost")
@DecimalMin(value = "0.00", message = "Amount must be greater than or equal 0")
@Digits(integer = 13, fraction = 2, message = "Amount must have at most 2 decimal places")
@ -57,4 +61,12 @@ public class DestinationUpdateDTO {
public void setRouteSelectedId(Integer routeSelectedId) {
this.routeSelectedId = routeSelectedId;
}
public Integer getAnnualAmount() {
return annualAmount;
}
public void setAnnualAmount(Integer annualAmount) {
this.annualAmount = annualAmount;
}
}

View file

@ -1,7 +1,10 @@
package de.avatic.lcc.dto.generic;
public enum ContainerType {
FEU(12030, 2350, 2390, 67.7, 24,21), TEU(5890 ,2350,2390, 33.0, 11,10), HQ(12030, 2350, 2690, 76.4, 24,21), TRUCK(13600,2450, 2650, 88.3, 34, 33);
FEU(12030, 2350, 2390, 67.7, 24,21),
TEU(5890 ,2350,2390, 33.0, 11,10),
HQ(12030, 2350, 2690, 76.4, 24,21),
TRUCK(13600,2450, 2650, 88.3, 34, 33);
private final int length;
private final int width;

View file

@ -51,7 +51,6 @@ public class CalculationJobDestination {
private String layerStructure; // JSON as String
private Integer layerCount;
private Boolean transportWeightExceeded;
private BigDecimal transportsPerYear;
private BigDecimal annualTransportationCost;
private BigDecimal containerUtilization;
@ -343,14 +342,6 @@ public class CalculationJobDestination {
this.transportWeightExceeded = transportWeightExceeded;
}
public BigDecimal getTransportsPerYear() {
return transportsPerYear;
}
public void setTransportsPerYear(BigDecimal transportsPerYear) {
this.transportsPerYear = transportsPerYear;
}
public BigDecimal getAnnualTransportationCost() {
return annualTransportationCost;
}

View file

@ -27,6 +27,7 @@
private BigDecimal annualChanceCost;
private BigDecimal annualCost;
private Integer transitTime;
private BigDecimal utilization;
public BigDecimal getAnnualRiskCost() {
@ -188,4 +189,12 @@
public void setDistance(BigDecimal distance) {
this.distance = distance;
}
public void setUtilization(BigDecimal utilization) {
this.utilization = utilization;
}
public BigDecimal getUtilization() {
return utilization;
}
}

View file

@ -145,4 +145,8 @@ public class PackagingDimension {
var widthInX = unit.convertFromMM(width);
return lengthInX.doubleValue() * widthInX.doubleValue();
}
public double getWeight(WeightUnit weightUnit) {
return weightUnit.convertFromG(this.weight);
}
}

View file

@ -34,7 +34,7 @@ public class Premise {
private String hsCode;
@Digits(integer = 7, fraction = 2)
private BigDecimal customRate;
private BigDecimal tariffRate;
@Size(max = 16)
private PremiseState state;
@ -157,12 +157,12 @@ public class Premise {
this.hsCode = hsCode;
}
public BigDecimal getCustomRate() {
return customRate;
public BigDecimal getTariffRate() {
return tariffRate;
}
public void setCustomRate(BigDecimal customRate) {
this.customRate = customRate;
public void setTariffRate(BigDecimal tariffRate) {
this.tariffRate = tariffRate;
}
public PremiseState getState() {

View file

@ -27,7 +27,7 @@ public enum SystemPropertyMappingId {
TRUCK_LOAD("Maximum truck load [kg]", "25000"),
START_REF("Reference route segment start node mapping id", "CNXMN"),
END_REF("Reference route segment end node mapping id","HAM"),
END_REF("Reference route segment end node mapping id","DEHAM"),
RISK_REF("The historically highest rate for the reference route segment for 40ft containers [EUR]", "1000,00 €"),
CHANCE_REF("The historically lowest rate for the reference route segment for 40ft containers [EUR]", "20000,00 €"),

View file

@ -86,7 +86,6 @@ public class CalculationJobDestinationRepository {
entity.setLayerStructure(rs.getString("layer_structure"));
entity.setLayerCount(rs.getInt("layer_count"));
entity.setTransportWeightExceeded(rs.getBoolean("transport_weight_exceeded"));
entity.setTransportsPerYear(rs.getBigDecimal("transports_per_year"));
entity.setShippingFrequency(rs.getInt("shipping_frequency"));
entity.setAnnualTransportationCost(rs.getBigDecimal("annual_transportation_cost"));

View file

@ -3,13 +3,15 @@ package de.avatic.lcc.repositories.calculation;
import de.avatic.lcc.model.calculations.CalculationJob;
import de.avatic.lcc.model.calculations.CalculationJobDestination;
import de.avatic.lcc.model.calculations.CalculationJobState;
import de.avatic.lcc.util.exception.internalerror.DatabaseException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.xml.crypto.Data;
import java.sql.*;
import java.util.List;
import java.util.Optional;
@ -23,7 +25,28 @@ public class CalculationJobRepository {
@Transactional
public Integer insert(CalculationJob job) {
return null; //TODO implement me
String sql = """
INSERT INTO calculation_job (premise_id, calculation_date, validity_period_id, property_set_id, job_state, user_id)
VALUES (?, ?, ?, ?, ?, ?)
""";
GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, job.getPremiseId());
ps.setTimestamp(2, job.getCalculationDate() == null ? null : Timestamp.valueOf(job.getCalculationDate()));
ps.setInt(3, job.getValidityPeriodId());
ps.setInt(4, job.getPropertySetId());
ps.setString(5, job.getJobState().name()); // Convert enum to string
ps.setInt(6, job.getUserId());
return ps;
}, keyHolder);
// Return the generated ID
return keyHolder.getKey() != null ? keyHolder.getKey().intValue() : null;
}
@Transactional
@ -52,6 +75,16 @@ public class CalculationJobRepository {
return Optional.of(job.getFirst());
}
public void setStateTo(Integer id, CalculationJobState calculationJobState) {
String sql = "UPDATE calculation_job SET job_state = ? WHERE id = ?";
var affectedRows = jdbcTemplate.update(sql, calculationJobState.name(), id);
if(1 != affectedRows) {
throw new DatabaseException("Unable to update calculation job with id " + id);
}
}
private static class CalculationJobMapper implements RowMapper<CalculationJob> {
@Override

View file

@ -51,7 +51,7 @@ public class DestinationRepository {
}
@Transactional
public void update(Integer id, BigDecimal repackingCost, BigDecimal disposalCost, BigDecimal handlingCost) {
public void update(Integer id, Integer annualAmount, BigDecimal repackingCost, BigDecimal disposalCost, BigDecimal handlingCost) {
if (id == null) {
throw new InvalidArgumentException("ID cannot be null");
}
@ -76,6 +76,11 @@ public class DestinationRepository {
parameters.put("handlingCost", handlingCost);
}
if (annualAmount != null) {
setClauses.add("annual_amount = :annualAmount");
parameters.put("annualAmount", annualAmount);
}
// If no parameters to update, return early
if (setClauses.isEmpty()) {
return;
@ -125,7 +130,7 @@ public class DestinationRepository {
@Transactional
public List<Destination> getByPremiseIdsAndNodeId(List<Integer> premiseId, Integer nodeId, Integer userId) {
String placeholder = String.join(",", Collections.nCopies(premiseId.size(), "?"));
String query = "SELECT * FROM premise_destination JOIN premise ON premise_destination.premise_id = premise.id WHERE premise_id IN ("+placeholder+") AND premise_destination.destination_node_id AND premise.user_id = ?";
String query = "SELECT * FROM premise_destination JOIN premise ON premise_destination.premise_id = premise.id WHERE premise_id IN ("+placeholder+") AND premise_destination.destination_node_id = ? AND premise.user_id = ?";
return jdbcTemplate.query(query, new DestinationMapper(), premiseId, nodeId, userId);
}
@ -134,7 +139,7 @@ public class DestinationRepository {
public Integer insert(Destination destination) {
KeyHolder keyHolder = new GeneratedKeyHolder();
String query = "INSERT INTO premise_destination (annual_amount, premise_id, destination_node_id, country_id, rate_d2d, lead_time_d2d, is_d2d, repacking_cost, handling_cost, disposal_cost) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
String query = "INSERT INTO premise_destination (annual_amount, premise_id, destination_node_id, country_id, rate_d2d, lead_time_d2d, is_d2d, repacking_cost, handling_cost, disposal_cost, geo_lat, geo_lng) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(connection -> {
var ps = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
@ -159,6 +164,10 @@ public class DestinationRepository {
ps.setBigDecimal(8, destination.getRepackingCost());
ps.setBigDecimal(9, destination.getHandlingCost());
ps.setBigDecimal(10, destination.getDisposalCost());
ps.setBigDecimal(11, destination.getGeoLat());
ps.setBigDecimal(12, destination.getGeoLng());
return ps;
}, keyHolder);

View file

@ -832,7 +832,7 @@ public class PremiseRepository {
entity.setHsCode(rs.getString("hs_code"));
entity.setCustomRate(rs.getBigDecimal("tariff_rate"));
entity.setTariffRate(rs.getBigDecimal("tariff_rate"));
entity.setFcaEnabled(rs.getBoolean("is_fca_enabled"));
if(rs.wasNull())

View file

@ -121,6 +121,7 @@ public class DestinationService {
destinationRepository.update(id,
destinationUpdateDTO.getAnnualAmount(),
destinationUpdateDTO.getRepackingCost() == null ? null : BigDecimal.valueOf(destinationUpdateDTO.getRepackingCost().doubleValue()),
destinationUpdateDTO.getDisposalCost() == null ? null : BigDecimal.valueOf(destinationUpdateDTO.getDisposalCost().doubleValue()),
destinationUpdateDTO.getHandlingCost() == null ? null : BigDecimal.valueOf(destinationUpdateDTO.getHandlingCost().doubleValue()));

View file

@ -79,6 +79,7 @@ public class PremisesService {
@Transactional
public Integer startCalculation(List<Integer> premises) {
var userId = 1; // TODO get current user id
@ -101,11 +102,19 @@ public class PremisesService {
calculationIds.add(calculationJobRepository.insert(job));
});
//TODO set premise to completed.
calculationIds.forEach(calculationExecutionService::calculateJob);
calculationIds.forEach(this::scheduleCalculation);
return calculationStatusService.schedule(calculationIds);
}
//TODO: scheduled should be set by worker thread that processes the job.
public void scheduleCalculation(Integer id) {
calculationJobRepository.setStateTo(id, CalculationJobState.SCHEDULED);
calculationExecutionService.calculateJob(id);
}
public CalculationStatus getCalculationStatus(Integer processId) {
return calculationStatusService.getCalculationStatus(processId);
}

View file

@ -97,7 +97,7 @@ public class PremiseCreationService {
private void copyPremise(TemporaryPremise p, Integer userId) {
var old = p.getPremise();
premiseRepository.updateMaterial(Collections.singletonList(p.getId()), old.getHsCode(), old.getCustomRate());
premiseRepository.updateMaterial(Collections.singletonList(p.getId()), old.getHsCode(), old.getTariffRate());
premiseRepository.updatePrice(Collections.singletonList(p.getId()), old.getMaterialCost(), old.getFcaEnabled(), old.getOverseaShare());
premiseRepository.updatePackaging(Collections.singletonList(p.getId()), dimensionTransformer.toDimensionEntity(old), old.getHuStackable(), old.getHuMixable());
premiseRepository.setPackagingId(p.getId(), old.getId());

View file

@ -21,15 +21,19 @@ import de.avatic.lcc.repositories.premise.RouteRepository;
import de.avatic.lcc.repositories.premise.RouteSectionRepository;
import de.avatic.lcc.repositories.properties.PropertyRepository;
import de.avatic.lcc.service.calculation.execution.steps.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
@Service
public class CalculationExecutionService {
private static final Logger log = LoggerFactory.getLogger(CalculationExecutionService.class);
private final PremiseRepository premiseRepository;
private final DestinationRepository destinationRepository;
private final RouteRepository routeRepository;
@ -46,6 +50,7 @@ public class CalculationExecutionService {
private final CalculationJobRepository calculationJobRepository;
private final CalculationJobDestinationRepository calculationJobDestinationRepository;
public CalculationExecutionService(PremiseRepository premiseRepository, DestinationRepository destinationRepository, RouteRepository routeRepository, RouteSectionRepository routeSectionRepository, CustomCostCalculationService customCostCalculationService, RouteSectionCostCalculationService routeSectionCostCalculationService, HandlingCostCalculationService handlingCostCalculationService, InventoryCostCalculationService inventoryCostCalculationService, PropertyRepository propertyRepository, AirfreightCalculationService airfreightCalculationService, PremiseToHuService premiseToHuService, ContainerCalculationService containerCalculationService, ShippingFrequencyCalculationService shippingFrequencyCalculationService, CalculationJobRepository calculationJobRepository, CalculationJobDestinationRepository calculationJobDestinationRepository) {
this.premiseRepository = premiseRepository;
this.destinationRepository = destinationRepository;
@ -100,10 +105,10 @@ public class CalculationExecutionService {
//TODO: save the stuff
//calculationJobDestinationRepository.createDestination(destinationInfos);
log.info("Calculation job {} finished", calculationId);
}
}
private DestinationInfo doDestinationCalculation(Destination destination, Premise premise, BigDecimal materialCost, BigDecimal fcaFee) {
@ -113,46 +118,31 @@ public class CalculationExecutionService {
CustomResult customCost;
List<SectionInfo> sections;
AirfreightResult airfreightCost = airfreightCalculationService.doCalculation(premise, destination);
ContainerType usedContainerType = null;
CalculationJobDestination destinationCalculationJob = new CalculationJobDestination();
boolean hasMainRun = true;
BigDecimal leadTime = null;
if (destination.getD2d()) {
// Get container calculation
PackagingDimension hu = premiseToHuService.createHuFromPremise(premise);
var containerCalculation = containerCalculationService.doCalculation(hu, ContainerType.FEU);
var routeCost = routeSectionCostCalculationService.doD2dCalculation(premise, destination, containerCalculation);
handlingCost = handlingCostCalculationService.doCalculation(premise, destination, true);
inventoryCost = inventoryCostCalculationService.doCalculation(premise, destination, BigDecimal.valueOf(destination.getLeadTimeD2d()));
customCost = customCostCalculationService.doD2dCalculation(premise, destination, routeCost);
sections = List.of(new SectionInfo(null, routeCost, containerCalculation));
destinationCalculationJob.setContainerType(ContainerType.FEU);
var containerCalculation = containerCalculationService.doCalculation(premiseToHuService.createHuFromPremise(premise), ContainerType.FEU);
sections = List.of(new SectionInfo(null, routeSectionCostCalculationService.doD2dCalculation(premise, destination, containerCalculation), containerCalculation));
leadTime = BigDecimal.valueOf(destination.getLeadTimeD2d());
usedContainerType = ContainerType.FEU;
} else {
var route = routeRepository.getSelectedByDestinationId(destination.getId()).orElseThrow();
List<RouteSection> routeSections = routeSectionRepository.getByRouteId(route.getId());
Map<ContainerType, List<SectionInfo>> sectionInfos = new HashMap<>();
Map<ContainerType, ContainerCalculationResult> containerCalculation = new HashMap<>();
// Get container calculation
PackagingDimension hu = premiseToHuService.createHuFromPremise(premise);
Arrays.stream(ContainerType.values()).forEach(type -> containerCalculation.put(type, containerCalculationService.doCalculation(hu, type)));
Arrays.stream(ContainerType.values()).forEach(type -> sectionInfos.put(type, routeSections.stream().map(s -> new SectionInfo(s, doSectionCalculation(premise, destination, s, type, containerCalculation), containerCalculation.get(type))).toList()));
ContainerType bestContainerType = getBestContainerType(sectionInfos);
customCost = customCostCalculationService.doCalculation(premise, destination, sectionInfos.get(bestContainerType));
handlingCost = handlingCostCalculationService.doCalculation(premise, destination, sectionInfos.get(bestContainerType).stream().anyMatch(s -> s.section().getMainRun()));
inventoryCost = inventoryCostCalculationService.doCalculation(premise, destination, BigDecimal.valueOf(sectionInfos.get(bestContainerType).stream().mapToInt(s -> s.result().getTransitTime()).sum()));
sections = sectionInfos.get(bestContainerType);
destinationCalculationJob.setContainerType(bestContainerType);
var bestContainerTypeResult = getSectionsFromBestContainerType(destination, premise);
sections = bestContainerTypeResult.sections;
usedContainerType = bestContainerTypeResult.containerType;
hasMainRun = sections.stream().anyMatch(s -> s.section().getMainRun());
leadTime = BigDecimal.valueOf(sections.stream().mapToInt(s -> s.result().getTransitTime()).sum());
}
customCost = customCostCalculationService.doCalculation(premise, destination, sections);
handlingCost = handlingCostCalculationService.doCalculation(premise, destination, hasMainRun);
inventoryCost = inventoryCostCalculationService.doCalculation(premise, destination, leadTime);
destinationCalculationJob.setContainerType(usedContainerType);
destinationCalculationJob.setMaterialCost(materialCost);
destinationCalculationJob.setFcaCost(fcaFee);
@ -205,15 +195,43 @@ public class CalculationExecutionService {
destinationCalculationJob.setTotalRiskCost(totalRiskCost);
destinationCalculationJob.setTotalChanceCost(totalChanceCost);
destinationCalculationJob.setTotalTransitTime(sections.stream().mapToInt(s -> s.result().getTransitTime()).sum());
destinationCalculationJob.setContainerUtilization(sections.stream().map(s -> s.result().getUtilization()).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(sections.size()), 10, RoundingMode.HALF_UP));
return new DestinationInfo(destination, destinationCalculationJob, sections);
}
private CalculationJobRouteSection doSectionCalculation(Premise premise, Destination destination, RouteSection section, ContainerType containerType, Map<ContainerType, ContainerCalculationResult> calculationResult) {
if (RateType.MATRIX == section.getRateType()) {
return routeSectionCostCalculationService.doCalculation(premise, destination, section, calculationResult.get(ContainerType.TRUCK));
} else {
return routeSectionCostCalculationService.doCalculation(premise, destination, section, calculationResult.get(containerType));
private BestContainerTypeResult getSectionsFromBestContainerType(Destination destination, Premise premise) {
PackagingDimension hu = premiseToHuService.createHuFromPremise(premise);
var route = routeRepository.getSelectedByDestinationId(destination.getId()).orElseThrow();
List<RouteSection> routeSections = routeSectionRepository.getByRouteId(route.getId());
Map<ContainerType, List<SectionInfo>> sectionInfos = new HashMap<>();
Map<ContainerType, ContainerCalculationResult> containerCalculation = new HashMap<>();
// Get container calculation
for (var containerType : ContainerType.values()) {
containerCalculation.put(containerType, containerCalculationService.doCalculation(hu, containerType));
if (!containerType.equals(ContainerType.TRUCK)) {
var sectionInfo = new ArrayList<SectionInfo>();
for (var section : routeSections) {
var container = RateType.MATRIX == section.getRateType() ? containerCalculation.get(ContainerType.TRUCK) : containerCalculation.get(containerType);
sectionInfo.add(new SectionInfo(section, routeSectionCostCalculationService.doCalculation(premise, destination, section, container), containerCalculation.get(containerType)));
}
sectionInfos.put(containerType, sectionInfo);
}
}
var bestContainerType = getBestContainerType(sectionInfos);
return new BestContainerTypeResult(bestContainerType, sectionInfos.get(bestContainerType));
}
private record BestContainerTypeResult(ContainerType containerType, List<SectionInfo> sections) {
}
private record DestinationInfo(Destination destination, CalculationJobDestination destinationCalculationJob,

View file

@ -27,12 +27,12 @@ public class ChangeRiskFactorCalculationService {
public ChangeRiskFactorCalculationResult getChanceRiskFactors() {
var rate = findRate();
var riskValue = Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.RISK_REF).orElseThrow().getCurrentValue());
var chanceValue = Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.CHANCE_REF).orElseThrow().getCurrentValue());
var riskValue = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.RISK_REF).orElseThrow().getCurrentValue()));
var chanceValue = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.CHANCE_REF).orElseThrow().getCurrentValue()));
var result = new ChangeRiskFactorCalculationResult();
result.setChanceFactor(rate.getRateFeu().divide(BigDecimal.valueOf(chanceValue), 2, RoundingMode.HALF_UP));
result.setRiskFactor(rate.getRateFeu().divide(BigDecimal.valueOf(riskValue), 2, RoundingMode.HALF_UP));
result.setChanceFactor(chanceValue.divide(rate.getRateFeu(), 2, RoundingMode.HALF_UP));
result.setRiskFactor(riskValue.divide(rate.getRateFeu(), 2, RoundingMode.HALF_UP));
return result;
}

View file

@ -7,6 +7,7 @@ import de.avatic.lcc.model.packaging.PackagingDimension;
import de.avatic.lcc.model.properties.SystemPropertyMappingId;
import de.avatic.lcc.model.utils.WeightUnit;
import de.avatic.lcc.repositories.properties.PropertyRepository;
import org.jetbrains.annotations.Debug.Renderer;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@ -31,14 +32,14 @@ public class ContainerCalculationService {
var dimensions = hu.withTolerance(DIMENSION_TOLERANCE);
var solutionHorizontal = solveLayer(dimensions, containerType.getLength(), containerType.getWidth());
var solutionVertical = solveLayer(dimensions, containerType.getWidth(), containerType.getLength());
var solutionHorizontal = solveLayer(SolutionType.HORIZONTAL, dimensions, containerType.getLength(), containerType.getWidth());
var solutionVertical = solveLayer(SolutionType.VERTICAL, dimensions, containerType.getWidth(), containerType.getLength());
var bestSolution = solutionHorizontal.getTotal() < solutionVertical.getTotal() ? solutionVertical : solutionHorizontal;
int layers = getLayerCount(dimensions, containerType);
if(PalletType.EURO_PALLET.fitsOn(dimensions) && bestSolution.getTotal() < containerType.getPalletCount(PalletType.EURO_PALLET)) {
if(PalletType.EURO_PALLET.fitsOn(hu) && bestSolution.getTotal() < containerType.getPalletCount(PalletType.EURO_PALLET)) {
return new ContainerCalculationResult(Math.min(containerType.getPalletCount(PalletType.EURO_PALLET)*layers,maxUnitByWeight), layers, null, containerType.getPalletCount(PalletType.EURO_PALLET) > maxUnitByWeight, containerType, dimensions, maxContainerLoad);
} else if(PalletType.INDUSTRIAL_PALLET.fitsOn(dimensions) && bestSolution.getTotal() < containerType.getPalletCount(PalletType.INDUSTRIAL_PALLET)) {
} else if(PalletType.INDUSTRIAL_PALLET.fitsOn(hu) && bestSolution.getTotal() < containerType.getPalletCount(PalletType.INDUSTRIAL_PALLET)) {
return new ContainerCalculationResult(Math.min(containerType.getPalletCount(PalletType.INDUSTRIAL_PALLET)*layers,maxUnitByWeight), layers, null, containerType.getPalletCount(PalletType.INDUSTRIAL_PALLET) > maxUnitByWeight, containerType, dimensions, maxContainerLoad);
}
@ -46,14 +47,15 @@ public class ContainerCalculationService {
}
private static Solution solveLayer(PackagingDimension dimension,
private static Solution solveLayer(SolutionType type, PackagingDimension dimension,
int containerWidth, int containerLength) {
var horizontalColumn = new Column(new Block(dimension, BlockType.HORIZONTAL), containerWidth);
var verticalColumn = new Column(new Block(dimension, BlockType.VERTICAL), containerWidth);
var circularColumn = new Column(new Block(dimension, BlockType.CIRCULAR), containerWidth);
Solution bestSolution = new Solution(0, 0, 0, horizontalColumn, verticalColumn, circularColumn);
Solution bestSolution = new Solution(type,0, 0, 0, horizontalColumn, verticalColumn, circularColumn);
int maxHorizontalColumns = containerLength / horizontalColumn.getColumnWidth();
int maxVerticalColumns = containerLength / verticalColumn.getColumnWidth();
@ -66,7 +68,7 @@ public class ContainerCalculationService {
if (fitsInContainer(horizontalColumn, verticalColumn, circularColumn,
horizontalColumnCount, verticalColumnCount, circularColumnCount, containerLength)) {
Solution current = new Solution(
Solution current = new Solution(type,
horizontalColumnCount, verticalColumnCount, circularColumnCount,
horizontalColumn, verticalColumn, circularColumn);
@ -93,7 +95,8 @@ public class ContainerCalculationService {
Map<ContainerType, SystemPropertyMappingId> mappings = Map.of(
ContainerType.FEU, SystemPropertyMappingId.FEU_LOAD,
ContainerType.TRUCK, SystemPropertyMappingId.TRUCK_LOAD,
ContainerType.TEU, SystemPropertyMappingId.TEU_LOAD
ContainerType.TEU, SystemPropertyMappingId.TEU_LOAD,
ContainerType.HQ, SystemPropertyMappingId.FEU_LOAD
);
SystemPropertyMappingId mappingId = mappings.get(containerType);
@ -101,9 +104,11 @@ public class ContainerCalculationService {
throw new IllegalArgumentException("Unsupported container type: " + containerType);
}
return Integer.parseInt(propertyRepository.getPropertyByMappingId(mappingId)
var value = propertyRepository.getPropertyByMappingId(mappingId)
.orElseThrow(() -> new IllegalStateException("Missing property: " + mappingId))
.getCurrentValue());
.getCurrentValue();
return Integer.parseInt(value);
}
private int getLayerCount(PackagingDimension dimensions, ContainerType containerType) {
@ -115,7 +120,7 @@ public class ContainerCalculationService {
ContainerType containerType, PackagingDimension hu, int maxContainerLoad) {
int totalUnits = Math.min(solution.getTotal() * layers, maxUnitByWeight);
boolean weightExceeded = solution.getTotal() > maxUnitByWeight;
boolean weightExceeded = (solution.getTotal()* layers) > maxUnitByWeight;
return new ContainerCalculationResult(
totalUnits, layers, null, weightExceeded,
@ -153,19 +158,27 @@ public class ContainerCalculationService {
}
private static enum SolutionType {
HORIZONTAL, VERTICAL
}
@Renderer(text = "getFullDebugInfo()")
private static class Solution {
SolutionType type;
Map<BlockType, Integer> rowCount = new HashMap<>();
Map<BlockType, Column> columns = new HashMap<>();
public Solution(int horizontalCount, int verticalCount, int circularCount, Column horizontalColumn, Column verticalColumn, Column circularColumn) {
public Solution(SolutionType type, int horizontalCount, int verticalCount, int circularCount, Column horizontalColumn, Column verticalColumn, Column circularColumn) {
rowCount.put(BlockType.HORIZONTAL, horizontalCount);
rowCount.put(BlockType.VERTICAL, verticalCount);
rowCount.put(BlockType.CIRCULAR, circularCount);
columns.put(BlockType.HORIZONTAL, horizontalColumn);
columns.put(BlockType.VERTICAL, verticalColumn);
columns.put(BlockType.CIRCULAR, circularColumn);
this.type = type;
}
public int getTotal() {
@ -173,8 +186,14 @@ public class ContainerCalculationService {
+ rowCount.get(BlockType.VERTICAL) * columns.get(BlockType.VERTICAL).getResultValue()
+ rowCount.get(BlockType.CIRCULAR) * columns.get(BlockType.CIRCULAR).getResultValue();
}
public String getFullDebugInfo() {
return String.format("Solution [%s HUs: %d]",
type, getTotal());
}
}
@Renderer(text = "getFullDebugInfo()")
private static class Column {
private final int blocksPerColumn;
@ -192,8 +211,13 @@ public class ContainerCalculationService {
public int getColumnWidth() {
return block.getBlockWidth();
}
public String getFullDebugInfo() {
return "Column " + blocksPerColumn + "x" + block.getFullDebugInfo();
}
}
@Renderer(text = "getFullDebugInfo()")
private static class Block {
private final PackagingDimension dimension;
@ -215,5 +239,9 @@ public class ContainerCalculationService {
public int getBlockWidth() {
return type.getColumnWidth(dimension);
}
public String getFullDebugInfo() {
return "BLOCK %s W%s L%s H%s".formatted(type.name(), type.getColumnWidth(dimension), type.getBlockColumnLength(dimension), dimension.getHeight());
}
}
}

View file

@ -1,7 +1,6 @@
package de.avatic.lcc.service.calculation.execution.steps;
import de.avatic.lcc.calculationmodel.CustomResult;
import de.avatic.lcc.model.calculations.CalculationJobRouteSection;
import de.avatic.lcc.model.premises.Premise;
import de.avatic.lcc.model.premises.route.Destination;
import de.avatic.lcc.model.properties.CountryPropertyMappingId;
@ -35,7 +34,7 @@ public class CustomCostCalculationService {
this.shippingFrequencyCalculationService = shippingFrequencyCalculationService;
}
public CustomResult doD2dCalculation(Premise premise, Destination destination, CalculationJobRouteSection routeCost) {
public CustomResult doD2dCalculation(Premise premise, Destination destination, List<SectionInfo> sections) {
var destUnion = countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.UNION, destination.getCountryId()).orElseThrow();
var sourceUnion = countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.UNION, premise.getCountryId()).orElseThrow();
@ -43,7 +42,7 @@ public class CustomCostCalculationService {
if (!CustomUnionType.EU.name().equals(destUnion.getCurrentValue()) || !CustomUnionType.NONE.name().equals(sourceUnion.getCurrentValue()))
return CustomResult.EMPTY;
return getCustomCalculationResult(premise, destination, routeCost.getAnnualCost(), routeCost.getAnnualChanceCost(), routeCost.getAnnualRiskCost());
return getCustomCalculationResult(premise, destination, sections.getFirst().result().getAnnualCost(), sections.getFirst().result().getAnnualChanceCost(), sections.getFirst().result().getAnnualRiskCost());
}
public CustomResult doCalculation(Premise premise, Destination destination, List<SectionInfo> sections) {
@ -51,10 +50,14 @@ public class CustomCostCalculationService {
var destUnion = countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.UNION, destination.getCountryId()).orElseThrow();
var sourceUnion = countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.UNION, premise.getCountryId()).orElseThrow();
if (CustomUnionType.EU.name().equals(destUnion.getCurrentValue()) && CustomUnionType.NONE.name().equals(sourceUnion.getCurrentValue())) {
var transportationCost = getCustomRelevantRouteSections(sections).stream().map(s -> s.result().getAnnualCost()).reduce(BigDecimal.ZERO, BigDecimal::add);
var transportationChanceCost = getCustomRelevantRouteSections(sections).stream().map(s -> s.result().getAnnualChanceCost()).reduce(BigDecimal.ZERO, BigDecimal::add);
var transportationRiskCost = getCustomRelevantRouteSections(sections).stream().map(s -> s.result().getAnnualChanceCost()).reduce(BigDecimal.ZERO, BigDecimal::add);
if (CustomUnionType.EU.name().equals(destUnion.getCurrentValue()) && (sourceUnion.getCurrentValue() == null || CustomUnionType.NONE.name().equals(sourceUnion.getCurrentValue()))) {
var relevantSections = getCustomRelevantRouteSections(sections);
var transportationCost = relevantSections.stream().map(s -> s.result().getAnnualCost()).reduce(BigDecimal.ZERO, BigDecimal::add);
var transportationChanceCost = relevantSections.stream().map(s -> s.result().getAnnualChanceCost()).reduce(BigDecimal.ZERO, BigDecimal::add);
var transportationRiskCost = relevantSections.stream().map(s -> s.result().getAnnualRiskCost()).reduce(BigDecimal.ZERO, BigDecimal::add);
return getCustomCalculationResult(premise, destination, transportationCost, transportationChanceCost, transportationRiskCost);
}
@ -64,7 +67,8 @@ public class CustomCostCalculationService {
private CustomResult getCustomCalculationResult(Premise premise, Destination destination, BigDecimal transportationCost, BigDecimal transportationChanceCost, BigDecimal transportationRiskCost) {
var shippingFrequency = shippingFrequencyCalculationService.doCalculation(destination.getAnnualAmount());
var customFee = Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.CUSTOM_FEE).orElseThrow().getCurrentValue());
var tariffRate = customApiService.getTariffRate(premise.getHsCode(), premise.getCountryId());
var tariffRate = premise.getTariffRate() == null ? customApiService.getTariffRate(premise.getHsCode(), premise.getCountryId()) : premise.getTariffRate();
var materialCost = premise.getMaterialCost();
var fcaFee = BigDecimal.ZERO;
@ -96,8 +100,8 @@ public class CustomCostCalculationService {
List<SectionInfo> customSections = new ArrayList<>();
for (SectionInfo section : sections) {
if (CustomUnionType.EU == getCustomUnionByRouteNodeId(section.section().getFromRouteNodeId()) &&
CustomUnionType.EU == getCustomUnionByRouteNodeId(section.section().getToRouteNodeId())) {
if (!(CustomUnionType.EU == getCustomUnionByRouteNodeId(section.section().getFromRouteNodeId()) &&
CustomUnionType.EU == getCustomUnionByRouteNodeId(section.section().getToRouteNodeId()))) {
customSections.add(section);
}
}
@ -112,6 +116,9 @@ public class CustomCostCalculationService {
private CustomUnionType getCustomUnionByCountryId(Integer countryId) {
var property = countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.UNION, countryId).orElseThrow();
if(property.getCurrentValue() == null)
return CustomUnionType.NONE;
return CustomUnionType.valueOf(property.getCurrentValue().toUpperCase());
}

View file

@ -20,11 +20,13 @@ public class HandlingCostCalculationService {
private final CountryPropertyRepository countryPropertyRepository;
private final PropertyRepository propertyRepository;
private final PremiseToHuService premiseToHuService;
private final ShippingFrequencyCalculationService shippingFrequencyCalculationService;
public HandlingCostCalculationService(CountryPropertyRepository countryPropertyRepository, PropertyRepository propertyRepository, PremiseToHuService premiseToHuService) {
public HandlingCostCalculationService(CountryPropertyRepository countryPropertyRepository, PropertyRepository propertyRepository, PremiseToHuService premiseToHuService, ShippingFrequencyCalculationService shippingFrequencyCalculationService) {
this.countryPropertyRepository = countryPropertyRepository;
this.propertyRepository = propertyRepository;
this.premiseToHuService = premiseToHuService;
this.shippingFrequencyCalculationService = shippingFrequencyCalculationService;
}
public HandlingResult doCalculation(Premise premise, Destination destination, Boolean addRepackingCosts) {
@ -56,9 +58,9 @@ public class HandlingCostCalculationService {
return switch (type) {
case SLC ->
Double.parseDouble((hu.getWeight() < 15.000) ? propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.KLT_REPACK_S).orElseThrow().getCurrentValue() : propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.KLT_REPACK_M).orElseThrow().getCurrentValue());
Double.parseDouble((hu.getWeight() < 15_000) ? propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.KLT_REPACK_S).orElseThrow().getCurrentValue() : propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.KLT_REPACK_M).orElseThrow().getCurrentValue());
case LLC ->
Double.parseDouble(((hu.getWeight() < 15.000) ? propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_REPACK_S) : (hu.getWeight() < 2000.000) ? propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_REPACK_M) : propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_REPACK_L)).orElseThrow().getCurrentValue());
Double.parseDouble(((hu.getWeight() < 15_000) ? propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_REPACK_S) : (hu.getWeight() < 2_000_000) ? propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_REPACK_M) : propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.GLT_REPACK_L)).orElseThrow().getCurrentValue());
};
}
@ -73,11 +75,11 @@ public class HandlingCostCalculationService {
double wageFactor = Double.parseDouble(countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.WAGE, destination.getCountryId()).orElseThrow().getCurrentValue());
double booking = Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.BOOKING).orElseThrow().getCurrentValue());
return new HandlingResult(LoadCarrierType.SLC,
BigDecimal.valueOf(getRepackingCost(hu, type, addRepackingCosts) * huAnnualAmount),
BigDecimal.valueOf(handling*huAnnualAmount),
BigDecimal.valueOf(disposal * huAnnualAmount),
BigDecimal.valueOf(huAnnualAmount * (((handling + booking + release + dispatch + getRepackingCost(hu, type, addRepackingCosts)) * wageFactor) + disposal)));
var annualRepacking = BigDecimal.valueOf(getRepackingCost(hu, type, addRepackingCosts) * wageFactor * huAnnualAmount);
var annualHandling = BigDecimal.valueOf((handling+dispatch+release)*wageFactor*huAnnualAmount + (booking * shippingFrequencyCalculationService.doCalculation(huAnnualAmount)));
var annualDisposal = BigDecimal.valueOf(disposal * huAnnualAmount);
return new HandlingResult(LoadCarrierType.LLC, annualRepacking, annualHandling, annualDisposal, annualRepacking.add(annualHandling).add(annualDisposal));
}

View file

@ -48,20 +48,20 @@ public class InventoryCostCalculationService {
var interestRate = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.INTEREST_RATE).orElseThrow().getCurrentValue()));
var annualAmount = BigDecimal.valueOf(destination.getAnnualAmount().doubleValue());
var dailyAmount = annualAmount.divide(BigDecimal.valueOf(365));
var workdayAmount = annualAmount.divide(workdays);
var dailyAmount = annualAmount.divide(BigDecimal.valueOf(365), 10, RoundingMode.HALF_UP);
var workdayAmount = annualAmount.divide(workdays, 10, RoundingMode.HALF_UP);
var opStock = (annualAmount.divide(BigDecimal.valueOf(Math.max(shippingFrequencyCalculationService.doCalculation(destination.getAnnualAmount()),1))).multiply(BigDecimal.valueOf(.5)));
var opStock = (annualAmount.divide(BigDecimal.valueOf(Math.max(shippingFrequencyCalculationService.doCalculation(destination.getAnnualAmount()),1)), 10, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(.5)));
var safetyStock = safetydays.multiply(workdayAmount);
var stockedInventory = opStock.add(safetyStock);
var inTransportStock = dailyAmount.multiply(leadTime);
var stockBeforePayment = dailyAmount.multiply(paymentTerms);
var capitalCostStock = stockedInventory.add(inTransportStock).subtract(stockBeforePayment);
var storageCostStock = roundToHu(hu, safetyStock).add(opStock);
var storageCostStock = roundToHu(hu, safetyStock.add(opStock));
var capitalCost = capitalCostStock.multiply(interestRate).multiply(premise.getMaterialCost().add(fcaFee));
var storageCost = storageCostStock.divide(BigDecimal.valueOf(hu.getContentUnitCount())).multiply(getSpaceCostPerHu(hu));
var storageCost = storageCostStock.multiply(getSpaceCostPerHu(hu)).multiply(BigDecimal.valueOf(365));
return new InventoryCostResult(opStock, safetyStock, stockedInventory, inTransportStock, stockBeforePayment, capitalCost, storageCost, safetydays );
@ -70,7 +70,8 @@ public class InventoryCostCalculationService {
private BigDecimal getSpaceCostPerHu(PackagingDimension hu) {
var spaceCost = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.SPACE_COST).orElseThrow().getCurrentValue()));
return BigDecimal.valueOf(hu.getFloorArea(DimensionUnit.M)*hu.getRoundedHeight(DimensionUnit.M)).multiply(spaceCost);
var spaceCostPerHu = BigDecimal.valueOf(hu.getFloorArea(DimensionUnit.M)*hu.getRoundedHeight(DimensionUnit.M)).multiply(spaceCost);
return spaceCostPerHu;
}
private BigDecimal roundToHu(PackagingDimension hu, BigDecimal safetyStock) {

View file

@ -14,6 +14,7 @@ import de.avatic.lcc.model.properties.SystemPropertyMappingId;
import de.avatic.lcc.model.rates.ContainerRate;
import de.avatic.lcc.model.rates.MatrixRate;
import de.avatic.lcc.model.utils.DimensionUnit;
import de.avatic.lcc.model.utils.WeightUnit;
import de.avatic.lcc.repositories.premise.RouteNodeRepository;
import de.avatic.lcc.repositories.properties.PropertyRepository;
import de.avatic.lcc.repositories.rates.ContainerRateRepository;
@ -22,6 +23,7 @@ import de.avatic.lcc.service.calculation.DistanceService;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.NoSuchElementException;
@Service
@ -86,6 +88,7 @@ public class RouteSectionCostCalculationService {
result.setWeightPrice(containerCalculation.isWeightExceeded());
result.setCbmPrice(prices.volumePrice);
result.setWeightPrice(prices.weightPrice);
result.setUtilization(prices.utilization);
var chanceRiskFactors = changeRiskFactorCalculationService.getChanceRiskFactors();
@ -112,7 +115,7 @@ public class RouteSectionCostCalculationService {
// Set premise metadata
result.setStacked(premise.getHuStackable());
result.setUnmixedPrice(premise.getHuMixable());
result.setUnmixedPrice(!premise.getHuMixable());
// Get nodes and distance
RouteNode fromNode = routeNodeRepository.getById(section.getFromRouteNodeId()).orElseThrow();
@ -125,7 +128,7 @@ public class RouteSectionCostCalculationService {
int transitTime;
if (RateType.CONTAINER == section.getRateType()) {
ContainerRate containerRate = findContainerRate(section);
ContainerRate containerRate = findContainerRate(section, fromNode, toNode);
rate = getContainerRate(containerRate, containerCalculation.getContainerType());
transitTime = containerRate.getLeadTime();
} else if (RateType.MATRIX == section.getRateType()) {
@ -140,8 +143,10 @@ public class RouteSectionCostCalculationService {
result.setTransitTime(transitTime);
// Calculate price and annual cost
int huAnnualAmount = destination.getAnnualAmount() / containerCalculation.getHu().getContentUnitCount();
BigDecimal utilization = getUtilization(section.getRateType());
double annualVolume = destination.getAnnualAmount() * containerCalculation.getHu().getVolume(DimensionUnit.M);
BigDecimal annualVolume = BigDecimal.valueOf(huAnnualAmount * containerCalculation.getHu().getVolume(DimensionUnit.M));
BigDecimal annualWeight = BigDecimal.valueOf(huAnnualAmount * containerCalculation.getHu().getWeight(WeightUnit.KG));
PriceCalculationResult prices = calculatePrices(
premise.getHuMixable(),
@ -155,10 +160,11 @@ public class RouteSectionCostCalculationService {
result.setWeightPrice(containerCalculation.isWeightExceeded());
result.setCbmPrice(prices.volumePrice);
result.setWeightPrice(prices.weightPrice);
result.setUtilization(prices.utilization);
var chanceRiskFactors = changeRiskFactorCalculationService.getChanceRiskFactors();
BigDecimal annualCost = (containerCalculation.isWeightExceeded() ? prices.weightPrice : prices.volumePrice).multiply(BigDecimal.valueOf(annualVolume));
BigDecimal annualCost = (containerCalculation.isWeightExceeded() ? prices.weightPrice.multiply(annualWeight) : prices.volumePrice.multiply(annualVolume));
BigDecimal annualRiskCost = annualCost.multiply(chanceRiskFactors.getRiskFactor());
BigDecimal annualChanceCost = annualCost.multiply(chanceRiskFactors.getChanceFactor());
@ -175,31 +181,36 @@ public class RouteSectionCostCalculationService {
ContainerType containerType,
int maxContainerWeight,
BigDecimal totalVolumeUtilization,
BigDecimal utilization) {
BigDecimal propertyUtilization) {
BigDecimal utilization;
BigDecimal volumePrice;
BigDecimal weightPrice;
BigDecimal cbmRate = rate.divide(BigDecimal.valueOf(containerType.getVolume()));
BigDecimal cbmRate = rate.divide(BigDecimal.valueOf(containerType.getVolume()), 10, RoundingMode.HALF_UP);
BigDecimal weightRate = rate.divide(BigDecimal.valueOf(maxContainerWeight), 10, RoundingMode.HALF_UP);
if (huMixable) {
volumePrice = cbmRate.divide(utilization);
weightPrice = (rate.divide(BigDecimal.valueOf(maxContainerWeight))).divide(utilization);
volumePrice = cbmRate.divide(propertyUtilization, 10, RoundingMode.HALF_UP);
weightPrice = weightRate.divide(propertyUtilization, 10, RoundingMode.HALF_UP);
utilization = propertyUtilization;
} else {
volumePrice = cbmRate.divide(totalVolumeUtilization);
weightPrice = (rate.divide(BigDecimal.valueOf(maxContainerWeight))).divide(totalVolumeUtilization);
volumePrice = cbmRate.divide(totalVolumeUtilization, 10, RoundingMode.HALF_UP);
weightPrice = weightRate.divide(totalVolumeUtilization, 10, RoundingMode.HALF_UP);
utilization = totalVolumeUtilization;
}
return new PriceCalculationResult(volumePrice, weightPrice);
return new PriceCalculationResult(volumePrice, weightPrice, utilization);
}
private ContainerRate findContainerRate(RouteSection section) {
private ContainerRate findContainerRate(RouteSection section, RouteNode fromNode, RouteNode toNode) {
return containerRateRepository.findRoute(
section.getFromRouteNodeId(),
section.getToRouteNodeId(),
fromNode.getNodeId(),
toNode.getNodeId(),
TransportType.valueOf(section.getTransportType().name()))
.orElseThrow(() -> new NoSuchElementException(
"ContainerRate not found for route: " + section.getFromRouteNodeId() +
" to " + section.getToRouteNodeId()));
"ContainerRate not found for route: " + fromNode.getName() + "(" + fromNode.getNodeId() + ")" +
" to " + toNode.getName() + "(" + toNode.getNodeId() + ")"));
}
private MatrixRate findMatrixRate(RouteNode fromNode, RouteNode toNode) {
@ -250,6 +261,6 @@ public class RouteSectionCostCalculationService {
/**
* Simple data class to hold volume and weight price results
*/
private record PriceCalculationResult(BigDecimal volumePrice, BigDecimal weightPrice) {}
private record PriceCalculationResult(BigDecimal volumePrice, BigDecimal weightPrice, BigDecimal utilization) {}
}

View file

@ -5,51 +5,134 @@
-- Description -> name
-- ===================================================
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Reference route segment start node mapping id', 'START_REF', 'TEXT', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Reference route segment end node mapping id', 'END_REF', 'TEXT', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'The historically highest rate for the reference route segment for 40ft containers [EUR]', 'RISK_REF', 'CURRENCY', '{"GT":0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'The historically lowest rate for the reference route segment for 40ft containers [EUR]', 'CHANCE_REF', 'CURRENCY', '{"GT":0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Annual working days', 'WORKDAYS', 'INT', '{GT: 0, LT: 366}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Interest rate inventory [%]', 'INTEREST_RATE', 'PERCENTAGE', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'FCA fee [%]', 'FCA_FEE', 'PERCENTAGE', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Default customs duty [%]', 'TARIFF_RATE', 'PERCENTAGE', '{GTE:0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Customs clearance fee per import & HS code', 'CUSTOM_FEE', 'CURRENCY', '{GTE:0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Standard-Report Format', 'REPORTING', 'ENUMERATION', '{ENUM:[\'MEK_B\',\'MEK_C\']}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Payment terms [days]', 'PAYMENT_TERMS', 'INT', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Annual working days', 'WORKDAYS', 'INT', '{"GT": 0, "LT": 366}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Interest rate inventory [%]', 'INTEREST_RATE', 'PERCENTAGE', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'FCA fee [%]', 'FCA_FEE', 'PERCENTAGE', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Default customs duty [%]', 'TARIFF_RATE', 'PERCENTAGE', '{"GTE":0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Customs clearance fee per import & HS code', 'CUSTOM_FEE', 'CURRENCY', '{"GTE":0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Standard-Report Format', 'REPORTING', 'ENUMERATION', '{"ENUM":["MEK_B","MEK_C"]}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( '40''', 'FEU', 'BOOLEAN', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( '20''', 'TEU', 'BOOLEAN', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( '40''HC', 'FEU_HQ', 'BOOLEAN', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Container utilization in mixed containers [%]', 'CONTAINER_UTIL', 'PERCENTAGE', '{GTE:0,LTE:1}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Truck utilization road transport EMEA [%]', 'TRUCK_UTIL', 'PERCENTAGE', '{GTE:0,LTE:1}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max validity of container freight rates [days]', 'VALID_DAYS', 'INT', '{GT: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Metropolition region size (diameter) [km]', 'RADIUS_REGION', 'INT', '{GT: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Min delivery frequency / year for containtrer transports', 'FREQ_MIN', 'INT', '{GT: 0, LT: 366}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max delivery frequency / year for containtrer transports', 'FREQ_MAX', 'INT', '{GT: 0, LT: 366}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max load of 20'' container [kg]', 'TEU_LOAD', 'INT', '{GT: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max load of 40'' container [kg]', 'FEU_LOAD', 'INT', '{GT: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Pre-carriage [EUR/kg]', 'AIR_PRECARRIAGE', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Pre-carriage handling [EUR]', 'AIR_HANDLING', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Main carriage [EUR/kg]', 'AIR_MAINCARRIAGE', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Hand over fee [EUR]', 'AIR_HANDOVER_FEE', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Customs clearance fee [EUR]', 'AIR_CUSTOM_FEE', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'On-carriage [EUR/kg]', 'AIR_ONCARRIAGE', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Terminal handling fee [EUR/kg]', 'AIR_TERMINAL_FEE', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GR handling KLT [EUR/HU]', 'KLT_HANDLING', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GR handling GLT [EUR/HU]', 'GLT_HANDLING', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GLT/KLT booking & document handling [EUR/GR]', 'BOOKING', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GLT release from storage [EUR/GLT release]', 'GLT_RELEASE', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'KLT release from storage [EUR/KLT release]', 'KLT_RELEASE', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GLT dispatch [EUR/GLT dispatch]', 'GLT_DISPATCH', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'KLT dispacth [EUR/KLT dispatch]', 'KLT_DISPATCH', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking KLT, HU <15kg [EUR/HU]', 'KLT_REPACK_S', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking KLT, HU >=15kg [EUR/HU]', 'KLT_REPACK_M', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking GLT, HU <15kg [EUR/HU]', 'GLT_REPACK_S', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking GLT, HU 15 - 2000kg [EUR/HU]', 'GLT_REPACK_M', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking GLT, HU > 2000kg [EUR/HU]', 'GLT_REPACK_L', 'INT', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GLT disposal [EUR/GLT]', 'DISPOSAL', 'INT', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Space costs / m3 per night [EUR/m3]', 'SPACE_COST', 'CURRENCY', '{GTE: 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Container utilization in mixed containers [%]', 'CONTAINER_UTIL', 'PERCENTAGE', '{"GTE":0,"LTE":1}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Truck utilization road transport EMEA [%]', 'TRUCK_UTIL', 'PERCENTAGE', '{"GTE":0,"LTE":1}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max validity of container freight rates [days]', 'VALID_DAYS', 'INT', '{"GT": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Metropolition region size (diameter) [km]', 'RADIUS_REGION', 'INT', '{"GT": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Min delivery frequency / year for containtrer transports', 'FREQ_MIN', 'INT', '{"GT": 0, "LT": 366}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max delivery frequency / year for containtrer transports', 'FREQ_MAX', 'INT', '{"GT": 0, "LT": 366}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max load of 20'' container [kg]', 'TEU_LOAD', 'INT', '{"GT": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max load of 40'' container [kg]', 'FEU_LOAD', 'INT', '{"GT": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max load of a truck [kg]', 'TRUCK_LOAD', 'INT', '{"GT": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Pre-carriage [EUR/kg]', 'AIR_PRECARRIAGE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Pre-carriage handling [EUR]', 'AIR_HANDLING', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Main carriage [EUR/kg]', 'AIR_MAINCARRIAGE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Hand over fee [EUR]', 'AIR_HANDOVER_FEE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Customs clearance fee [EUR]', 'AIR_CUSTOM_FEE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'On-carriage [EUR/kg]', 'AIR_ONCARRIAGE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Terminal handling fee [EUR/kg]', 'AIR_TERMINAL_FEE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GR handling KLT [EUR/HU]', 'KLT_HANDLING', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GR handling GLT [EUR/HU]', 'GLT_HANDLING', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GLT/KLT booking & document handling [EUR/GR]', 'BOOKING', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GLT release from storage [EUR/GLT release]', 'GLT_RELEASE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'KLT release from storage [EUR/KLT release]', 'KLT_RELEASE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GLT dispatch [EUR/GLT dispatch]', 'GLT_DISPATCH', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'KLT dispacth [EUR/KLT dispatch]', 'KLT_DISPATCH', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking KLT, HU <15kg [EUR/HU]', 'KLT_REPACK_S', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking KLT, HU >=15kg [EUR/HU]', 'KLT_REPACK_M', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking GLT, HU <15kg [EUR/HU]', 'GLT_REPACK_S', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking GLT, HU 15 - 2000kg [EUR/HU]', 'GLT_REPACK_M', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Repacking GLT, HU > 2000kg [EUR/HU]', 'GLT_REPACK_L', 'INT', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'GLT disposal [EUR/GLT]', 'DISPOSAL', 'INT', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Space costs / m3 per night [EUR/m3]', 'SPACE_COST', 'CURRENCY', '{"GTE": 0}');
-- ===================================================
-- INSERT Statements für system_property
-- Verwendung von Subqueries für dynamische ID-Ermittlung
-- ===================================================
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'PAYMENT_TERMS'),
'30'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'START_REF'),
'CNXMN'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'END_REF'),
'DEHAM'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'RISK_REF'),
'20000.00'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'CHANCE_REF'),
'1000.00'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'TRUCK_UTIL'),
'0.7'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps

View file

@ -595,6 +595,7 @@ SELECT
FROM `country` c, `country_property_type` cpt
WHERE cpt.external_mapping_id = 'AIR_SHARE';
-- Wage Factor Properties (only for countries with defined values)
-- Wage Factor Properties (only for countries with defined values)
INSERT INTO `country_property`
(`country_id`, `country_property_type_id`, `property_set_id`, `property_value`)
@ -608,32 +609,32 @@ SELECT
ORDER BY ps.start_date DESC
LIMIT 1),
CASE c.iso_code
WHEN 'AT' THEN '99'
WHEN 'BE' THEN '114'
WHEN 'BG' THEN '23'
WHEN 'CZ' THEN '44'
WHEN 'DE' THEN '100'
WHEN 'DK' THEN '116'
WHEN 'EE' THEN '60'
WHEN 'ES' THEN '90'
WHEN 'FI' THEN '102'
WHEN 'FR' THEN '105'
WHEN 'GR' THEN '35'
WHEN 'HR' THEN '31'
WHEN 'HU' THEN '35'
WHEN 'IE' THEN '97'
WHEN 'IT' THEN '72'
WHEN 'LT' THEN '36'
WHEN 'LU' THEN '131'
WHEN 'LV' THEN '33'
WHEN 'MT' THEN '41'
WHEN 'NL' THEN '105'
WHEN 'PL' THEN '27'
WHEN 'PT' THEN '41'
WHEN 'RO' THEN '27'
WHEN 'SE' THEN '94'
WHEN 'SI' THEN '62'
WHEN 'SK' THEN '42'
WHEN 'AT' THEN '0.99'
WHEN 'BE' THEN '1.14'
WHEN 'BG' THEN '0.23'
WHEN 'CZ' THEN '0.44'
WHEN 'DE' THEN '1.00'
WHEN 'DK' THEN '1.16'
WHEN 'EE' THEN '0.60'
WHEN 'ES' THEN '0.90'
WHEN 'FI' THEN '1.02'
WHEN 'FR' THEN '1.05'
WHEN 'GR' THEN '0.35'
WHEN 'HR' THEN '0.31'
WHEN 'HU' THEN '0.35'
WHEN 'IE' THEN '0.97'
WHEN 'IT' THEN '0.72'
WHEN 'LT' THEN '0.36'
WHEN 'LU' THEN '1.31'
WHEN 'LV' THEN '0.33'
WHEN 'MT' THEN '0.41'
WHEN 'NL' THEN '1.05'
WHEN 'PL' THEN '0.27'
WHEN 'PT' THEN '0.41'
WHEN 'RO' THEN '0.27'
WHEN 'SE' THEN '0.94'
WHEN 'SI' THEN '0.62'
WHEN 'SK' THEN '0.42'
END
FROM `country` c, `country_property_type` cpt
WHERE c.iso_code IN ('AT', 'BE', 'BG', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK')

View file

@ -0,0 +1,96 @@
package de.avatic.lcc.controller.calculation;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.avatic.lcc.dto.calculation.DestinationDTO;
import de.avatic.lcc.dto.calculation.edit.destination.DestinationCreateDTO;
import de.avatic.lcc.dto.calculation.edit.destination.DestinationUpdateDTO;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
@Import({PremiseControllerTestData.class, PremiseTestsHelper.class})
public class CalculationIntegrationTests {
@Autowired
protected JdbcTemplate jdbcTemplate;
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private PremiseTestsHelper testHelper;
@Nested
@Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
@Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS)
@Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = {"classpath:master_data/job-cleanup.sql", "classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
@DisplayName("GET /api/calculation/start - Start Calculations Tests")
class StartCalculationTests {
@Test
@DisplayName("PUT /api/calculation/start - happy path")
public void startCalculationCase1() throws Exception {
var nodeId = testHelper.getNodeIdByExternalMappingId("AB");
var premisesBeforeUpdate = testHelper.getPremisesFromDb();
var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow();
var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var createDto = new DestinationCreateDTO();
createDto.setPremiseId(Collections.singletonList(premise1.getId()));
createDto.setDestinationNodeId(nodeId);
var response = mockMvc.perform(post("/api/calculation/destination")
.content(objectMapper.writeValueAsString(createDto))
.contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andReturn();
var destinations = objectMapper.readValue(response.getResponse().getContentAsString(), new TypeReference<Map<Integer, DestinationDTO>>() {});
var destinationId = destinations.get(premise1.getId()).getId();
var routeId = destinations.get(premise1.getId()).getRoutes().getFirst().getId();
var updateDto = new DestinationUpdateDTO();
updateDto.setAnnualAmount(100);
updateDto.setRouteSelectedId(routeId);
mockMvc.perform(put("/api/calculation/destination/" + destinationId)
.content(objectMapper.writeValueAsString(updateDto)).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
mockMvc.perform(put("/api/calculation/start")
.content(objectMapper.writeValueAsString(Arrays.asList(premise1.getId(), premise3.getId())))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andDo(print());
}
}
//Test unselected route.
//modifiy premise in database with invalid values.
}

View file

@ -330,37 +330,5 @@ public class DestinationIntegrationTest {
}
@Nested
@Sql(scripts = {"classpath:master_data/alldata.sql", "classpath:master_data/users.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_CLASS)
@Sql(scripts = {"classpath:master_data/users-cleanup.sql", "classpath:master_data/alldata-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_CLASS)
@Sql(scripts = {"classpath:master_data/premises.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Sql(scripts = {"classpath:master_data/premises-cleanup.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
@DisplayName("GET /api/calculation/start - Start Calculations Tests")
class StartCalculationTests {
@Test
@DisplayName("PUT /api/calculation/start - happy path")
public void startCalculationCase1() throws Exception {
var nodeId = testHelper.getNodeIdByExternalMappingId("AB");
var premisesBeforeUpdate = testHelper.getPremisesFromDb();
var premise1 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 2).findFirst().orElseThrow();
var premise3 = premisesBeforeUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var dto = new DestinationCreateDTO();
dto.setPremiseId(Arrays.asList(premise1.getId(), premise3.getId()));
dto.setDestinationNodeId(nodeId);
mockMvc.perform(post("/api/calculation/destination")
.content(objectMapper.writeValueAsString(dto))
.contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk()).andDo(print());
mockMvc.perform(put("/api/calculation/start")
.content(objectMapper.writeValueAsString(Arrays.asList(premise1, premise3)))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andDo(print());
}
}
}

View file

@ -719,9 +719,9 @@ public class PremiseControllerIntegrationTest {
var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var premiseAfter8 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow();
assertThat(premiseAfter1.getCustomRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter3.getCustomRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter8.getCustomRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter1.getTariffRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter3.getTariffRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter8.getTariffRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter1.getHsCode()).isEqualTo(premise1.getHsCode());
assertThat(premiseAfter3.getHsCode()).isEqualTo(premise3.getHsCode());
@ -751,9 +751,9 @@ public class PremiseControllerIntegrationTest {
var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var premiseAfter8 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow();
assertThat(premiseAfter1.getCustomRate()).isEqualByComparingTo(premise1.getCustomRate());
assertThat(premiseAfter3.getCustomRate()).isEqualByComparingTo(premise3.getCustomRate());
assertThat(premiseAfter8.getCustomRate()).isEqualByComparingTo(premise8.getCustomRate());
assertThat(premiseAfter1.getTariffRate()).isEqualByComparingTo(premise1.getTariffRate());
assertThat(premiseAfter3.getTariffRate()).isEqualByComparingTo(premise3.getTariffRate());
assertThat(premiseAfter8.getTariffRate()).isEqualByComparingTo(premise8.getTariffRate());
assertThat(premiseAfter1.getHsCode()).isEqualTo("12345678");
assertThat(premiseAfter3.getHsCode()).isEqualTo("12345678");
@ -784,9 +784,9 @@ public class PremiseControllerIntegrationTest {
var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var premiseAfter8 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow();
assertThat(premiseAfter1.getCustomRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter3.getCustomRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter8.getCustomRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter1.getTariffRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter3.getTariffRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter8.getTariffRate()).isEqualByComparingTo(BigDecimal.valueOf(13.5));
assertThat(premiseAfter1.getHsCode()).isEqualTo("12345678");
assertThat(premiseAfter3.getHsCode()).isEqualTo("12345678");
@ -817,9 +817,9 @@ public class PremiseControllerIntegrationTest {
var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var premiseAfter8 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow();
assertThat(premiseAfter1.getCustomRate()).isEqualByComparingTo(premise1.getCustomRate());
assertThat(premiseAfter3.getCustomRate()).isEqualByComparingTo(premise3.getCustomRate());
assertThat(premiseAfter8.getCustomRate()).isEqualByComparingTo(premise8.getCustomRate());
assertThat(premiseAfter1.getTariffRate()).isEqualByComparingTo(premise1.getTariffRate());
assertThat(premiseAfter3.getTariffRate()).isEqualByComparingTo(premise3.getTariffRate());
assertThat(premiseAfter8.getTariffRate()).isEqualByComparingTo(premise8.getTariffRate());
assertThat(premiseAfter1.getHsCode()).isEqualTo(premise1.getHsCode());
assertThat(premiseAfter3.getHsCode()).isEqualTo(premise3.getHsCode());
@ -849,9 +849,9 @@ public class PremiseControllerIntegrationTest {
var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var premiseAfter8 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow();
assertThat(premiseAfter1.getCustomRate()).isEqualByComparingTo(premise1.getCustomRate());
assertThat(premiseAfter3.getCustomRate()).isEqualByComparingTo(premise3.getCustomRate());
assertThat(premiseAfter8.getCustomRate()).isEqualByComparingTo(premise8.getCustomRate());
assertThat(premiseAfter1.getTariffRate()).isEqualByComparingTo(premise1.getTariffRate());
assertThat(premiseAfter3.getTariffRate()).isEqualByComparingTo(premise3.getTariffRate());
assertThat(premiseAfter8.getTariffRate()).isEqualByComparingTo(premise8.getTariffRate());
assertThat(premiseAfter1.getHsCode()).isEqualTo(premise1.getHsCode());
assertThat(premiseAfter3.getHsCode()).isEqualTo(premise3.getHsCode());
@ -881,9 +881,9 @@ public class PremiseControllerIntegrationTest {
var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var premiseAfter8 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow();
assertThat(premiseAfter1.getCustomRate()).isEqualByComparingTo(premise1.getCustomRate());
assertThat(premiseAfter3.getCustomRate()).isEqualByComparingTo(premise3.getCustomRate());
assertThat(premiseAfter8.getCustomRate()).isEqualByComparingTo(premise8.getCustomRate());
assertThat(premiseAfter1.getTariffRate()).isEqualByComparingTo(premise1.getTariffRate());
assertThat(premiseAfter3.getTariffRate()).isEqualByComparingTo(premise3.getTariffRate());
assertThat(premiseAfter8.getTariffRate()).isEqualByComparingTo(premise8.getTariffRate());
assertThat(premiseAfter1.getHsCode()).isEqualTo(premise1.getHsCode());
assertThat(premiseAfter3.getHsCode()).isEqualTo(premise3.getHsCode());
@ -914,9 +914,9 @@ public class PremiseControllerIntegrationTest {
var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var premiseAfter8 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow();
assertThat(premiseAfter1.getCustomRate()).isEqualByComparingTo(premise1.getCustomRate());
assertThat(premiseAfter3.getCustomRate()).isEqualByComparingTo(premise3.getCustomRate());
assertThat(premiseAfter8.getCustomRate()).isEqualByComparingTo(premise8.getCustomRate());
assertThat(premiseAfter1.getTariffRate()).isEqualByComparingTo(premise1.getTariffRate());
assertThat(premiseAfter3.getTariffRate()).isEqualByComparingTo(premise3.getTariffRate());
assertThat(premiseAfter8.getTariffRate()).isEqualByComparingTo(premise8.getTariffRate());
assertThat(premiseAfter1.getHsCode()).isEqualTo(premise1.getHsCode());
assertThat(premiseAfter3.getHsCode()).isEqualTo(premise3.getHsCode());
@ -964,9 +964,9 @@ public class PremiseControllerIntegrationTest {
var premiseAfter3 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 3).findFirst().orElseThrow();
var premiseAfter8 = premisesAfterUpdate.stream().filter(p -> p.getHuUnitCount() == 8).findFirst().orElseThrow();
assertThat(premiseAfter1.getCustomRate()).isEqualByComparingTo(premise1.getCustomRate());
assertThat(premiseAfter3.getCustomRate()).isEqualByComparingTo(premise3.getCustomRate());
assertThat(premiseAfter8.getCustomRate()).isEqualByComparingTo(premise8.getCustomRate());
assertThat(premiseAfter1.getTariffRate()).isEqualByComparingTo(premise1.getTariffRate());
assertThat(premiseAfter3.getTariffRate()).isEqualByComparingTo(premise3.getTariffRate());
assertThat(premiseAfter8.getTariffRate()).isEqualByComparingTo(premise8.getTariffRate());
assertThat(premiseAfter1.getHsCode()).isEqualTo(premise1.getHsCode());
assertThat(premiseAfter3.getHsCode()).isEqualTo(premise3.getHsCode());

View file

@ -59,7 +59,7 @@ public class PremiseTestsHelper {
entity.setHsCode(rs.getString("hs_code"));
entity.setCustomRate(rs.getBigDecimal("tariff_rate"));
entity.setTariffRate(rs.getBigDecimal("tariff_rate"));
entity.setFcaEnabled(rs.getBoolean("is_fca_enabled"));
if (rs.wasNull())

View file

@ -26,6 +26,13 @@ WHERE NOT EXISTS (
-- Mapping: external mapping id -> external_mapping_id
-- Description -> name
-- ===================================================
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Reference route segment start node mapping id', 'START_REF', 'TEXT', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Reference route segment end node mapping id', 'END_REF', 'TEXT', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'The historically highest rate for the reference route segment for 40ft containers [EUR]', 'RISK_REF', 'CURRENCY', '{"GT":0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'The historically lowest rate for the reference route segment for 40ft containers [EUR]', 'CHANCE_REF', 'CURRENCY', '{"GT":0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Payment terms [days]', 'PAYMENT_TERMS', 'INT', '{}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Annual working days', 'WORKDAYS', 'INT', '{"GT": 0, "LT": 366}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Interest rate inventory [%]', 'INTEREST_RATE', 'PERCENTAGE', '{"GTE": 0}');
@ -44,6 +51,7 @@ INSERT INTO system_property_type ( name, external_mapping_id, data_type, validat
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max delivery frequency / year for containtrer transports', 'FREQ_MAX', 'INT', '{"GT": 0, "LT": 366}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max load of 20'' container [kg]', 'TEU_LOAD', 'INT', '{"GT": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max load of 40'' container [kg]', 'FEU_LOAD', 'INT', '{"GT": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Max load of a truck [kg]', 'TRUCK_LOAD', 'INT', '{"GT": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Pre-carriage [EUR/kg]', 'AIR_PRECARRIAGE', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Pre-carriage handling [EUR]', 'AIR_HANDLING', 'CURRENCY', '{"GTE": 0}');
INSERT INTO system_property_type ( name, external_mapping_id, data_type, validation_rule) VALUES ( 'Main carriage [EUR/kg]', 'AIR_MAINCARRIAGE', 'CURRENCY', '{"GTE": 0}');
@ -71,6 +79,66 @@ INSERT INTO system_property_type ( name, external_mapping_id, data_type, validat
-- Verwendung von Subqueries für dynamische ID-Ermittlung
-- ===================================================
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'START_REF'),
'CNXMN'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'PAYMENT_TERMS'),
'30'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'END_REF'),
'DEHAM'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'RISK_REF'),
'20000.00'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'CHANCE_REF'),
'1000.00'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
@ -276,6 +344,18 @@ VALUES (
'21000'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
WHERE ps.state = 'VALID'
AND ps.start_date <= NOW()
AND (ps.end_date IS NULL OR ps.end_date > NOW())
ORDER BY ps.start_date DESC
LIMIT 1),
(SELECT spt.id FROM system_property_type spt WHERE spt.external_mapping_id = 'TRUCK_LOAD'),
'25000'
);
INSERT INTO system_property (property_set_id, system_property_type_id, property_value)
VALUES (
(SELECT ps.id FROM `property_set` ps
@ -1126,6 +1206,7 @@ SELECT
FROM `country` c, `country_property_type` cpt
WHERE cpt.external_mapping_id = 'AIR_SHARE';
-- Wage Factor Properties (only for countries with defined values)
-- Wage Factor Properties (only for countries with defined values)
INSERT INTO `country_property`
(`country_id`, `country_property_type_id`, `property_set_id`, `property_value`)
@ -1139,37 +1220,36 @@ SELECT
ORDER BY ps.start_date DESC
LIMIT 1),
CASE c.iso_code
WHEN 'AT' THEN '99'
WHEN 'BE' THEN '114'
WHEN 'BG' THEN '23'
WHEN 'CZ' THEN '44'
WHEN 'DE' THEN '100'
WHEN 'DK' THEN '116'
WHEN 'EE' THEN '60'
WHEN 'ES' THEN '90'
WHEN 'FI' THEN '102'
WHEN 'FR' THEN '105'
WHEN 'GR' THEN '35'
WHEN 'HR' THEN '31'
WHEN 'HU' THEN '35'
WHEN 'IE' THEN '97'
WHEN 'IT' THEN '72'
WHEN 'LT' THEN '36'
WHEN 'LU' THEN '131'
WHEN 'LV' THEN '33'
WHEN 'MT' THEN '41'
WHEN 'NL' THEN '105'
WHEN 'PL' THEN '27'
WHEN 'PT' THEN '41'
WHEN 'RO' THEN '27'
WHEN 'SE' THEN '94'
WHEN 'SI' THEN '62'
WHEN 'SK' THEN '42'
WHEN 'AT' THEN '0.99'
WHEN 'BE' THEN '1.14'
WHEN 'BG' THEN '0.23'
WHEN 'CZ' THEN '0.44'
WHEN 'DE' THEN '1.00'
WHEN 'DK' THEN '1.16'
WHEN 'EE' THEN '0.60'
WHEN 'ES' THEN '0.90'
WHEN 'FI' THEN '1.02'
WHEN 'FR' THEN '1.05'
WHEN 'GR' THEN '0.35'
WHEN 'HR' THEN '0.31'
WHEN 'HU' THEN '0.35'
WHEN 'IE' THEN '0.97'
WHEN 'IT' THEN '0.72'
WHEN 'LT' THEN '0.36'
WHEN 'LU' THEN '1.31'
WHEN 'LV' THEN '0.33'
WHEN 'MT' THEN '0.41'
WHEN 'NL' THEN '1.05'
WHEN 'PL' THEN '0.27'
WHEN 'PT' THEN '0.41'
WHEN 'RO' THEN '0.27'
WHEN 'SE' THEN '0.94'
WHEN 'SI' THEN '0.62'
WHEN 'SK' THEN '0.42'
END
FROM `country` c, `country_property_type` cpt
WHERE c.iso_code IN ('AT', 'BE', 'BG', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK')
AND cpt.external_mapping_id = 'WAGE';
-- =============================================================================
-- VERIFICATION QUERIES (Optional - for testing)
-- =============================================================================

View file

@ -1482,32 +1482,32 @@ SELECT
ORDER BY ps.start_date DESC
LIMIT 1),
CASE c.iso_code
WHEN 'AT' THEN '99'
WHEN 'BE' THEN '114'
WHEN 'BG' THEN '23'
WHEN 'CZ' THEN '44'
WHEN 'DE' THEN '100'
WHEN 'DK' THEN '116'
WHEN 'EE' THEN '60'
WHEN 'ES' THEN '90'
WHEN 'FI' THEN '102'
WHEN 'FR' THEN '105'
WHEN 'GR' THEN '35'
WHEN 'HR' THEN '31'
WHEN 'HU' THEN '35'
WHEN 'IE' THEN '97'
WHEN 'IT' THEN '72'
WHEN 'LT' THEN '36'
WHEN 'LU' THEN '131'
WHEN 'LV' THEN '33'
WHEN 'MT' THEN '41'
WHEN 'NL' THEN '105'
WHEN 'PL' THEN '27'
WHEN 'PT' THEN '41'
WHEN 'RO' THEN '27'
WHEN 'SE' THEN '94'
WHEN 'SI' THEN '62'
WHEN 'SK' THEN '42'
WHEN 'AT' THEN '0.99'
WHEN 'BE' THEN '1.14'
WHEN 'BG' THEN '0.23'
WHEN 'CZ' THEN '0.44'
WHEN 'DE' THEN '1.00'
WHEN 'DK' THEN '1.16'
WHEN 'EE' THEN '0.60'
WHEN 'ES' THEN '0.90'
WHEN 'FI' THEN '1.02'
WHEN 'FR' THEN '1.05'
WHEN 'GR' THEN '0.35'
WHEN 'HR' THEN '0.31'
WHEN 'HU' THEN '0.35'
WHEN 'IE' THEN '0.97'
WHEN 'IT' THEN '0.72'
WHEN 'LT' THEN '0.36'
WHEN 'LU' THEN '1.31'
WHEN 'LV' THEN '0.33'
WHEN 'MT' THEN '0.41'
WHEN 'NL' THEN '1.05'
WHEN 'PL' THEN '0.27'
WHEN 'PT' THEN '0.41'
WHEN 'RO' THEN '0.27'
WHEN 'SE' THEN '0.94'
WHEN 'SI' THEN '0.62'
WHEN 'SK' THEN '0.42'
END
FROM `country` c, `country_property_type` cpt
WHERE c.iso_code IN ('AT', 'BE', 'BG', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK')

View file

@ -0,0 +1,13 @@
delete
from calculation_job_route_section
where 1;
delete
from calculation_job_destination
where 1;
delete
from calculation_job
where 1;
ALTER TABLE calculation_job_route_section AUTO_INCREMENT = 1;
ALTER TABLE calculation_job_destination AUTO_INCREMENT = 1;
ALTER TABLE calculation_job AUTO_INCREMENT = 1;