9.4 KiB
title, type, status, date
| title | type | status | date |
|---|---|---|---|
| Complete Automatic Sales Summary Calculations and Ledger Posting | feat | completed | 2026-04-24 |
Complete Automatic Sales Summary Calculations and Ledger Posting
What's Incomplete
- Automatic Totals: Aggregate attributes (e.g.,
:sales-summary/total-card-payments) are not calculated/stored by the job. - Data Persistence: Automatic recalculations risk overwriting manual user adjustments.
- Automation Gap: Ledger entries are currently imported from external Excel files rather than generated automatically from the summaries.
- UI Polish: "Clientization" and HTMX context (
client-id) TODOs remain in the admin interface.
Overview
...
This plan completes the implementation of automatic sales summary calculations and ensures they are correctly posted to the ledger. Currently, the sales-summaries-v2 job calculates detailed daily summaries, but it doesn't store aggregate totals, preserve manual adjustments, or trigger the creation of actual ledger entries. Additionally, the admin UI has several unresolved TODOs.
Problem Frame
The system currently aggregates raw sales data into a sales-summary entity, but the final step—creating balanced journal entries for the general ledger—is a manual process involving external Excel calculations and subsequent imports. This creates a dependency on external tools and increases the risk of data entry errors. The goal is to automate this pipeline entirely within the product.
Requirements Trace
- R1. Calculate and store aggregate totals (e.g.,
:sales-summary/total-card-payments) on thesales-summaryentity. - R2. Preserve user-made manual adjustments (
:sales-summary-item/manual? true) during automatic recalculations. - R3. Aggregate detailed
sales-summary-items into balancedjournal-entrylines by account and location. - R4. Automate the posting of these aggregated totals to the ledger.
- R5. Resolve UI TODOs in the Sales Summaries admin page, specifically regarding client-scoping ("clientize") and HTMX context (
client-id).
Scope Boundaries
- In-Scope:
- Enhancements to the
sales-summaries-v2job. - Implementation of the summary-to-ledger aggregation and posting logic.
- Cleanup of the Sales Summaries admin UI.
- Enhancements to the
- Out-of-Scope:
- Changing the fundamental calculation logic for sales orders/refunds.
- Creating new ledger accounts (assume existing account mapping is sufficient).
- Changing the naming of refunds/returns (user requested to keep as is).
Context & Research
Relevant Code and Patterns
- Jobs:
src/clj/auto_ap/jobs/sales_summaries.cljcontains the main calculation logic. - UI:
src/clj/auto_ap/ssr/admin/sales_summaries.cljimplements the admin interface. - Ledger Posting:
src/clj/auto_ap/ledger.cljandiol_ion/src/iol_ion/tx/upsert_ledger.cljhandle journal entry creation. - Reconciliation Pattern:
reconcile-ledgerinsrc/clj/auto_ap/ledger.cljshows how to find missing ledger entries and trigger their creation.
Institutional Learnings
- No existing documented patterns for sales summary posting were found in
docs/solutions/. This implementation will establish the pattern.
Key Technical Decisions
- Detailed Summary
\toAggregated Ledger: Thesales-summarywill maintain granular detail (line items, specific fee types), but the ledger posting will aggregate these items by account and location to create balancedjournal-entrylines. - Automatic Posting: Posting to the ledger will be integrated into the reconciliation process, similar to how invoices and transactions are handled in
reconcile-ledger. - Location Handling: Since
sales-summary-items don't have a location, a default location for the client will be used for ledger posting.
Open Questions
Resolved During Planning
- Architectural Decision: Use a detailed summary that aggregates into the ledger.
- Renaming: Keep "Refunds/Returns" as is.
Deferred to Implementation
- Default Location Logic: Exactly how the "default location" for a client is retrieved or defined.
Implementation Units
- U1. Enhance
sales-summaries-v2Job
Goal: Ensure the job stores aggregate totals and preserves manual adjustments.
Requirements: R1, R2
Dependencies: None
Files:
- Modify:
src/clj/auto_ap/jobs/sales_summaries.clj
Approach:
- Update
sales-summaries-v2to calculate totals for attributes like:sales-summary/total-card-payments,:sales-summary/total-cash-payments, etc., based on the generated items. - Implement a merge strategy: when updating a summary, keep any items where
:sales-summary-item/manual?is true, and only replace the automatically calculated items.
Test scenarios:
- Happy path: Running the job for a client with sales and refunds results in a
sales-summarywith correct:sales-summary/total-*attributes. - Edge case: Running the job on a summary that already has a manual item ensures the manual item is not overwritten.
Verification:
- Datomic query shows
sales-summaryentities have populated total attributes and preserved manual items.
- U2. Implement Summary-to-Ledger Aggregation
Goal: Create a function to transform detailed summary items into balanced ledger lines.
Requirements: R3
Dependencies: U1
Files:
- Create:
src/clj/auto_ap/ledger/sales_summaries.clj(or add tosrc/clj/auto_ap/ledger.clj) - Test:
test/clj/auto_ap/ledger_test.clj
Approach:
- Create a function
aggregate-summary-itemsthat:- Groups
sales-summary-items by:ledger-mapped/account. - Sums the
:ledger-mapped/amountbased on:ledger-mapped/ledger-side(debit vs credit). - Assigns a location (default client location).
- Returns a list of
journal-entry-linemaps.
- Groups
Test scenarios:
- Happy path: A set of items with mixed accounts and sides aggregates into the correct number of ledger lines with summed amounts.
- Edge case: Items with
nilaccounts are handled gracefully (e.g., mapped to an "Unknown" account or logged as error).
Verification:
- Unit tests verify that a list of
sales-summary-items is correctly transformed intojournal-entry-lines.
- U3. Implement Automatic Ledger Posting for Summaries
Goal: Ensure sales summaries trigger the creation of ledger entries.
Requirements: R4
Dependencies: U2
Files:
- Modify:
src/clj/auto_ap/ledger.clj - Modify:
src/clj/auto_ap/jobs/sales_summaries.clj
Approach:
- Implement a
:upsert-sales-summary-ledgertransaction or function that takes asales-summaryand uses the aggregation logic from U2 to post to the ledger. - Integrate this into the
reconcile-ledgerfunction insrc/clj/auto_ap/ledger.cljto find summaries missing ledger entries and post them.
Test scenarios:
- Integration: Running
reconcile-ledgeridentifies asales-summarymissing ajournal-entryand creates a balancedjournal-entryfor it. - Happy path: The created
journal-entryhas the correct total amount and matches the summary totals.
Verification:
- A
sales-summaryentity is linked to ajournal-entryvia:journal-entry/original-entity.
- U4. Resolve UI TODOs in Sales Summaries Admin
Goal: Fix client-scoping and HTMX context in the admin UI.
Requirements: R5
Dependencies: None
Files:
- Modify:
src/clj/auto_ap/ssr/admin/sales_summaries.clj
Approach:
- Resolve "clientize" TODOs: Ensure the data pulled for the table and edit wizard is correctly scoped and transformed using client-specific context.
- Fix HTMX
client-idpassing: Update thenew-summary-itemtrigger to correctly pass theclient-idviahx-valsfrom the form state. - Clean up any remaining schema TODOs in the SSR file.
Test scenarios:
- Integration: Adding a new summary item in the UI correctly sends the
client-idand the item is created for the correct client. - Happy path: The summary table displays correctly and "missing account" warnings appear only for items without a mapped account.
Verification:
- Manual verification in the browser: New items are added correctly, and the UI is free of "missing account" red pills for mapped items.
System-Wide Impact
- Interaction graph: The
sales-summaries-v2job now feeds into the ledger system viareconcile-ledger. - Error propagation: Failures in the aggregation logic will prevent the
journal-entryfrom being created, which will be surfaced byreconcile-ledgeras a missing entry. - State lifecycle risks: Ensuring that
manual?items are not overwritten during automatic recalculation is critical to avoid losing user adjustments. - Integration coverage: Integration tests must cover the full flow:
sales-orders\tosales-summary\tojournal-entry.
Risks & Dependencies
| Risk | Mitigation |
|---|---|
| Overwriting manual adjustments | Implement explicit merge logic based on the :sales-summary-item/manual? flag. |
| Unbalanced ledger entries | Use a strict aggregation function that ensures debits = credits for every posted summary. |
| Missing location data | Implement a robust fallback to a default client location. |
Sources & References
- Related code:
src/clj/auto_ap/jobs/sales_summaries.clj - Related code:
src/clj/auto_ap/ssr/admin/sales_summaries.clj - Related code:
src/clj/auto_ap/ledger.clj - Related code:
iol_ion/src/iol_ion/tx/upsert_ledger.clj