- Add taxDeductible boolean to expenses schema + migration 0002
- Update expenses router, form, and list to support tax-deductible flag
- Fix invoice-view tax calculation (was hardcoded $0.00; now uses taxRate)
- New Tax Summary tab in Reports: year selector, income/deductions breakdown,
SE tax + federal income estimates, quarterly bar chart
- CSV export for accountant with income + expense rows and tax summary
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
The previous baseline blindly recorded all migrations as applied.
Now on startup the script validates every recorded migration against
the actual schema; any entry whose schema changes don't exist is
deleted so migrate() will re-run that migration.
This unblocks the existing deployment where 0001 was recorded as done
but beenvoice_client.currency was never actually added.
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
Previously the baseline marked ALL migrations as done, causing 0001 to
be skipped even on databases that didn't have the currency column yet.
Now each migration is checked against a sentinel column/table before
being seeded into the tracking table. Migrations whose changes don't
exist yet are left out so migrate() runs them normally.
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
When switching from db:push to db:migrate on an existing database,
the migration table is empty so Drizzle tries to re-run all migrations,
failing with "relation already exists".
Detect this case (tables exist but no migration history) and seed the
__drizzle_migrations tracking table with all current migrations so
Drizzle treats them as already applied. Future migrations run normally.
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi
Migrations:
- drizzle.config.ts: add out: './drizzle' so drizzle-kit generate writes
SQL migration files instead of only supporting push
- drizzle/0000_glossy_magneto.sql: initial migration capturing all 9
current tables (users, accounts, sessions, verification_tokens,
sso_providers, clients, businesses, invoices, invoice_items)
- src/server/db/migrate.ts: programmatic runner using drizzle-orm's
migrate() — tracks applied migrations in __drizzle_migrations,
safe to run on every deploy
- package.json: db:migrate now runs the programmatic runner instead of
drizzle-kit migrate (CLI requires devDeps at runtime)
- start.sh: replace drizzle-kit push with bun src/server/db/migrate.ts
- Dockerfile: copy drizzle/ folder into the runner image so migrations
are available at container startup
Mobile fixes:
- data-table.tsx: pagination buttons grow from 32px to 40px on mobile
(h-10 w-10 md:h-8 md:w-8) to meet 44px touch-target guidelines
- floating-action-bar.tsx: stack left-content + action buttons to column
layout on narrow screens (flex-col sm:flex-row), reduce padding on
mobile (p-3 sm:p-4)
- revenue-chart.tsx: responsive chart height (h-48 md:h-64) so the chart
doesn't consume too much vertical space on small screens
https://claude.ai/code/session_012sqEgNQpx676isepeoX4Mi