Skip to content

AR/AP Management Detail Reports — Customer / Vendor / Cash Requirements

Date: 2026-07-01

Problem / motivation

Peachtree exposes three "management detail" reports that answer what is owed to me and what I owe, right now: Customer Management Detail ("invoices that are due with customer credit and balance information"), Vendor Management Detail ("invoices that are due with vendor terms and balance information"), and Cash Requirements ("bills you need to pay as of a date you select, with aging"). We already surface aged receivables/payables as bucket summaries; these are the open-document detail behind them, as-of a chosen date. Closes three rows on the Peachtree Report Parity tracker.

In scope

  • customer_management_detail(as_of_date?, generate_csv) — every open customer invoice (due_amount > 0) as of the date, with client name, payment_terms, invoice/due dates, days overdue, and amount due.
  • vendor_management_detail(as_of_date?, generate_csv) — every open supplier invoice as of the date, vendor-centric (ordered by supplier then date), with due date and amount due.
  • cash_requirements(as_of_date?, generate_csv) — the same open supplier invoices ordered by due date (most urgent first): a "what to pay now" list.
  • as_of_date defaults to today (tenant-local). CSV export via generate_csv. Path.REPORTS.

Out of scope

  • Customer credit limit — not modeled today (Client has no credit_limit); we surface payment_terms + per-invoice amount_due instead. A follow-up can add a credit-limit column.
  • Early-payment discount in Cash Requirements — supplier invoices carry no term-discount field yet; aging (days overdue) is included, discount is deferred.
  • Grouped per-entity subtotals server-side (flat rows; the client groups/sums).

Data model changes

None. Reads invoices/invoice_balances/clients and supplier_invoices/supplier_invoice_balances/suppliers. "Open" = total_amount − paid_amount − canceled_amount > 0. Customer due date = invoice_date + payment_terms days; supplier due date = invoice_due_date (falls back to invoice_date). No migration, no new Path/Resource.

What's being implemented

  • Responsesapp/graphql/reports/strawberry/management_detail/management_detail_report_response.py (CustomerManagementDetailResponse, SupplierManagementDetailResponse).
  • Repositoryapp/graphql/reports/repositories/management_detail/management_detail_report_repository.py (open_customer_invoices, open_supplier_invoices).
  • Serviceapp/graphql/reports/services/management_detail/management_detail_report_service.py.
  • Queriesapp/graphql/reports/queries/management_detail/management_detail_report_queries.py.
  • Teststests/graphql/reports/test_management_detail_reports.py.

GraphQL surface

customerManagementDetail(asOfDate: Date, generateCsv: Boolean! = false): GenericReportPage!
vendorManagementDetail(asOfDate: Date, generateCsv: Boolean! = false): GenericReportPage!
cashRequirements(asOfDate: Date, generateCsv: Boolean! = false): GenericReportPage!

type CustomerManagementDetail {
  clientId: UUID!, clientName: String!, paymentTerms: PaymentTerms,
  reference: String!, invoiceDate: Date!, dueDate: Date!, daysOverdue: Int!,
  totalAmount: Decimal!, paidAmount: Decimal!, amountDue: Decimal!
}
type SupplierManagementDetail {
  supplierId: UUID!, supplierName: String!,
  reference: String!, invoiceDate: Date!, dueDate: Date!, daysOverdue: Int!,
  totalAmount: Decimal!, paidAmount: Decimal!, amountDue: Decimal!
}

Frontend contract

  • Three reports under Reports; optional asOfDate (defaults to today).
  • Customer/Vendor Management Detail: group rows by client/supplier, sum amountDue per group = the entity's outstanding balance; show paymentTerms/dueDate and daysOverdue.
  • Cash Requirements: render as a flat list already sorted by urgency (dueDate asc); daysOverdue > 0 means past due. generateCsv: true returns csvUrl.

Future additions

  • Customer credit limit + available-credit column once modeled on Client.
  • Term-discount column on Cash Requirements when supplier invoice terms carry an early-pay discount.