Versie 0.3.3

This commit is contained in:
Atreides Assets committed 2026-10-30 12:28:48 +01:00
1 parent 1cf6eeed29
commit 6e741a51fe
57 files changed
+1362 -2135

No files matched your search

+33 -4
View File
@@ -1,4 +1,4 @@
// Generated, do not edit. sha256:1c5123afde8b42e8b0c7944a90a9a3952b38ed44748eb715f09bb8aa35f593d5
// Generated, do not edit. sha256:a56d0789a1d23362a10302d4a28be7384372f8aa39766c83b8df92fa4456f11e
import { mkdir, readdir, rename, rm, readFile, writeFile, copyFile, stat } from 'node:fs/promises';
import { join, sep, resolve } from 'node:path';
@@ -6,7 +6,7 @@ import {
installDir, portfolioDir, archiveDir, assertValidName, sameName,
activeName, writeActiveName, listPortfolios,
} from './portfolios.mjs';
import { run } from './db/conn.mjs';
import { run, peekDatabase } from './db/conn.mjs';
import { createDatabase } from './db.js';
import { CONFIG } from '../shared/config.js';
import { fail } from '../shared/app-error.js';
@@ -45,7 +45,7 @@ export async function createPortfolio(naam, { kopieVan = null, baseCurrency = nu
if (kopieVan && baseCurrency) {
throw new Error('A copy keeps the unit of account of its source; do not pass baseCurrency with kopieVan.');
}
const max = capacityReached('portfolios', listPortfolios().length);
const max = capacityReached('portfolios', listPortfolios().filter(p => !p.demo).length);
if (max !== null) {
fail('portfolios.maxFree', { max },
`The free version holds ${max} portfolio(s). A licence lifts that; nothing is removed in the meantime.`);
@@ -155,11 +155,40 @@ export async function purgeArchived(naam) {
return { naam, map };
}
function keyFigures(naam) {
const pad = join(portfolioDir(naam), 'db.sqlite');
const perSoort = rijen => Object.fromEntries(rijen.map(r => [r.kind, r.n]));
try {
return peekDatabase(pad, ({ one, all }) => {
const backup = one(`SELECT value FROM Preference WHERE scope = 'app' AND key = 'last_backup_at'`);
const eerste = [
one(`SELECT MIN(occurredAt) AS d FROM Event WHERE type <> 'reservation'`).d,
one(`SELECT MIN(rateAt) AS d FROM Valuation WHERE accountId IS NOT NULL`).d,
].filter(Boolean).sort()[0] || null;
const portfolio = one(`SELECT baseCurrency, createdAt FROM Portfolio WHERE id = 1`);
return {
munt: portfolio?.baseCurrency ?? null,
aangemaakt: portfolio?.createdAt ?? null,
boekingen: one(`SELECT COUNT(*) AS n FROM Event WHERE type <> 'reservation'`).n,
balansen: one(`SELECT COUNT(*) AS n FROM Valuation`).n,
assets: perSoort(all(`SELECT kind, COUNT(*) AS n FROM Asset WHERE id IN (
SELECT assetId FROM Event WHERE type <> 'reservation' UNION SELECT assetId FROM Valuation)
GROUP BY kind`)),
accounts: perSoort(all(`SELECT kind, COUNT(*) AS n FROM Account WHERE isActive = 1 GROUP BY kind`)),
eersteJaar: eerste ? Number(eerste.slice(0, 4)) : null,
laatsteBackup: (backup && JSON.parse(backup.value)) || null,
};
});
} catch {
return null;
}
}
export async function overviewPortfolios() {
return {
actief: activeName(),
installatie: installDir(),
portefeuilles: listPortfolios(),
portefeuilles: listPortfolios().map(p => ({ ...p, kerncijfers: p.heeftDatabase ? keyFigures(p.naam) : null })),
archief: await listArchived(),
};
}