Skip to content

Accounting Jobs Workflow

1. Executive Summary

Purpose

The Accounting Jobs workflow is the mechanism by which all financial events in UTA Client Payments are converted into double-entry subledger transactions for transmission to the enterprise General Ledger (GL). Every significant financial event — revenue recognition, billing, cash receipts, cash applications, payouts, FX adjustments, client ledger entries, and period-end AR true-ups — produces a balanced pair of debit and credit entries in the transaction table. These transactions are never created directly by users; they are generated by batch jobs that scan for unposted source records and produce grouped batches. The workflow also provides an Accounting Jobs Dashboard where administrators can trigger these jobs for a selected effective date, monitor the most recent execution of each job type, and inspect the resulting transaction ledger through four aggregated and detail views.

Scope

Covered:

  • Running one or more batch accounting jobs against a selected effective date
  • Setting the current fiscal period as part of job execution
  • Viewing the last execution date for each job type on the dashboard
  • Searching and filtering subledger transactions by class, source, account, period, client, entity, department, batch, and date
  • Viewing transactions in four perspectives: Top Level crosstab (period × source × account), Client Level crosstab (period × source × client × rev ref × account), Rev Level crosstab (rev ref × account), and Transaction Detail flat list
  • Drilling down from a crosstab cell into the matching Transaction Detail rows
  • Reading job execution history from accounting_job_execution_history

Not covered (documented separately):

  • Revenue schedules — see the Billing Items workflow (billing-items.md) for how revenue items are created and scheduled
  • Billing items and billing item details — see the Billing Items workflow for how billing items are created and due dates are set
  • Cash receipts — see the Cash Receipts workflow (cash-receipts.md) for how receipts are posted and reach CR-eligible status
  • Worksheets and cash applications — see the Worksheets workflow (worksheets.md) for the Apply step that makes applications eligible for the APP job
  • Settlements and payouts — see the Settlements workflow for the bank confirmation step that makes payouts eligible for the PO job
  • GL transmission to the enterprise system — the transaction.gl_status_cd lifecycle is defined in the data model but the actual GL transmission adapter is not yet implemented in the PoC

Key Objectives

  • Provide a single, controlled point of entry for converting business events into balanced subledger journal entries
  • Ensure idempotency: jobs can be safely re-run for the same effective date because prior transactions for the same source and date range are deleted before new ones are inserted
  • Record an audit trail of every job execution (start time, end time, outcome, record counts) in accounting_job_execution_history
  • Give accounting staff a multi-dimensional view of the transaction ledger for reconciliation and period-end close work

2. Process Overview

mermaid
flowchart TD
    A[User opens Accounting Jobs Dashboard] --> B[Select effective date]
    B --> C[Select one or more job types]
    C --> D[Submit: Run Selected Jobs]
    D --> E[Set current fiscal period\nbased on effective date]
    E --> F{For each selected job}
    F --> G[REV: Revenue Recognition]
    F --> H[BILL: Billing Posting]
    F --> I[CR: Cash Receipt Posting]
    F --> J[APP: Cash Application Posting]
    F --> K[PO: Payout Posting]
    F --> L[TRUE: AR True-Up]
    F --> M[FX / CL: Not yet implemented]
    G --> N[Cleanup prior transactions\nfor this source/date]
    H --> N
    I --> N
    J --> N
    K --> N
    L --> N
    N --> O[Reset source record posting status]
    O --> P[Fetch eligible source records\nup to effective date]
    P --> Q[Compute posting date per record\nusing posting date formula]
    Q --> R[Generate debit/credit pairs\ngrouped by batch_id]
    R --> S[Batch insert into transaction table]
    S --> T[Mark source records as Posted]
    T --> U[Record execution in\naccounting_job_execution_history]
    U --> F
    F --> V[Return summary to dashboard]
    V --> W[Dashboard refreshes:\nlast execution dates updated]
    W --> X[User searches transactions\nusing filter panel]
    X --> Y{Select view tab}
    Y --> |Top Level| Z[Period × Source × Account crosstab]
    Y --> |Client Level| AA[Period × Source × Client × Rev Ref × Account crosstab]
    Y --> |Rev Level| AB[Rev Ref × Account crosstab]
    Y --> |Transaction Detail| AC[Flat transaction list]
    Z --> AD[Click cell to drill down\ninto Transaction Detail]
    AA --> AD
    AB --> AD

