Compare commits

..

52 Commits

Author SHA1 Message Date
ed62e72e6a
Limit GenerateBalances builder to transactions in the requested period 2025-05-28 23:02:24 +10:00
763e27db03
[libdrcr] Fix misspecified statement_lines.db format 2025-05-28 23:02:21 +10:00
79a6eecfbd
Validate balance assertions in the background 2025-05-28 23:02:18 +10:00
3f580799c6
Synchronise amounts in transaction editor if only 2 postings 2025-05-28 23:02:14 +10:00
b3defb562f
Refresh journal/general ledger view when transaction updated 2025-05-28 23:02:10 +10:00
62b7981224 Add 'libdrcr/' from commit '0d680275df56300ff9059928f5611b9da2313b74'
git-subtree-dir: libdrcr
git-subtree-mainline: a40e2f81ba7f5d01ea3fbce037d47c1949d1b64d
git-subtree-split: 0d680275df56300ff9059928f5611b9da2313b74
2025-05-28 23:00:56 +10:00
0d680275df
Restore account links to dynamic reports 2025-05-28 00:33:54 +10:00
a40e2f81ba
Account transactions view using libdrcr 2025-05-28 00:26:12 +10:00
d326b3ae43
Implement getting balance assertions from database 2025-05-28 00:15:52 +10:00
4f1db12688
Implement getting transactions from database 2025-05-27 23:48:40 +10:00
00c7833706
Implement trial balance report 2025-05-27 22:19:36 +10:00
2a2fb5764c
Implement PostUnreconciledStatementLines 2025-05-27 17:54:48 +10:00
bb8383b222
Only calculate YTD figures in CurrentEarningsToEquity 2025-05-27 17:36:39 +10:00
e02b927b69
Fix Spacer being dropped when DynamicReport is calculated 2025-05-27 17:31:11 +10:00
280a2090d9
Execute reporting steps in parallel 2025-05-27 17:28:34 +10:00
aa5238917e
Fix UpdateBalancesBetween using incorrect period 2025-05-27 17:28:22 +10:00
0518163c3e
Sanity check reporting products 2025-05-27 16:16:15 +10:00
148390f030
Make reporting API async 2025-05-27 14:29:27 +10:00
b111e7023c
Cache database metadata 2025-05-27 00:53:26 +10:00
541467a2da
Implement IncomeStatement step 2025-05-27 00:21:30 +10:00
b8b2547aab
Refactor DynamicReport to use RefCell<DynamicReportEntry>
Allows calculations to refer to the results of previous calculations
Rather than the same cloned DynamicReport being passed to all calculations
2025-05-27 00:21:17 +10:00
eb3fbccc85
Add ids for total rows in balance sheet 2025-05-26 23:07:18 +10:00
f4c232ae35
Fix multiple logic errors when reporting for not current year 2025-05-26 22:43:59 +10:00
3cfcdf6778
Implement JSON serialisation for DynamicReport 2025-05-25 01:23:35 +10:00
33252739d9
Update documentation 2025-05-25 01:20:37 +10:00
3913558410
Remove unused dependency from Cargo.toml 2025-05-25 01:20:30 +10:00
737ed5bfb2
Implement formal BalanceSheet report 2025-05-24 21:07:18 +10:00
eb13bd5a87
CurrentYearEarningsToEquity depends on AllTransactionsExceptEarningsToEquity 2025-05-24 14:32:01 +10:00
004f749c33
Refactor steps_for_targets to accept Vec<ReportingProductId> 2025-05-24 01:01:03 +10:00
fd761934e0
Refactor build_step_for_product into standalone function
Prepare for changing steps_for_targets to take list of products.
2025-05-24 00:51:24 +10:00
a0c4aedb2d
Validate dynamic builder outputs 2025-05-24 00:43:40 +10:00
fa7381fce5
Add function to visualise dependency tree via graphviz 2025-05-24 00:40:27 +10:00
fa76461926
Implement CurrentYearEarningsToEquity 2025-05-24 00:10:37 +10:00
3add701d3c
Implement RetainedEarningsToEquity 2025-05-23 23:27:00 +10:00
ec470f8ced
Basic implementation of DBBalances 2025-05-28 22:57:07 +10:00
0eb583d028
Statically require single member for AllTransactionsExceptRetainedEarnings.product_kinds 2025-05-21 22:29:18 +10:00
1bed0f269e
Update documentation 2025-05-21 22:26:40 +10:00
98018bb4bc
Refactor update_balances_from_transactions 2025-05-21 21:53:35 +10:00
40b0afe492
Stub implementations for all steps 2025-05-21 21:48:57 +10:00
71c3629898
Refactor register_lookup_fns and register_dynamic_builders for readability 2025-05-21 20:22:06 +10:00
db89814498
Basic framework for executing reports 2025-05-21 20:15:18 +10:00
9e34360abf
Refactoring and documentation 2025-05-21 19:59:57 +10:00
d422e83275
Rename Dependency.dependency to Dependency.product 2025-05-21 19:18:14 +10:00
2d7250e943
Implement RetainedEarningsToEquity 2025-05-21 18:24:59 +10:00
959a8d8fb2
Fix off by one error in BalancesAtToBalancesBetween 2025-05-21 18:24:29 +10:00
ed0fbfb5dd
Refactor AllTransactionsIncludingRetainedEarnings 2025-05-21 18:20:19 +10:00
e47ad229eb
Refactor CalculateIncomeTax 2025-05-21 18:10:08 +10:00
d78d6ed1fe
Implement UpdateBalancesAt 2025-05-21 17:58:42 +10:00
b28c75c00f
Implement Display for ReportingStep 2025-05-21 17:16:25 +10:00
4add6292a1
Implement GenerateBalances dynamic builder 2025-05-21 17:11:20 +10:00
a7e9c74dd1
Refactor representation of ReportingStep args 2025-05-21 16:39:18 +10:00
f15d190112
Basic dependency resolution code 2025-05-21 00:33:00 +10:00
7 changed files with 59 additions and 12 deletions

