Serienvorlagen in Liquiditätsprognose einplanen
This commit is contained in:
@@ -16,7 +16,7 @@ import {
|
||||
} from "../../db/schema";
|
||||
import { secrets } from "./secrets";
|
||||
|
||||
type ForecastEventSource = "open_createddocument" | "open_incominginvoice" | "recurring_bankstatement" | "draft_createddocument" | "tax_settlement";
|
||||
type ForecastEventSource = "open_createddocument" | "open_incominginvoice" | "recurring_bankstatement" | "draft_createddocument" | "tax_settlement" | "serial_template";
|
||||
|
||||
type TaxEvaluationPeriod = "monthly" | "quarterly" | "yearly";
|
||||
|
||||
@@ -186,6 +186,15 @@ const addInterval = (date: dayjs.Dayjs, interval: RecurringCandidate["interval"]
|
||||
return date.add(1, "month");
|
||||
};
|
||||
|
||||
const addSerialInterval = (date: dayjs.Dayjs, interval: string) => {
|
||||
if (interval === "wöchentlich") return date.add(1, "week");
|
||||
if (interval === "2 - wöchentlich") return date.add(2, "week");
|
||||
if (interval === "vierteljährlich") return date.add(3, "month");
|
||||
if (interval === "halbjährlich") return date.add(6, "month");
|
||||
if (interval === "jährlich") return date.add(1, "year");
|
||||
return date.add(1, "month");
|
||||
};
|
||||
|
||||
const getStatementPartner = (statement: any) => {
|
||||
return statement.amount < 0
|
||||
? statement.credName || statement.debName || statement.text || "Regelmäßige Ausgabe"
|
||||
@@ -538,6 +547,58 @@ const buildTaxForecastPeriods = (
|
||||
return periods;
|
||||
};
|
||||
|
||||
const buildSerialTemplateEvents = (
|
||||
documents: any[],
|
||||
today: dayjs.Dayjs,
|
||||
endDate: dayjs.Dayjs
|
||||
) => {
|
||||
const events: ForecastEvent[] = [];
|
||||
|
||||
documents
|
||||
.filter((document) => document.type === "serialInvoices")
|
||||
.filter((document) => document.serialConfig?.active)
|
||||
.forEach((document) => {
|
||||
const firstExecution = dayjs(document.serialConfig?.firstExecution);
|
||||
const executionUntil = dayjs(document.serialConfig?.executionUntil);
|
||||
|
||||
if (!firstExecution.isValid() || !executionUntil.isValid()) return;
|
||||
|
||||
const amount = getCreatedDocumentGrossAmount(document, documents);
|
||||
if (amount <= 0.01) return;
|
||||
|
||||
let executionDate = firstExecution.startOf("day");
|
||||
let guard = 0;
|
||||
|
||||
while (executionDate.isBefore(today, "day") && guard < 240) {
|
||||
executionDate = addSerialInterval(executionDate, String(document.serialConfig?.intervall || ""));
|
||||
guard += 1;
|
||||
}
|
||||
|
||||
while (
|
||||
executionDate.isValid()
|
||||
&& !executionDate.isAfter(executionUntil, "day")
|
||||
&& !executionDate.isAfter(endDate, "day")
|
||||
&& guard < 400
|
||||
) {
|
||||
const dueDate = executionDate.add(Number(document.paymentDays || 0), "day");
|
||||
|
||||
events.push({
|
||||
date: dueDate.isBefore(today, "day") ? today.format("YYYY-MM-DD") : dueDate.format("YYYY-MM-DD"),
|
||||
amount,
|
||||
label: document.documentNumber || document.title || `Serienvorlage ${document.id}`,
|
||||
source: "serial_template",
|
||||
sourceId: document.id,
|
||||
confidence: 0.75,
|
||||
});
|
||||
|
||||
executionDate = addSerialInterval(executionDate, String(document.serialConfig?.intervall || ""));
|
||||
guard += 1;
|
||||
}
|
||||
});
|
||||
|
||||
return events.sort((a, b) => a.date.localeCompare(b.date));
|
||||
};
|
||||
|
||||
export const generateLiquidityForecast = async (
|
||||
server: FastifyInstance,
|
||||
tenantId: number,
|
||||
@@ -701,9 +762,11 @@ export const generateLiquidityForecast = async (
|
||||
sourceId: period.key,
|
||||
confidence: 0.95,
|
||||
}));
|
||||
const serialTemplateEvents = buildSerialTemplateEvents(activeDocuments, today, endDate);
|
||||
const events = [
|
||||
...openEvents,
|
||||
...taxEvents,
|
||||
...serialTemplateEvents,
|
||||
...expandRecurringEvents(recurring, endDate),
|
||||
].filter((event) => {
|
||||
const date = dayjs(event.date);
|
||||
|
||||
Reference in New Issue
Block a user