All checks were successful
Deploy / build-deploy (push) Successful in 3m32s
The webhook is deregistered at bunq and the callback endpoint, its parser, default-deny classifier, dedup ledger and signature check are removed; the code is in git history if a bank feed ever comes back. /financials keeps reading the hand-maintained aggregates file, and sales + shop donations stay live from the order ledger. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
60 lines
3 KiB
C++
60 lines
3 KiB
C++
/*
|
|
catcrafts.net
|
|
Copyright (C) 2026 Catcrafts
|
|
|
|
The source code of this website is made available for viewing purposes only.
|
|
No permission is granted to copy, modify, distribute, or create derivative works.
|
|
*/
|
|
|
|
// The financials page over real HTTP. Liveness is the page's promise: the
|
|
// aggregates file appears (written by the owner's tooling — the retired bunq
|
|
// callback used to do this; see git history) and the very next request
|
|
// reflects it — no restart, no cache, no delay.
|
|
|
|
import std;
|
|
import Catcrafts.E2eHarness;
|
|
|
|
using namespace Catcrafts::E2e;
|
|
|
|
int main(int argc, char** argv) {
|
|
TestServer srv(argv[1], 8215);
|
|
|
|
// ── the financials page ───────────────────────────────────────────
|
|
// Aggregate-only by construction: totals and counts, machine-readable via
|
|
// the data-fin-* attributes. Live is the page's promise, so it must never
|
|
// sit in a shared cache.
|
|
srv.HeaderHas("/financials", "cache-control", "no-store", "financials are never cached");
|
|
srv.BodyHas("/financials", "data-fin-sales-count=\"0\"", "financials start at zero sales");
|
|
// Before the bank-aggregates file exists the page says so, and publishes
|
|
// no donation figures at all — an unknowable €0 would be a lie.
|
|
srv.BodyHas("/financials", "not been published yet", "unpublished bank figures say so");
|
|
srv.BodyLacks("/financials", "data-fin-donations-count",
|
|
"no donation figures before the file exists");
|
|
|
|
// The aggregates file appears, exactly as the owner's tooling writes it,
|
|
// and the very next request reflects it — this is the liveness the
|
|
// donation counter depends on.
|
|
WriteFile(std::filesystem::path(srv.Orders().string() + ".financials.json"),
|
|
R"({"as_of":"2026-08-14",)"
|
|
"\n"
|
|
R"( "donations":{"count":3,"total_minor":4500},)"
|
|
"\n"
|
|
R"( "expenses":[{"label":"Hosting","total_minor":1200},)"
|
|
"\n"
|
|
R"( {"label":"Inventory","total_minor":230000}]})"
|
|
"\n");
|
|
srv.BodyHas("/financials", "data-fin-donations-count=\"3\"", "donation count picked up live");
|
|
srv.BodyHas("/financials", "data-fin-expenses-minor=\"231200\"",
|
|
"expense total picked up live");
|
|
// Net = (donations 4500 + sales 0) - expenses 231200. Negative on
|
|
// purpose: a shop that has bought stock but not sold it is exactly this
|
|
// shape, and the figure has to survive going below zero.
|
|
srv.BodyHas("/financials", "data-fin-net-minor=\"-226700\"",
|
|
"net is published and may be negative");
|
|
srv.BodyHas("/financials", "€-2267", "a negative net renders with its sign");
|
|
srv.BodyHas("/financials", "Hosting", "an expense category renders");
|
|
srv.BodyHas("/financials", "Inventory", "a second expense category renders");
|
|
srv.BodyHas("/financials", "2026-08-14", "bank figures carry their as-of date");
|
|
|
|
return Finish();
|
|
}
|