Walkthrough

  1. Select effective date — The user enters an effective date on the dashboard. This date controls which fiscal period becomes "current" and determines the upper boundary for eligible source records across all jobs.

  2. Select job types — The user checks one or more of the eight job type checkboxes: REV, BILL, CR, APP, PO, FX, TRUE, CL. Each checkbox shows the effective date of the last successful execution for that job type, allowing the user to see which jobs are stale.

  3. Submit — The user clicks "Run Selected Jobs." The system first sets the current fiscal period by finding the fiscal_period row whose date range contains the effective date, resetting all others to non-current.

  4. Jobs execute sequentially — Each selected job runs in order. A failure in one job is recorded but does not halt subsequent jobs. The common job pattern is: (a) delete prior transactions for the same source and date range, (b) reset source records to unposted, (c) fetch eligible records up to the effective date, (d) compute posting dates, (e) generate balanced debit/credit transaction pairs, (f) batch-insert transactions, (g) mark source records as posted.

  5. Execution history recorded — After each job completes (successfully or not), one row is inserted into accounting_job_execution_history with the job code, effective date, start and end timestamps, outcome status, and result summary (counts or error details).

  6. Dashboard refreshes — On success, the dashboard re-fetches the last execution dates so each job checkbox shows the newly updated effective date.

  7. Transaction search — Independently of job execution, the user can search the transaction ledger using a filter panel. All four dataset queries (enriched detail, top-level aggregation, rev-level aggregation, client-level aggregation) execute concurrently when the user clicks Search.

  8. Crosstab views — Three of the four tabs display transactions as dynamic crosstab grids with account names as column headers. Amounts in parentheses represent negative values. A pinned Total row at the top shows column sums.

  9. Drill-down — Clicking any non-zero, non-total cell in a crosstab tab switches the active tab to Transaction Detail and re-fetches the flat transaction list with the crosstab row's dimensional filters (period, source, account class, account number, client, rev ref) added on top of the existing global filters.


3. Business Rules

3.1 Effective Date Sets the Current Fiscal Period

Business rule: Before any job runs, the system identifies the fiscal period whose date range contains the selected effective date and marks it as the current period (fiscal_period.current_ind = true). All other periods are set to false. If no fiscal period covers the effective date, the job run fails with an error before any transactions are created.

Foundation reference: Set Current Period and Run Jobs Step 1

Workflow context: The dashboard displays the current period's reference string, start date, and end date in a summary block below the effective date field. This gives the user immediate confirmation of which period will be active before submitting. If the effective date changes, the current period display updates reactively.


3.2 Jobs Are Idempotent via Delete-Before-Insert

Business rule: Each job deletes all prior transaction rows for its source_cd and posting date range (on or after the effective date) before inserting new ones. This means a job can be safely re-run for the same effective date without producing duplicate transactions.

Foundation reference: Accounting Procedures — each job's Cleanup Step

Workflow context: The "Run Selected Jobs" button can be clicked multiple times for the same date without data corruption. Users should understand that re-running a job regenerates all transactions for that source from the effective date forward — it does not append to prior runs.


3.3 At Least One Job Must Be Selected

Business rule: The form cannot be submitted without selecting at least one job type. An effective date alone is not sufficient to trigger a run.

Foundation reference: Run Jobs input validation

Workflow context: The "Run Selected Jobs" button submits the form. If no job checkboxes are checked, the server action returns an error message: "At least one job must be selected." No fiscal period change occurs, and no history record is created.


3.4 Posting Date Logic

Business rule: Transactions do not necessarily post on the date their source record was created. If a source record's creation date is earlier than its business event date (the "driver date"), the transaction posts on the first day of the fiscal period containing the driver date. If the creation date is on or after the driver date, the transaction posts on the creation date. This prevents retroactive entries from landing in the wrong period.

Foundation reference: Posting Date Determination


3.5 Batches Must Balance (Net to Zero)

Business rule: All transaction rows sharing a batch_id must have their debit amounts equal their credit amounts (total nets to zero). Every accounting job produces exactly two transaction rows per source record: one debit and one credit. The batch ID groups these two rows together.

Foundation reference: Batch must net to zero validation and Batch ID Generation


3.6 REV Applications Post Immediately; PAY Payouts Post Only After Bank Confirmation

Business rule: Cash application transactions (APP job) are created as soon as a worksheet reaches Applied status, because REV money stays in UTA accounts. Payout transactions (PO job) are created only after the bank confirms the payment has been sent (payment_item.payment_execution_status_cd is ACKNOWLEDGED or PAID), because the money must physically leave the building before the GL entry is made.

Foundation reference: APP vs PO posting timing

IMPORTANT

This two-stage timing distinction is critical to the reversal model. A payment that was never sent never had a GL entry posted for it, so its reversal must not post to GL either. See the CLAUDE.md domain notes for the full explanation.


3.7 Jobs Execute Sequentially; Failures Are Isolated

Business rule: When multiple jobs are selected, they execute in sequence (not in parallel). A failure in one job is recorded in accounting_job_execution_history with status_cd = 'FAILED', but subsequent jobs in the same run continue to execute. The overall run does not abort on a single job failure.

Foundation reference: Run Jobs Step 2

Workflow context: The result summary displayed after a run lists each job's outcome (e.g., "REV: 42 processed, BILL: Failed (No eligible records), CR: 7 processed"). A toast notification indicates overall success or failure.


