From 10a52521d585a87fef7542dfe59beef1229e683f Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Mon, 11 May 2026 03:35:36 +0200 Subject: [PATCH] Fix invoicing period invoice action --- .../views/InvoicingBillingPeriodViewAll.vue | 204 +++++++++++++----- tests/e2e/invoicing-period.smoke.spec.js | 84 +++++++- ...oicing-period-queue-state.behavior.spec.js | 63 +++++- 3 files changed, 291 insertions(+), 60 deletions(-) diff --git a/src/views/dashboards/superUserDashboard/InvoicingBillingPeriod/views/InvoicingBillingPeriodViewAll.vue b/src/views/dashboards/superUserDashboard/InvoicingBillingPeriod/views/InvoicingBillingPeriodViewAll.vue index f18b3947..1d1453d7 100644 --- a/src/views/dashboards/superUserDashboard/InvoicingBillingPeriod/views/InvoicingBillingPeriodViewAll.vue +++ b/src/views/dashboards/superUserDashboard/InvoicingBillingPeriod/views/InvoicingBillingPeriodViewAll.vue @@ -42,7 +42,9 @@ const doesCustomerHaveTransactionsDifferentDays = (customer: any) => { return false; } - const datesSet = new Set(customer.transactions.map((transaction: any) => new Date(transaction.date).toISOString().split("T")[0])); + const datesSet = new Set( + customer.transactions.map((transaction: any) => new Date(transaction.date).toISOString().split("T")[0]) + ); return datesSet.size > 1; }; @@ -57,9 +59,9 @@ const onFilterChanged = (filters: any) => { tmpFilters.value = filters; }; -const customersInCurrentView = computed(() => ( - view.variables.sharedVariables.value?.types?.[view.computed.componentName.value] ?? [] -)); +const customersInCurrentView = computed( + () => view.variables.sharedVariables.value?.types?.[view.computed.componentName.value] ?? [] +); const getTransactionIds = (customer: any) => { if (!customer.transactions || customer.transactions.length === 0) { @@ -83,23 +85,41 @@ const getExcludedTransactionIds = (customer: any) => { const transactionIdsInvoiceCollectionCache = ref<{ [key: number]: number | null }>({}); +const queueInvoiceCollections = (invoiceCollectionIds: number[]) => { + const uniqueInvoiceCollectionIds = Array.from( + new Set( + invoiceCollectionIds.filter( + (invoiceCollectionId) => Number.isInteger(invoiceCollectionId) && invoiceCollectionId > 0 + ) + ) + ); + + if (uniqueInvoiceCollectionIds.length === 0) { + return; + } + + invoiceQueue.addInvoiceCollectionsToQueue(uniqueInvoiceCollectionIds); + invoiceQueue.processInvoiceCollectionQueue(); +}; + const onClickInvoiceNow = async (customer: any, transactionIds: number[]) => { if (transactionIds.length === 0) { if (customer?.meta?.fixed_pricing) { const month = dates.variables.start.value.getMonth() + 1; const year = dates.variables.start.value.getFullYear(); - await SessionUser.objects.collectedOrderInvoices.functions.createVehicleSubscriptionInvoice(customer.customer_number, month, year) + await SessionUser.objects.collectedOrderInvoices.functions + .createVehicleSubscriptionInvoice(customer.customer_number, month, year) .then((response: any) => { const newInvoiceCollectionId = response?.data?.data?.id; if (!newInvoiceCollectionId) { return; } - SessionUser.objects.collectedOrderInvoices.functions.add_fixed_pricing(newInvoiceCollectionId) + SessionUser.objects.collectedOrderInvoices.functions + .add_fixed_pricing(newInvoiceCollectionId) .then(() => { - invoiceQueue.addInvoiceCollectionsToQueue([newInvoiceCollectionId]); - invoiceQueue.processInvoiceCollectionQueue(); + queueInvoiceCollections([newInvoiceCollectionId]); }) .catch((error: any) => { console.error("Error adding fixed pricing to invoice collection:", error); @@ -112,17 +132,18 @@ const onClickInvoiceNow = async (customer: any, transactionIds: number[]) => { const month = dates.variables.start.value.getMonth() + 1; const year = dates.variables.start.value.getFullYear(); - await SessionUser.objects.collectedOrderInvoices.functions.createVehicleSubscriptionInvoice(customer.customer_number, month, year) + await SessionUser.objects.collectedOrderInvoices.functions + .createVehicleSubscriptionInvoice(customer.customer_number, month, year) .then((response: any) => { const newInvoiceCollectionId = response?.data?.data?.id; if (!newInvoiceCollectionId) { return; } - SessionUser.objects.collectedOrderInvoices.functions.add_vehicle_subscriptions(newInvoiceCollectionId) + SessionUser.objects.collectedOrderInvoices.functions + .add_vehicle_subscriptions(newInvoiceCollectionId) .then(() => { - invoiceQueue.addInvoiceCollectionsToQueue([newInvoiceCollectionId]); - invoiceQueue.processInvoiceCollectionQueue(); + queueInvoiceCollections([newInvoiceCollectionId]); }) .catch((error: any) => { console.error("Error adding vehicle subscriptions to invoice collection:", error); @@ -136,21 +157,23 @@ const onClickInvoiceNow = async (customer: any, transactionIds: number[]) => { return; } - fetchMissingInvoiceCollections(transactionIds).then(() => { - const invoiceCollectionIds = transactionIds - .map((transactionId) => transactionIdsInvoiceCollectionCache.value[transactionId]) - .filter((invoiceCollectionId): invoiceCollectionId is number => invoiceCollectionId !== null); - const uniqueInvoiceCollectionIds = Array.from(new Set(invoiceCollectionIds)); - - if (uniqueInvoiceCollectionIds.length > 0) { - invoiceQueue.addInvoiceCollectionsToQueue(uniqueInvoiceCollectionIds); - invoiceQueue.processInvoiceCollectionQueue(); - } - }); + await fetchMissingInvoiceCollections(customer, transactionIds); + queueInvoiceCollections(getInvoiceCollectionIdsForTransactionIds(customer, transactionIds)); }; -const fetchMissingInvoiceCollections = async (transactionIds: number[]) => { - const uncachedTransactionIds = transactionIds.filter((transactionId) => !(transactionId in transactionIdsInvoiceCollectionCache.value)); +const getTransactionById = (customer: any, transactionId: number) => { + return Array.isArray(customer?.transactions) + ? customer.transactions.find((transaction: any) => Number(transaction?.id) === Number(transactionId)) + : null; +}; + +const fetchMissingInvoiceCollections = async (customer: any, transactionIds: number[]) => { + const uncachedTransactionIds = transactionIds.filter( + (transactionId) => + !(transactionId in transactionIdsInvoiceCollectionCache.value) && + getTransactionInvoiceCollectionId(getTransactionById(customer, transactionId) ?? { id: transactionId }) === null + ); + if (uncachedTransactionIds.length === 0) { return Promise.resolve(); } @@ -174,32 +197,51 @@ const getTransactionInvoiceCollectionId = (transaction: any) => { : null; }; +const getInvoiceCollectionIdsForTransactionIds = (customer: any, transactionIds: number[]) => { + return transactionIds + .map((transactionId) => + getTransactionInvoiceCollectionId(getTransactionById(customer, transactionId) ?? { id: transactionId }) + ) + .filter((invoiceCollectionId): invoiceCollectionId is number => invoiceCollectionId !== null); +}; + const isInvoiceCollectionQueuedLocally = (invoiceCollectionId: number | null | undefined) => { if (!invoiceCollectionId) { return false; } - return invoiceQueue.invoiceCollectionQueueInProgress.value.includes(invoiceCollectionId) - || invoiceQueue.invoiceCollectionQueue.value.includes(invoiceCollectionId); + return ( + invoiceQueue.invoiceCollectionQueueInProgress.value.includes(invoiceCollectionId) || + invoiceQueue.invoiceCollectionQueue.value.includes(invoiceCollectionId) + ); }; const getCustomerActionableTransactions = (customer: any) => { - return getTransactionsInView(customer).filter((transaction: any) => transaction?.booked !== true && transaction?.excluded !== true); + return getTransactionsInView(customer).filter( + (transaction: any) => transaction?.booked !== true && transaction?.excluded !== true + ); }; const getLocalQueuedInvoiceCollectionIdsForCustomer = (customer: any) => { - return Array.from(new Set( - getCustomerActionableTransactions(customer) - .map((transaction: any) => getTransactionInvoiceCollectionId(transaction)) - .filter((invoiceCollectionId): invoiceCollectionId is number => ( - Number.isInteger(invoiceCollectionId) && (invoiceCollectionId ?? 0) > 0 && isInvoiceCollectionQueuedLocally(invoiceCollectionId) - )) - )); + return Array.from( + new Set( + getCustomerActionableTransactions(customer) + .map((transaction: any) => getTransactionInvoiceCollectionId(transaction)) + .filter( + (invoiceCollectionId): invoiceCollectionId is number => + Number.isInteger(invoiceCollectionId) && + (invoiceCollectionId ?? 0) > 0 && + isInvoiceCollectionQueuedLocally(invoiceCollectionId) + ) + ) + ); }; const getCustomerQueueStatuses = (customer: any) => { const backendStatuses = Array.isArray(customer?.queue?.statuses) - ? Array.from(new Set(customer.queue.statuses.filter((status: string) => typeof status === "string" && status.length > 0))) + ? Array.from( + new Set(customer.queue.statuses.filter((status: string) => typeof status === "string" && status.length > 0)) + ) : []; if (backendStatuses.length > 0) { @@ -212,12 +254,12 @@ const getCustomerQueueStatuses = (customer: any) => { } const statuses = []; - const hasProcessing = queuedInvoiceCollectionIds.some((invoiceCollectionId) => ( + const hasProcessing = queuedInvoiceCollectionIds.some((invoiceCollectionId) => invoiceQueue.invoiceCollectionQueueInProgress.value.includes(invoiceCollectionId) - )); - const hasQueued = queuedInvoiceCollectionIds.some((invoiceCollectionId) => ( + ); + const hasQueued = queuedInvoiceCollectionIds.some((invoiceCollectionId) => invoiceQueue.invoiceCollectionQueue.value.includes(invoiceCollectionId) - )); + ); if (hasProcessing) { statuses.push(ECONOMIC_QUEUE_STATUS.PROCESSING); @@ -241,7 +283,11 @@ const isCustomerQueueBlocked = (customer: any) => { return actionableTransactions.every((transaction: any) => { const invoiceCollectionId = getTransactionInvoiceCollectionId(transaction); - return Number.isInteger(invoiceCollectionId) && (invoiceCollectionId ?? 0) > 0 && isInvoiceCollectionQueuedLocally(invoiceCollectionId); + return ( + Number.isInteger(invoiceCollectionId) && + (invoiceCollectionId ?? 0) > 0 && + isInvoiceCollectionQueuedLocally(invoiceCollectionId) + ); }); }; @@ -269,8 +315,10 @@ const isAllCustomerTransactionsBooked = (customer: any, transactionIds: number[] .filter((transaction: any) => transaction.excluded === true) .map((transaction: any) => transaction.id); - return transactionIds.every((transactionId) => bookedTransactionIds.includes(transactionId)) - || transactionIds.every((transactionId) => excludedTransactionIds.includes(transactionId)); + return ( + transactionIds.every((transactionId) => bookedTransactionIds.includes(transactionId)) || + transactionIds.every((transactionId) => excludedTransactionIds.includes(transactionId)) + ); }; const getTransactionQueryParameters = () => { @@ -286,15 +334,16 @@ const getTransactionQueryParameters = () => {
-
+
-