Fachlogik fuer Guthaben, CC-Lebenszyklus und Import
Die beiden zentralen Regeln stehen jeweils an genau einer Stelle: Ein CC-Paket erzeugt immer CC +1 und REDESIGN_PAID +1. Die Zeilen dafuer baut buildPackageRows, das sowohl die manuelle Eingabe als auch der Import nutzen - so koennen beide Wege nicht auseinanderlaufen. Ein CC kommt nur dann gratis zurueck, wenn er wegen Spieler-Inaktivitaet entfernt wurde. Ein reworkter CC existiert im Original nicht mehr und kostet deshalb ein Redesign- oder CC-Guthaben. Ueberzogene Toepfe werden zugelassen statt blockiert; die Aktion meldet das ueber ein overdrawn-Flag zurueck. Storniert wird per Gegenbuchung, nie durch Loeschen. Der Import berechnet den Plan vorab und dedupliziert ueber die Bestell-ID, sowohl gegen bereits gebuchte als auch innerhalb einer Datei.
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import type { Prisma } from '@prisma/client';
|
||||
import { prisma } from '../db.js';
|
||||
|
||||
export interface ActionContext {
|
||||
// null fuer Vorgaenge ohne angemeldeten Account, etwa ein fehlgeschlagener Login.
|
||||
actorId: number | null;
|
||||
actorName: string;
|
||||
ip?: string | undefined;
|
||||
}
|
||||
|
||||
export interface AuditEntry {
|
||||
action: string;
|
||||
targetType: string;
|
||||
targetId?: string | number | null;
|
||||
details?: Prisma.InputJsonValue;
|
||||
}
|
||||
|
||||
type Client = Pick<typeof prisma, 'auditLog'>;
|
||||
|
||||
export async function recordAudit(
|
||||
client: Client,
|
||||
ctx: ActionContext,
|
||||
entry: AuditEntry,
|
||||
): Promise<void> {
|
||||
await client.auditLog.create({
|
||||
data: {
|
||||
actorUserId: ctx.actorId,
|
||||
actorName: ctx.actorName,
|
||||
action: entry.action,
|
||||
targetType: entry.targetType,
|
||||
targetId: entry.targetId == null ? null : String(entry.targetId),
|
||||
details: entry.details ?? undefined,
|
||||
ip: ctx.ip ?? null,
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user