Skip to content

F20: Basic expenses — categories + expense recording with monthly view (admin-only) #87

Closed

Description

@mforce

Phase 1.1 slice of spec §16 ("Expenses and Profitability") — the "basic expenses" cut named in tech spec §Phase 1.1. Money data → admin-only end to end per the agreed split (production data open to workers, money admin-only).

In scope

ExpenseCategory (farm-scoped, admin-managed — mirrors the egg-grade catalog pattern):

  • name (required, ≤100, case-insensitive unique per farm — precheck + expression index like grades), active flag
  • create / rename / deactivate-reactivate; deactivation hides it from new expenses, existing expenses keep it (grandfathered render, like deactivated grades on entries)

Expense:

  • farm, category (must be an active category of that farm at record time), date (not future), description (required, ≤200), amount in minor units (> 0), optional note (≤500)
  • currency code + minor unit copied from the account at creation (spec §7/§16) — expenses never re-denominate if the farm's currency changes later
  • optional flock link (direct allocation only; bird-count/revenue-share allocation is NOT in this slice)
  • Version concurrency token; admin edit with base-version 409 on mismatch (correction pattern per F16 water); no delete — corrections edit in place, audit log later
  • AGENTS.md race rule: parallel edit test with Version delta 1

API (/api/v1/expense-categories, /api/v1/expenses, all AdminOnly):

  • categories: POST / GET / rename / activate+deactivate (follow the grades endpoint shapes)
  • expenses: POST (idempotency-key), GET list (month or from/to + category filter, paged, newest first), GET by id, PUT/adjust with version
  • list response includes a period total (server-side sum — the SPA must not sum pages)

SPA (/expenses, nav + route admin-only, API enforces regardless):

  • month picker (default current month), category filter, running month total
  • add form: date (≤ today), category (active only), description, amount (farm currency), optional flock, optional note
  • edit inline (admin correction; version-based conflict banner reusing the History rebind pattern)
  • structurally boring per UI design revamp — distinctive visual identity #52

Docs (same PR): Help page section + "Who can do what" bullet; GLOSSARY entries (Expense, Expense category).

Out of scope (explicitly)

Allocation methods beyond direct-to-flock, receipt attachments, suppliers link, payment methods, profitability reports (those land with core reports), expense import.

Part of #14.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions