Files
pleno-vue/src/services/invoiceMonthSplitWarning.js
T
2026-07-06 16:02:10 +02:00

140 lines
4.3 KiB
JavaScript

import Swal from "sweetalert2";
import i18n from "@/i18n";
export const MULTI_MONTH_INVOICE_ACTION = {
CONTINUE: "continue",
CANCEL: "cancel",
SPLIT: "split",
};
const toPositiveInteger = (value) => {
const parsed = Number.parseInt(String(value ?? ""), 10);
return Number.isInteger(parsed) && parsed > 0 ? parsed : null;
};
const getDateKey = (value) => {
const rawValue = String(value ?? "").trim();
const directMatch = rawValue.match(/^(\d{4})-(\d{2})-(\d{2})/);
if (directMatch) {
return `${directMatch[1]}-${directMatch[2]}-${directMatch[3]}`;
}
const parsedDate = new Date(rawValue);
if (Number.isNaN(parsedDate.getTime())) {
return null;
}
const year = parsedDate.getFullYear();
const month = String(parsedDate.getMonth() + 1).padStart(2, "0");
const day = String(parsedDate.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
export const getMonthKey = (value) => {
const dateKey = getDateKey(value);
return dateKey ? dateKey.slice(0, 7) : null;
};
const translate = (key, params = {}) => i18n.global.t(key, params);
const getSplitResponsePayload = (response = {}) => response?.data?.data ?? response?.data ?? {};
export const buildMultiMonthInvoiceContext = (
items = [],
{
getDate = (item) => item?.created_at ?? item?.date,
getInvoiceCollectionId = (item) => item?.invoice_collection_id,
} = {}
) => {
const months = new Set();
const dateKeys = [];
const invoiceCollectionIds = new Set();
(Array.isArray(items) ? items : []).forEach((item) => {
const dateValue = getDate(item);
const dateKey = getDateKey(dateValue);
if (dateKey) {
dateKeys.push(dateKey);
months.add(dateKey.slice(0, 7));
}
const invoiceCollectionId = toPositiveInteger(getInvoiceCollectionId(item));
if (invoiceCollectionId) {
invoiceCollectionIds.add(invoiceCollectionId);
}
});
dateKeys.sort();
return {
months: Array.from(months).sort(),
dateFrom: dateKeys[0] ?? null,
dateTo: dateKeys[dateKeys.length - 1] ?? null,
invoiceCollectionIds: Array.from(invoiceCollectionIds).sort((left, right) => left - right),
};
};
export const shouldWarnAboutMultiMonthInvoice = (context = {}) => (
Array.isArray(context.months) &&
context.months.length > 1 &&
Array.isArray(context.invoiceCollectionIds) &&
context.invoiceCollectionIds.length > 0 &&
Boolean(context.dateFrom) &&
Boolean(context.dateTo)
);
export const promptMultiMonthInvoiceWarning = async ({
context,
splitByMonth,
parseErrorMessage = (error) => error?.message ?? String(error),
} = {}) => {
if (!shouldWarnAboutMultiMonthInvoice(context)) {
return MULTI_MONTH_INVOICE_ACTION.CONTINUE;
}
const months = context.months.join(", ");
const confirmation = await Swal.fire({
icon: "warning",
title: translate("invoicing_period.multi_month_invoice_warning.title"),
text: translate("invoicing_period.multi_month_invoice_warning.text", { months }),
showCancelButton: true,
showDenyButton: true,
confirmButtonText: translate("invoicing_period.multi_month_invoice_warning.split_by_month"),
denyButtonText: translate("invoicing_period.multi_month_invoice_warning.invoice_together"),
cancelButtonText: translate("common.cancel"),
});
if (confirmation.isDenied) {
return MULTI_MONTH_INVOICE_ACTION.CONTINUE;
}
if (!confirmation.isConfirmed) {
return MULTI_MONTH_INVOICE_ACTION.CANCEL;
}
try {
const response = await splitByMonth(context.dateFrom, context.dateTo, {
invoiceCollectionIds: context.invoiceCollectionIds,
preview: false,
});
const result = getSplitResponsePayload(response);
await Swal.fire({
icon: "success",
title: translate("invoicing_period.multi_month_invoice_warning.split_success_title"),
text: translate("invoicing_period.multi_month_invoice_warning.split_success_text", {
processed: result.processed_count ?? 0,
changed: result.changed_count ?? 0,
skipped: result.skipped_count ?? 0,
}),
});
return MULTI_MONTH_INVOICE_ACTION.SPLIT;
} catch (error) {
await Swal.fire({
icon: "error",
title: translate("invoicing_period.multi_month_invoice_warning.split_error_title"),
text: parseErrorMessage(error),
});
return MULTI_MONTH_INVOICE_ACTION.CANCEL;
}
};