Container CI, Money in cents, statement fixes, DB env vars #2

Merged
whysthatso merged 17 commits from development into main 2026-10-08 13:17:07 +00:00
Owner

Brings main up to date with everything merged into development since #1.

Changes

  • Container, CI and deployment — Ruby 4 Alpine image running puma on port 3000,
    everything synchronous (Active Job :inline, no Solid Queue/Cache/Cable, one
    production database), Woodpecker lint/test on every push, build and CapRover deploy
    on a tag.
  • Reminder deadline — reminder mails show the deadline and invoice date as full
    localised dates.
  • Statement vendor match — the bank statement review pre-selects the vendor that
    matches the booking name.
  • Money — amounts stored as Money in bigint cents, tax rates as percentages.
  • Schema headers — annotaterb headers in models, model tests and fixtures.
  • LHV statement layout — statements read by header name, upload encoding fixed,
    bill sign flipped for imported debits.
  • Production database from env — DB_HOST, DB_NAME, DB_USER, DB_PASS.

Before tagging a release

  • Set DB_HOST (Tailscale IP of fb), DB_NAME, DB_USER and DB_PASS in the
    CapRover app config; WHY_ACCOUNTING_DB_PASS_PROD is no longer read. The full
    checklist is documentation/user_manual/deployment.md.
  • The first start runs two data migrations (move_amounts_to_cents,
    store_tax_rates_as_percentages) through db:prepare. Take a database backup first.

🤖 Generated with Claude Code

Brings `main` up to date with everything merged into `development` since #1. ## Changes - **Container, CI and deployment** — Ruby 4 Alpine image running puma on port 3000, everything synchronous (Active Job `:inline`, no Solid Queue/Cache/Cable, one production database), Woodpecker lint/test on every push, build and CapRover deploy on a tag. - **Reminder deadline** — reminder mails show the deadline and invoice date as full localised dates. - **Statement vendor match** — the bank statement review pre-selects the vendor that matches the booking name. - **Money** — amounts stored as Money in `bigint` cents, tax rates as percentages. - **Schema headers** — annotaterb headers in models, model tests and fixtures. - **LHV statement layout** — statements read by header name, upload encoding fixed, bill sign flipped for imported debits. - **Production database from env** — `DB_HOST`, `DB_NAME`, `DB_USER`, `DB_PASS`. ## Before tagging a release - Set `DB_HOST` (Tailscale IP of `fb`), `DB_NAME`, `DB_USER` and `DB_PASS` in the CapRover app config; `WHY_ACCOUNTING_DB_PASS_PROD` is no longer read. The full checklist is `documentation/user_manual/deployment.md`. - The first start runs two data migrations (`move_amounts_to_cents`, `store_tax_rates_as_percentages`) through `db:prepare`. Take a database backup first. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- Gemfile declares ruby "~> 4"; lock re-resolved (bundler 4.1.0.beta2)
- Drop Solid Queue/Cache/Cable and thruster; Active Job runs :inline so
  Active Storage analyze/purge jobs run in the request; one production DB
- npm only: remove yarn.lock, bin/setup uses npm, pin @herb-tools/linter
- Dockerfile: npm ci, drop preview tools, no node_modules or test gems
  in the image; Rails 8 entrypoint; .dockerignore excludes mise.local.toml
- .woodpecker.yml: lint and test on every event (Postgres service "db"),
  build and deploy to CapRover app why-accounting on tag
- herb lint excludes Rails' generated public/*.html
- README, deployment manual, feature, history 02, project rules; resolves
  issue dockerfile-toolchain-drift-2026-10-07

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge FEATURE-container-ci-2026-10-08 into development
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
3e2b63966c
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Invoice#reminder_deadline returns Date.current one week ahead
- Reminder templates print it and the invoice date with
  l(date, format: :long) inside the invoice's locale
