@fin.cx/skr
Version:
SKR03 and SKR04 German accounting standards for double-entry bookkeeping
263 lines • 18.7 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var Transaction_1;
import * as plugins from './plugins.js';
import { getDbSync } from './skr.database.js';
import { Account } from './skr.classes.account.js';
const { SmartDataDbDoc, svDb, unI, index, searchable } = plugins.smartdata;
let Transaction = Transaction_1 = class Transaction extends SmartDataDbDoc {
constructor(data) {
super();
if (data) {
this.id = plugins.smartunique.shortId();
this.transactionNumber = this.generateTransactionNumber();
this.date = data.date || new Date();
this.debitAccount = data.debitAccount || '';
this.creditAccount = data.creditAccount || '';
this.amount = data.amount || 0;
this.description = data.description || '';
this.reference = data.reference || '';
this.skrType = data.skrType || 'SKR03';
this.vatAmount = data.vatAmount || 0;
this.costCenter = data.costCenter || '';
this.status = 'pending';
this.reversalOf = '';
this.reversedBy = '';
// Set period and fiscal year
const transDate = new Date(this.date);
this.period = `${transDate.getFullYear()}-${String(transDate.getMonth() + 1).padStart(2, '0')}`;
this.fiscalYear = transDate.getFullYear();
this.createdAt = new Date();
this.postedAt = null;
this.createdBy = 'system';
}
}
generateTransactionNumber() {
const timestamp = Date.now();
const random = Math.floor(Math.random() * 1000);
return `TXN-${timestamp}-${random}`;
}
static async createTransaction(data) {
const transaction = new Transaction_1(data);
await transaction.validateAndPost();
return transaction;
}
static async getTransactionById(id) {
const transaction = await Transaction_1.getInstance({ id });
return transaction;
}
static async getTransactionsByAccount(accountNumber, skrType) {
const transactionsDebit = await Transaction_1.getInstances({
debitAccount: accountNumber,
skrType,
status: 'posted',
});
const transactionsCredit = await Transaction_1.getInstances({
creditAccount: accountNumber,
skrType,
status: 'posted',
});
const transactions = [...transactionsDebit, ...transactionsCredit];
return transactions;
}
static async getTransactionsByPeriod(period, skrType) {
const transactions = await Transaction_1.getInstances({
period,
skrType,
status: 'posted',
});
return transactions;
}
static async getTransactionsByDateRange(dateFrom, dateTo, skrType) {
const allTransactions = await Transaction_1.getInstances({
skrType,
status: 'posted',
});
const transactions = allTransactions.filter((t) => t.date >= dateFrom && t.date <= dateTo);
return transactions;
}
async validateAndPost() {
// Validate transaction
await this.validateTransaction();
// Update account balances
await this.updateAccountBalances();
// Mark as posted
this.status = 'posted';
this.postedAt = new Date();
await this.save();
}
async validateTransaction() {
// Check if accounts exist
const debitAccount = await Account.getAccountByNumber(this.debitAccount, this.skrType);
const creditAccount = await Account.getAccountByNumber(this.creditAccount, this.skrType);
if (!debitAccount) {
throw new Error(`Debit account ${this.debitAccount} not found for ${this.skrType}`);
}
if (!creditAccount) {
throw new Error(`Credit account ${this.creditAccount} not found for ${this.skrType}`);
}
// Check if accounts are active
if (!debitAccount.isActive) {
throw new Error(`Debit account ${this.debitAccount} is not active`);
}
if (!creditAccount.isActive) {
throw new Error(`Credit account ${this.creditAccount} is not active`);
}
// Validate amount
if (this.amount <= 0) {
throw new Error('Transaction amount must be greater than zero');
}
// Check for same account
if (this.debitAccount === this.creditAccount) {
throw new Error('Debit and credit accounts cannot be the same');
}
}
async updateAccountBalances() {
const debitAccount = await Account.getAccountByNumber(this.debitAccount, this.skrType);
const creditAccount = await Account.getAccountByNumber(this.creditAccount, this.skrType);
if (debitAccount) {
await debitAccount.updateBalance(this.amount, 0);
}
if (creditAccount) {
await creditAccount.updateBalance(0, this.amount);
}
}
async reverseTransaction() {
if (this.status !== 'posted') {
throw new Error('Can only reverse posted transactions');
}
if (this.reversedBy) {
throw new Error('Transaction has already been reversed');
}
// Create reversal transaction
const reversalData = {
date: new Date(),
debitAccount: this.creditAccount, // Swap accounts
creditAccount: this.debitAccount, // Swap accounts
amount: this.amount,
description: `Reversal of ${this.transactionNumber}: ${this.description}`,
reference: `REV-${this.transactionNumber}`,
skrType: this.skrType,
vatAmount: this.vatAmount,
costCenter: this.costCenter,
};
const reversalTransaction = new Transaction_1(reversalData);
reversalTransaction.reversalOf = this.id;
await reversalTransaction.validateAndPost();
// Update original transaction
this.reversedBy = reversalTransaction.id;
this.status = 'reversed';
await this.save();
return reversalTransaction;
}
async beforeSave() {
// Additional validation before saving
if (!this.debitAccount || !this.creditAccount) {
throw new Error('Both debit and credit accounts are required');
}
if (!this.date) {
throw new Error('Transaction date is required');
}
if (!this.description) {
throw new Error('Transaction description is required');
}
}
};
__decorate([
unI(),
__metadata("design:type", String)
], Transaction.prototype, "id", void 0);
__decorate([
svDb(),
index(),
__metadata("design:type", String)
], Transaction.prototype, "transactionNumber", void 0);
__decorate([
svDb(),
index(),
__metadata("design:type", Date)
], Transaction.prototype, "date", void 0);
__decorate([
svDb(),
index(),
__metadata("design:type", String)
], Transaction.prototype, "debitAccount", void 0);
__decorate([
svDb(),
index(),
__metadata("design:type", String)
], Transaction.prototype, "creditAccount", void 0);
__decorate([
svDb(),
__metadata("design:type", Number)
], Transaction.prototype, "amount", void 0);
__decorate([
svDb(),
searchable(),
__metadata("design:type", String)
], Transaction.prototype, "description", void 0);
__decorate([
svDb(),
index(),
__metadata("design:type", String)
], Transaction.prototype, "reference", void 0);
__decorate([
svDb(),
index(),
__metadata("design:type", String)
], Transaction.prototype, "skrType", void 0);
__decorate([
svDb(),
__metadata("design:type", Number)
], Transaction.prototype, "vatAmount", void 0);
__decorate([
svDb(),
__metadata("design:type", String)
], Transaction.prototype, "costCenter", void 0);
__decorate([
svDb(),
index(),
__metadata("design:type", String)
], Transaction.prototype, "status", void 0);
__decorate([
svDb(),
__metadata("design:type", String)
], Transaction.prototype, "reversalOf", void 0);
__decorate([
svDb(),
__metadata("design:type", String)
], Transaction.prototype, "reversedBy", void 0);
__decorate([
svDb(),
index(),
__metadata("design:type", String)
], Transaction.prototype, "period", void 0);
__decorate([
svDb(),
__metadata("design:type", Number)
], Transaction.prototype, "fiscalYear", void 0);
__decorate([
svDb(),
__metadata("design:type", Date)
], Transaction.prototype, "createdAt", void 0);
__decorate([
svDb(),
__metadata("design:type", Date)
], Transaction.prototype, "postedAt", void 0);
__decorate([
svDb(),
__metadata("design:type", String)
], Transaction.prototype, "createdBy", void 0);
Transaction = Transaction_1 = __decorate([
plugins.smartdata.Collection(() => getDbSync()),
__metadata("design:paramtypes", [Object])
], Transaction);
export { Transaction };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tyLmNsYXNzZXMudHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9za3IuY2xhc3Nlcy50cmFuc2FjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQU9uRCxNQUFNLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7QUFHcEUsSUFBTSxXQUFXLG1CQUFqQixNQUFNLFdBQVksU0FBUSxjQUF3QztJQW1FdkUsWUFBWSxJQUFnQztRQUMxQyxLQUFLLEVBQUUsQ0FBQztRQUVSLElBQUksSUFBSSxFQUFFLENBQUM7WUFDVCxJQUFJLENBQUMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDeEMsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1lBQzFELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3BDLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSxDQUFDLFlBQVksSUFBSSxFQUFFLENBQUM7WUFDNUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztZQUM5QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO1lBQy9CLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUM7WUFDMUMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJ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