Skip to content

Accounting Data Model

1. Executive Summary

Purpose

The accounting domain provides the General Ledger (GL) posting infrastructure for UTA Client Payments. It captures every financial event — revenue recognition, billing, cash receipt posting, cash application, payouts, FX adjustments, and AR true-ups — as double-entry transactions that can be transmitted to the enterprise GL system. Transactions are never created directly by users; they are produced by batch accounting jobs that scan for unposted source records and generate balanced debit/credit batches grouped by batch_id. The fiscal_period table controls which accounting period a transaction falls into and whether that period is open for new postings. The account table provides the chart of accounts that every transaction line posts against. The accounting_job_execution_history table records an audit trail of every batch run.

Scope

Covered:

  • transaction — The subledger journal. Every financial event produces one or more balanced debit/credit rows here, grouped into a batch that nets to zero.
  • account — The chart of accounts (GL account master). Each transaction line references an account.
  • fiscal_period — Accounting period calendar. Controls which period a transaction posts into and whether a period is open or closed.
  • accounting_job_execution_history — Audit log for batch accounting jobs. Records when each job type ran, what date it processed through, and whether it succeeded or failed.

Not covered (documented separately):


2. Data Model

2.1 Entity-Relationship Diagram

mermaid
erDiagram
    transaction }o--o| account : "posts to"
    transaction }o--o| fiscal_period : "belongs to period"
    transaction }o--o| uta_entity : "belongs to entity"
    transaction }o--o| department : "belongs to department"
    transaction }o--o| party : "associated client"

    transaction {
        serial transaction_id PK
        varchar class_cd
        varchar source_cd
        integer source_id
        varchar source_ref
        varchar rev_ref
        varchar batch_id
        integer account_id FK
        varchar type_cd
        boolean reverse_ind
        decimal trans_amt
        decimal group_amt
        decimal reporting_amt
        varchar trans_currency_cd
        varchar group_currency_cd
        varchar reporting_currency_cd
        date transaction_ref_dt
        date posting_dt
        integer posting_period_id FK
        varchar posting_period_ref
        integer uta_entity_id FK
        integer department_id FK
        integer client_id FK
        varchar gl_status_cd
        date gl_posting_dt
    }

    account {
        serial account_id PK
        varchar account_class
        varchar account_description
        varchar account_number
        varchar account_full_name
        varchar status_cd
    }

    fiscal_period {
        serial fiscal_period_id PK
        date period_start_dt
        date period_end_dt
        date period_closed_dt
        integer period_year
        integer period_month
        varchar period_ref
        boolean current_ind
        boolean current_cash_ind
    }

    accounting_job_execution_history {
        serial accounting_job_execution_history_id PK
        varchar job_cd
        date effective_dt
        timestamp started_at
        timestamp completed_at
        varchar status_cd
        jsonb result_summary
        varchar created_by
    }

2.2 transaction

The subledger journal table. Each row is one side (debit or credit) of a double-entry posting. Rows are grouped into balanced batches via batch_id. Transactions are never inserted directly by users — they are produced by batch accounting jobs.