Binary file not shown.

View File

@ -199,7 +199,7 @@ impl DbConnection {
).map(|r: SqliteRow| StatementLine {
id: Some(r.get("id")),
source_account: r.get("source_account"),
dt: NaiveDateTime::parse_from_str(r.get("dt"), "%Y-%m-%d").expect("Invalid statement_lines.dt"),
dt: NaiveDateTime::parse_from_str(r.get("dt"), "%Y-%m-%d %H:%M:%S.%6f").expect("Invalid statement_lines.dt"),
description: r.get("description"),
quantity: r.get("quantity"),
balance: r.get("balance"),

View File

@ -397,7 +397,12 @@ impl ReportingStep for GenerateBalances {
let mut balances = BalancesAt {
balances: HashMap::new(),
};
update_balances_from_transactions(&mut balances.balances, transactions.iter());
update_balances_from_transactions(
&mut balances.balances,
transactions
.iter()
.filter(|t| t.transaction.dt.date() <= self.args.date),
);
// Store result
let mut result = ReportingProducts::new();

View File

@ -1,6 +1,6 @@
<!--
DrCr: Web-based double-entry bookkeeping framework
Copyright (C) 20222025 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
@ -62,7 +62,7 @@
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<span class="text-gray-500">{{ db.metadata.reporting_commodity }}</span>
</div>
<input type="text" class="bordered-field pl-7" v-model="posting.amount_abs">
<input type="text" class="bordered-field pl-7" v-model="posting.amount_abs" @input="onAmountChange(posting)">
</div>
</td>
<td class="amount-cr py-1 pl-1"></td>
@ -74,7 +74,7 @@
<div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
<span class="text-gray-500">{{ db.metadata.reporting_commodity }}</span>
</div>
<input type="text" class="bordered-field pl-7" v-model="posting.amount_abs">
<input type="text" class="bordered-field pl-7" v-model="posting.amount_abs" @input="onAmountChange(posting)">
</div>
</td>
</template>
@ -312,4 +312,15 @@
await getCurrentWindow().close();
}
async function onAmountChange(posting: EditingPosting) {
// Synchronise the amounts if only two postings
if (transaction.postings.length == 2) {
for (const otherPosting of transaction.postings) {
if (otherPosting !== posting) {
otherPosting.amount_abs = posting.amount_abs;
}
}
}
}
</script>

View File

@ -48,8 +48,8 @@
<td class="py-0.5 px-1 text-gray-900 text-end">{{ pp(Math.abs(assertion.quantity)) }}</td>
<td class="py-0.5 pr-1 text-gray-900">{{ assertion.quantity >= 0 ? 'Dr' : 'Cr' }}</td>
<td class="py-0.5 px-1 text-gray-900">
<CheckIcon class="w-4 h-4" v-if="assertion.is_valid" />
<XMarkIcon class="w-4 h-4 text-red-500" v-if="!assertion.is_valid" />
<CheckIcon class="w-4 h-4" v-if="assertion.is_valid === true" />
<XMarkIcon class="w-4 h-4 text-red-500" v-if="assertion.is_valid === false" />
</td>
<td class="py-0.5 pl-1 text-gray-900 text-end">
<a :href="'/balance-assertions/edit/' + assertion.id" class="text-gray-500 hover:text-gray-700" onclick="return openLinkInNewWindow(this);">
@ -68,6 +68,7 @@
import { invoke } from '@tauri-apps/api/core';
import { ref } from 'vue';
import { db } from '../db.ts';
import { pp } from '../display.ts';
const balanceAssertions = ref([] as ValidatedBalanceAssertion[]);
@ -83,6 +84,15 @@
}
async function load() {
// Since validating the assertions takes a while, first load them from database
const session = await db.load();
balanceAssertions.value = await session.select(
`SELECT id, dt, description, account, quantity, commodity, NULL as is_valid
FROM balance_assertions
ORDER BY dt DESC, id DESC`
);
// Then validate them in the background
balanceAssertions.value = JSON.parse(await invoke('get_validated_balance_assertions'));
}

View File

@ -1,6 +1,6 @@
<!--
DrCr: Web-based double-entry bookkeeping framework
Copyright (C) 20222025 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
@ -63,6 +63,7 @@
import dayjs from 'dayjs';
import { PencilIcon, PlusIcon } from '@heroicons/vue/24/outline';
import { invoke } from '@tauri-apps/api/core';
import { UnlistenFn, listen } from '@tauri-apps/api/event';
import { onUnmounted, ref, watch } from 'vue';
import { Transaction } from '../db.ts';
@ -151,9 +152,20 @@
load();
// Refresh transaction list when transaction updated
let unlistenTransactionUpdated: UnlistenFn | null = null;
(async () => {
// Cannot await at top level without <Suspense> therefore do this in an async function
unlistenTransactionUpdated = await listen('transaction-updated', async (_event) => { await load(); });
})();
onUnmounted(() => {
if (clusterize !== null) {
clusterize.destroy();
}
if (unlistenTransactionUpdated !== null) {
unlistenTransactionUpdated();
}
});
</script>

View File

@ -1,6 +1,6 @@
<!--
DrCr: Web-based double-entry bookkeeping framework
Copyright (C) 20222025 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
@ -60,12 +60,10 @@
<script setup lang="ts">
import Clusterize from 'clusterize.js';
import dayjs from 'dayjs';
import { PencilIcon } from '@heroicons/vue/24/outline';
import { PlusIcon } from '@heroicons/vue/16/solid';
import { UnlistenFn, listen } from '@tauri-apps/api/event';
import { onUnmounted, ref, watch } from 'vue';
import { JoinedTransactionPosting, Transaction, db, joinedToTransactions } from '../db.ts';
@ -157,9 +155,20 @@
load();
// Refresh transaction list when transaction updated
let unlistenTransactionUpdated: UnlistenFn | null = null;
(async () => {
// Cannot await at top level without <Suspense> therefore do this in an async function
unlistenTransactionUpdated = await listen('transaction-updated', async (_event) => { await load(); });
})();
onUnmounted(() => {
if (clusterize !== null) {
clusterize.destroy();
}
if (unlistenTransactionUpdated !== null) {
unlistenTransactionUpdated();
}
});
</script>