3.8 Only Active Accounts Receive New Postings

Business rule: Only account rows with account.status_cd = 'A' (Active) are valid targets for new transaction postings. Inactive accounts (status_cd = 'I') cannot receive new entries, though existing transactions referencing them are unaffected.

Foundation reference: Active-only posting


3.9 AR True-Up Job Requires REV and BILL Jobs to Have Run First

Business rule: The TRUE job computes adjustments by reading existing transaction rows for each distinct rev_ref in the current period. If neither REV nor BILL has run for the current period, the TRUE job will find no candidates and produce no transactions. The recommended execution order for a full period-end close is: REVBILLCRAPPPOTRUE.

Foundation reference: AR True-Up Job


3.10 Transaction Search Results Are Capped at 1,000 Rows

Business rule: The Transaction Detail tab returns at most 1,000 raw transaction rows per search. Aggregated crosstab views have no row limit because they group transactions before returning them.

Foundation reference: searchTransactionsEnriched

Workflow context: Users who need to view more than 1,000 transactions should narrow their filter criteria (e.g., restrict the period range or source code) to reduce result size.


4. Data Access & Operations References

4.1 Queries Used

OperationFoundation DocPurpose in This Workflow
getCurrentPeriodGet Current PeriodLoad current fiscal period on dashboard page entry to display period summary below the effective date field
getLastExecutionsGet Last ExecutionsLoad the most recent execution date for each job type to display next to each job checkbox
searchTransactionsEnrichedSearch Transactions EnrichedPower the Transaction Detail tab; returns up to 1,000 enriched rows with resolved account, client, department, and entity names
getAggregatedTransactionsGet Aggregated TransactionsPower the Top Level crosstab tab; groups transactions by period, source, and account
getRevLevelAggregatedTransactionsGet Rev Level Aggregated TransactionsPower the Client Level crosstab tab; groups transactions by period, source, client, rev ref, and account
getRevenueLevelAggregatedTransactionsGet Revenue Level Aggregated TransactionsPower the Rev Level crosstab tab; groups transactions by rev ref and account only
searchAccountsSearch AccountsDrive the Account autocomplete filter; returns up to 20 matching accounts by name or number
getAllPeriodsGet All PeriodsLoad all fiscal periods into memory at the start of each job for efficient in-memory date-to-period matching

4.2 Procedures Used

OperationFoundation DocTrigger in This Workflow
runJobsJob OrchestrationUser submits the Run Selected Jobs form with an effective date and one or more job types
setCurrentPeriodSet Current PeriodCalled automatically as Step 1 of every runJobs execution
runRevJobRevenue Recognition Job (REV)User selects REV checkbox and submits; dispatched by runJobs
runBillJobBilling Posting Job (BILL)User selects BILL checkbox and submits; dispatched by runJobs
runCashReceiptJobCash Receipt Posting Job (CR)User selects CR checkbox and submits; dispatched by runJobs
runCashReceiptApplicationJobCash Application Posting Job (APP)User selects APP checkbox and submits; dispatched by runJobs
runPayoutJobPayout Posting Job (PO)User selects PO checkbox and submits; dispatched by runJobs
runTrueUpJobAR True-Up Job (TRUE)User selects TRUE checkbox and submits; dispatched by runJobs
createJobExecutionCreate Job ExecutionCalled automatically after each job completes (success or failure) to write the history record

5. Key User Actions

5.1 Run Accounting Jobs

Preconditions:

  • At least one fiscal period must exist in fiscal_period that covers the selected effective date
  • At least one job type checkbox must be checked
  • The user must have IT role access (only IT may execute accounting jobs — see Section 6)

Procedure reference: Job Orchestration

Steps:

  1. User enters an effective date in the date field. The current fiscal period summary updates to show the period that would become current.
  2. User checks one or more job type checkboxes. Each checkbox optionally shows the effective date of its last successful run.
  3. User clicks "Run Selected Jobs." The button label changes to "Processing Jobs..." and becomes disabled while the run is in progress.
  4. The system sets the current fiscal period, then executes each selected job sequentially per the procedures referenced above.
  5. On completion, the dashboard displays a summary message listing each job's outcome and record counts.

Postconditions:

  • fiscal_period.current_ind = true on the period matching the effective date; all other periods have current_ind = false
  • One accounting_job_execution_history row inserted per dispatched job, with status_cd of SUCCESS or FAILED
  • For each successfully run job: new balanced transaction rows inserted with gl_status_cd = 'U'; prior transactions for the same source/date range deleted; source records updated to posted status
  • The "last run" date next to each executed job checkbox updates to the effective date

UI trigger: "Run Selected Jobs" button in the Run Accounting Jobs panel. Enabled when at least one job checkbox is checked. Disabled while the form is submitting.


5.2 Search Transactions

Preconditions:

  • The Transaction section is always visible on the Accounting Jobs Dashboard
  • No jobs need to have run first — the search panel queries existing transactions

