fix(drafts): serialize draft session flushes and register reminders via fds__setReminder
Playwright Tests / test (push) Canceled after 0s
Playwright Tests / test (push) Canceled after 0s
Make invoice/reminder live-draft edits concurrency-safe with an explicit DraftFlushResult, add the fds__setReminder stored procedure, and harden the date helper functions. Includes concurrency and SQL contract tests. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
d0002ccdad
commit
546648533b
@@ -107,16 +107,15 @@ public partial class IntranetController
|
||||
{
|
||||
if (!HasForm("token")) return BadRequest400();
|
||||
string token = Form("token");
|
||||
var before = _invoiceDrafts.Get(token);
|
||||
if (before == null) return DraftGone();
|
||||
bool existed = !string.IsNullOrEmpty(before.InvId);
|
||||
|
||||
var fdInv = await _invoiceDrafts.FlushToDbAsync(token, UserAccountID, DbSec);
|
||||
if (fdInv == null) return DraftGone();
|
||||
// Create vs update is decided inside the flush (flushes of one session are serialised), not
|
||||
// from the session state seen here: a save overlapping the first registration is an update.
|
||||
var flush = await _invoiceDrafts.FlushToDbAsync(token, UserAccountID, DbSec);
|
||||
if (flush == null) return DraftGone();
|
||||
var fdInv = flush.Data;
|
||||
if (string.IsNullOrEmpty(fdInv.Id))
|
||||
return await InvoiceIssueResult("Der Zwischenstand konnte aufgrund eines Fehlers nicht gespeichert werden.");
|
||||
|
||||
await _events.InvoiceDraftRegisteredAsync(fdInv, existed, UserAccountID);
|
||||
await _events.InvoiceDraftRegisteredAsync(fdInv, flush.Updated, UserAccountID);
|
||||
var after = _invoiceDrafts.Get(token);
|
||||
if (after != null) await _draftNotifier.SignalDraftReadyAsync(after.Token, after.Version);
|
||||
return await JSONAsync(new { ok = true, invid = fdInv.Id });
|
||||
|
||||
@@ -82,16 +82,14 @@ public partial class IntranetController
|
||||
{
|
||||
if (!HasForm("token")) return BadRequest400();
|
||||
string token = Form("token");
|
||||
var before = _reminderDrafts.Get(token);
|
||||
if (before == null) return DraftGone();
|
||||
bool existed = !string.IsNullOrEmpty(before.RemId);
|
||||
|
||||
var fdRem = await _reminderDrafts.FlushToDbAsync(token, UserAccountID, DbSec);
|
||||
if (fdRem == null) return DraftGone();
|
||||
// Create vs update is decided inside the flush (serialised per session) — see HandleDraftSave.
|
||||
var flush = await _reminderDrafts.FlushToDbAsync(token, UserAccountID, DbSec);
|
||||
if (flush == null) return DraftGone();
|
||||
var fdRem = flush.Data;
|
||||
if (string.IsNullOrEmpty(fdRem.Id))
|
||||
return await ReminderIssueResult("Der Zwischenstand konnte aufgrund eines Fehlers nicht gespeichert werden.");
|
||||
|
||||
await _events.ReminderDraftRegisteredAsync(fdRem, existed, UserAccountID);
|
||||
await _events.ReminderDraftRegisteredAsync(fdRem, flush.Updated, UserAccountID);
|
||||
var after = _reminderDrafts.Get(token);
|
||||
if (after != null) await _draftNotifier.SignalDraftReadyAsync(after.Token, after.Version);
|
||||
return await JSONAsync(new { ok = true, remid = fdRem.Id });
|
||||
|
||||
Reference in New Issue
Block a user