140 lines
4.3 KiB
JavaScript
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;
|
|
}
|
|
};
|