- en/de override date.formats.long with %-d so the day is not padded
- Drop the unused :month_and_year and :short_ordinal Date formats
- Mailer tests frozen on a single-digit day pin both languages and
  both parts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Plan archive, history 03, feature and user-manual updates
- Project rule for dates in mails
- Resolves issue reminder-deadline-format-2026-10-08; doc removed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Vendor.matching: equal name ignoring case, else the one contained name
- BankStatement loads vendors once; StatementEntry.from_booking sets
  vendor_id or new_vendor_name, so the view has no value: fallback and a
  422 re-render keeps a cleared "New vendor" empty
- statement-entry controller hides and disables "New vendor" while a
  vendor is chosen, so it is not submitted
- Review partial loads its select collections once, not per card
- System test for the toggle; Capybara.save_path set

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Plan archive, history 04, feature and user-manual updates
- CLAUDE.md and project rule for per-record form partials
- Resolves issue statement-review-vendor-toggle-2026-10-07; doc removed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- MoveAmountsToCents: every decimal(15,2) amount becomes a bigint
  *_cents column, converted exactly; NOT NULL on brutto, netto, amount
  and the invoice sums (default 0, NULL sums become 0); reversible
- StoreTaxRatesAsPercentages: taxes.rate (float multiplier) becomes
  taxes.percentage decimal(5,2); Tax#multiplier stays an exact BigDecimal
- money-rails configured for EUR, ROUND_HALF_UP and the :i18n backend;
  Bill, InvoiceElement and Invoice monetize their amounts; no .round(2)
- euros helper for every screen amount; the invoice and bill lists now
  print formatted amounts; PDF and mail output unchanged
- Seeds create taxes idempotently and fix "VAT 22%"
- Fixtures and tests in cents; rounding, parsing and form pins
- Read-only production diagnostic in documentation/helper_scripts

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Plan archive, history 05, new feature page money-amounts.md
- Feature and user-manual updates for Money, rounding and tax percentages
- CLAUDE.md and project rules: Money in cents, euros, forms under :en,
  annotaterb excludes
- Negative statement amounts issue moved to the cents columns
- New issue: statement-entry-bill-validation-2026-10-08
- Resolves issue money-rails-for-amounts-2026-10-07; doc removed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- annotaterb models against the current schema: the four money models
  had pre-migration headers (a round-trip rollback rewrote them), and
  model tests and fixtures get the headers .annotaterb.yml asks for
- Project rule and development manual: headers belong everywhere;
  migrate/rollback re-annotates from whichever database it ran on
- Plan archive and history 06

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LHV's 2026 export has 16 columns; the importer read positions 8 and 11 and
silently took the archiving code as amount and the register code as
description. Columns are now looked up by header name, a file missing one
is refused with BankStatement::InvalidFile, and the binary upload is forced
to UTF-8 with its BOM stripped (Vendor.matching raised on non-ASCII names).

A statement bill now stores the negated amount: debits become positive
bills, credits filed as bills become refunds. Existing bills are unchanged.
Bill entries also validate account and a numeric amount, so a bad card
returns 422 instead of a 500.

Fixture replaced by a redacted September 2026 export. Resolves issues
negative-statement-amounts and statement-entry-bill-validation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge FEATURE-statement-layout-2026-10-08 into development
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
69f205def4
Configure the production database through DB_* env vars
Some checks failed
ci/woodpecker/pull_request_closed/woodpecker Pipeline is pending
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was canceled
336038cb5b
Production reads DB_HOST, DB_NAME, DB_USER and DB_PASS instead of the
hard-coded db.whyservices.net, whyaccounting and WHY_ACCOUNTING_DB_PASS_PROD.
The shared default host is gone; development and test set their own.

The database now lives on the Tailscale machine fb, whose name need not
resolve inside the CapRover container, so the deployment manual sets
DB_HOST to its Tailscale IP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
whysthatso deleted branch development 2026-10-08 13:17:07 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
whyservices/accounting!2
No description provided.