From ac09b4e33b379a37fa58f1ff1079adf1f7aaf1e4 Mon Sep 17 00:00:00 2001 From: nielserik Date: Wed, 25 Feb 2026 13:00:38 +0100 Subject: [PATCH 1/2] MODEUR-166 etc: add view to normalise usage data - view for collapsing multiple invoices (and other data items) for an agreement line to avoid repeat counting of usage for every invoice etc. --- .../folio/eusage/reports/api/CostPerUse.java | 6 +- .../eusage/reports/api/EusageReportsApi.java | 55 +++++++++++++++++-- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/folio/eusage/reports/api/CostPerUse.java b/src/main/java/org/folio/eusage/reports/api/CostPerUse.java index 486c47e0..ee2cc825 100644 --- a/src/main/java/org/folio/eusage/reports/api/CostPerUse.java +++ b/src/main/java/org/folio/eusage/reports/api/CostPerUse.java @@ -155,9 +155,9 @@ static JsonObject titlesToJsonObject(RowSet rowSet, Periods usePeriods) { item.put("poLineIDs", poLineIDs); JsonArray invoiceNumbers = new JsonArray(); - String invoiceNumber = row.getString("invoicenumber"); - if (invoiceNumber != null) { - invoiceNumbers.add(invoiceNumber); + String invoicenumbers = row.getString("invoicenumbers"); + if (invoicenumbers != null) { + invoiceNumbers.add(invoicenumbers); } item.put("invoiceNumbers", invoiceNumbers); if (usageDateRange != null) { diff --git a/src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java b/src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java index 4ab73010..f0ab8257 100644 --- a/src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java +++ b/src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java @@ -81,6 +81,9 @@ static String agreementEntriesTable(TenantPgPool pool) { return pool.getSchema() + ".agreement_entries"; } + static String deduplicatedAgreementsView(TenantPgPool pool) { + return pool.getSchema() + ".unique_agreement_entries_with_aggregated_invoices"; + } static String statusTable(TenantPgPool pool) { return pool.getSchema() + ".status"; } @@ -1240,7 +1243,7 @@ Future parsePoLine(JsonObject poLine, RoutingContext ctx) { result.put("fiscalYear", fiscalYears); result.put("invoicedPeriods", invoicedPeriods); JsonArray invoiceNumbers = new JsonArray(); - result.put("invoiceNumber", invoiceNumbers); + result.put("invoiceNumbers", invoiceNumbers); UUID poLineId = UUID.fromString(poLine.getString("poLineId")); return lookupOrderLine(poLineId, ctx).compose(orderLine -> { result.put("poLineNumber", orderLine.getString("poLineNumber")); @@ -1382,7 +1385,7 @@ private Future populateParsedPoLine(TenantPgPool pool, SqlConnection con, JsonArray fiscalYears = poResult.getJsonArray("fiscalYear"); JsonArray subscriptionPeriods = poResult.getJsonArray("subscriptionPeriods"); JsonArray invoicedPeriods = poResult.getJsonArray("invoicedPeriods"); - JsonArray invoiceNumbers = poResult.getJsonArray("invoiceNumber"); + JsonArray invoiceNumbers = poResult.getJsonArray("invoiceNumbers"); if (subscriptionPeriods.isEmpty()) { return insertAgreementLine(pool, con, agreementId, agreementLineId, coverageDateRanges, type, kbTitleId, kbPackageId, poLineId, poResult, @@ -1730,10 +1733,10 @@ static Future> getTitlesCost(TenantPgPool pool, Boolean isJournal, b + " kbPackageId, kbPackageName, printISSN, onlineISSN, ISBN," + " NULL AS publicationDate, NULL AS usageDateRange," + " NULL AS uniqueAccessCount, NULL AS totalAccessCount, TRUE AS openAccess," - + " orderType, poLineNumber, invoiceNumber," + + " orderType, poLineNumber, invoiceNumbers," + " fiscalYearRange, subscriptionDateRange," + " encumberedCost, invoicedCost" - + " FROM " + agreementEntriesTable(pool) + + " FROM " + deduplicatedAgreementsView(pool) + " AS agreement_entries" + " LEFT JOIN " + packageEntriesTable(pool) + " USING (kbPackageId)" + " JOIN " + titleEntriesTable(pool) + " ON" + " title_entries.kbTitleId = agreement_entries.kbTitleId OR" @@ -1745,10 +1748,10 @@ static Future> getTitlesCost(TenantPgPool pool, Boolean isJournal, b + " title_entries.kbTitleId AS kbId, kbTitleName AS title," + " kbPackageId, kbPackageName, printISSN, onlineISSN, ISBN," + " publicationDate, usageDateRange, uniqueAccessCount, totalAccessCount, openAccess," - + " orderType, poLineNumber, invoiceNumber," + + " orderType, poLineNumber, invoiceNumbers," + " fiscalYearRange, subscriptionDateRange," + " encumberedCost, invoicedCost" - + " FROM " + agreementEntriesTable(pool) + + " FROM " + deduplicatedAgreementsView(pool) + " AS agreement_entries " + " LEFT JOIN " + packageEntriesTable(pool) + " USING (kbPackageId)" + " JOIN " + titleEntriesTable(pool) + " ON" + " title_entries.kbTitleId = agreement_entries.kbTitleId OR" @@ -1956,6 +1959,46 @@ public Future postInit(Vertx vertx, String tenant, JsonObject tenantAttrib + "id UUID PRIMARY KEY, " + "status json" + ")", + "DROP VIEW IF EXISTS " + deduplicatedAgreementsView(pool), + "CREATE VIEW " + deduplicatedAgreementsView(pool) + " AS\n" + + "SELECT kbtitleid,\n" + + " kbpackageid,\n" + + " type,\n" + + " agreementid,\n" + + " agreementlineid,\n" + + " coveragedateranges,\n" + + " ordertype,\n" + + " date_part('year', lower(subscriptiondaterange)) AS year,\n" + + " TRANSLATE(CAST(range_agg(subscriptiondaterange) AS TEXT),'{}','') " + + " AS subscriptiondaterange,\n" + + " TRANSLATE(CAST(range_agg(fiscalyearrange) AS TEXT),'{}','') " + + " AS fiscalyearrange,\n" + + " string_agg(polinenumber, ';') AS poLineNumber,\n" + + " string_agg(invoicenumber, ';') AS invoicenumbers,\n" + + " sum(invoicedcost) AS invoicedcost,\n" + + " sum(encumberedcost) AS encumberedcost\n" + + "FROM (SELECT DISTINCT kbtitleid,\n" + + " kbpackageid,\n" + + " type,\n" + + " agreementid,\n" + + " agreementlineid,\n" + + " fiscalyearrange,\n" + + " subscriptiondaterange,\n" + + " coveragedateranges,\n" + + " ordertype,\n" + + " polinenumber,\n" + + " invoicenumber,\n" + + " invoicedcost,\n" + + " encumberedcost\n" + + " FROM " + agreementEntriesTable(pool) + ")\n" + + "GROUP BY kbtitleid,\n" + + " kbpackageid,\n" + + " type,\n" + + " agreementid,\n" + + " agreementlineid,\n" + + " year,\n" + + " coveragedateranges,\n" + + " ordertype", "CREATE OR REPLACE FUNCTION " + pool.getSchema() + ".floor_months(date, integer)" + " RETURNS date AS $$\n" + "-- floor_months(date, n) returns the start of the period date belongs to,\n" From 7cfac3873ea150be6e74cc4841e1a986ad38b577 Mon Sep 17 00:00:00 2001 From: nielserik Date: Wed, 25 Feb 2026 13:06:18 +0100 Subject: [PATCH 2/2] MODEUR-166 etc: add view to normalise usage data - view for collapsing multiple invoices (and other data items) for an agreement line to avoid repeat counting of usage for every invoice etc. --- src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java b/src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java index f0ab8257..ce151df1 100644 --- a/src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java +++ b/src/main/java/org/folio/eusage/reports/api/EusageReportsApi.java @@ -84,6 +84,7 @@ static String agreementEntriesTable(TenantPgPool pool) { static String deduplicatedAgreementsView(TenantPgPool pool) { return pool.getSchema() + ".unique_agreement_entries_with_aggregated_invoices"; } + static String statusTable(TenantPgPool pool) { return pool.getSchema() + ".status"; }