Backend Request: Full Settlement for User Admin Bulk Transfer
Date: 2026-01-20 From: Frontend Claude To: Backend Claude Priority: High
Summary
The User Admin bulk transfer endpoint (POST /adminUsers/transfer-docs) needs to perform full RoC settlement, not just ownership transfer. Currently it only updates documents_${orgId}.user_id without settling fees or RoC credits.
Business Context
The "on behalf of" workflow is designed to help onboard new users:
- Admin creates queue item to upload document on behalf of non-existent user (using their email)
- Admin processes queue, uploading the document/chunks
- Admin incurs the upload fees
- Over time, other users query the document, generating RoC for the admin
- The intended user registers and gets a
users.id - Admin transfers ownership via User Admin bulk transfer (by email)
The intent is onboarding assistance, not revenue sharing. The original uploader should be made whole:
- Reimbursed for upload fees they paid
- RoC credits earned should transfer to the new owner
Current Behavior
POST /adminUsers/transfer-docs (called from dist/js/admin/users.js line 950):
const result = await callAdminApi('transfer-docs', {
method: 'POST',
body: { email, newOwnerId },
});
Current behavior:
- Finds documents where
metadata->>dc_creator_emailmatches the email - Updates
documents_${orgId}.user_idto the new owner - ❌ Does NOT reimburse upload fees
- ❌ Does NOT transfer RoC credits
- ❌ Does NOT create audit transactions
Required Behavior
For each document transferred, perform full settlement:
- Reimburse Upload Fees: Find
document_addtransactions for thissource_urland reimburse the original uploader - Transfer RoC Credits: Find
credit_earnedtransactions for thissource_urland transfer to new owner - Create Audit Transactions: Record the transfer with full accounting details
- Update Ownership: Set
documents_${orgId}.user_idto new owner
Implementation Options
Option A: Reuse Queue Settlement Logic
The POST /manageQueue/transfer/:id endpoint already has settlement logic. Extract it into a shared utility that can work by source_url:
// Shared settlement utility
async function settleDocumentTransfer(
supabase: SupabaseClient,
sourceUrl: string,
fromUserId: string,
toUserId: string,
orgId: string
): Promise<SettlementResult>
Option B: Call Queue Transfer for Each Document
If each document has a corresponding queue item, the User Admin endpoint could call the queue transfer endpoint for each document. However, this may not work for documents uploaded before the queue system existed.
Response Format (Suggested)
interface TransferResult {
documentsTransferred: number;
settlementSummary: {
totalFeesReimbursed: number;
totalRocTransferred: number;
documentsSettled: number;
documentsSkipped: number; // e.g., already settled or no transactions
};
details: Array<{
sourceUrl: string;
title: string;
feesReimbursed: number;
rocTransferred: number;
status: 'settled' | 'skipped' | 'error';
}>;
}
Files to Modify
| File | Change |
|---|---|
supabase/functions/adminUsers/handlers/transfer-docs.ts |
Add settlement logic |
supabase/functions/manageQueue/handlers/transfer.ts |
Extract shared settlement utility |
supabase/functions/_shared/settlement.ts |
New shared utility (optional) |
Testing Considerations
- Test with documents that have
credit_earnedtransactions - Test with documents that have no RoC yet (just upload fees)
- Test idempotency (calling transfer twice should not double-settle)
- Test with Google Docs URLs (multiple URL formats for same doc)
Questions for Backend Claude
- Does the existing queue transfer settlement logic handle URL normalization for Google Docs?
- Should we track "already settled" status per document to prevent double-settlement?
- What happens if the original uploader no longer exists in the users table?
Related Files
- Frontend:
dist/js/admin/users.js(line 950 -handleTransfer) - Frontend:
src/admin/users/index.njk(Document Transfer tab) - Backend:
supabase/functions/adminUsers/(current transfer-docs endpoint) - Backend:
supabase/functions/manageQueue/handlers/transfer.ts(existing settlement logic) - Docs:
src/dev/readme_manageQueue.md(queue transfer API docs)