Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ primary key - so a plain cascade only declares `filterBy` and a narrow-to-refere
auto-allocation settlement leave it empty; it exists to guide **manual** allocation (pick the
customer -> see only their payments -> amount pre-filled).

## Reports

Four management reports over the invoice data ([`sales-invoices.intent`](sales-invoices/sales-invoices.intent)
`reports:`), rendered by the generated Harmonia report pages (sidebar **Reports** + dashboard tiles):

| Report | Shows |
|---|---|
| `InvoicesByCustomer` | invoice count, revenue, paid and outstanding balance per customer |
| `InvoicesByStatus` | pipeline overview - count and value per status |
| `OverdueInvoices` | unpaid invoices past their due date (listing with a compound filter) |
| `SalesByProduct` | quantity sold and revenue per product |

`Customer` and `Product` are **cross-model dimensions**: the report joins the owning model's table
and shows the name instead of the raw FK id. Every report table offers **typed per-column filters**
(date ranges, number ranges, text contains) applied server-side - pagination, count and CSV export
all reflect them.

## One shared shell (no app-hopping)

Each domain project generates its own standalone app shell (handy for running or testing a single
Expand Down
26 changes: 26 additions & 0 deletions sales-invoices/sales-invoices.intent
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,32 @@ processes:
- { name: cancel, kind: serviceTask, args: { setRelationField: Status, value: 5, next: end } }
- { name: end, kind: end }

# Management reports over the invoice data. Dimensions may be plain fields, same-model relations
# (Status - shows the status name) or cross-model relations (Customer / Product - joined against the
# owning model's table, showing the name instead of the raw FK id). The generated report page offers
# typed per-column filters (date/number ranges, text contains) applied server-side.
reports:
- name: InvoicesByCustomer
source: SalesInvoice
description: Invoice count, revenue, paid and outstanding balance per customer
dimensions: [Customer]
measures: ["count(*)", "sum(total)", "sum(paid)", "sum(balance)"]
- name: InvoicesByStatus
source: SalesInvoice
description: Pipeline overview - invoice count and value per status
dimensions: [Status]
measures: ["count(*)", "sum(total)"]
- name: OverdueInvoices
source: SalesInvoice
description: Unpaid invoices past their due date
dimensions: [number, date, due, Customer, total, balance]
filter: "due <= CURRENT_DATE AND balance > 0"
- name: SalesByProduct
source: SalesInvoiceItem
description: Quantity sold and revenue per product
dimensions: [Product]
measures: ["sum(quantity)", "count(*)", "sum(total)"]

forms:
- { name: ApproveSalesInvoice, forEntity: SalesInvoice, fields: [number, date, due, Customer, total, Status], actions: [approve, reject] }
- { name: IssueSalesInvoice, forEntity: SalesInvoice, fields: [number, date, Customer, total, Status], actions: [issue] }
Expand Down