FieldTypeRequiredDefaultDescription
transaction_idserialYesAutoPrimary key.
class_cdvarchar(50)NoTransaction class. Categorizes the financial nature of the entry. See Section 5 for values (REV, AR, CASH, TAX, FX).
source_cdvarchar(50)NoSource job code. Identifies which accounting job created this transaction. See Section 5 for values (REV, BILL, CR, APP, PO, FX, TRUE, CL).
source_idintegerNoID of the source record that triggered this transaction (e.g., a revenue schedule ID, a cash receipt ID, a cash receipt application ID).
source_refvarchar(255)NoHuman-readable reference string for the source record (e.g., the sales item reference from the originating revenue item).
rev_refvarchar(255)NoRevenue reference. Links the transaction back to its originating revenue item for aggregation and reporting (e.g., period-end AR true-up candidates are identified by distinct rev_ref values).
batch_idvarchar(100)YesGroups debits and credits into a balanced batch. All transactions sharing a batch_id must net to zero. Format: YYYYMMDDHHMMSS + zero-padded six-digit sequence number.
account_idintegerNoFK to account.account_id. The GL account this entry posts to.
type_cdvarchar(1)NoDebit/credit indicator. D = Debit, C = Credit. See Section 5.
reverse_indbooleanNofalseWhen true, this transaction is a reversal entry (negates a prior posting). Set to true for negative-amount transactions (e.g., write-off reversals).
trans_amtdecimal(15,2)NoAmount in the transaction's original currency (trans_currency_cd).
group_amtdecimal(15,2)NoAmount converted to the UTA entity's group currency (group_currency_cd).
reporting_amtdecimal(15,2)NoAmount converted to the reporting currency, typically USD (reporting_currency_cd).
trans_currency_cdvarchar(10)NoISO currency code for trans_amt.
group_currency_cdvarchar(10)NoISO currency code for group_amt.
reporting_currency_cdvarchar(10)NoISO currency code for reporting_amt (typically USD).
transaction_ref_dtdateNoThe business date of the underlying event (e.g., the revenue recognition date, the receipt booking date). May differ from posting_dt when a transaction is recognized retroactively.
posting_dtdateNoThe date this transaction is posted to the subledger. Determined by posting-date logic: if the source record's creation date is before the driver date (revenue date, check date, due date), posts to the first day of the driver date's fiscal period; otherwise posts to the creation date.
posting_period_idintegerNoFK to fiscal_period.fiscal_period_id. The accounting period this transaction belongs to.
posting_period_refvarchar(20)NoDenormalized period reference string (e.g., 2026-01) for query convenience. Matches fiscal_period.period_ref.
uta_entity_idintegerNoFK to uta_entity.uta_entity_id. The UTA legal entity this transaction belongs to.
department_idintegerNoFK to department.department_id. The department associated with this transaction.
client_idintegerNoFK to party.party_id. The client (artist/talent) associated with this transaction.
gl_status_cdvarchar(1)NoGL transmission status. See Section 3 for the lifecycle. Values: U (Unposted), P (Posted), X (Excluded), F (Failed).
gl_posting_dtdateNoThe date this transaction was successfully transmitted to the enterprise GL. null while gl_status_cd is U or F.

2.3 account

The GL chart of accounts. Each account represents a line in the general ledger that transactions post against. Accounts are managed by the accounting team and loaded from the enterprise chart of accounts.

FieldTypeRequiredDefaultDescription
account_idserialYesAutoPrimary key. Referenced by transaction.account_id.
account_classvarchar(100)NoClassification grouping (e.g., Deferred, Unbilled, Revenue, Liability). Used for aggregating transaction totals by type in reporting and AR true-up calculations.
account_descriptionvarchar(500)NoDescriptive label for the account.
account_numbervarchar(50)NoThe GL account number. Used for matching and reporting against the enterprise chart of accounts.
account_full_namevarchar(500)NoFull display name including any hierarchical path. Shown in transaction display views.
status_cdvarchar(20)NoActive/inactive flag. A = Active, I = Inactive. Only active accounts should receive new postings. See Section 3.

NOTE

Pure audit columns (created_by, created_dt, updated_by, updated_dt) are omitted unless they carry business meaning.


2.4 fiscal_period

Defines accounting periods (one row per calendar month by default). Controls which period transactions post into, whether the period is open for new postings, and whether it is open for cash-related postings. A separate current_cash_ind allows cash processing to operate in a different open period from general accounting when needed.

FieldTypeRequiredDefaultDescription
fiscal_period_idserialYesAutoPrimary key. Referenced by transaction.posting_period_id.
period_start_dtdateNoFirst day of the accounting period (inclusive).
period_end_dtdateNoLast day of the accounting period (inclusive).
period_closed_dtdateNoDate the period was closed. null if still open. Once set, no new transactions should post to this period.
period_yearintegerNoFiscal year (e.g., 2026).
period_monthintegerNoFiscal month (1–12).
period_refvarchar(20)NoHuman-readable period reference (e.g., 2026-01). Matches transaction.posting_period_ref.
current_indbooleanNoWhen true, this is the currently active accounting period. At most one period should have this flag set to true at any time. Updated by the accounting job runner before each job batch executes.
current_cash_indbooleanNoWhen true, this period is currently open for cash-related postings. Allows cash processing to operate independently from the general accounting period.

