|
7 | 7 | - Endpoints: |
8 | 8 | - `GET /billing-accounts` |
9 | 9 | - `POST /billing-accounts` |
10 | | - - `GET /billing-accounts/:billingAccountId` (includes locked/consumed arrays + budget totals) |
| 10 | + - `GET /billing-accounts/:billingAccountId` (includes locked/consumed arrays + budget totals; line items expose `amount`, `date`, `externalId`, `externalType`, `externalName`, and `challengeId` only for challenge compatibility) |
11 | 11 | - `GET /billing-accounts/users/:userId` (list billing accounts accessible by the given Topcoder user ID — resolved via Salesforce resource object) |
12 | 12 | - `PATCH /billing-accounts/:billingAccountId` |
13 | | - - `PATCH /billing-accounts/:billingAccountId/lock-amount` (0 amount = unlock) |
14 | | - - `PATCH /billing-accounts/:billingAccountId/consume-amount` (deletes locks for challenge, then upserts consumed) |
| 13 | + - `PATCH /billing-accounts/:billingAccountId/lock-amount` (challenge-only typed reference; non-negative amount; 0 amount = unlock; rejects insufficient remaining funds) |
| 14 | + - `PATCH /billing-accounts/:billingAccountId/consume-amount` (positive amount; challenge typed references delete the matching lock and overwrite consumed; engagement typed references append a consumed row; rejects insufficient remaining funds) |
15 | 15 | - `GET /billing-accounts/:billingAccountId/users` (list users with access) |
16 | 16 | - `POST /billing-accounts/:billingAccountId/users` (grant access; accepts `{ param: { userId } }` or `{ userId }`) |
17 | 17 | - `DELETE /billing-accounts/:billingAccountId/users/:userId` (revoke access) |
@@ -74,6 +74,38 @@ pnpm run build && pnpm start |
74 | 74 | - Lookup the matching `user_account` by `user_account_id`, then query the Members DB by `user_name` (handle) |
75 | 75 | - Upsert `BillingAccountAccess` for the resolved `userId` |
76 | 76 |
|
| 77 | +- Engagement payment consumed backfill: |
| 78 | + - Required env: |
| 79 | + - `DATABASE_URL` for billing-accounts-api-v6. |
| 80 | + - `FINANCE_DB_URL` for tc-finance-api (`winnings` and `payment`). |
| 81 | + - `ENGAGEMENTS_DB_URL` for engagements-api-v6 (`EngagementAssignment` and `Engagement`). |
| 82 | + - `PROJECTS_DB_URL` for projects-api-v6 (`projects.billingAccountId`, matching the trusted project lookup used by engagements-api-v6). |
| 83 | + - Optional `TGBillingAccounts` for finance-compatible TopGear exemptions. If unset, the script uses finance's default exempt accounts `80000062,80002800`. |
| 84 | + - Dry run: |
| 85 | + - `pnpm run backfill:engagementPayments -- --dry-run` |
| 86 | + - Dry run is the default. It reads finance engagement payments, resolves assignment/project/billing account context, plans inserts/updates, and writes a JSON audit report under `scripts/output/`. |
| 87 | + - Apply: |
| 88 | + - `pnpm run backfill:engagementPayments -- --apply` |
| 89 | + - Optional filters: `--assignmentId=<id>[,<id>]`, `--winningId=<id>[,<id>]`, `--since=<iso-date>`, `--until=<iso-date>`, `--limit=<n>`, `--report=<path>`. |
| 90 | + - Behavior: |
| 91 | + - Uses `payment.challenge_markup` first as a markup rate and computes `total_amount + (total_amount * challenge_markup)`. |
| 92 | + - If `payment.challenge_markup` is absent and `payment.challenge_fee` is present, treats `challenge_fee` as an absolute fee amount, computes `total_amount + challenge_fee`, and records the row in the `absoluteFee` audit bucket. |
| 93 | + - If neither finance value is present, falls back to the current `BillingAccount.markup` and records that fallback in the audit report. |
| 94 | + - Skips automated consumed-row planning for TopGear-exempt billing accounts and records those payments in the `exemptBillingAccounts` audit bucket. |
| 95 | + - Apply mode runs billing mutations, post-apply total calculation, and report writing inside one billing database transaction. If a write, verification read, or report write fails before commit, the billing mutations are rolled back. |
| 96 | + - Reconciles one assignment-level aggregate row for historical idempotency. Existing correct rows are left alone; a single incorrect row is updated; multiple existing rows are only moved when their total already matches the legacy expected amount. |
| 97 | + - Exceptions such as missing assignments, missing project billing accounts, missing billing accounts, and ambiguous consumed duplicates are reported without blocking resolvable assignments. |
| 98 | + - Validation: |
| 99 | + - The dry-run/apply report includes expected legacy totals and current/projected billing totals. |
| 100 | + - `verify:engagementPayments` invokes `psql` directly, so export `DATABASE_URL` in the shell before running it. |
| 101 | + - If the source schemas are visible in one Postgres session, run: |
| 102 | + - `pnpm run verify:engagementPayments -- -v finance_schema=finance -v engagements_schema=public -v projects_schema=projects -v billing_schema=billing-accounts -v exempt_billing_account_ids=80000062,80002800` |
| 103 | + - The verification SQL lists mismatches between expected legacy engagement-payment consumes and `ConsumedAmount` rows with `externalType = ENGAGEMENT`. TopGear-exempt accounts are reported separately as `topgear_exempt_*` statuses. |
| 104 | + - Rollback: |
| 105 | + - Use the JSON report from the apply run. A successful apply only commits after that report is written. Delete rows listed with `action: "insert"` and `createdId`; restore rows listed with `action: "update_single"` from `previous`; restore rows listed with `action: "move_existing_rows"` from their `existingRows` billing account ids. |
| 106 | + - If apply mode exits with an error before writing the report, the transaction rolled back and there should be no partial billing-ledger changes from that run. |
| 107 | + - If apply mode exits with an error after a report file exists, run the verifier or a dry run before rollback; the billing transaction should have committed all planned actions or none. |
| 108 | + |
77 | 109 | ## Downstream Usage |
78 | 110 |
|
79 | 111 | - This service is consumed (directly or indirectly) by multiple Topcoder apps. The pointers below help with debugging. |
|
0 commit comments