Procedure reference: searchTransactionsEnriched, getAggregatedTransactions, getRevLevelAggregatedTransactions, getRevenueLevelAggregatedTransactions

Steps:

  1. User sets one or more filter values in the filter panel (see Section 8 for filter fields).
  2. User clicks the "Search" button or presses Enter.
  3. All four dataset queries execute concurrently: enriched transaction list, top-level aggregation, client-level aggregation, and revenue-level aggregation.
  4. Results populate all four tabs simultaneously. The currently active tab updates first.

Postconditions:

  • transactions state updated with up to 1,000 enriched transaction rows matching the filters
  • aggregatedTransactions, revLevelTransactions, and clientLevelTransactions states updated with aggregated rows

UI trigger: "Search" button in the Transactions section filter panel. Enabled at all times. Also triggered by pressing Enter while focus is in any filter field.


5.3 Drill Down from Crosstab to Transaction Detail

Preconditions:

  • A Search has been performed and crosstab data is populated
  • The user is viewing the Top Level, Client Level, or Rev Level tab
  • The target cell must be non-zero and must not be the Total row

Procedure reference: searchTransactionsEnriched

Steps:

  1. User clicks an amount cell in the Top Level, Client Level, or Rev Level crosstab.
  2. The dashboard automatically switches to the Transaction Detail tab.
  3. A new enriched transaction search executes with the crosstab row's dimensional filters (period ref, source code, account class, account number, and optionally client name or rev ref) merged with any existing global filter values.
  4. Drill-down active filters appear as removable badge chips above the tab list.

Postconditions:

  • activeTab state set to 'transactions'
  • activeDrillDownFilters state set to the dimensional filters from the clicked cell
  • transactions state updated with the matching enriched transaction rows

UI trigger: Clicking any non-zero, non-total amount cell in the Top Level, Client Level, or Rev Level crosstab. Each clickable cell renders as a button with hover underline styling.


5.4 Clear Drill-Down Filters

Preconditions:

  • Active drill-down filters are present (the user has previously drilled down from a crosstab cell)

Procedure reference: searchTransactionsEnriched

Steps:

  1. User clicks "Clear All" to remove all drill-down filters at once, or clicks the "×" on an individual filter badge to remove that single filter dimension.
  2. The Transaction Detail tab re-fetches using only the remaining global filters (no drill-down context).

Postconditions:

  • activeDrillDownFilters state cleared (null) or reduced by the removed key
  • transactions state updated with results using only global filters

UI trigger: "Clear All" button visible next to drill-down badge chips when activeDrillDownFilters is non-null. Individual "×" buttons on each badge chip.


6. Permissions & Role-Based Access

ActionCASH_MANAGERCASH_PROCESSORSETTLEMENT_APPROVERIT
Run accounting jobs (submit the jobs form)Yes
View Accounting Jobs DashboardYes
Search and view transactionsYes
View job execution history (last run dates)Yes

Field-level restrictions:

  • The Accounting Jobs Dashboard and all accounting job operations are restricted to the IT role. No other role can access this screen or trigger batch job execution.
  • In the PoC, role enforcement is not fully implemented at the server action layer for this feature. The production system must enforce IT-only access on the runAccountingJobsAction server action and on the page route.

**PoC Artifact:**

The PoC does not enforce role-based access control on the Accounting Jobs Dashboard page or the runAccountingJobsAction server action. Any authenticated user can access the dashboard and trigger jobs. The production system must add IT-only authorization before shipping.


7. Integration Points

7.1 Upstream

SourceData ProvidedMechanism
Revenue schedules workflowrevenue_item_schedule rows with revenue_item_posting_status_cd = 'U' and revenue_dt <= effective_date — inputs to the REV jobFK reference: transaction.source_idrevenue_item_schedule.revenue_item_schedule_id
Billing items workflowbilling_item_detail rows with posting_status_cd = 'U' and parent billing_item.billing_item_due_dt <= effective_date — inputs to the BILL jobFK reference: transaction.source_idbilling_item_detail.billing_item_detail_id
Cash receipts workflowcash_receipt rows with posting_status_cd = 'U' — inputs to the CR jobFK reference: transaction.source_idcash_receipt.cash_receipt_id
Worksheets workflowcash_receipt_application rows with billing_item_detail_type_cd = 'REV' from worksheets at Applied (P) or Returned (R) status — inputs to the APP jobFK reference: transaction.source_idcash_receipt_application.cash_receipt_application_id
Worksheets workflowcash_receipt_client_ledger rows from Applied worksheets — inputs to the CL jobFK reference: transaction.source_idcash_receipt_client_ledger.cash_receipt_client_ledger_id
Settlements / Payments workflowpayment_item rows with payment_execution_status_cd IN (ACKNOWLEDGED, PAID) — inputs to the PO jobFK reference: transaction.source_idpayment_item.payment_item_id
Transaction table (self)Existing transaction rows with matching rev_ref — used by the TRUE job to compute Deferred/Unbilled balances for AR true-upAggregated by transaction.rev_ref and account.account_class