2.5 accounting_job_execution_history

Audit trail for batch accounting job executions. Each row records one run of one job type: when it started, when it finished, the as-of date it processed through, and its outcome. Populated automatically by the accounting job runner after each job completes (successfully or with failure).

FieldTypeRequiredDefaultDescription
accounting_job_execution_history_idserialYesAutoPrimary key.
job_cdvarchar(50)YesThe job type code (e.g., REV, BILL, CR, APP, PO, FX, TRUE, CL). Matches the source_cd values on transaction. See Section 5.
effective_dtdateYesThe "as-of" date the job was run against. Transactions are created for source records on or before this date.
started_attimestampYesNowTimestamp when the job began executing.
completed_attimestampNoTimestamp when the job finished. null if the job is still running.
status_cdvarchar(20)YesExecution outcome. See Section 3. Values: RUNNING, SUCCESS, FAILED.
result_summaryjsonbNoStructured summary of the job result. On success: { "processedCount": 42, "batchIds": [...] }. On failure: { "error": "..." }.
created_byvarchar(100)NoUser or system actor that initiated the job. Defaults to SYSTEM for scheduled runs.

3. Status Lifecycle

3.1 Transaction GL Status (transaction.gl_status_cd)

Tracks whether a subledger transaction has been transmitted to the enterprise GL system.

StatusCodeDescriptionAllowed Transitions
UnpostedUTransaction created in the subledger but not yet sent to the enterprise GL. Default state for all new transactions.→ Posted (P), → Excluded (X), → Failed (F)
PostedPTransaction successfully transmitted to and accepted by the enterprise GL. gl_posting_dt is set.— (terminal)
ExcludedXTransaction intentionally excluded from GL transmission (e.g., internal adjustments, test data).— (terminal)
FailedFGL transmission was attempted but failed. Eligible for retry.→ Posted (P), → Excluded (X)
mermaid
stateDiagram-v2
    [*] --> U : Transaction created by accounting job
    U --> P : GL transmission succeeds
    U --> X : Manually excluded
    U --> F : GL transmission fails
    F --> P : Retry succeeds
    F --> X : Manually excluded after failure

Transition: U → P

  • Trigger: GL posting batch transmits the transaction to the enterprise GL and receives confirmation.
  • Preconditions: gl_status_cd is U or F.
  • Side-effects: transaction.gl_posting_dt set to the transmission date; transaction.gl_status_cd set to P.

Transition: U → F

  • Trigger: GL posting batch attempts transmission but the enterprise GL rejects or does not respond.
  • Preconditions: gl_status_cd is U.
  • Side-effects: transaction.gl_status_cd set to F. The result_summary on the corresponding accounting_job_execution_history row records the error.

Transition: F → P

  • Trigger: GL posting batch retries the previously failed transaction and transmission succeeds.
  • Preconditions: gl_status_cd is F.
  • Side-effects: transaction.gl_posting_dt set; transaction.gl_status_cd set to P.

Transition: U/F → X

  • Trigger: Manual exclusion by an administrator (e.g., test data cleanup or internal adjustment identified as not requiring GL posting).
  • Preconditions: gl_status_cd is U or F.
  • Side-effects: transaction.gl_status_cd set to X. No GL entry is created.

3.2 Account Status (account.status_cd)

Controls whether an account can receive new transaction postings.

StatusCodeDescriptionAllowed Transitions
ActiveAAccount is available for new postings.→ Inactive (I)
InactiveIAccount is retired. Existing transactions remain but no new postings should reference this account.→ Active (A)

Transition: A → I

  • Trigger: Accounting team retires a GL account (e.g., chart of accounts restructuring).
  • Preconditions: None enforced at the database level.
  • Side-effects: Accounting job logic must exclude inactive accounts when selecting posting targets. Existing transaction rows referencing this account are unaffected.

3.3 Job Execution Status (accounting_job_execution_history.status_cd)

