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
|
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
|
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
|
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();
|
transactionsForStage: Map<ReportingStage, Transaction[]> = new Map();
|
||||||
reportsForStage: Map<ReportingStage, DrcrReport[]> = new Map();
|
reportsForStage: Map<ReportingStage, DrcrReport[]> = new Map();
|
||||||
|
|
||||||
async generate(session: ExtendedDatabase, dt?: string) {
|
async generate(session: ExtendedDatabase, dt?: string, dtStart?: string) {
|
||||||
// ------------------------
|
// ------------------------
|
||||||
// TransactionsFromDatabase
|
// TransactionsFromDatabase
|
||||||
|
|
||||||
@ -152,9 +152,23 @@ export class ReportingWorkflow {
|
|||||||
// AccumulatedSurplusToEquity
|
// AccumulatedSurplusToEquity
|
||||||
|
|
||||||
{
|
{
|
||||||
// Compute balances at end of last financial year
|
// Compute balances at period start for TransactionsFromDatabase
|
||||||
const last_eofy_date = dayjs(db.metadata.eofy_date).subtract(1, 'year');
|
let dayBeforePeriodStart;
|
||||||
const balancesLastEofy = await totalBalancesAtDate(session, last_eofy_date.format('YYYY-MM-DD'));
|
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
|
// Get income and expense accounts
|
||||||
const incomeAccounts = await getAccountsForKind(session, 'drcr.income');
|
const incomeAccounts = await getAccountsForKind(session, 'drcr.income');
|
||||||
@ -165,29 +179,29 @@ export class ReportingWorkflow {
|
|||||||
// Prepare transactions
|
// Prepare transactions
|
||||||
const transactions = [];
|
const transactions = [];
|
||||||
for (const account of pandlAccounts) {
|
for (const account of pandlAccounts) {
|
||||||
if (balancesLastEofy.has(account)) {
|
if (balancesAtPeriodStart.has(account)) {
|
||||||
const balanceLastEofy = balancesLastEofy.get(account)!;
|
const balanceAtPeriodStart = balancesAtPeriodStart.get(account)!;
|
||||||
if (balanceLastEofy === 0) {
|
if (balanceAtPeriodStart === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
transactions.push(new Transaction(
|
transactions.push(new Transaction(
|
||||||
null,
|
null,
|
||||||
last_eofy_date.format(DT_FORMAT),
|
dayBeforePeriodStart.format(DT_FORMAT),
|
||||||
'Accumulated surplus/deficit',
|
'Accumulated surplus/deficit',
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
id: null,
|
id: null,
|
||||||
description: null,
|
description: null,
|
||||||
account: account,
|
account: account,
|
||||||
quantity: -balanceLastEofy,
|
quantity: -balanceAtPeriodStart,
|
||||||
commodity: db.metadata.reporting_commodity
|
commodity: db.metadata.reporting_commodity
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: null,
|
id: null,
|
||||||
description: null,
|
description: null,
|
||||||
account: 'Accumulated surplus (deficit)',
|
account: 'Accumulated surplus (deficit)',
|
||||||
quantity: balanceLastEofy,
|
quantity: balanceAtPeriodStart,
|
||||||
commodity: db.metadata.reporting_commodity
|
commodity: db.metadata.reporting_commodity
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<!--
|
<!--
|
||||||
DrCr: Web-based double-entry bookkeeping framework
|
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
|
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
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
@ -57,25 +57,53 @@
|
|||||||
<!-- Report display -->
|
<!-- Report display -->
|
||||||
|
|
||||||
<template>
|
<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>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<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 { Computed, DynamicReport, Section, Spacer, Subtotal } from './base.ts';
|
||||||
import { db } from '../db.ts';
|
import { db } from '../db.ts';
|
||||||
|
import { ExtendedDatabase } from '../dbutil.ts';
|
||||||
import DynamicReportComponent from '../components/DynamicReportComponent.vue';
|
import DynamicReportComponent from '../components/DynamicReportComponent.vue';
|
||||||
import { ReportingStage, ReportingWorkflow } from '../reporting.ts';
|
import { ReportingStage, ReportingWorkflow } from '../reporting.ts';
|
||||||
|
|
||||||
const report = ref(null as IncomeStatementReport | null);
|
const report = ref(null as IncomeStatementReport | null);
|
||||||
|
|
||||||
|
const dt = ref(null as string | null);
|
||||||
|
const dtStart = ref(null as string | null);
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
const session = await db.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();
|
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;
|
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();
|
load();
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user