Invoices and records Required
Log every staff action on money
Log every manual refund, credit, price change, discount and subscription change with who did it, when, why and the values before and after.
How to do it
Write the log row in the same transaction as the change. Changes made at the provider, such as a subscription's price, are logged when your admin screen sends them. Require a reason for refunds and credits. Require a second person for refunds above a set amount, such as 10,000 SEK. Keep the log as long as the payment records, in a table the app can only add to. The general rules are in security logging and access logging.
Example
await db.tx(async t => {
const before = await t.one('SELECT id, credit_minor FROM accounts WHERE id = $1 FOR UPDATE', [accountId])
const after = await t.one('UPDATE accounts SET credit_minor = credit_minor + $1 WHERE id = $2 RETURNING id, credit_minor', [creditMinor, accountId])
await t.none('INSERT INTO money_audit (staff_id, action, reason, before, after) VALUES ($1, $2, $3, $4, $5)',
[staffId, 'account.credit', reason, before, after])
})
from psycopg.rows import dict_row
from psycopg.types.json import Jsonb
with connection.transaction(), connection.cursor(row_factory=dict_row) as cursor:
before = cursor.execute("SELECT id, credit_minor FROM accounts WHERE id = %s FOR UPDATE", (account_id,)).fetchone()
after = cursor.execute(
"UPDATE accounts SET credit_minor = credit_minor + %s WHERE id = %s RETURNING id, credit_minor",
(credit_minor, account_id),
).fetchone()
cursor.execute(
"INSERT INTO money_audit (staff_id, action, reason, before, after) VALUES (%s, %s, %s, %s, %s)",
(staff_id, "account.credit", reason, Jsonb(before), Jsonb(after)),
)
How to check
Issue a refund from the admin screen. A log row with the staff ID, reason, amount, time and the values before and after appears. The app role cannot UPDATE or DELETE it.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers payments playbook: https://agentwranglers.se/playbook/payments/invoices-and-records/money-audit-log.