Tracks the outcome of a single batch accounting job run.

StatusCodeDescriptionAllowed Transitions
RunningRUNNINGJob is currently executing. completed_at is null.→ Success (SUCCESS), → Failed (FAILED)
SuccessSUCCESSJob completed without errors. result_summary contains processing counts and batch IDs.— (terminal)
FailedFAILEDJob encountered an error and did not complete normally. result_summary contains the error message.— (terminal)
mermaid
stateDiagram-v2
    [*] --> RUNNING : Job initiated
    RUNNING --> SUCCESS : Job completes without error
    RUNNING --> FAILED : Job encounters error

Transition: RUNNING → SUCCESS

  • Trigger: The accounting job completes all processing steps without throwing an error.
  • Preconditions: status_cd is RUNNING.
  • Side-effects: completed_at set to the current timestamp; result_summary populated with { processedCount, batchIds }.

Transition: RUNNING → FAILED

  • Trigger: The accounting job throws an unhandled exception during processing.
  • Preconditions: status_cd is RUNNING.
  • Side-effects: completed_at set to the current timestamp; result_summary populated with { error: "..." }.

4. Validation & Database Constraints

Unique Constraints

TableConstraintColumnsBusiness Rule
transaction(none defined at DB level)Uniqueness is enforced by the application-layer idempotency pattern: all prior transactions for a given source_cd + source_id combination are deleted before new ones are inserted.

Business Validation

  • Batch must net to zero: All transaction rows sharing a batch_id must have debits equal to credits (sum nets to zero). Enforced at the application layer during batch creation — no database constraint.

  • batch_id is required: transaction.batch_id has a NOT NULL constraint. Every transaction must belong to a batch, even if the batch contains only two rows (one debit, one credit).

  • Active-only posting: Only accounts with account.status_cd = A should receive new postings. Enforced at the application layer; no database constraint prevents posting to inactive accounts.

  • Closed-period guard: Once fiscal_period.period_closed_dt is set, no new transactions should post to that period. Enforced at the application layer.

  • Single current period: At most one fiscal_period row should have current_ind = true at any time. Enforced at the application layer: the period-setting operation resets all rows to false before setting the target period to true.

  • Period coverage: Each posting date should fall within exactly one fiscal period (no gaps, no overlaps between period_start_dt and period_end_dt). Enforced by the accounting team when defining periods.

  • job_cd, effective_dt, started_at, and status_cd are required: accounting_job_execution_history has NOT NULL constraints on these four fields. All other fields are optional.

Posting Date Logic

The accounting jobs apply a consistent rule to determine transaction.posting_dt:

  1. If the source record's created_dt is before the driver date (e.g., revenue recognition date, check date, or billing due date), the posting_dt is set to the first day of the fiscal period that contains the driver date.
  2. If the source record's created_dt is on or after the driver date, the posting_dt is set to the created_dt.

This ensures that retroactive entries land in the correct accounting period while current-day entries post as of their creation date.

IMPORTANT

The transaction_ref_dt always records the original business date of the event (the driver date), regardless of what posting_dt resolves to. This is the distinction between when something economically occurred versus when it was posted.


5. Code Master Values

5.1 CLASS_CD — Transaction Class

Used by transaction.class_cd. Categorizes the financial nature of a journal entry.

CodeDescriptionBehavior / When Used
REVRevenueEntries produced by the revenue recognition job (source_cd = REV). Records realized revenue from revenue schedules.
ARAccounts ReceivableEntries produced by the billing job (source_cd = BILL). Records the AR balance created when billing items are processed.
CASHCashEntries produced by the cash receipt job (source_cd = CR) and payout job (source_cd = PO). Records cash inflows (receipts) and outflows (payouts).
TAXTax / VATEntries related to withholding tax or VAT. Produced when tax deductions are applied.
FXForeign ExchangeGain/loss entries from currency conversions. Produced by the FX adjustment job (source_cd = FX).

Default on creation: No default — set explicitly by each accounting job based on the nature of the source record.


5.2 SOURCE_CD — Transaction Source Job

