From 175ac4266b5d5df920beaad31965846541bfd95f Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 13 Dec 2025 23:15:10 +0100 Subject: [PATCH 1/2] Refactor Report DTOs: extracted `ReportPremisesDTO`, adjusted `ReportDestinationDTO`, updated frontend to align with new structure, and enhanced reporting logic. --- .../src/components/UI/CollapsibleBox.vue | 11 +- .../src/components/layout/report/Report.vue | 232 ++++++++++++------ src/frontend/src/pages/Reporting.vue | 6 +- src/frontend/src/store/reports.js | 10 +- .../report/ReportingController.java | 19 +- .../de/avatic/lcc/dto/report/ReportDTO.java | 25 +- .../lcc/dto/report/ReportDestinationDTO.java | 104 +------- .../lcc/dto/report/ReportPremisesDTO.java | 108 ++++++++ .../dto/report/ReportSearchRequestDTO.java | 13 + .../lcc/service/bulk/BulkImportService.java | 17 +- .../service/report/ExcelReportingService.java | 29 ++- .../transformer/report/ReportTransformer.java | 97 +++++--- 12 files changed, 437 insertions(+), 234 deletions(-) create mode 100644 src/main/java/de/avatic/lcc/dto/report/ReportPremisesDTO.java create mode 100644 src/main/java/de/avatic/lcc/dto/report/ReportSearchRequestDTO.java diff --git a/src/frontend/src/components/UI/CollapsibleBox.vue b/src/frontend/src/components/UI/CollapsibleBox.vue index c138875..1fb44d1 100644 --- a/src/frontend/src/components/UI/CollapsibleBox.vue +++ b/src/frontend/src/components/UI/CollapsibleBox.vue @@ -133,9 +133,12 @@ export default { .box-content.collapsed { max-height: 0; opacity: 0; - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; + + margin: 0 !important; /* ← !important um alle margins zu überschreiben */ + padding: 0 !important; + overflow: hidden; } + + + \ No newline at end of file diff --git a/src/frontend/src/components/layout/report/Report.vue b/src/frontend/src/components/layout/report/Report.vue index a36c328..1dc1e74 100644 --- a/src/frontend/src/components/layout/report/Report.vue +++ b/src/frontend/src/components/layout/report/Report.vue @@ -7,42 +7,53 @@ +
- +
-
MEK B
-
{{ report.risk.mek_b.total.toFixed(2) }} €
-
-
- -
-
Opportunity scenario
-
{{ report.risk.opportunity_scenario.total.toFixed(2) }} €
+
MEK A
+
{{ report.overview.mek_a.total.toFixed(2) }} €
{{ - `${(report.risk.opportunity_scenario.percentage * 100).toFixed(2)} %` + `${(report.overview.mek_a.percentage * 100).toFixed(2)} %` }}
-
Risk scenario
-
{{ report.risk.risk_scenario.total.toFixed(2) }} €
-
{{ `${(report.risk.risk_scenario.percentage * 100).toFixed(2)} %`}}
+
Logistics cost
+
{{ report.overview.logistics.total.toFixed(2) }} €
+
{{ + `${(report.overview.logistics.percentage * 100).toFixed(2)} %` + }} +
- +
+
MEK B
+
{{ + report.overview.mek_b.total.toFixed(2) + }} € +
+
{{ + `${(report.overview.mek_b.percentage * 100).toFixed(2)} %` + }} +
+
+ +
+
@@ -142,18 +153,129 @@
{{ (report.costs.capital.percentage * 100).toFixed(2) }}
+
+
Total
+
{{ + report.costs.total.total.toFixed(2) + }} +
+
+ {{ (report.costs.total.percentage * 100).toFixed(2) }} +
+
+ + +
+ -
+
- +
+
total [€]
+
of MEK_B [%]
+
+ +
+
Opportunity scenario
+
{{ report.overview.opportunity_scenario.total.toFixed(2) }} €
+
{{ + `${(report.overview.opportunity_scenario.percentage * 100).toFixed(2)}` + }} +
+
+ +
+
Risk scenario
+
{{ report.overview.risk_scenario.total.toFixed(2) }} €
+
+ {{ `${(report.overview.risk_scenario.percentage * 100).toFixed(2)}` }} +
+
+
+ + +
+
+ + + +
+ + +
+ +
+
Part number
+
{{ report.material.part_number }}
+
+ + +
+
HS code
+
{{ report.premises.hs_code }}
+
+ +
+
Tariff rate
+
{{ (report.premises.tariff_rate * 100).toFixed(2) }}%
+
+ +
+ +
Handling unit
+ +
+ +
+
Dimensions [{{ report.premises.dimension_unit }}]
+
{{ + toFixedDimension(report.premises.length, report.premises.dimension_unit) + }} x + {{ toFixedDimension(report.premises.width, report.premises.dimension_unit) }} x + {{ toFixedDimension(report.premises.height, report.premises.dimension_unit) }} +
+
+ +
+
Weight [{{ report.premises.weight_unit }}]
+
{{ + toFixedWeight(report.premises.weight, report.premises.weight_unit) + }} +
+
+ +
+
Unit count
+
{{ report.premises.hu_unit_count }}
+
+ +
+
Mixed transport
+
{{ report.premises.mixed ? 'Yes' : 'No' }}
+
+ +
+ +
+ +
+ + +
+ +
-
General
@@ -162,69 +284,31 @@
Annual Quantity
-
{{ premise.annual_quantity }}
-
- -
-
HS code
-
{{ premise.hs_code }}
-
- -
-
Tariff rate
-
{{ (premise.tariff_rate * 100).toFixed(2) }}%
+
{{ destination.annual_quantity }}
Oversea share
-
{{ (premise.oversea_share * 100).toFixed(2) }}%
+
{{ (destination.oversea_share * 100).toFixed(2) }}%
-
+
Airfreight share
-
{{ (premise.air_freight_share * 100).toFixed(2) }}%
+
{{ (destination.air_freight_share * 100).toFixed(2) }}%
Transit time [days]
-
{{ premise.transport_time }}
+
{{ destination.transport_time }}
Safety stock [w-days]
-
{{ premise.safety_stock }}
+
{{ destination.safety_stock }}
-
Handling unit
- -
- -
-
Dimensions [{{ premise.dimension_unit }}]
-
{{ toFixedDimension(premise.length, premise.dimension_unit) }} x - {{ toFixedDimension(premise.width, premise.dimension_unit) }} x - {{ toFixedDimension(premise.height, premise.dimension_unit) }} -
-
- -
-
Weight [{{ premise.weight_unit }}]
-
{{ toFixedWeight(premise.weight, premise.weight_unit) }}
-
- -
-
Unit count
-
{{ premise.hu_unit_count }}
-
- -
-
Mixed transport
-
{{ premise.mixed ? 'Yes' : 'No' }}
-
- -
Container
@@ -232,29 +316,31 @@
Stacked layers
-
{{ hasMainRun(premise.sections) ? premise.layer : '-' }}
+
{{ + hasMainRun(destination.sections) ? destination.layer : '-' + }} +
Container unit count
- {{ hasMainRun(premise.sections) ? (premise.unit_count * premise.hu_unit_count) : '-' }} + {{ hasMainRun(destination.sections) ? (destination.unit_count * report.premises.hu_unit_count) : '-' }}
-
Container type
- {{ hasMainRun(premise.sections) ? getContainerTypeName(premise.container_type) : '-' }} + {{ hasMainRun(destination.sections) ? getContainerTypeName(destination.container_type) : '-' }}
Limiting factor
- {{ hasMainRun(premise.sections) ? premise.weight_exceeded ? 'Weight' : 'Volume' : '-' }} + {{ hasMainRun(destination.sections) ? destination.weight_exceeded ? 'Weight' : 'Volume' : '-' }}
@@ -390,6 +476,14 @@ export default { font-size: 1.2rem; } +.report-content-container--3-col-2 { + display: grid; + grid-template-columns: 5fr 3fr 3fr; + gap: 1rem; + margin-top: 1.6rem; + font-size: 1.2rem; +} + .report-content-row { display: contents; color: #6B869C; diff --git a/src/frontend/src/pages/Reporting.vue b/src/frontend/src/pages/Reporting.vue index 8ff009d..e5fbc28 100644 --- a/src/frontend/src/pages/Reporting.vue +++ b/src/frontend/src/pages/Reporting.vue @@ -75,12 +75,12 @@ export default { }, routeSectionScale() { const reports = this.reportsStore.reports; - const scale = new Array(reports.map(r => r.premises.length).reduce((max, n) => Math.max(n, max), 0)).fill(0); + const scale = new Array(reports.map(r => r.destinations.length).reduce((max, n) => Math.max(n, max), 0)).fill(0); for (let i = 0; i < scale.length; i++) { for (const report of reports) { - if(report.premises.length > i) { - scale[i] = Math.max(scale[i], report.premises[i].sections.length); + if(report.destinations.length > i) { + scale[i] = Math.max(scale[i], report.destinations[i].sections.length); } } } diff --git a/src/frontend/src/store/reports.js b/src/frontend/src/store/reports.js index d83e54e..0e73e42 100644 --- a/src/frontend/src/store/reports.js +++ b/src/frontend/src/store/reports.js @@ -22,8 +22,8 @@ export const useReportsStore = defineStore('reports', { let max = 0; state.reports.forEach(report => { - max = Math.max(report.risk.mek_b.total, max); - max = Math.max(report.risk.risk_scenario.total, max); + max = Math.max(report.overview.mek_b.total, max); + max = Math.max(report.overview.risk_scenario.total, max); }) const magnitude = Math.pow(10, Math.floor(Math.log10(max))); @@ -74,14 +74,14 @@ export const useReportsStore = defineStore('reports', { this.showComparableWarning = false; for (const [idx, report] of this.reports.entries()) { for (const otherReport of this.reports.slice(idx + 1)) { - if (report.premises.length !== otherReport.premises.length) { + if (report.destinations.length !== otherReport.destinations.length) { this.showComparableWarning = true; break; } - for (const premise of report.premises) { + for (const premise of report.destinations) { - const otherPremise = otherReport.premises.find(otherPremise => otherPremise.destination.external_mapping_id === premise.destination.external_mapping_id); + const otherPremise = otherReport.destinations.find(otherPremise => otherPremise.destination.external_mapping_id === premise.destination.external_mapping_id); if((otherPremise ?? null) == null) { this.showComparableWarning = true; diff --git a/src/main/java/de/avatic/lcc/controller/report/ReportingController.java b/src/main/java/de/avatic/lcc/controller/report/ReportingController.java index 070bfd9..423dfe1 100644 --- a/src/main/java/de/avatic/lcc/controller/report/ReportingController.java +++ b/src/main/java/de/avatic/lcc/controller/report/ReportingController.java @@ -2,18 +2,17 @@ package de.avatic.lcc.controller.report; import de.avatic.lcc.dto.generic.NodeDTO; import de.avatic.lcc.dto.report.ReportDTO; +import de.avatic.lcc.dto.report.ReportSearchRequestDTO; import de.avatic.lcc.service.report.ExcelReportingService; import de.avatic.lcc.service.report.ReportingService; +import jakarta.validation.constraints.Min; import org.apache.coyote.Response; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -25,7 +24,6 @@ import java.util.List; @RequestMapping("/api/reports") public class ReportingController { - //TODO: rollenbeschränkung private final ReportingService reportingService; private final ExcelReportingService excelReportingService; @@ -42,6 +40,17 @@ public class ReportingController { this.excelReportingService = excelReportingService; } + @GetMapping({"/", ""}) + @PreAuthorize("hasAnyRole('SUPER', 'CALCULATION', 'BASIC')") + public ResponseEntity listReports(@RequestBody(required = false) ReportSearchRequestDTO filter, + @RequestParam(defaultValue = "20") @Min(1) int limit, + @RequestParam(defaultValue = "1") @Min(1) int page) { + + //TODO implement me + + return ResponseEntity.ok().build(); + + } /** diff --git a/src/main/java/de/avatic/lcc/dto/report/ReportDTO.java b/src/main/java/de/avatic/lcc/dto/report/ReportDTO.java index 156e818..2f6ed7f 100644 --- a/src/main/java/de/avatic/lcc/dto/report/ReportDTO.java +++ b/src/main/java/de/avatic/lcc/dto/report/ReportDTO.java @@ -23,10 +23,13 @@ public class ReportDTO { @JsonProperty("costs") public Map cost; - @JsonProperty("risk") - public Map risk; + @JsonProperty("overview") + public Map overview; @JsonProperty("premises") + private ReportPremisesDTO premises; + + @JsonProperty("destinations") public List destinations; public NodeDTO getSupplier() { @@ -49,12 +52,12 @@ public class ReportDTO { this.cost = cost; } - public Map getRisk() { - return risk; + public Map getOverview() { + return overview; } - public void setRisk(Map risk) { - this.risk = risk; + public void setOverview(Map overview) { + this.overview = overview; } public List getDestinations() { @@ -88,4 +91,14 @@ public class ReportDTO { public void setEndDate(LocalDateTime endDate) { this.endDate = endDate; } + + + public ReportPremisesDTO getPremises() { + return premises; + } + + public void setPremises(ReportPremisesDTO premises) { + this.premises = premises; + } + } diff --git a/src/main/java/de/avatic/lcc/dto/report/ReportDestinationDTO.java b/src/main/java/de/avatic/lcc/dto/report/ReportDestinationDTO.java index 905c304..bed315e 100644 --- a/src/main/java/de/avatic/lcc/dto/report/ReportDestinationDTO.java +++ b/src/main/java/de/avatic/lcc/dto/report/ReportDestinationDTO.java @@ -16,16 +16,6 @@ public class ReportDestinationDTO { private List sections; /* general */ - - @JsonProperty("annual_quantity") - private Integer annualQuantity; - - @JsonProperty("hs_code") - private String hsCode; - - @JsonProperty("tariff_rate") - private Number tariffRate; - @JsonProperty("oversea_share") private Double overseaShare; @@ -38,29 +28,12 @@ public class ReportDestinationDTO { @JsonProperty("safety_stock") private Integer safetyStock; - /* packaging */ - - private Double width; - - private Double height; - - private Double length; - - private Double weight; - - @JsonProperty("dimension_unit") - private DimensionUnit dimensionUnit; - - @JsonProperty("weight_unit") - private WeightUnit weightUnit; - - @JsonProperty("hu_unit_count") - private Integer huUnitCount; + @JsonProperty("annual_quantity") + private Integer annualQuantity; private Integer layer; /* container */ - @JsonProperty("unit_count") private Number unitCount; @@ -77,7 +50,6 @@ public class ReportDestinationDTO { private Boolean mixed; - public Integer getId() { return id; } @@ -110,22 +82,6 @@ public class ReportDestinationDTO { this.annualQuantity = annualQuantity; } - public String getHsCode() { - return hsCode; - } - - public void setHsCode(String hsCode) { - this.hsCode = hsCode; - } - - public Number getTariffRate() { - return tariffRate; - } - - public void setTariffRate(Number tariffRate) { - this.tariffRate = tariffRate; - } - public Double getOverseaShare() { return overseaShare; } @@ -158,62 +114,6 @@ public class ReportDestinationDTO { this.safetyStock = safetyStock; } - public Double getWidth() { - return width; - } - - public void setWidth(Double width) { - this.width = width; - } - - public Double getHeight() { - return height; - } - - public void setHeight(Double height) { - this.height = height; - } - - public Double getLength() { - return length; - } - - public void setLength(Double length) { - this.length = length; - } - - public Double getWeight() { - return weight; - } - - public void setWeight(Double weight) { - this.weight = weight; - } - - public DimensionUnit getDimensionUnit() { - return dimensionUnit; - } - - public void setDimensionUnit(DimensionUnit dimensionUnit) { - this.dimensionUnit = dimensionUnit; - } - - public WeightUnit getWeightUnit() { - return weightUnit; - } - - public void setWeightUnit(WeightUnit weightUnit) { - this.weightUnit = weightUnit; - } - - public Integer getHuUnitCount() { - return huUnitCount; - } - - public void setHuUnitCount(Integer huUnitCount) { - this.huUnitCount = huUnitCount; - } - public Integer getLayer() { return layer; } diff --git a/src/main/java/de/avatic/lcc/dto/report/ReportPremisesDTO.java b/src/main/java/de/avatic/lcc/dto/report/ReportPremisesDTO.java new file mode 100644 index 0000000..d325ac6 --- /dev/null +++ b/src/main/java/de/avatic/lcc/dto/report/ReportPremisesDTO.java @@ -0,0 +1,108 @@ +package de.avatic.lcc.dto.report; + +import com.fasterxml.jackson.annotation.JsonProperty; +import de.avatic.lcc.model.db.utils.DimensionUnit; +import de.avatic.lcc.model.db.utils.WeightUnit; + +public class ReportPremisesDTO { + + + @JsonProperty("hs_code") + private String hsCode; + + @JsonProperty("tariff_rate") + private Number tariffRate; + + + /* packaging */ + + private Double width; + + private Double height; + + private Double length; + + private Double weight; + + @JsonProperty("dimension_unit") + private DimensionUnit dimensionUnit; + + @JsonProperty("weight_unit") + private WeightUnit weightUnit; + + @JsonProperty("hu_unit_count") + private Integer huUnitCount; + + + public String getHsCode() { + return hsCode; + } + + public void setHsCode(String hsCode) { + this.hsCode = hsCode; + } + + public Number getTariffRate() { + return tariffRate; + } + + public void setTariffRate(Number tariffRate) { + this.tariffRate = tariffRate; + } + + public Double getWidth() { + return width; + } + + public void setWidth(Double width) { + this.width = width; + } + + public Double getHeight() { + return height; + } + + public void setHeight(Double height) { + this.height = height; + } + + public Double getLength() { + return length; + } + + public void setLength(Double length) { + this.length = length; + } + + public Double getWeight() { + return weight; + } + + public void setWeight(Double weight) { + this.weight = weight; + } + + public DimensionUnit getDimensionUnit() { + return dimensionUnit; + } + + public void setDimensionUnit(DimensionUnit dimensionUnit) { + this.dimensionUnit = dimensionUnit; + } + + public WeightUnit getWeightUnit() { + return weightUnit; + } + + public void setWeightUnit(WeightUnit weightUnit) { + this.weightUnit = weightUnit; + } + + public Integer getHuUnitCount() { + return huUnitCount; + } + + public void setHuUnitCount(Integer huUnitCount) { + this.huUnitCount = huUnitCount; + } +} diff --git a/src/main/java/de/avatic/lcc/dto/report/ReportSearchRequestDTO.java b/src/main/java/de/avatic/lcc/dto/report/ReportSearchRequestDTO.java new file mode 100644 index 0000000..fe38958 --- /dev/null +++ b/src/main/java/de/avatic/lcc/dto/report/ReportSearchRequestDTO.java @@ -0,0 +1,13 @@ +package de.avatic.lcc.dto.report; + +import java.util.List; + +public class ReportSearchRequestDTO { + + List supplierIds; + + List materialIds; + + + +} diff --git a/src/main/java/de/avatic/lcc/service/bulk/BulkImportService.java b/src/main/java/de/avatic/lcc/service/bulk/BulkImportService.java index aa77891..5ec349e 100644 --- a/src/main/java/de/avatic/lcc/service/bulk/BulkImportService.java +++ b/src/main/java/de/avatic/lcc/service/bulk/BulkImportService.java @@ -3,6 +3,7 @@ package de.avatic.lcc.service.bulk; import de.avatic.lcc.dto.bulk.BulkFileType; import de.avatic.lcc.model.bulk.BulkFileTypes; import de.avatic.lcc.model.bulk.BulkOperation; +import de.avatic.lcc.model.db.materials.Material; import de.avatic.lcc.service.api.BatchGeoApiService; import de.avatic.lcc.service.bulk.bulkImport.*; import de.avatic.lcc.service.excelMapper.*; @@ -11,6 +12,8 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.util.RecordFormatException; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.io.ByteArrayInputStream; @@ -34,6 +37,10 @@ public class BulkImportService { private final BatchGeoApiService batchGeoApiService; private final MaterialFastExcelMapper materialFastExcelMapper; + private static final Logger log = LoggerFactory.getLogger(BulkImportService.class); + + + public BulkImportService(MatrixRateExcelMapper matrixRateExcelMapper, ContainerRateExcelMapper containerRateExcelMapper, MaterialExcelMapper materialExcelMapper, PackagingExcelMapper packagingExcelMapper, NodeExcelMapper nodeExcelMapper, NodeBulkImportService nodeBulkImportService, PackagingBulkImportService packagingBulkImportService, MaterialBulkImportService materialBulkImportService, MatrixRateImportService matrixRateImportService, ContainerRateImportService containerRateImportService, BatchGeoApiService batchGeoApiService, MaterialFastExcelMapper materialFastExcelMapper) { this.matrixRateExcelMapper = matrixRateExcelMapper; this.containerRateExcelMapper = containerRateExcelMapper; @@ -63,7 +70,15 @@ public class BulkImportService { private void processOperationWithFastExcel(BulkOperation op) throws IOException { var materials = materialFastExcelMapper.importFromExcel(op.getFile()); - materials.forEach(materialBulkImportService::processMaterialInstructions); + + int processed = 0; + for(var material : materials) { + + if(processed++ % 1000 == 0) + log.info("Processed {} of {} materials", processed, materials.size()); + + materialBulkImportService.processMaterialInstructions(material); + } } private void processOperationWithApachePOI(BulkOperation op) throws IOException { diff --git a/src/main/java/de/avatic/lcc/service/report/ExcelReportingService.java b/src/main/java/de/avatic/lcc/service/report/ExcelReportingService.java index 64f7c83..2c9990f 100644 --- a/src/main/java/de/avatic/lcc/service/report/ExcelReportingService.java +++ b/src/main/java/de/avatic/lcc/service/report/ExcelReportingService.java @@ -5,6 +5,7 @@ import de.avatic.lcc.dto.generic.TransportType; import de.avatic.lcc.dto.report.ReportDTO; import de.avatic.lcc.dto.report.ReportDestinationDTO; import de.avatic.lcc.dto.report.ReportEntryDTO; +import de.avatic.lcc.dto.report.ReportPremisesDTO; import de.avatic.lcc.service.bulk.helper.HeaderCellStyleProvider; import de.avatic.lcc.service.bulk.helper.HeaderGenerator; import org.apache.poi.ss.usermodel.Cell; @@ -140,11 +141,26 @@ public class ExcelReportingService { // TODO: hardcoded (otherwise values wont match report.getCost().keySet().forEach(costName -> addData(costName, report.getCost().get(costName))); - report.getRisk().keySet().forEach(riskName -> addData(riskName, report.getRisk().get(riskName))); + report.getOverview().keySet().forEach(riskName -> addData(riskName, report.getOverview().get(riskName))); + + commonPremisses(report.getPremises()); report.getDestinations().forEach(this::flattenDestination); } + private void commonPremisses(ReportPremisesDTO premises) { + addData(DESTINATION_HS_CODE, premises.getHsCode()); + addData(DESTINATION_TARIFF_RATE, premises.getTariffRate().toString()); + + addData(DESTINATION_WIDTH, premises.getWidth().toString()); + addData(DESTINATION_HEIGHT, premises.getHeight().toString()); + addData(DESTINATION_LENGTH, premises.getLength().toString()); + addData(DESTINATION_DIMENSION_UNIT, premises.getDimensionUnit().toString()); + addData(DESTINATION_WEIGHT, premises.getWeight().toString()); + addData(DESTINATION_WEIGHT_UNIT, premises.getWeightUnit().toString()); + addData(DESTINATION_HU_UNIT_COUNT, premises.getHuUnitCount().toString()); + } + private void flattenDestination(ReportDestinationDTO destination) { var hasMainRun = destination.getSections().stream().anyMatch(s -> s.getTransportType().equals(TransportType.RAIL) || s.getTransportType().equals(TransportType.SEA)); @@ -153,8 +169,7 @@ public class ExcelReportingService { addData(DESTINATION_ADDRESS, destination.getDestination().getAddress()); addData(DESTINATION_QUANTITY, destination.getAnnualQuantity().toString()); - addData(DESTINATION_HS_CODE, destination.getHsCode()); - addData(DESTINATION_TARIFF_RATE, destination.getTariffRate().toString()); + addData(DESTINATION_OVERSHARE, destination.getOverseaShare().toString()); if(destination.getAirFreightShare() != null) @@ -162,13 +177,7 @@ public class ExcelReportingService { addData(DESTINATION_TRANSPORT_TIME, destination.getTransportTime().toString()); addData(DESTINATION_SAFETY_STOCK, destination.getSafetyStock().toString()); - addData(DESTINATION_WIDTH, destination.getWidth().toString()); - addData(DESTINATION_HEIGHT, destination.getHeight().toString()); - addData(DESTINATION_LENGTH, destination.getLength().toString()); - addData(DESTINATION_DIMENSION_UNIT, destination.getDimensionUnit().toString()); - addData(DESTINATION_WEIGHT, destination.getWeight().toString()); - addData(DESTINATION_WEIGHT_UNIT, destination.getWeightUnit().toString()); - addData(DESTINATION_HU_UNIT_COUNT, destination.getHuUnitCount().toString()); + addData(DESTINATION_CONTAINER_LAYER, !hasMainRun ? "-" : destination.getLayer().toString()); addData(DESTINATION_CONTAINER_UNIT_COUNT, !hasMainRun ? "-" : destination.getUnitCount().toString()); diff --git a/src/main/java/de/avatic/lcc/service/transformer/report/ReportTransformer.java b/src/main/java/de/avatic/lcc/service/transformer/report/ReportTransformer.java index 210f2a1..3f23b41 100644 --- a/src/main/java/de/avatic/lcc/service/transformer/report/ReportTransformer.java +++ b/src/main/java/de/avatic/lcc/service/transformer/report/ReportTransformer.java @@ -2,10 +2,7 @@ package de.avatic.lcc.service.transformer.report; import de.avatic.lcc.dto.generic.NodeType; import de.avatic.lcc.dto.generic.RateType; -import de.avatic.lcc.dto.report.ReportDTO; -import de.avatic.lcc.dto.report.ReportDestinationDTO; -import de.avatic.lcc.dto.report.ReportEntryDTO; -import de.avatic.lcc.dto.report.ReportSectionDTO; +import de.avatic.lcc.dto.report.*; import de.avatic.lcc.model.db.calculations.CalculationJob; import de.avatic.lcc.model.db.calculations.CalculationJobDestination; import de.avatic.lcc.model.db.calculations.CalculationJobRouteSection; @@ -67,23 +64,18 @@ public class ReportTransformer { public ReportDTO toReportDTO(CalculationJob job) { - ReportDTO reportDTO = new ReportDTO(); - - var reportingProperty = propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.REPORTING).orElseThrow(); - boolean includeAirfreight = reportingProperty.getCurrentValue().equals("MEK_C"); + /* + * STEP 1: Fetch all infos. + */ List destinations = calculationJobDestinationRepository.getDestinationsByJobId(job.getId()); Map> sections = calculationJobRouteSectionRepository.getRouteSectionsByDestinationIds(destinations.stream().map(CalculationJobDestination::getId).toList()); + var reportingProperty = propertyRepository.getPropertyByMappingId(SystemPropertyMappingId.REPORTING).orElseThrow(); + boolean includeAirfreight = reportingProperty.getCurrentValue().equals("MEK_C"); var weightedTotalCost = getWeightedTotalCosts(sections); Premise premise = premiseRepository.getPremiseById(job.getPremiseId()).orElseThrow(); - reportDTO.setMaterial(materialTransformer.toMaterialDTO(materialRepository.getByIdIncludeDeprecated(premise.getMaterialId()).orElseThrow())); - - var period = getPeriod(job); - - reportDTO.setStartDate(period.startDate); - reportDTO.setEndDate(period.endDate); Node sourceNode = null; @@ -93,10 +85,29 @@ public class ReportTransformer { if (premise.getUserSupplierNodeId() != null) sourceNode = userNodeRepository.getById(premise.getUserSupplierNodeId()).orElseThrow(); + /* + * STEP 2: Create report DTO. + */ + + ReportDTO reportDTO = new ReportDTO(); + + reportDTO.setMaterial(materialTransformer.toMaterialDTO(materialRepository.getByIdIncludeDeprecated(premise.getMaterialId()).orElseThrow())); + + var period = getPeriod(job); + + reportDTO.setStartDate(period.startDate); + reportDTO.setEndDate(period.endDate); + + reportDTO.setPremises(getPremisesDTO(job, premise)); + if (!destinations.isEmpty()) { - reportDTO.setCost(getCostMap(job, destinations, weightedTotalCost, includeAirfreight)); - reportDTO.setRisk(getRisk(job, destinations, weightedTotalCost, includeAirfreight)); + var costs = getCostMap(job, destinations, weightedTotalCost, includeAirfreight); + reportDTO.setCost(costs); + + /* costs.total contains all logistic costs */ + reportDTO.setOverview(getOverview(job, destinations, weightedTotalCost, includeAirfreight, costs)); + Node finalSourceNode = sourceNode; reportDTO.setDestination(destinations.stream().map(d -> getDestinationDTO(d, sections.get(d.getId()), premise, finalSourceNode, includeAirfreight)).toList()); } else { @@ -160,12 +171,32 @@ public class ReportTransformer { return new WeightedTotalCosts(totalPreRunCost, totalMainRunCost, totalPostRunCost, totalD2D, totalCost); } - private ReportDestinationDTO getDestinationDTO(CalculationJobDestination destination, List sections, Premise premise, Node sourceNode, boolean includeAirfreight) { - var destinationNode = nodeRepository.getByDestinationId(destination.getPremiseDestinationId()).orElseThrow(); + private ReportPremisesDTO getPremisesDTO(CalculationJob job, Premise premise) { + ReportPremisesDTO premisesDTO = new ReportPremisesDTO(); var dimensionUnit = premise.getHuDisplayedDimensionUnit(); var weightUnit = premise.getHuDisplayedWeightUnit(); + premisesDTO.setDimensionUnit(dimensionUnit); + premisesDTO.setWeightUnit(weightUnit); + premisesDTO.setHeight(dimensionUnit.convertFromMM(premise.getIndividualHuHeight())); + premisesDTO.setWidth(dimensionUnit.convertFromMM(premise.getIndividualHuWidth())); + premisesDTO.setLength(dimensionUnit.convertFromMM(premise.getIndividualHuLength())); + premisesDTO.setWeight(weightUnit.convertFromG(premise.getIndividualHuWeight())); + premisesDTO.setHuUnitCount(premise.getHuUnitCount()); + + premisesDTO.setHsCode(premise.getHsCode()); + premisesDTO.setTariffRate(premise.getTariffRate()); + + + return premisesDTO; + } + + private ReportDestinationDTO getDestinationDTO(CalculationJobDestination destination, List sections, Premise premise, Node sourceNode, boolean includeAirfreight) { + var destinationNode = nodeRepository.getByDestinationId(destination.getPremiseDestinationId()).orElseThrow(); + + + ReportDestinationDTO destinationDTO = new ReportDestinationDTO(); destinationDTO.setSections(sections.stream().map(s -> getSection(s, sourceNode, destinationNode, premise)).toList()); @@ -182,14 +213,6 @@ public class ReportTransformer { destinationDTO.setDestination(nodeTransformer.toNodeDTO(destinationNode)); - destinationDTO.setDimensionUnit(dimensionUnit); - destinationDTO.setWeightUnit(weightUnit); - destinationDTO.setHeight(dimensionUnit.convertFromMM(premise.getIndividualHuHeight())); - destinationDTO.setWidth(dimensionUnit.convertFromMM(premise.getIndividualHuWidth())); - destinationDTO.setLength(dimensionUnit.convertFromMM(premise.getIndividualHuLength())); - destinationDTO.setWeight(weightUnit.convertFromG(premise.getIndividualHuWeight())); - destinationDTO.setHuUnitCount(premise.getHuUnitCount()); - CalculationJobRouteSection mainRun = sections.stream().filter(CalculationJobRouteSection::getMainRun).findFirst().orElse(null); destinationDTO.setLayer(destination.getLayerCount()); @@ -209,8 +232,7 @@ public class ReportTransformer { destinationDTO.setUnitCount(destination.getHuCount()); destinationDTO.setWeightExceeded(destination.getTransportWeightExceeded()); - destinationDTO.setHsCode(premise.getHsCode()); - destinationDTO.setTariffRate(destination.getTariffRate()); + return destinationDTO; } @@ -247,7 +269,7 @@ public class ReportTransformer { return sectionDTO; } - private Map getRisk(CalculationJob job, List destination, WeightedTotalCosts weightedTotalCost, boolean includeAirfreight) { + private Map getOverview(CalculationJob job, List destination, WeightedTotalCosts weightedTotalCost, boolean includeAirfreight, Map weightedCostBreakDown) { Map risk = new HashMap<>(); var annualAmount = destination.stream().map(CalculationJobDestination::getAnnualAmount).reduce(BigDecimal.ZERO, BigDecimal::add); @@ -261,6 +283,18 @@ public class ReportTransformer { totalValue = totalValue.add(airfreightValue.multiply(BigDecimal.valueOf(includeAirfreight ? 1 : 0))); + var totalLogistics = getTotalLogistics(weightedCostBreakDown); + + ReportEntryDTO mekA = new ReportEntryDTO(); + mekA.setTotal(weightedCostBreakDown.get("mek_a").getTotal()); + mekA.setPercentage(weightedCostBreakDown.get("mek_a").getTotal().doubleValue() / (totalValue.doubleValue())); + risk.put("mek_a", mekA); + + ReportEntryDTO logistics = new ReportEntryDTO(); + logistics.setTotal(totalLogistics); + logistics.setPercentage(totalLogistics / (totalValue.doubleValue())); + risk.put("logistics", logistics); + ReportEntryDTO total = new ReportEntryDTO(); total.setTotal(totalValue); total.setPercentage(totalValue.divide(totalValue, 4, RoundingMode.HALF_UP)); @@ -279,6 +313,11 @@ public class ReportTransformer { return risk; } + private Double getTotalLogistics(Map weightedCostBreakDown) { + return weightedCostBreakDown.get("total").getTotal().doubleValue() - weightedCostBreakDown.get("mek_a").getTotal().doubleValue(); + + } + private Map getCostMap(CalculationJob job, List destination, WeightedTotalCosts weightedTotalCost, boolean includeAirfreight) { Map cost = new HashMap<>(); From 0b78321e58773e50f5afe7faa330e5eeaada36b9 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 14 Dec 2025 16:58:15 +0100 Subject: [PATCH 2/2] added container info to d2d transports --- .../src/components/layout/report/Report.vue | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/frontend/src/components/layout/report/Report.vue b/src/frontend/src/components/layout/report/Report.vue index 1dc1e74..4ea9a50 100644 --- a/src/frontend/src/components/layout/report/Report.vue +++ b/src/frontend/src/components/layout/report/Report.vue @@ -317,7 +317,7 @@
Stacked layers
{{ - hasMainRun(destination.sections) ? destination.layer : '-' + hasMainRunOrD2D(destination.sections) ? destination.layer : '-' }}
@@ -325,7 +325,9 @@
Container unit count
- {{ hasMainRun(destination.sections) ? (destination.unit_count * report.premises.hu_unit_count) : '-' }} + {{ + hasMainRunOrD2D(destination.sections) ? (destination.unit_count * report.premises.hu_unit_count) : '-' + }}
@@ -333,14 +335,14 @@
Container type
- {{ hasMainRun(destination.sections) ? getContainerTypeName(destination.container_type) : '-' }} + {{ hasMainRunOrD2D(destination.sections) ? getContainerTypeName(destination.container_type) : '-' }}
Limiting factor
- {{ hasMainRun(destination.sections) ? destination.weight_exceeded ? 'Weight' : 'Volume' : '-' }} + {{ hasMainRunOrD2D(destination.sections) ? destination.weight_exceeded ? 'Weight' : 'Volume' : '-' }}
@@ -379,8 +381,8 @@ export default { } }, methods: { - hasMainRun(sections) { - return sections.some(section => section.transport_type === 'SEA' || section.transport_type === 'RAIL'); + hasMainRunOrD2D(sections) { + return sections.some(section => section.transport_type === 'SEA' || section.transport_type === 'RAIL' || section.rate_type === 'D2D'); }, shorten(text, length) { if (text !== null && text !== undefined && text.length > length) {