Include austax account kinds in chart of accounts

This commit is contained in:
RunasSudo 2025-06-02 23:19:41 +10:00
parent 6ae2106a8a
commit 815b4843e2
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
12 changed files with 127 additions and 14 deletions

View File

@ -15,6 +15,8 @@
-- You should have received a copy of the GNU Affero General Public License
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
-- NB: Content of this file is also parsed by frontend src/plugins/austax/account_kinds.ts
-- Check the syntax is compatible with that parser!
local income_types = {
{'income1', 'Salary or wages', '1'},
{'income2', 'Allowances, earnings, tips, director\'s fees etc.', '2'},
@ -42,6 +44,8 @@ local income_types = {
{'income24', 'Other income', '24'},
}
-- NB: Content of this file is also parsed by frontend src/plugins/austax/account_kinds.ts
-- Check the syntax is compatible with that parser!
local deduction_types = {
{'d1', 'Work-related car expenses', 'D1'},
{'d2', 'Work-related travel expenses', 'D2'},

View File

@ -13,6 +13,7 @@
"@heroicons/vue": "^2.2.0",
"@tauri-apps/api": "^2.5.0",
"@tauri-apps/plugin-dialog": "~2.2.2",
"@tauri-apps/plugin-fs": "~2.3.0",
"@tauri-apps/plugin-shell": "^2.2.1",
"@tauri-apps/plugin-sql": "~2.2.0",
"@tauri-apps/plugin-store": "~2.2.0",

10
pnpm-lock.yaml generated
View File

@ -17,6 +17,9 @@ importers:
'@tauri-apps/plugin-dialog':
specifier: ~2.2.2
version: 2.2.2
'@tauri-apps/plugin-fs':
specifier: ~2.3.0
version: 2.3.0
'@tauri-apps/plugin-shell':
specifier: ^2.2.1
version: 2.2.1
@ -459,6 +462,9 @@ packages:
'@tauri-apps/plugin-dialog@2.2.2':
resolution: {integrity: sha512-Pm9qnXQq8ZVhAMFSEPwxvh+nWb2mk7LASVlNEHYaksHvcz8P6+ElR5U5dNL9Ofrm+uwhh1/gYKWswK8JJJAh6A==}
'@tauri-apps/plugin-fs@2.3.0':
resolution: {integrity: sha512-G9gEyYVUaaxhdRJBgQTTLmzAe0vtHYxYyN1oTQzU3zwvb8T+tVLcAqCdFMWHq0qGeGbmynI5whvYpcXo5LvZ1w==}
'@tauri-apps/plugin-shell@2.2.1':
resolution: {integrity: sha512-G1GFYyWe/KlCsymuLiNImUgC8zGY0tI0Y3p8JgBCWduR5IEXlIJS+JuG1qtveitwYXlfJrsExt3enhv5l2/yhA==}
@ -1305,6 +1311,10 @@ snapshots:
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/plugin-fs@2.3.0':
dependencies:
'@tauri-apps/api': 2.5.0
'@tauri-apps/plugin-shell@2.2.1':
dependencies:
'@tauri-apps/api': 2.5.0

1
src-tauri/Cargo.lock generated
View File

@ -804,6 +804,7 @@ dependencies = [
"tauri",
"tauri-build",
"tauri-plugin-dialog",
"tauri-plugin-fs",
"tauri-plugin-shell",
"tauri-plugin-sql",
"tauri-plugin-store",

View File

@ -26,6 +26,7 @@ serde_json = "1"
sqlx = { version = "0.8", features = ["json", "time"] }
tauri = { version = "2", features = [] }
tauri-plugin-dialog = "2"
tauri-plugin-fs = "2"
tauri-plugin-shell = "2"
tauri-plugin-sql = { version = "2", features = ["sqlite"] }
tauri-plugin-store = "2"

View File

@ -12,6 +12,9 @@
"core:window:allow-set-title",
"core:window:allow-show",
"dialog:default",
"fs:default",
"fs:allow-read-text-file",
"fs:allow-resource-read-recursive",
"shell:allow-open",
"sql:default",
"sql:allow-execute",

View File

@ -85,6 +85,7 @@ pub fn run() {
Ok(())
})
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_sql::Builder::new().build())
.plugin(tauri_plugin_store::Builder::new().build())

View File

@ -44,7 +44,7 @@ async function initApp() {
{ path: '/statement-lines/import', name: 'import-statement', component: () => import('./pages/ImportStatementView.vue') },
{ path: '/transactions/:account', name: 'transactions', component: () => import('./pages/TransactionsView.vue') },
{ path: '/trial-balance', name: 'trial-balance', component: () => import('./reports/TrialBalanceReport.vue') },
{ path: '/austax/tax-summary', name: 'tax-summary', component: () => import('./austax/TaxSummaryReport.vue') },
{ path: '/austax/tax-summary', name: 'tax-summary', component: () => import('./plugins/austax/TaxSummaryReport.vue') },
];
const router = createRouter({
history: createWebHistory(),

View File

@ -1,6 +1,6 @@
<!--
DrCr: Web-based double-entry bookkeeping framework
Copyright (C) 20222024 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,20 +57,21 @@
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { computed, ref } from 'vue';
import { accountKinds } from '../registry.ts';
import { drcrAccountKinds, getAccountKinds } from '../registry.ts';
import { db } from '../db.ts';
import DropdownBox from '../components/DropdownBox.vue';
const accountKindsMap = new Map(accountKinds);
const accountKindsByModule = [...Map.groupBy(accountKinds, (k) => k[0].split('.')[0]).entries()];
const accountKinds = ref([...drcrAccountKinds]);
const accountKindsMap = computed(() => new Map(accountKinds.value));
const accountKindsByModule = computed(() => [...Map.groupBy(accountKinds.value, (k) => k[0].split('.')[0]).entries()]);
const accounts = ref(new Map<string, string[]>());
const selectedAccounts = ref([]);
const selectedAccountKind = ref(accountKinds[0]);
const selectedAccountKind = ref(drcrAccountKinds[0]);
async function load() {
async function loadAccountConfigurations() {
const session = await db.load();
const accountKindsRaw: {account: string, kind: string | null}[] = await session.select(
@ -88,7 +89,12 @@
}
}
load();
async function loadAccountKinds() {
accountKinds.value = await getAccountKinds();
}
loadAccountConfigurations();
loadAccountKinds();
async function addAccountType() {
// Associate selected accounts with the selected account kind
@ -109,7 +115,7 @@
// Reload data
accounts.value.clear();
await load();
await loadAccountConfigurations();
}
async function removeAccountType() {
@ -131,6 +137,6 @@
// Reload data
accounts.value.clear();
await load();
await loadAccountConfigurations();
}
</script>

View File

@ -24,8 +24,8 @@
import { invoke } from '@tauri-apps/api/core';
import { ref } from 'vue';
import DynamicReportComponent from '../components/DynamicReportComponent.vue';
import { DynamicReport } from '../reports/base.ts';
import DynamicReportComponent from '../../components/DynamicReportComponent.vue';
import { DynamicReport } from '../../reports/base.ts';
const report = ref(null as DynamicReport | null);

View File

@ -0,0 +1,75 @@
/*
DrCr: Web-based double-entry bookkeeping framework
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { resolveResource } from '@tauri-apps/api/path';
import { readTextFile } from '@tauri-apps/plugin-fs';
// Dodgy implementation to parse Lua table as JSON
function parseLua(luaArray: string): any[] {
luaArray = luaArray.trim();
// Remove surrounding { and }
if (!luaArray.startsWith('{') || !luaArray.endsWith('}')) {
throw new Error('Unparseable Lua array');
}
luaArray = luaArray.substring(1, luaArray.length - 1).trim();
if (luaArray.endsWith(',')) {
// Remove trailing comma as this is invalid JSON
luaArray = luaArray.substring(0, luaArray.length - 1);
}
// Replace Lua {...} with JSON [...]
luaArray = luaArray.replaceAll('{', '[').replaceAll('}', ']');
// Replace single quotes with double quotes
luaArray = luaArray.replaceAll(/(?<!\\)'/g, '"');
luaArray = luaArray.replaceAll("\\'", "'");
return JSON.parse('[' + luaArray + ']');
}
export async function getAccountKinds(): Promise<[string, string][]> {
// Read contents of account_kinds.luau
const luaFilePath = await resolveResource('plugins/austax/account_kinds.luau');
const luaFileContent = await readTextFile(luaFilePath);
const accountKinds: [string, string][] = [];
// Parse income_types
const incomeTypesLua = luaFileContent.match(/local income_types = ({.*?\n})\n/s)![1];
const incomeTypes = parseLua(incomeTypesLua);
for (const [code, name, number] of incomeTypes) {
accountKinds.push(['austax.' + code, name + ' (' + number + ')']);
}
// Parse deduction_types
const deductionTypesLua = luaFileContent.match(/local deduction_types = ({.*?\n})\n/s)![1];
const deductionTypes = parseLua(deductionTypesLua);
for (const [code, name, number] of deductionTypes) {
accountKinds.push(['austax.' + code, name + ' (' + number + ')']);
}
// Hard-coded types
accountKinds.push(['austax.offset', 'Tax offset']);
accountKinds.push(['austax.paygw', 'PAYG withheld amounts']);
accountKinds.push(['austax.cgtasset', 'CGT asset']);
accountKinds.push(['austax.rfb', 'Reportable fringe benefit']);
return accountKinds;
}

View File

@ -16,10 +16,21 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export const accountKinds: [string, string][] = [
import * as austax from './plugins/austax/account_kinds.ts';
export const drcrAccountKinds: [string, string][] = [
['drcr.asset', 'Asset'],
['drcr.liability', 'Liability'],
['drcr.income', 'Income'],
['drcr.expense', 'Expense'],
['drcr.equity', 'Equity']
];
export async function getAccountKinds() {
const accountKinds = [...drcrAccountKinds];
// FIXME: Make this customisable
accountKinds.push(...await austax.getAccountKinds());
return accountKinds;
}