7.2 Downstream

ConsumerData ConsumedMechanism
Enterprise GL systemtransaction rows with gl_status_cd = 'U' — awaiting transmissionGL posting batch reads unposted transactions; sets gl_status_cd = 'P' and gl_posting_dt on success
AR Aging reporttransaction rows — particularly BILL-sourced AR entries and APP-sourced applicationsDirect query of transaction table filtered by source_cd and class_cd

7.3 External Integrations

No external integrations for this workflow. The Accounting Jobs Dashboard is an internal operational tool. GL transmission to the enterprise system is a downstream process triggered separately outside this workflow.


8. Functional Screen Requirements

8.1 Accounting Jobs Dashboard

Route: /accounting/accounting-jobs

Data loading:

  • getCurrentFiscalPeriodAction — loads the current fiscal period on mount to display the period summary; see Get Current Period
  • getLastJobExecutionsAction — loads one execution summary row per job type to display last-run dates next to each checkbox; see Get Last Executions
  • searchUtaEntitiesAction — loads UTA entity options for the Entity multi-select filter in the Transactions section

Run Accounting Jobs Panel

Displays a form for selecting an effective date and one or more batch job types to execute.

Field / ColumnSourceEditable?Condition
Effective DateUser input; defaults to today's dateYesAlways visible
Current period summary (Period ref, Start, End)fiscal_period.period_ref, fiscal_period.period_start_dt, fiscal_period.period_end_dtNoVisible when a fiscal period exists for the effective date
REV — Revenue Job checkboxStatic job definition; last run date from accounting_job_execution_history.effective_dtYesAlways visible
BILL — Billing Job checkboxStatic job definition; last run date from accounting_job_execution_history.effective_dtYesAlways visible
CR — Cash Receipt checkboxStatic job definition; last run date from accounting_job_execution_history.effective_dtYesAlways visible
APP — Cash Application checkboxStatic job definition; last run date from accounting_job_execution_history.effective_dtYesAlways visible
PO — Payouts checkboxStatic job definition; last run date from accounting_job_execution_history.effective_dtYesAlways visible
FX — FX Adjustment checkboxStatic job definition; last run date from accounting_job_execution_history.effective_dtYesAlways visible
TRUE — AR True-Up checkboxStatic job definition; last run date from accounting_job_execution_history.effective_dtYesAlways visible
CL — Client Ledger Job checkboxStatic job definition; last run date from accounting_job_execution_history.effective_dtYesAlways visible
Last Job Status messageaccounting_job_execution_history.result_summary (rendered after submit)NoVisible after a run has completed in this session

Conditional display:

  • Current period summary block visible only when the effective date maps to an existing fiscal_period row
  • "Processing Jobs..." label and disabled state on the Run button while the form submission is in flight
  • Last Job Status block visible only after the form has been submitted at least once in the current session
  • Each job checkbox shows a parenthetical last-run date (formatted as local date) when accounting_job_execution_history has a record for that job_cd

Transactions Filter Panel

Provides filter controls that drive all four transaction view tabs simultaneously.

Field / ColumnSourceEditable?Condition
Class Cd (multi-select)Options: REV, AR, CASH, TAX, FX — matches transaction.class_cdYesAlways visible
Source Cd (multi-select)Options: REV, BILL, CR, APP, PO, FX, TRUE, CL — matches transaction.source_cdYesAlways visible
Parent RefFree text — case-insensitive substring match on transaction.rev_refYesAlways visible
Source RefFree text — case-insensitive substring match on transaction.source_refYesAlways visible
AccountAutocomplete — resolves to transaction.account_id; searches account.account_full_name and account.account_numberYesAlways visible
Posting FromDate input — lower bound on transaction.posting_dt (inclusive)YesAlways visible
Posting ToDate input — upper bound on transaction.posting_dt (inclusive)YesAlways visible
ClientClient search autocomplete — resolves to transaction.client_idYesAlways visible
Entity (multi-select)Loaded from uta_entity — matches transaction.uta_entity_idYesAlways visible
DeptDepartment autocomplete — resolves to transaction.department_idYesAlways visible
Period Ref FromFree text in YYYY-MM format — lower bound on transaction.posting_period_ref (inclusive)YesAlways visible
Period Ref ToFree text in YYYY-MM format — upper bound on transaction.posting_period_ref (inclusive)YesAlways visible
Batch IDFree text — case-insensitive substring match on transaction.batch_idYesAlways visible
Search buttonAlways visible

Grid features:

  • No grid in the filter panel itself — it drives the tab grids below
  • Pressing Enter while focused in any filter field triggers the Search action

Conditional display:

  • All filters are always visible; none are conditionally shown or hidden
  • The Search button shows "Searching..." and is disabled while queries are in flight

