Allow customising income report dates
This commit is contained in:
parent
064f50e668
commit
12f1c85a81
@ -1,6 +1,6 @@
|
||||
/*
|
||||
DrCr: Web-based double-entry bookkeeping framework
|
||||
Copyright (C) 2022–2024 Lee Yingtong Li (RunasSudo)
|
||||
Copyright (C) 2022–2025 Lee Yingtong Li (RunasSudo)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -56,7 +56,7 @@ export class ReportingWorkflow {
|
||||
transactionsForStage: Map<ReportingStage, Transaction[]> = new Map();
|
||||
reportsForStage: Map<ReportingStage, DrcrReport[]> = new Map();
|
||||
|
||||
async generate(session: ExtendedDatabase, dt?: string) {
|
||||
async generate(session: ExtendedDatabase, dt?: string, dtStart?: string) {
|
||||
// ------------------------
|
||||
// TransactionsFromDatabase
|
||||
|
||||
@ -152,9 +152,23 @@ export class ReportingWorkflow {
|
||||
// AccumulatedSurplusToEquity
|
||||
|
||||
{
|
||||
// Compute balances at end of last financial year
|
||||
const last_eofy_date = dayjs(db.metadata.eofy_date).subtract(1, 'year');
|
||||
const balancesLastEofy = await totalBalancesAtDate(session, last_eofy_date.format('YYYY-MM-DD'));
|
||||
// Compute balances at period start for TransactionsFromDatabase
|
||||
let dayBeforePeriodStart;
|
||||
if (dtStart) {
|
||||
dayBeforePeriodStart = dayjs(dtStart).subtract(1, 'day');
|
||||
} else {
|
||||
dayBeforePeriodStart = dayjs(db.metadata.eofy_date).subtract(1, 'year');
|
||||
}
|
||||
const balancesAtPeriodStart = await totalBalancesAtDate(session, dayBeforePeriodStart.format('YYYY-MM-DD'));
|
||||
|
||||
// Add balances at period start for OrdinaryAPITransactions
|
||||
for (const transaction of this.transactionsForStage.get(ReportingStage.OrdinaryAPITransactions)!) {
|
||||
if (!dayjs(transaction.dt).isAfter(dayBeforePeriodStart)) {
|
||||
for (const posting of transaction.postings) {
|
||||
balancesAtPeriodStart.set(posting.account, (balancesAtPeriodStart.get(posting.account) ?? 0) + asCost(posting.quantity, posting.commodity));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get income and expense accounts
|
||||
const incomeAccounts = await getAccountsForKind(session, 'drcr.income');
|
||||
@ -165,29 +179,29 @@ export class ReportingWorkflow {
|
||||
// Prepare transactions
|
||||
const transactions = [];
|
||||
for (const account of pandlAccounts) {
|
||||
if (balancesLastEofy.has(account)) {
|
||||
const balanceLastEofy = balancesLastEofy.get(account)!;
|
||||
if (balanceLastEofy === 0) {
|
||||
if (balancesAtPeriodStart.has(account)) {
|
||||
const balanceAtPeriodStart = balancesAtPeriodStart.get(account)!;
|
||||
if (balanceAtPeriodStart === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
transactions.push(new Transaction(
|
||||
null,
|
||||
last_eofy_date.format(DT_FORMAT),
|
||||
dayBeforePeriodStart.format(DT_FORMAT),
|
||||
'Accumulated surplus/deficit',
|
||||
[
|
||||
{
|
||||
id: null,
|
||||
description: null,
|
||||
account: account,
|
||||
quantity: -balanceLastEofy,
|
||||
quantity: -balanceAtPeriodStart,
|
||||
commodity: db.metadata.reporting_commodity
|
||||
},
|
||||
{
|
||||
id: null,
|
||||
description: null,
|
||||
account: 'Accumulated surplus (deficit)',
|
||||
quantity: balanceLastEofy,
|
||||
quantity: balanceAtPeriodStart,
|
||||
commodity: db.metadata.reporting_commodity
|
||||
},
|
||||
]
|
||||
|
@ -1,6 +1,6 @@
|
||||
<!--
|
||||
DrCr: Web-based double-entry bookkeeping framework
|
||||
Copyright (C) 2022–2024 Lee Yingtong Li (RunasSudo)
|
||||
Copyright (C) 2022–2025 Lee Yingtong Li (RunasSudo)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
@ -57,25 +57,53 @@
|
||||
<!-- Report display -->
|
||||
|
||||
<template>
|
||||
<DynamicReportComponent :report="report" />
|
||||
<DynamicReportComponent :report="report">
|
||||
<div class="my-2 py-2 flex">
|
||||
<div class="grow flex gap-x-2 items-baseline">
|
||||
<input type="date" class="bordered-field" v-model="dtStart">
|
||||
<span>to</span>
|
||||
<input type="date" class="bordered-field" v-model="dt">
|
||||
</div>
|
||||
</div>
|
||||
</DynamicReportComponent>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
import { Computed, DynamicReport, Section, Spacer, Subtotal } from './base.ts';
|
||||
import { db } from '../db.ts';
|
||||
import { ExtendedDatabase } from '../dbutil.ts';
|
||||
import DynamicReportComponent from '../components/DynamicReportComponent.vue';
|
||||
import { ReportingStage, ReportingWorkflow } from '../reporting.ts';
|
||||
|
||||
const report = ref(null as IncomeStatementReport | null);
|
||||
|
||||
const dt = ref(null as string | null);
|
||||
const dtStart = ref(null as string | null);
|
||||
|
||||
async function load() {
|
||||
const session = await db.load();
|
||||
|
||||
dt.value = db.metadata.eofy_date;
|
||||
dtStart.value = dayjs(db.metadata.eofy_date).subtract(1, 'year').add(1, 'day').format('YYYY-MM-DD');
|
||||
|
||||
await updateReport(session);
|
||||
}
|
||||
|
||||
async function updateReport(session: ExtendedDatabase) {
|
||||
const reportingWorkflow = new ReportingWorkflow();
|
||||
await reportingWorkflow.generate(session);
|
||||
await reportingWorkflow.generate(session, dt.value!, dtStart.value!);
|
||||
|
||||
report.value = reportingWorkflow.getReportAtStage(ReportingStage.InterimIncomeStatement, IncomeStatementReport) as IncomeStatementReport;
|
||||
}
|
||||
|
||||
// Update report when dates etc. changed
|
||||
watch([dt, dtStart], async () => {
|
||||
const session = await db.load();
|
||||
updateReport(session);
|
||||
});
|
||||
|
||||
load();
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user