/** * Read-only worker earnings/payout ledger. */ response = { "OK": false }; try { requestData = deserializeJSON(toString(getHttpRequestData().content)); userID = val(requestData.UserID ?: 0); if (userID == 0 && structKeyExists(request, "UserID")) { userID = val(request.UserID); } if (userID == 0) { response["ERROR"] = "missing_params"; response["MESSAGE"] = "UserID is required."; writeOutput(serializeJSON(response)); abort; } // Get ledger entries (most recent first) qLedger = queryTimed(" SELECT ID, TaskID, GrossEarningsCents, ActivationWithheldCents, NetTransferCents, Status, CreatedAt FROM WorkPayoutLedgers WHERE UserID = :userID ORDER BY CreatedAt DESC LIMIT 100 ", { userID: userID }, { datasource: "payfrit" }); // Get totals qTotals = queryTimed(" SELECT COALESCE(SUM(GrossEarningsCents), 0) AS TotalGrossCents, COALESCE(SUM(ActivationWithheldCents), 0) AS TotalWithheldCents, COALESCE(SUM(CASE WHEN Status = 'transferred' THEN NetTransferCents ELSE 0 END), 0) AS TotalTransferredCents FROM WorkPayoutLedgers WHERE UserID = :userID ", { userID: userID }, { datasource: "payfrit" }); ledgerEntries = []; for (row in qLedger) { arrayAppend(ledgerEntries, { "ID": row.ID, "TaskID": row.TaskID, "GrossEarningsCents": row.GrossEarningsCents, "ActivationWithheldCents": row.ActivationWithheldCents, "NetTransferCents": row.NetTransferCents, "Status": row.Status, "CreatedAt": dateTimeFormat(row.CreatedAt, "yyyy-MM-dd'T'HH:nn:ss") & "Z" }); } response["OK"] = true; response["LEDGER"] = ledgerEntries; response["TOTALS"] = { "TotalGrossCents": val(qTotals.TotalGrossCents), "TotalWithheldCents": val(qTotals.TotalWithheldCents), "TotalTransferredCents": val(qTotals.TotalTransferredCents) }; } catch (any e) { response["ERROR"] = e.message; } writeOutput(serializeJSON(response));