Top Level Crosstab Tab

Displays transactions aggregated by fiscal period and source job, with one dynamic column per unique account class-number combination found in the result set.

Field / ColumnSourceEditable?Condition
Fiscal Periodfiscal_period.period_ref (via transaction.posting_period_id)NoAlways visible
Sourcetransaction.source_cdNoAlways visible
[Account Class]-[Account Number] (dynamic, one column per unique account)SUM(transaction.trans_amt) grouped by period, source, account.account_class, account.account_numberNoColumn appears when at least one matching transaction exists for that account
Total rowSum of all rows per account columnNoPinned at the top of the grid

Grid features:

  • Sortable columns: Fiscal Period, Source, all account columns
  • Filters: None (global filters applied via the filter panel above)
  • Row selection: None
  • Pagination: Yes
  • Column ordering: User can reorder columns
  • Amounts displayed with currency formatting; negative amounts shown in parentheses (e.g., ($1,234.56))

Conditional display:

  • Amount cells in the Total row are not clickable (not drill-down targets)
  • Amount cells with value 0 are not clickable
  • Non-zero, non-total amount cells are clickable drill-down triggers that switch to the Transaction Detail tab

Client Level Crosstab Tab

Displays transactions aggregated at the most granular level: fiscal period, source job, client name, and revenue reference, with one dynamic column per unique account.

Field / ColumnSourceEditable?Condition
Fiscal Periodfiscal_period.period_refNoAlways visible
Sourcetransaction.source_cdNoAlways visible
Clientparty.display_name (via transaction.client_id)NoAlways visible
Rev Reftransaction.rev_refNoAlways visible
[Account Class]-[Account Number] (dynamic)SUM(transaction.trans_amt) grouped by period, source, client, rev ref, and accountNoColumn appears when at least one matching transaction exists
Total rowSum of all rows per account columnNoPinned at the top of the grid

Grid features:

  • Sortable columns: Fiscal Period, Source, Client, Rev Ref, all account columns
  • Filters: None (global filters applied via filter panel)
  • Row selection: None
  • Pagination: Yes
  • Column ordering: User can reorder columns

Conditional display:

  • Same clickable cell behavior as Top Level: Total row and zero-value cells are not drill-down targets; all others are

Rev Level Crosstab Tab

Displays transactions aggregated by revenue reference only, with one dynamic column per unique account. Useful for tracing all postings against a specific deal or revenue item across all periods.

Field / ColumnSourceEditable?Condition
Rev Reftransaction.rev_refNoAlways visible
[Account Class]-[Account Number] (dynamic)SUM(transaction.trans_amt) grouped by rev ref and accountNoColumn appears when at least one matching transaction exists
Total rowSum of all rows per account columnNoPinned at the top of the grid

Grid features:

  • Sortable columns: Rev Ref, all account columns
  • Filters: None (global filters applied via filter panel)
  • Row selection: None
  • Pagination: Yes
  • Column ordering: User can reorder columns

Conditional display:

  • Same clickable cell behavior as Top Level

Transaction Detail Tab

Displays the raw enriched transaction list, one row per transaction record, up to 1,000 rows.

Field / ColumnSourceEditable?Condition
IDtransaction.transaction_idNoAlways visible
Posting Datetransaction.posting_dtNoAlways visible
Ref Datetransaction.transaction_ref_dtNoAlways visible
Classtransaction.class_cdNoAlways visible
Sourcetransaction.source_cdNoAlways visible
Rev Reftransaction.rev_refNoAlways visible; rendered as a hyperlink to /revenue?salesItemRef=[value] when non-null
Reftransaction.source_refNoAlways visible; for BILL and APP source codes, the link resolves using transaction.rev_ref as the lookup value rather than source_ref itself
Amounttransaction.trans_amtNoAlways visible; rendered right-aligned with debit/credit type indicator in parentheses; positive entries shown in green, reversal entries (transaction.reverse_ind = true) shown in red
Clientparty.display_name (via transaction.client_id)NoAlways visible; rendered as hyperlink to /clients/[client_id]?tab=revenue when client_id is non-null
Deptdepartment.name (via transaction.department_id)NoAlways visible
Accountaccount.account_full_name (via transaction.account_id)NoAlways visible; falls back to transaction.account_id when name is unavailable
Entityuta_entity.name (via transaction.uta_entity_id)NoAlways visible; falls back to transaction.uta_entity_id
Batch IDtransaction.batch_idNoAlways visible

Grid features:

  • Sortable columns: ID, Posting Date, Ref Date, Class, Source, Rev Ref, Ref, Amount, Client, Dept, Account, Entity, Batch ID
  • Filters: None (global filters and drill-down filters applied via filter panel and drill-down action)
  • Row selection: None
  • Pagination: Yes (standard page size)

