# Learn: Transfer of Product Ownership (Accounting view)

This page explains what happens to **Abacus contracts and revenue** when a product is
transferred from one account to another. For the operational detail see the
[backend runbook](../runbooks/transfer-of-product-ownership/backend.md) and the
[frontend runbook](../runbooks/transfer-of-product-ownership/frontend.md).

## The problem

When a project moves from one account (the **originating account**) to another (the
**destination account**), we want to keep the same UPCs and avoid a takedown and redelivery.
That means the catalog moves, but the Abacus contracts that pay out on that catalog do not
move automatically. Without help, the originating account's product and track terms would keep
paying on content it no longer owns, and the destination account would have nothing attached.

## What gets queued

In Abacus, the Solutions team queues a transfer from the Transfer Projects screen: originating
account, project, destination account, and destination contract. They also choose which
contract terms should follow the products:

- **Label terms:** apply the destination contract's label rate to everything transferred.
- **Custom product/track terms:** specific rates for specific UPCs (products) or ISRCs (tracks).

Queuing does two things: it creates a transfer job (with a snapshot of the project's releases),
and it stages the chosen terms. Nothing is changed in the contracts yet, and the job sits
`QUEUED`. The **revenue cutoff** is set to the last day of the prior month.

## What happens at execution

At the start of the next accounting run an operator executes the queued jobs. Each job runs
through the transfer state machine. Two parts matter for accounting, and they run in parallel:

```mermaid
flowchart TD
    EX["Execute queued job"] --> CT["Move content<br>(UPCs now owned by destination)"]
    CT --> P{{"PostTransfer"}}
    P --> EA["Edit Attachments<br>(contract terms)"]
    P --> DT["Update Dim Tables<br>(revenue cutoff)"]
    EA --> DONE["Job complete"]
    DT --> DONE
```

### Contract terms (Edit Attachments)

The accounting step rewrites the affected contract terms so payouts follow ownership:

1. It takes the UPCs and ISRCs that moved.
2. It **removes** those UPCs from the originating account's product terms and those ISRCs from
   its track terms. If a term ends up with nothing attached, that term is retired
   (soft-deleted) rather than left empty.
3. It **adds** those UPCs/ISRCs to the destination account using the terms staged at queue time.
   Each staged product or track term becomes its own new contract term on the destination, with
   its own attachments and rate. This is idempotent, so re-running never creates duplicates.

The result: after the run, the originating account stops being paid on the transferred content,
and the destination account is paid on it under the agreed terms.

### Revenue cutoff (Update Dim Tables)

Revenue is split by a hard cutoff based on the statement period, not by activity date. The
analytics step writes an effective-dated ownership timeline (`FACTS.DIM_RELEASE_HISTORY`): the
originating account keeps revenue booked through the cutoff, and everything booked after goes to
the destination, including late-arriving revenue for pre-cutoff activity. The revenue-analysis
breakdowns read ownership from that timeline, so there is no double counting.

There is no separate dbt cutoff filter and no moneyhub cache step in this flow; both were
considered and ended up as no-ops. The cutoff lives entirely in the ownership timeline.

## Things to know

- **No automatic rollback.** Re-transferring is a brand new job. Reversing the accounting side
  of a move is done with a database PR that re-attaches the UPCs/ISRCs to the originating
  account's terms and removes them from the destination. See the backend runbook.
- **Idempotent.** The accounting step can be safely re-run; removing an absent attachment or
  re-adding an existing one does nothing.
- **Label vs product/track.** Only product and track staged terms are recreated on the
  destination by the accounting step. A label-mode selection is captured as the contract's
  label-term conditions at queue time.