Used by transaction.source_cd and accounting_job_execution_history.job_cd. Identifies which accounting job produced the transactions.

CodeDescriptionSource EntityGL Posting Timing
REVRevenue recognition jobRevenue schedules (revenue_item_schedules)At job execution, when revenue_dt is on or before effective_dt
BILLBilling jobBilling items (billing_item)At job execution, when billing item is created/due
CRCash receipt posting jobCash receipts (cash_receipt)At job execution, after receipt is posted
APPCash application jobREV-type cash receipt applications (cash_receipt_application)At job execution after worksheet reaches Applied (P) status
POPayout jobPAY-type cash receipt payouts (cash_receipt_payout)At job execution, only after bank confirms payment (ACKNOWLEDGED or PAID)
FXFX adjustment jobCurrency conversion eventsAt job execution, when FX adjustments are processed
TRUEAR true-up jobPeriod-end AR reconciliation (aggregated by rev_ref)At job execution during period-end close
CLClient ledger jobClient ledger entries (cash_receipt_client_ledger)At job execution after worksheet reaches Applied (P) status

Default on creation: No default — set explicitly by the job that creates the transaction.

IMPORTANT

The distinction between APP and PO posting timing is critical. REV application transactions (APP) post to the GL at Apply time because the money stays in UTA accounts. PAY payout transactions (PO) post to the GL only after the bank confirms the payment has been sent — because the money must physically leave the building before the GL entry is made. This two-stage posting model is fundamental to the system's reversal and return logic.


5.3 TYPE_CD — Debit/Credit Indicator

Used by transaction.type_cd.

CodeDescriptionBehavior / When Used
DDebitThe debit side of a double-entry journal entry.
CCreditThe credit side of a double-entry journal entry.

Default on creation: No default — set explicitly based on which side of the journal entry this row represents.


5.4 GL_STATUS_CD — GL Transmission Status

Used by transaction.gl_status_cd. See Section 3.1 for the full lifecycle.

CodeDescriptionBehavior / When Used
UUnpostedDefault on creation. Transaction is in the subledger, awaiting GL transmission.
PPostedGL transmission succeeded. gl_posting_dt is set. Terminal state.
XExcludedIntentionally skipped. Used for internal adjustments or test data that should not reach the enterprise GL. Terminal state.
FFailedGL transmission was attempted but failed. Eligible for retry.

Default on creation: U


5.5 ACCOUNT_STATUS_CD — Account Active Status

Used by account.status_cd. See Section 3.2 for transitions.

CodeDescriptionBehavior / When Used
AActiveAccount is available for new transaction postings. Accounting jobs may select this account.
IInactiveAccount has been retired. No new postings should reference it. Existing transactions are unaffected.

Default on creation: A


5.6 JOB_STATUS_CD — Job Execution Outcome

Used by accounting_job_execution_history.status_cd. See Section 3.3 for transitions.

CodeDescriptionBehavior / When Used
RUNNINGJob is currently executingSet at job start. completed_at is null.
SUCCESSJob completed successfullySet at job end when no errors occurred. result_summary contains counts and batch IDs.
FAILEDJob encountered an errorSet at job end when an exception was thrown. result_summary contains the error message.

Default on creation: RUNNING


6. Cross-References

DocumentRelationship
Worksheets Data Modelcash_receipt_application rows with billing_item_detail_type_cd = REV are the source records for APP-sourced transactions. cash_receipt_client_ledger rows are the source for CL-sourced transactions. Both post when the worksheet reaches Applied (P) status.
Settlements Data Modelcash_receipt_payout rows derived from PAY-type settlement items are the source for PO-sourced transactions. These post only after the bank confirms the payment (ACKNOWLEDGED or PAID).
Cash Receipts Data ModelPosted cash_receipt records are the source for CR-sourced transactions recording the cash inflow. transaction.source_id links back to cash_receipt.cash_receipt_id.
Billing Items Data ModelCreated billing_item records are the source for BILL-sourced transactions establishing the AR balance. Revenue schedules (revenue_item_schedules) are the source for REV-sourced transactions.

Confidential. For internal use only.