Conditional display:

  • When drill-down filters are active, a row of removable badge chips appears above the tab list showing each active drill-down dimension (e.g., periodRef: 2026-01, sourceCd: REV)
  • "Clear All" button appears next to the badge chips when drill-down filters are active
  • Each badge chip has an "×" to remove that individual dimension and re-run the search

9. Additional Diagrams

Job Execution State Diagram

mermaid
stateDiagram-v2
    [*] --> RUNNING : Job dispatched by runJobs
    RUNNING --> SUCCESS : Job completes without error
    RUNNING --> FAILED : Job throws unhandled exception
    SUCCESS --> [*]
    FAILED --> [*]

Jobs do not retry automatically. A failed job must be re-run manually by the user.

Transaction GL Status Lifecycle

mermaid
stateDiagram-v2
    [*] --> U : Created by accounting job\n(gl_status_cd = 'U')
    U --> P : GL transmission succeeds\n(gl_posting_dt set)
    U --> X : Manually excluded
    U --> F : GL transmission fails
    F --> P : Retry succeeds
    F --> X : Manually excluded after failure

All new transactions start in state U (Unposted). The progression to P (Posted) is performed by a separate GL transmission batch outside the scope of this workflow.

mermaid
flowchart LR
    A[REV\nRevenue Recognition] --> B[BILL\nBilling Posting]
    B --> C[CR\nCash Receipt Posting]
    C --> D[APP\nCash Application Posting]
    D --> E[PO\nPayout Posting]
    E --> F[TRUE\nAR True-Up]
    G[CL\nClient Ledger] --> F

REV and BILL must precede TRUE because the true-up job reads their transaction output. APP must precede TRUE because application transactions affect Deferred/Unbilled balances. CL and PO can be run before TRUE but are independent of the REV/BILL ordering constraint.


10. Cross-References

DocumentRelationship
Accounting Data ModelDefines transaction, account, fiscal_period, and accounting_job_execution_history — all four tables used in this workflow
Accounting QueriesSpecifies all read operations: transaction search variants, aggregation queries, account search, fiscal period queries, and job history queries
Accounting ProceduresSpecifies all eight batch job procedures: REV, BILL, CR, APP, PO, TRUE, FX (not implemented), CL (not implemented); plus the job orchestration and fiscal period management procedures
Cash Receipts WorkflowUpstream: posted cash_receipt records are the source records for the CR job
Worksheets WorkflowUpstream: REV-type cash_receipt_application records from Applied worksheets are source records for the APP job; cash_receipt_client_ledger records are source records for the CL job
Settlements WorkflowUpstream: payment_item records with bank-confirmed execution status are source records for the PO job
Billing Items WorkflowUpstream: billing_item_detail records and revenue_item_schedule records are source records for the BILL and REV jobs respectively

11. Gherkin Scenarios

gherkin
Feature: Accounting Jobs - Job Execution

  Scenario: Successful multi-job run sets fiscal period and creates transactions
    Given fiscal_period rows exist for 2026-03 with period_start_dt = '2026-03-01' and period_end_dt = '2026-03-31'
    And revenue_item_schedule rows exist with revenue_item_posting_status_cd = 'U' and revenue_dt <= '2026-03-15'
    And billing_item_detail rows exist with posting_status_cd = 'U' and parent billing_item.billing_item_due_dt <= '2026-03-15'
    When the user submits the Run Accounting Jobs form with effective_date = '2026-03-15' and job_types = ['REV', 'BILL']
    Then fiscal_period.current_ind = true for the period with period_ref = '2026-03'
    And all other fiscal_period.current_ind values are set to false
    And two transaction rows (debit account_id = 1, credit account_id = 13) are inserted per eligible revenue_item_schedule with gl_status_cd = 'U'
    And two transaction rows (debit account_id = 4, credit account_id = 6) are inserted per eligible billing_item_detail with gl_status_cd = 'U'
    And two accounting_job_execution_history rows exist with job_cd IN ('REV', 'BILL') and status_cd = 'SUCCESS' and effective_dt = '2026-03-15'
    And the REV job checkbox on the dashboard shows last run date '2026-03-15'

  Scenario: Job run is idempotent — re-running deletes and regenerates transactions
    Given accounting jobs REV and BILL were previously run with effective_date = '2026-03-10'
    And transaction rows exist with source_cd = 'REV' and posting_dt = '2026-03-01'
    And transaction rows exist with source_cd = 'BILL' and posting_dt = '2026-03-01'
    When the user re-submits the Run Accounting Jobs form with effective_date = '2026-03-15' and job_types = ['REV', 'BILL']
    Then all prior transaction rows with source_cd = 'REV' and posting_dt >= '2026-03-15' are deleted before new rows are inserted
    And all prior transaction rows with source_cd = 'BILL' and posting_dt >= '2026-03-15' are deleted before new rows are inserted
    And the resulting transaction count matches the current count of eligible source records up to '2026-03-15'
    And no duplicate transaction rows exist for the same source_id

  Scenario: Job run fails when no fiscal period covers the effective date
    Given no fiscal_period row exists with period_start_dt <= '2026-06-15' and period_end_dt >= '2026-06-15'
    When the user submits the Run Accounting Jobs form with effective_date = '2026-06-15' and job_types = ['REV']
    Then the system returns an error: "Failed to set current fiscal period"
    And no transaction rows are inserted
    And no accounting_job_execution_history row is created

  Scenario: Submitting with no job types selected returns an error
    Given fiscal_period rows exist for 2026-03
    When the user submits the Run Accounting Jobs form with effective_date = '2026-03-15' and no job_types selected
    Then the system returns an error: "At least one job must be selected"
    And fiscal_period.current_ind is not changed
    And no accounting_job_execution_history row is created

