Skip to content

feat(billing): generate invoices and manual payments #20

Description

@temps-code

Objective

Implement basic billing with invoices and manual payment tracking, including
invoice lifecycle management via soft delete and administrative purge with strict
financial integrity safeguards, and paginated list navigation with filtering and
search.

MVP Metadata

  • MVP Phase: Billing
  • Module: billing
  • Priority: Medium
  • Type: Feature
  • FR: FR-11, FR-12, FR-16
  • Branch Target: features

Problem

Invoices can accumulate in pending or void states without associated payments,
particularly during testing or abandoned billing flows. Administrators need a
controlled mechanism to archive and purge these stale records.

However, financial data integrity is non-negotiable: any invoice with a registered
payment — even partial — must be permanently protected from deletion at the service
layer, regardless of role. Soft delete is limited to void or zero-payment invoices,
and hard delete is blocked the moment any payment record exists.

Acceptance Criteria

  • Invoices can be listed and generated for guests, reservations, or stays in the active property.
  • Manual payments can be registered against invoices.
  • Invoice status supports pending, partial, paid, and void where relevant.
  • Payment registration updates invoice paid amount and status consistently.
  • Paid invoices are protected from unrestricted edits at service/backend level, not only UI.
  • Billing data remains scoped by property.
  • Empty/loading/error states are handled safely.

Soft Delete & Lifecycle

  • Void or zero-payment invoices can be soft-deleted (set deleted_at) to archive them. Active list only shows records where deleted_at IS NULL.
  • Soft delete requires manager or administrator role.
  • Soft delete is blocked at service layer if the invoice has any registered payment (total paid > 0), returning a descriptive error.
  • A confirmation modal is shown before soft delete.

Hard Delete (Purge — Administrator Only)

  • Administrators can permanently purge a soft-deleted invoice from the recycle bin.
  • Purge is blocked at service layer if the invoice has any payment record whatsoever (even partial), returning a descriptive error to protect financial audit integrity.
  • A strict irreversible-action warning dialog is shown before purging, explicitly stating this affects financial records.

Filtering, Search & Pagination

  • Invoice list can be filtered by status (pending, partial, paid, void).
  • Invoice list can be filtered by date range (invoice date or payment date).
  • Invoice list can be filtered by guest or reservation.
  • Invoice list supports text search by invoice ID or guest name.
  • Invoice list is paginated server-side. Default page size: 20 records.
  • Empty/loading/error states are handled safely for all filter/search combinations.

Evidence Expected

  • Link related commits and PRs.
  • Include screenshots for UI changes when applicable.
  • Include test/build evidence when implementation touches app/runtime code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions