{
  "apiName": "Credits_Topup__c",
  "keyPrefix": "a0Y",
  "label": "Credits Top-up",
  "pluralLabel": "Credits Top-ups",
  "tableType": "custom_object",
  "category": "crm",
  "sharingModel": "ControlledByParent",
  "description": "Master-detail child of Credits__c. Each top-up is a separate approval request against an already-Active parent Credits engagement, allowing AE to extend a running engagement without re-submitting the original Initial_Credits__c (proposal §3, §6). ControlledByParent so sharing follows the parent Credits record. Approval routing mirrors the parent 3-step gated flow (Presales / Finance / BG Leader) but the threshold criteria compare against CUMULATIVE disbursement (parent.Total_Disbursed__c + this.Topup_Amount__c, which is what Cumulative_Disbursed__c returns while the record is un-approved and therefore what the criteria read) — successive small top-ups can't escape the larger-grant gating by being under the per-step threshold individually. The cumulative value is computed via the Cumulative_Disbursed__c active formula on this object (NX#947 substrate now closed). See docs/object-proposals/poc-credits-refactor.md.",
  "fields": [
    {
      "apiName": "Name",
      "label": "Top-up Name",
      "type": "string",
      "maxLength": 255,
      "isNameField": true,
      "required": false,
      "description": "Record display name. Auto-populated by the Credits Top-up — Auto-Assign Sequence Number Flow (RecordBeforeSave Create) as `Top-up #<sequence>`, so AE never types it. Required by the platform lookup-display contract (frontend useRecordList expands the parent lookup to `Credits__r.Name`, and this object's own rows render their Name in the parent's Top-ups Related List)."
    },
    {
      "apiName": "Credits__c",
      "label": "Parent Credits",
      "type": "masterdetail",
      "referenceTo": [
        "Credits__c"
      ],
      "relationshipName": "Topups",
      "childRelationshipName": "Topups",
      "required": true,
      "description": "Master-detail link to the parent Credits__c engagement. childRelationshipName registers `Topups` as the child collection on Credits.describe so SOQL parent.child subqueries (`SELECT ..., (SELECT Id FROM Topups) FROM Credits__c`) and Related List rendering work. ControlledByParent sharing inherits from this parent."
    },
    {
      "apiName": "Topup_Amount__c",
      "label": "Top-up Amount (USD)",
      "type": "currency",
      "required": true,
      "description": "AE-entered amount in USD. Phase 1 USD-only (matches parent Initial_Credits__c USD constraint; revisit if a future Credit_Type opens non-USD)."
    },
    {
      "apiName": "Effective_Date__c",
      "type": "date",
      "label": "Effective Date",
      "required": true,
      "description": "Date this top-up's credits become effective. Required, AE-filled on Create — NOT pre-filled. A time-extending top-up carries its own validity window that may differ from the parent Credits engagement window. Phase 1 captures the dates only; no approval-time propagation to the parent Expiration and no cross-window validation (deferred — see proposal)."
    },
    {
      "apiName": "Expiration_Date__c",
      "type": "date",
      "label": "Expiration Date",
      "required": true,
      "description": "Date this top-up's credits expire. Required, AE-filled on Create — NOT pre-filled. May differ from the parent Credits Expiration_Date__c (a top-up can extend the PoC time window). Phase 1 captures the date only; no auto-extension of the parent window on approval (deferred)."
    },
    {
      "apiName": "Cumulative_Disbursed__c",
      "label": "Cumulative Disbursed (USD)",
      "type": "formula",
      "formulaMode": "active",
      "returnType": "currency",
      "formula": "Credits__r.Total_Disbursed__c + IF(ISPICKVAL(Approval_Status__c, 'Approved'), 0, Topup_Amount__c)",
      "createable": false,
      "updateable": false,
      "description": "Active formula evaluated at request time. Returns the running grand total of disbursement for the parent engagement, counting this top-up exactly once. Parent.Total_Disbursed__c is Initial_Credits + sum-of-approved-Topups (rollupsummary whose filter is Approval_Status = 'Approved'), so whether this top-up is already inside the parent total depends on this record's own approval state, and the formula is guarded on that state: while the top-up is NOT Approved it is absent from the parent rollup and Topup_Amount__c is added by hand, giving the 'what would the running total become if this were approved' projection; once it IS Approved the amount has entered Approved_Topups__c and therefore the parent total, so nothing is added and this field equals parent.Total_Disbursed__c. Without that guard the amount was counted twice after approval (#5154 — all three approved production top-ups displayed an inflated total). Topup ProcessDefinition StepCriteria reference this field to apply the same 1000 / 3000 thresholds as the parent flow against the running total — preventing successive small top-ups from escaping the larger-grant gating (proposal §7, §3). Criteria are evaluated while the record is Pending, which is the NOT-Approved branch, so the gate reads exactly the value it read before the guard was added. In-flight pending top-ups DON'T inflate Approved_Topups__c on the parent, so simultaneous submissions don't race-condition the threshold. Requires NX#947 substrate (closed via #1125 — runtime acceptance proven by this object's end-to-end test). Build script must include this in `wave6_active_formula_fields` because formula uses relationship traversal (`Credits__r.Total_Disbursed__c`)."
    },
    {
      "apiName": "Requires_Finance_Approval__c",
      "label": "Requires Finance Approval",
      "type": "formula",
      "formulaMode": "active",
      "returnType": "boolean",
      "formula": "Credits__r.Requires_Finance_Approval__c",
      "createable": false,
      "updateable": false,
      "description": "DORMANT at launch — mirrors the parent's dormant Finance gate, so it is always false and the Topup Finance step never fires (hidden from all layouts). Active formula reading the parent engagement's Requires_Finance_Approval__c flag (Credits__r.Requires_Finance_Approval__c); the Topup ProcessDefinition Finance step is AND-gated exactly like the parent (Finance fires only when Cumulative_Disbursed__c > 1000 AND this flag is true). When the per-region annual-budget gate is enabled (see parent field + proposal §7 / A-blueprint), the parent flag becomes region-driven and this mirror follows automatically — no separate Topup change needed. Reading it live via the formula (rather than a create-time snapshot) means the gate reflects the current parent flag at submit time. Precedent for a child boolean active formula reading a parent boolean: Opportunity.FY22_IB__c = Account.FY22_IB__c. Build script must include this in `wave6_active_formula_fields` (relationship traversal `Credits__r.`)."
    },
    {
      "apiName": "Topup_Sequence__c",
      "label": "Top-up Sequence",
      "type": "double",
      "required": false,
      "createable": false,
      "updateable": false,
      "description": "Auto-assigned at create by Credits_Topup_Auto_Sequence Flow (1, 2, 3, ... within each parent Credits__c). createable:false hides from Create form — Flow stamps at RecordBeforeCreate after the prune pass."
    },
    {
      "apiName": "Reason__c",
      "label": "Reason",
      "type": "textarea",
      "required": false,
      "description": "AE-authored at create time. Why is this top-up needed (e.g., 'Customer extended PoC scope to multi-region', 'Initial 3-month POC running long'). Approvers read this on the approval inbox."
    },
    {
      "apiName": "Approval_Status__c",
      "label": "Approval Status",
      "type": "picklist",
      "required": true,
      "default": "NotSubmitted",
      "options": [
        {
          "value": "NotSubmitted",
          "label": "Not Submitted"
        },
        {
          "value": "Pending",
          "label": "Pending"
        },
        {
          "value": "Approved",
          "label": "Approved"
        },
        {
          "value": "Rejected",
          "label": "Rejected"
        },
        {
          "value": "NeedsTriage",
          "label": "Needs Triage"
        }
      ],
      "description": "Approval engine workflow state. Mirrors parent Credits__c.Approval_Status__c value set so approver-inbox UI is consistent. NotSubmitted = draft; Pending = under approval; Approved/Rejected = terminal; NeedsTriage = Stamp_Approvers Flow couldn't resolve approvers (incomplete Region_All__c row), retry Flow re-runs on NotSubmitted flip. Approved triggers Approved_Date__c stamping and contributes to parent.Approved_Topups__c rollup."
    },
    {
      "apiName": "Approved_Date__c",
      "label": "Approved Date",
      "type": "date",
      "createable": false,
      "updateable": false,
      "description": "Stamped by Credits_Topup_Activation_On_Approval Flow when Approval_Status__c flips to Approved. Audit-trail field for when each top-up went live."
    },
    {
      "apiName": "Presales_Manager_User__c",
      "label": "Presales Manager (Approver)",
      "type": "reference",
      "referenceTo": [
        "User"
      ],
      "relationshipName": "Topup_Presales_Manager",
      "deleteConstraint": "SetNull",
      "required": false,
      "createable": false,
      "updateable": false,
      "description": "Stamped at create by Credits_Topup_Stamp_Approvers Flow, following the chain $Record.Credits__c → Credits.Account__c → Account.Region__c → Region_All__c.Presales_Manager__c. Routes Topup ProcessDefinition Step 1 (the always-required step). createable:false — Flow-stamped, not AE-editable."
    },
    {
      "apiName": "Finance_Approver_User__c",
      "label": "Finance Approver",
      "type": "reference",
      "referenceTo": [
        "User"
      ],
      "relationshipName": "Topup_Finance_Approver",
      "deleteConstraint": "SetNull",
      "required": false,
      "createable": false,
      "updateable": false,
      "description": "Stamped at create from Region_All__c.Regional_Finance__c. Routes Topup ProcessDefinition Step 2 (fires when Cumulative_Disbursed > 1000 AND Requires_Finance_Approval flag on parent). createable:false."
    },
    {
      "apiName": "BG_Leader_User__c",
      "label": "BG Leader (Approver)",
      "type": "reference",
      "referenceTo": [
        "User"
      ],
      "relationshipName": "Topup_BG_Leader",
      "deleteConstraint": "SetNull",
      "required": false,
      "createable": false,
      "updateable": false,
      "description": "Stamped at create from Region_All__c.Region_BG_Leader__c. Routes Topup ProcessDefinition Step 3 (fires when Cumulative_Disbursed > 3000). createable:false."
    },
    {
      "apiName": "Regional_Ops_User__c",
      "label": "Regional Ops (Stamped)",
      "type": "reference",
      "referenceTo": [
        "User"
      ],
      "relationshipName": "Topup_Regional_Ops",
      "deleteConstraint": "SetNull",
      "required": false,
      "createable": false,
      "updateable": false,
      "description": "Stamped at create by Credits_Topup_Stamp_Approvers Flow from Region_All__c.Region_Ops__c (via $Record.Credits__c → Credits.Account__c → Account.Region__c → Region_All__c). Notified on final approval for the downstream credit reset in the external system (proposal §0 Phase 3 item 2). NOT approval-routing, NOT gated by NeedsTriage. createable:false — Flow-stamped, not AE-editable."
    }
  ]
}