Feature: Accounting Jobs - Transaction Search and Filtering

  Scenario: Searching by source code returns only matching transactions
    Given transaction rows exist with source_cd = 'REV' for client "Taylor Swift" and source_cd = 'APP' for client "Drake"
    When the user sets Source Cd filter to ['REV'] and clicks Search
    Then the Transaction Detail tab displays only transaction rows with transaction.source_cd = 'REV'
    And the Top Level crosstab shows only REV-sourced amounts per period per account
    And no APP-sourced rows appear in any tab

  Scenario: Drilling down from a Top Level crosstab cell filters Transaction Detail
    Given a search has returned aggregated data with a non-zero amount in period '2026-03', source 'REV', account class 'Revenue', account number '1300'
    When the user clicks that amount cell in the Top Level crosstab
    Then the active tab switches to 'transactions'
    And a new enriched transaction search is executed with added filters: periodRef = '2026-03', sourceCd = 'REV', accountClass = 'Revenue', accountNumber = '1300'
    And activeDrillDownFilters badge chips show 'periodRef: 2026-03', 'sourceCd: REV', 'accountClass: Revenue', 'accountNumber: 1300'

  Scenario: Removing a drill-down filter badge re-fetches with remaining filters
    Given the user has drilled down with activeDrillDownFilters = { periodRef: '2026-03', sourceCd: 'REV', accountClass: 'Revenue', accountNumber: '1300' }
    When the user clicks "×" on the 'sourceCd: REV' badge chip
    Then the Transaction Detail tab re-fetches with filters: periodRef = '2026-03', accountClass = 'Revenue', accountNumber = '1300' (no sourceCd filter)
    And the 'sourceCd' badge chip is no longer displayed

  Scenario: Transaction search result is capped at 1,000 rows
    Given more than 1,000 transaction rows exist with source_cd = 'REV'
    When the user searches with Source Cd filter = ['REV'] and no other filters
    Then the Transaction Detail tab displays exactly 1,000 rows
    And the Top Level and other aggregation tabs continue to show full totals (no row limit on aggregated queries)

Feature: Accounting Jobs - Posting Date Logic

  Scenario: Revenue schedule created before its revenue date posts to start of revenue period
    Given a revenue_item_schedule row exists with created_dt = '2026-01-15' and revenue_dt = '2026-03-10'
    And fiscal_period row exists for 2026-03 with period_start_dt = '2026-03-01'
    When the REV job runs with effective_date = '2026-03-15'
    Then the resulting transaction rows have posting_dt = '2026-03-01'
    And transaction.transaction_ref_dt = '2026-03-10'
    And transaction.posting_period_ref = '2026-03'

  Scenario: Revenue schedule created after its revenue date posts to the creation date
    Given a revenue_item_schedule row exists with created_dt = '2026-03-12' and revenue_dt = '2026-03-10'
    When the REV job runs with effective_date = '2026-03-15'
    Then the resulting transaction rows have posting_dt = '2026-03-12'
    And transaction.transaction_ref_dt = '2026-03-10'

Feature: Accounting Jobs - PAY vs REV Posting Timing

  Scenario: APP job creates transactions for REV-type applications only
    Given a cash_receipt_worksheet with worksheet_status_cd = 'P' (Applied)
    And the worksheet has cash_receipt_application rows: one with billing_item_detail_type_cd = 'REV' and one with billing_item_detail_type_cd = 'PAY'
    When the APP job runs with effective_date = '2026-03-15'
    Then transaction rows are created for the REV-type application (source_cd = 'APP')
    And no transaction rows are created for the PAY-type application

  Scenario: PO job creates transactions only for bank-confirmed payouts
    Given payment_item rows exist: one with payment_execution_status_cd = 'ACKNOWLEDGED' and one with payment_execution_status_cd = 'PENDING'
    When the PO job runs with effective_date = '2026-03-15'
    Then transaction rows (source_cd = 'PO') are created only for the payment_item with payment_execution_status_cd = 'ACKNOWLEDGED'
    And no transaction rows are created for the PENDING payment_item

Confidential. For internal use only.