@x47base/ch-finance-engine
Version:
This package is an finance and accounting engine specificly made based on the swiss system.
103 lines (89 loc) • 3.73 kB
JavaScript
const Engine = require("../models/engine");
const taskTemplates = [
{
description: "Ein Lieferant stellt die Lieferung von verschiedenen Küchengeräten über CHF {amount} (inkl. 7,7 % Mehrwertsteuer) in Rechnung.",
account1Type: "Aufwand",
account2Type: "Passiv",
accounts: {
account1: "Warenaufwand",
account2: "Verbindlichkeiten L+L",
account3: "Vorsteuer 1170"
},
generateValues: () => ({
amount: getRandomFloat(2000, 5000)
}),
generateBuchungen: (amount) => {
const nettoBetrag = Math.round(amount / 107.7 * 100 * 20) / 20;
const mwstBetrag = Math.round(amount / 107.7 * 7.7 * 20) / 20;
return [
{ account1: "Warenaufwand", account2: "Verbindlichkeiten L+L", amount: nettoBetrag },
{ account1: "Vorsteuer 1170", account2: "Verbindlichkeiten L+L", amount: mwstBetrag }
];
}
},
// Weitere Vorlagen können hier hinzugefügt werden
];
function getRandomFloat(min, max) {
return Math.round((Math.random() * (max - min) + min) * 20) / 20;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getAccountByName(engine, name) {
return engine.accounts.find(account => account.name === name);
}
function generateBuchungsaufgabe() {
const engine = new Engine("standard-config");
engine.loadTemplateAccounts();
const template = taskTemplates[getRandomInt(0, taskTemplates.length - 1)];
const values = template.generateValues();
const buchungen = template.generateBuchungen(values.amount);
const transactions = [];
buchungen.forEach(buchung => {
const account1 = getAccountByName(engine, buchung.account1);
const account2 = getAccountByName(engine, buchung.account2);
const txs = engine.performBuchung(
getRandomInt(1, 1000),
account1.code,
account2.code,
buchung.amount,
"CHF",
template.description.replace("{amount}", values.amount)
);
transactions.push(...txs);
});
if (!transactions || transactions.length === 0) {
throw new Error("No transactions were created.");
}
return {
task: {
description: template.description.replace("{amount}", values.amount),
account1: buchungen[0].account1,
account2: buchungen[0].account2,
amount: values.amount,
currency: "CHF"
},
solution: transactions.map(tx => tx.toJSON())
};
}
function verifySolution(userSolution, correctSolution) {
if (userSolution.length !== correctSolution.length) {
return { correct: false, message: "Die Anzahl der Buchungen stimmt nicht überein." };
}
for (let i = 0; i < userSolution.length; i++) {
const userTx = userSolution[i];
const correctTx = correctSolution[i];
if (
userTx.transactionSide !== correctTx.transactionSide ||
userTx.accountCode !== correctTx.accountCode ||
userTx.amount !== correctTx.amount ||
userTx.currency !== correctTx.currency ||
userTx.bookingType !== correctTx.bookingType ||
userTx.status !== correctTx.status
) {
return { correct: false, message: `Fehler in Buchung ${i + 1}: ${JSON.stringify(userTx)}` };
}
}
return { correct: true, message: "Alle Buchungen sind korrekt." };
}
module.exports = { generateBuchungsaufgabe, verifySolution };