From 0c88c5ed0f3acc25cfa6d5a0afa9a47bd5ed98a4 Mon Sep 17 00:00:00 2001 From: Jan Date: Sun, 19 Oct 2025 19:55:19 +0200 Subject: [PATCH] Bugfix: takes property set into account when collecting comparable reports. --- .../calculation/CalculationJobRepository.java | 12 ++--- .../rates/ValidityPeriodRepository.java | 53 +++++++++---------- .../configuration/RateApprovalService.java | 4 +- .../lcc/service/report/ReportingService.java | 11 ++-- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/main/java/de/avatic/lcc/repositories/calculation/CalculationJobRepository.java b/src/main/java/de/avatic/lcc/repositories/calculation/CalculationJobRepository.java index 9aeba04..ac65960 100644 --- a/src/main/java/de/avatic/lcc/repositories/calculation/CalculationJobRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/calculation/CalculationJobRepository.java @@ -73,12 +73,12 @@ public class CalculationJobRepository { } @Transactional - public Optional getCalculationJobWithJobStateValid(Integer periodId, Integer nodeId, Integer materialId) { + public Optional getCalculationJobWithJobStateValid(Integer periodId, Integer setId, Integer nodeId, Integer materialId) { /* there should only be one job per period id, node id and material id combination */ - String query = "SELECT * FROM calculation_job AS cj INNER JOIN premise AS p ON cj.premise_id = p.id WHERE job_state = 'VALID' AND validity_period_id = ? AND p.supplier_node_id = ? AND material_id = ? ORDER BY cj.calculation_date DESC LIMIT 1"; + String query = "SELECT * FROM calculation_job AS cj INNER JOIN premise AS p ON cj.premise_id = p.id WHERE job_state = 'VALID' AND validity_period_id = ? AND property_set_id = ? AND p.supplier_node_id = ? AND material_id = ? ORDER BY cj.calculation_date DESC LIMIT 1"; - var job = jdbcTemplate.query(query, new CalculationJobMapper(), periodId, nodeId, materialId); + var job = jdbcTemplate.query(query, new CalculationJobMapper(), periodId, setId, nodeId, materialId); if(job.isEmpty()) return Optional.empty(); @@ -87,12 +87,12 @@ public class CalculationJobRepository { } @Transactional - public Optional getCalculationJobWithJobStateValidUserNodeId(Integer periodId, Integer userNodeId, Integer materialId) { + public Optional getCalculationJobWithJobStateValidUserNodeId(Integer periodId, Integer setId, Integer userNodeId, Integer materialId) { /* there should only be one job per period id, node id and material id combination */ - String query = "SELECT * FROM calculation_job AS cj INNER JOIN premise AS p ON cj.premise_id = p.id WHERE job_state = 'VALID' AND validity_period_id = ? AND p.user_supplier_node_id = ? AND material_id = ? ORDER BY cj.calculation_date DESC LIMIT 1"; + String query = "SELECT * FROM calculation_job AS cj INNER JOIN premise AS p ON cj.premise_id = p.id WHERE job_state = 'VALID' AND validity_period_id = ? AND property_set_id = ? AND p.user_supplier_node_id = ? AND material_id = ? ORDER BY cj.calculation_date DESC LIMIT 1"; - var job = jdbcTemplate.query(query, new CalculationJobMapper(), periodId, userNodeId, materialId); + var job = jdbcTemplate.query(query, new CalculationJobMapper(), periodId, setId, userNodeId, materialId); if(job.isEmpty()) return Optional.empty(); diff --git a/src/main/java/de/avatic/lcc/repositories/rates/ValidityPeriodRepository.java b/src/main/java/de/avatic/lcc/repositories/rates/ValidityPeriodRepository.java index f2717d3..f242545 100644 --- a/src/main/java/de/avatic/lcc/repositories/rates/ValidityPeriodRepository.java +++ b/src/main/java/de/avatic/lcc/repositories/rates/ValidityPeriodRepository.java @@ -228,7 +228,7 @@ public class ValidityPeriodRepository { } @Transactional - public Optional getValidPeriodForReportingByMaterialId(Integer materialId, List nodeIds, List userNodeIds) { + public Optional getValidPeriodForReportingByMaterialId(Integer materialId, List nodeIds, List userNodeIds) { // Check if both lists are empty if ((nodeIds == null || nodeIds.isEmpty()) && (userNodeIds == null || userNodeIds.isEmpty())) { @@ -257,30 +257,27 @@ public class ValidityPeriodRepository { } String validityPeriodSql = """ - SELECT vp.* - FROM validity_period vp - INNER JOIN ( - SELECT - cj.validity_period_id, - COUNT(DISTINCT COALESCE(p.supplier_node_id, p.user_supplier_node_id)) as node_count - FROM - premise p - INNER JOIN - calculation_job cj ON p.id = cj.premise_id - WHERE - p.material_id = ? - """ + SELECT + cj.validity_period_id, + cj.property_set_id + FROM + premise p + INNER JOIN + calculation_job cj ON p.id = cj.premise_id + WHERE + p.material_id = ? + """ + whereClause + """ - - GROUP BY - cj.validity_period_id - HAVING - COUNT(DISTINCT COALESCE(p.supplier_node_id, p.user_supplier_node_id)) = ? - ) matching_periods ON vp.id = matching_periods.validity_period_id - ORDER BY - vp.start_date DESC - LIMIT 1 - """; + + GROUP BY + cj.validity_period_id, + cj.property_set_id + HAVING + COUNT(DISTINCT COALESCE(p.supplier_node_id, p.user_supplier_node_id)) = ? + ORDER BY + (SELECT start_date FROM validity_period WHERE id = cj.validity_period_id) DESC + LIMIT 1 + """; // Build parameters array Object[] params = new Object[1 + totalNodeCount + 1]; @@ -299,13 +296,15 @@ public class ValidityPeriodRepository { params[paramIndex] = totalNodeCount; - var periods = jdbcTemplate.query(validityPeriodSql, new ValidityPeriodMapper(), params); + var tuples = jdbcTemplate.query(validityPeriodSql, + (rs, cnt) -> new ValidityTuple(rs.getInt("validity_period_id"), rs.getInt("property_set_id")), + params); - if (periods.isEmpty()) { + if (tuples.isEmpty()) { return Optional.empty(); } - return Optional.of(periods.getFirst()); + return Optional.of(tuples.getFirst()); } @Transactional diff --git a/src/main/java/de/avatic/lcc/service/configuration/RateApprovalService.java b/src/main/java/de/avatic/lcc/service/configuration/RateApprovalService.java index 0394a83..c581f71 100644 --- a/src/main/java/de/avatic/lcc/service/configuration/RateApprovalService.java +++ b/src/main/java/de/avatic/lcc/service/configuration/RateApprovalService.java @@ -93,9 +93,9 @@ public class RateApprovalService { if (hasContainerDrafts || hasMatrixDrafts) { - if(hasContainerDrafts && !hasMatrixDrafts) + if (hasContainerDrafts && !hasMatrixDrafts) matrixRateRepository.copyCurrentToDraft(); - else if(!hasContainerDrafts && hasMatrixDrafts) + else if (!hasContainerDrafts && hasMatrixDrafts) containerRateRepository.copyCurrentToDraft(); validityPeriodRepository.applyDraft(); diff --git a/src/main/java/de/avatic/lcc/service/report/ReportingService.java b/src/main/java/de/avatic/lcc/service/report/ReportingService.java index be868fd..a78a518 100644 --- a/src/main/java/de/avatic/lcc/service/report/ReportingService.java +++ b/src/main/java/de/avatic/lcc/service/report/ReportingService.java @@ -50,15 +50,16 @@ public class ReportingService { } public List getReport(Integer materialId, List nodeIds, List userNodeIds) { - var period = validityPeriodRepository.getValidPeriodForReportingByMaterialId(materialId, nodeIds, userNodeIds); + var tuple = validityPeriodRepository.getValidPeriodForReportingByMaterialId(materialId, nodeIds, userNodeIds); - if (period.isEmpty()) + if (tuple.isEmpty()) throw new IllegalArgumentException("No valid period found"); - var periodId = period.get().getId(); + var periodId = tuple.get().periodId(); + var setId = tuple.get().propertySetId(); - var jobs = new ArrayList<>(nodeIds.stream().map(nodeId -> calculationJobRepository.getCalculationJobWithJobStateValid(periodId, nodeId, materialId)).filter(Optional::isPresent).map(Optional::get).toList()); - jobs.addAll(userNodeIds.stream().map(nodeId -> calculationJobRepository.getCalculationJobWithJobStateValidUserNodeId(periodId,nodeId ,materialId)).filter(Optional::isPresent).map(Optional::get).toList()); + var jobs = new ArrayList<>(nodeIds.stream().map(nodeId -> calculationJobRepository.getCalculationJobWithJobStateValid(periodId, setId, nodeId, materialId)).filter(Optional::isPresent).map(Optional::get).toList()); + jobs.addAll(userNodeIds.stream().map(nodeId -> calculationJobRepository.getCalculationJobWithJobStateValidUserNodeId(periodId, setId,nodeId ,materialId)).filter(Optional::isPresent).map(Optional::get).toList()); return jobs.stream().map(reportTransformer::toReportDTO).toList(); }