Skip to content

feat(budget): enforce includes_vat NOT NULL, align VAT behavior across pricing modes#1385

Merged
steilerDev merged 2 commits intobetafrom
feat/vat-not-null-migration
Apr 29, 2026
Merged

feat(budget): enforce includes_vat NOT NULL, align VAT behavior across pricing modes#1385
steilerDev merged 2 commits intobetafrom
feat/vat-not-null-migration

Conversation

@steilerDev
Copy link
Copy Markdown
Owner

Summary

  • VAT behavior alignment: Direct pricing mode now applies the same 1.19× multiplier as unit pricing mode. plannedAmount is always stored as the gross (VAT-inclusive) amount regardless of which pricing mode was used.
  • NOT NULL migration: Migration 0031 backfills NULLtrue for includes_vat in both work_item_budgets and household_item_budgets, then recreates the tables with NOT NULL DEFAULT 1 at the schema level.
  • Type cleanup: BaseBudgetLine.includesVat changed from boolean | null to boolean throughout shared types, routes, and services.
  • Default form state: includesVat defaults to true in the budget line form for both Work Items and Household Items.

Test plan

  • Create a budget line in direct mode with "Price includes VAT" unchecked — stored amount should be input × 1.19
  • Create a budget line in direct mode with "Price includes VAT" checked — stored amount should equal input
  • Create a budget line in unit mode with VAT unchecked — stored amount should be qty × price × 1.19
  • Verify the form VAT checkbox defaults to checked (true) when adding a new budget line
  • Verify existing budget lines (pre-migration) with NULL includes_vat are migrated to true
  • Run npm test — all unit and integration tests should pass

🤖 Generated with Claude Code

Frank Steiler and others added 2 commits April 29, 2026 08:11
…s pricing modes

- Add migration 0031 to backfill NULL includes_vat → true and enforce NOT NULL at DB level
- Update Drizzle schema: includesVat is now .notNull().default(true) on both budget tables
- Change shared types: BaseBudgetLine.includesVat is now boolean (not boolean | null)
- Update JSON schemas in workItemBudgets and householdItemBudgets routes
- Fix service converters to use ?? true fallback instead of ?? null
- Align direct pricing mode with unit pricing: both modes now apply the VAT multiplier
  (1 or 1.19) before storing plannedAmount, so the stored value is always gross (VAT-inclusive)
- Default includesVat form state to true in both WorkItemDetailPage and HouseholdItemDetailPage
- Update all test fixtures to use includesVat: true (was null)

Fixes: direct pricing VAT behavior was inconsistent with unit pricing mode.

Co-Authored-By: Claude backend-developer (claude-haiku-4-5-20251001) <noreply@anthropic.com>
Co-Authored-By: Claude frontend-developer (claude-haiku-4-5-20251001) <noreply@anthropic.com>
Co-Authored-By: Claude qa-integration-tester (claude-sonnet-4-6) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion

Migration 0031 recreated work_item_budgets and household_item_budgets without
the original CHECK(planned_amount >= 0) and CHECK(confidence IN (...)) constraints,
causing tests that expect these constraints to be enforced to fail. Also switch
to explicit column lists in INSERT...SELECT to be safe for existing databases
where column order differs from the new table definition.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@steilerDev steilerDev merged commit 53a1d77 into beta Apr 29, 2026
32 checks passed
@steilerDev steilerDev deleted the feat/vat-not-null-migration branch April 29, 2026 07:56
@github-actions
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.5.0-beta.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant