diff --git a/src/main/java/de/avatic/lcc/dto/configuration/apps/AppExchangeDTO.java b/src/main/java/de/avatic/lcc/dto/configuration/apps/AppExchangeDTO.java new file mode 100644 index 0000000..1ce2641 --- /dev/null +++ b/src/main/java/de/avatic/lcc/dto/configuration/apps/AppExchangeDTO.java @@ -0,0 +1,4 @@ +package de.avatic.lcc.dto.configuration.apps; + +public class AppExchangeDTO { +} diff --git a/src/main/java/de/avatic/lcc/model/calculation/ContainerCalculationResult.java b/src/main/java/de/avatic/lcc/model/calculation/ContainerCalculationResult.java index c2e69ca..cd879c9 100644 --- a/src/main/java/de/avatic/lcc/model/calculation/ContainerCalculationResult.java +++ b/src/main/java/de/avatic/lcc/model/calculation/ContainerCalculationResult.java @@ -215,7 +215,7 @@ public class ContainerCalculationResult { * @return The total utilization value for the container. */ public double getTotalUtilizationByVolume() { - return getHuUtilizationByVolume() * huUnitCount * layer; + return getHuUtilizationByVolume() * huUnitCount; } /** @@ -254,4 +254,7 @@ public class ContainerCalculationResult { return WeightUnit.KG.convertFromG(hu.getWeight()) / maxContainerWeight; } + public int getHuPerContainer() { + return this.huUnitCount; + } } diff --git a/src/main/java/de/avatic/lcc/service/calculation/execution/CalculationExecutionService.java b/src/main/java/de/avatic/lcc/service/calculation/execution/CalculationExecutionService.java index cd85c23..dfad5a0 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/execution/CalculationExecutionService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/execution/CalculationExecutionService.java @@ -137,13 +137,15 @@ public class CalculationExecutionService { AirfreightResult airfreightCost = airfreightCalculationService.doCalculation(setId, periodId, premise, destination); ContainerType usedContainerType = null; + ContainerCalculationResult selectedContainerCalculation = null; + CalculationJobDestination destinationCalculationJob = new CalculationJobDestination(); boolean hasMainRun = true; BigDecimal leadTime = null; if (destination.getD2d()) { - var containerCalculation = containerCalculationService.doCalculation(setId, premiseToHuService.createHuFromPremise(premise), ContainerType.FEU, premise.getHuMixable(), premise.getHuStackable()); - sections = List.of(new SectionInfo(null, routeSectionCostCalculationService.doD2dCalculation(setId, periodId, premise, destination, containerCalculation), containerCalculation)); + selectedContainerCalculation = containerCalculationService.doCalculation(setId, premiseToHuService.createHuFromPremise(premise), ContainerType.FEU, premise.getHuMixable(), premise.getHuStackable()); + sections = List.of(new SectionInfo(null, routeSectionCostCalculationService.doD2dCalculation(setId, periodId, premise, destination, selectedContainerCalculation), selectedContainerCalculation)); leadTime = BigDecimal.valueOf(destination.getLeadTimeD2d()); usedContainerType = ContainerType.FEU; } else { @@ -161,6 +163,8 @@ public class CalculationExecutionService { s.result().setPostRun(false); }); } + + selectedContainerCalculation = bestContainerTypeResult.selectedContainerCalculation; } destinationCalculationJob.setD2D(destination.getD2d()); @@ -168,9 +172,9 @@ public class CalculationExecutionService { if(destination.getD2d()) destinationCalculationJob.setRateD2D(destination.getRateD2d()); - customCost = customCostCalculationService.doCalculation(setId, premise, destination, sections); - handlingCost = handlingCostCalculationService.doCalculation(setId, premise, destination, hasMainRun); - inventoryCost = inventoryCostCalculationService.doCalculation(setId, premise, destination, leadTime); + customCost = customCostCalculationService.doCalculation(setId, premise, destination, sections, selectedContainerCalculation); + handlingCost = handlingCostCalculationService.doCalculation(setId, premise, destination, hasMainRun, selectedContainerCalculation); + inventoryCost = inventoryCostCalculationService.doCalculation(setId, premise, destination, leadTime, selectedContainerCalculation); destinationCalculationJob.setContainerType(usedContainerType); @@ -209,7 +213,7 @@ public class CalculationExecutionService { destinationCalculationJob.setHuCount(sections.getFirst().containerResult().getHuUnitCount()); destinationCalculationJob.setAnnualAmount(BigDecimal.valueOf(destination.getAnnualAmount())); - destinationCalculationJob.setShippingFrequency(shippingFrequencyCalculationService.doCalculation(setId, destination.getAnnualAmount())); + destinationCalculationJob.setShippingFrequency(shippingFrequencyCalculationService.doCalculation(setId, destination.getAnnualAmount(), selectedContainerCalculation.getHuPerContainer(),!premise.getHuMixable())); var commonCost = destinationCalculationJob.getAnnualHandlingCost() .add(destinationCalculationJob.getAnnualDisposalCost()) @@ -264,10 +268,10 @@ public class CalculationExecutionService { } var bestContainerType = getBestContainerType(sectionInfos); - return new BestContainerTypeResult(bestContainerType, sectionInfos.get(bestContainerType)); + return new BestContainerTypeResult(bestContainerType, sectionInfos.get(bestContainerType), containerCalculation.get(bestContainerType)); } - private record BestContainerTypeResult(ContainerType containerType, List sections) { + private record BestContainerTypeResult(ContainerType containerType, List sections, ContainerCalculationResult selectedContainerCalculation) { } } diff --git a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/CustomCostCalculationService.java b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/CustomCostCalculationService.java index 1e2686d..2b34abf 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/CustomCostCalculationService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/CustomCostCalculationService.java @@ -37,7 +37,7 @@ public class CustomCostCalculationService { this.shippingFrequencyCalculationService = shippingFrequencyCalculationService; } - public CustomResult doCalculation(Integer setId, Premise premise, Destination destination, List sections) { + public CustomResult doCalculation(Integer setId, Premise premise, Destination destination, List sections, ContainerCalculationResult containerCalculationResult) { var destUnion = countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.UNION, setId, destination.getCountryId()).orElseThrow(); var sourceUnion = countryPropertyRepository.getByMappingIdAndCountryId(CountryPropertyMappingId.UNION, setId, premise.getCountryId()).orElseThrow(); @@ -53,14 +53,15 @@ public class CustomCostCalculationService { double huAnnualAmount = BigDecimal.valueOf(destination.getAnnualAmount()).divide(BigDecimal.valueOf(premise.getHuUnitCount()),0, RoundingMode.CEILING).doubleValue(); - return getCustomCalculationResult(setId, premise, destination, huAnnualAmount, transportationCost, transportationChanceCost, transportationRiskCost); + return getCustomCalculationResult(setId, premise, destination, huAnnualAmount, transportationCost, transportationChanceCost, transportationRiskCost, containerCalculationResult); } return CustomResult.EMPTY; } - private CustomResult getCustomCalculationResult(Integer setId, Premise premise, Destination destination, double huAnnualAmount, BigDecimal transportationCost, BigDecimal transportationChanceCost, BigDecimal transportationRiskCost) { - var shippingFrequency = shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount); + private CustomResult getCustomCalculationResult(Integer setId, Premise premise, Destination destination, double huAnnualAmount, BigDecimal transportationCost, BigDecimal transportationChanceCost, BigDecimal transportationRiskCost, ContainerCalculationResult containerCalculationResult) { + + var shippingFrequency = shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount, containerCalculationResult.getHuPerContainer(), !premise.getHuMixable()); var customFee = Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.CUSTOM_FEE, setId).orElseThrow().getCurrentValue()); var tariffRate = premise.getTariffRate(); diff --git a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/HandlingCostCalculationService.java b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/HandlingCostCalculationService.java index d172f77..7c22837 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/HandlingCostCalculationService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/HandlingCostCalculationService.java @@ -1,5 +1,6 @@ package de.avatic.lcc.service.calculation.execution.steps; +import de.avatic.lcc.model.calculation.ContainerCalculationResult; import de.avatic.lcc.model.calculation.HandlingResult; import de.avatic.lcc.model.db.packaging.LoadCarrierType; import de.avatic.lcc.model.db.packaging.PackagingDimension; @@ -30,13 +31,13 @@ public class HandlingCostCalculationService { this.shippingFrequencyCalculationService = shippingFrequencyCalculationService; } - public HandlingResult doCalculation(Integer setId, Premise premise, Destination destination, Boolean addRepackingAndDisposalCost) { + public HandlingResult doCalculation(Integer setId, Premise premise, Destination destination, Boolean addRepackingAndDisposalCost, ContainerCalculationResult containerCalculationResult) { var hu = premiseToHuService.createHuFromPremise(premise); - return (LoadCarrierType.SLC == hu.getLoadCarrierType() ? getSLCCost(setId, destination, hu, hu.getLoadCarrierType(), addRepackingAndDisposalCost) : getLLCCost(setId, destination, hu, hu.getLoadCarrierType(), addRepackingAndDisposalCost)); + return (LoadCarrierType.SLC == hu.getLoadCarrierType() ? getSLCCost(setId, premise, destination, hu, hu.getLoadCarrierType(), addRepackingAndDisposalCost, containerCalculationResult) : getLLCCost(setId, premise, destination, hu, hu.getLoadCarrierType(), addRepackingAndDisposalCost, containerCalculationResult)); } - private HandlingResult getSLCCost(Integer setId, Destination destination, PackagingDimension hu, LoadCarrierType loadCarrierType, boolean addRepackingAndDisposalCost) { + private HandlingResult getSLCCost(Integer setId, Premise premise, Destination destination, PackagingDimension hu, LoadCarrierType loadCarrierType, boolean addRepackingAndDisposalCost, ContainerCalculationResult containerCalculationResult) { var destinationHandling = destination.getHandlingCost(); var destinationDisposal = destination.getDisposalCost(); @@ -77,7 +78,7 @@ public class HandlingCostCalculationService { } - private HandlingResult getLLCCost(Integer setId, Destination destination, PackagingDimension hu, LoadCarrierType type, boolean addRepackingAndDisposalCost) { + private HandlingResult getLLCCost(Integer setId, Premise premise, Destination destination, PackagingDimension hu, LoadCarrierType type, boolean addRepackingAndDisposalCost, ContainerCalculationResult containerCalculationResult) { var destinationHandling = destination.getHandlingCost(); var destinationDisposal = destination.getDisposalCost(); @@ -93,7 +94,7 @@ public class HandlingCostCalculationService { BigDecimal booking = BigDecimal.valueOf(Double.parseDouble(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.BOOKING, setId).orElseThrow().getCurrentValue())); var annualRepacking = getRepackingCost(setId, hu, type, addRepackingAndDisposalCost, destinationRepacking).multiply(wageFactor).multiply( huAnnualAmount); - var annualHandling = ((handling.add(dispatch).add(release)).multiply(wageFactor).multiply(huAnnualAmount)).add(booking.multiply(BigDecimal.valueOf(shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount.doubleValue())))); + var annualHandling = ((handling.add(dispatch).add(release)).multiply(wageFactor).multiply(huAnnualAmount)).add(booking.multiply(BigDecimal.valueOf(shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount.doubleValue(), containerCalculationResult.getHuPerContainer(), !premise.getHuMixable())))); var annualDisposal = (disposal.multiply(huAnnualAmount)); return new HandlingResult(LoadCarrierType.LLC, annualRepacking, annualHandling, annualDisposal, annualRepacking.add(annualHandling).add(annualDisposal)); diff --git a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/InventoryCostCalculationService.java b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/InventoryCostCalculationService.java index d9b0658..dafb733 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/InventoryCostCalculationService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/InventoryCostCalculationService.java @@ -1,5 +1,6 @@ package de.avatic.lcc.service.calculation.execution.steps; +import de.avatic.lcc.model.calculation.ContainerCalculationResult; import de.avatic.lcc.model.calculation.InventoryCostResult; import de.avatic.lcc.model.db.packaging.PackagingDimension; import de.avatic.lcc.model.db.premises.Premise; @@ -30,7 +31,7 @@ public class InventoryCostCalculationService { this.premiseToHuService = premiseToHuService; } - public InventoryCostResult doCalculation(Integer setId, Premise premise, Destination destination, BigDecimal leadTime) { + public InventoryCostResult doCalculation(Integer setId, Premise premise, Destination destination, BigDecimal leadTime, ContainerCalculationResult containerCalculationResult) { var fcaFee = BigDecimal.ZERO; @@ -53,7 +54,7 @@ public class InventoryCostCalculationService { 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(setId, huAnnualAmount),1)), 10, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(.5))); + var opStock = (annualAmount.divide(BigDecimal.valueOf(Math.max(shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount, containerCalculationResult.getHuPerContainer(), !premise.getHuMixable()),1)), 10, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(.5))); var safetyStock = safetyDays.multiply(workdayAmount); var stockedInventory = opStock.add(safetyStock); var inTransportStock = dailyAmount.multiply(leadTime); diff --git a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/RouteSectionCostCalculationService.java b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/RouteSectionCostCalculationService.java index db414e9..6139420 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/RouteSectionCostCalculationService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/RouteSectionCostCalculationService.java @@ -97,7 +97,7 @@ public class RouteSectionCostCalculationService { BigDecimal.valueOf(containerCalculation.getTotalUtilizationByVolume()), BigDecimal.valueOf(containerCalculation.getHuUtilizationByWeight()), utilization, - shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount.doubleValue()), + shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount.doubleValue(), containerCalculation.getHuPerContainer(), !premise.getHuMixable()), huAnnualAmount.doubleValue(), containerCalculation); @@ -183,7 +183,7 @@ public class RouteSectionCostCalculationService { BigDecimal.valueOf(containerCalculation.getTotalUtilizationByVolume()), BigDecimal.valueOf(containerCalculation.getTotalUtilizationByWeight()), utilization, - shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount.doubleValue()), + shippingFrequencyCalculationService.doCalculation(setId, huAnnualAmount.doubleValue(), containerCalculation.getHuPerContainer(), !premise.getHuMixable()), huAnnualAmount.doubleValue(), containerCalculation); @@ -243,7 +243,7 @@ public class RouteSectionCostCalculationService { double huPerContainer = annualHuAmount / shippingFrequency; // if the shipping frequency is bigger than the annual amount the "totalXXUtilization" cannot be used. - if(huPerContainer < (containerCalculationResult.getHuUnitCount() * containerCalculationResult.getLayer())) { + if(huPerContainer < (containerCalculationResult.getHuPerContainer())) { totalVolumeUtilization = BigDecimal.valueOf(huPerContainer * containerCalculationResult.getHu().getVolume(DimensionUnit.M)).divide(BigDecimal.valueOf(containerCalculationResult.getContainerType().getVolume()), 20, RoundingMode.HALF_UP); totalWeightUtilization = BigDecimal.valueOf(huPerContainer * containerCalculationResult.getHu().getWeight(WeightUnit.KG)).divide(BigDecimal.valueOf(containerCalculationResult.getMaxContainerWeight()), 20, RoundingMode.HALF_UP); diff --git a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/ShippingFrequencyCalculationService.java b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/ShippingFrequencyCalculationService.java index aa7213a..969e838 100644 --- a/src/main/java/de/avatic/lcc/service/calculation/execution/steps/ShippingFrequencyCalculationService.java +++ b/src/main/java/de/avatic/lcc/service/calculation/execution/steps/ShippingFrequencyCalculationService.java @@ -13,10 +13,16 @@ public class ShippingFrequencyCalculationService { this.propertyRepository = propertyRepository; } - public int doCalculation(Integer setId, int huAnnualAmount) { + public int doCalculation(Integer setId, int huAnnualAmount, int maxHuPerContainer, boolean fillContainer) { var minAnnualFrequency = Integer.parseInt(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.FREQ_MIN, setId).orElseThrow().getCurrentValue()); var maxAnnualFrequency = Integer.parseInt(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.FREQ_MAX, setId).orElseThrow().getCurrentValue()); + var fullContainers = huAnnualAmount / maxHuPerContainer; + + + if(fillContainer && huAnnualAmount > maxAnnualFrequency) + return fullContainers; + if (huAnnualAmount > maxAnnualFrequency) return maxAnnualFrequency; @@ -24,10 +30,15 @@ public class ShippingFrequencyCalculationService { } - public double doCalculation(Integer setId, double huAnnualAmount) { + public double doCalculation(Integer setId, double huAnnualAmount, int maxHuPerContainer, boolean fillContainer) { int minAnnualFrequency = Integer.parseInt(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.FREQ_MIN, setId).orElseThrow().getCurrentValue()); int maxAnnualFrequency = Integer.parseInt(propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.FREQ_MAX, setId).orElseThrow().getCurrentValue()); + var fullContainers = huAnnualAmount / maxHuPerContainer; + + if(fillContainer && huAnnualAmount > (double) maxAnnualFrequency) + return fullContainers; + if (huAnnualAmount > (double) maxAnnualFrequency) return maxAnnualFrequency;