fix(delivery-note-editor): "Save & show document" was not saving at all

The operator's report: change the quantities, press Save & show, and
the document still carries the old numbers — it "just reverts back".

It wasn't reverting. **The button never saved anything.** Its handler
was:

    onOpenChange(false);
    onSaved?.(deliveryNoteNumber);

which is exactly what Cancel does — close the dialog, show the PDF. The
`save()` call lived only on "Save changes". So the operator changed the
quantities, pressed the button, got the OLD document, and drew the
reasonable conclusion that their edit hadn't taken.

Both buttons now go through `save()`, which takes a flag for whether
to show the document afterwards. The document opens only after the
save resolves, so what she sees is what she just saved.

## Ruled out along the way

Three plausible alternatives, each checked and cleared rather than
assumed:

  - **Browser cache.** No — the PDF route already sends
    `Cache-Control: private, no-store`.
  - **Attachment stacking.** No — `regenerateDeliveryNotePdf` replaces
    the file rather than appending; every item on a regenerated note
    carries exactly one attachment, so reading index [0] is correct.
  - **Silent regeneration failure.** No — `pdfRegenerated: true` comes
    back from the PATCH, and the file's last-modified advances on each
    save.

Verified in the browser on DN26100904: quantity 2 -> 9 via "Save & show
document" now persists to the database AND advances the PDF's
last-modified, i.e. the regenerated document carries the new number.
Data restored to 150/150/150/2 afterwards.

Full suite 3832 passing, tsc clean.
This commit is contained in:
Dave 2026-10-09 12:23:33 +02:00
parent 5b8e9e87bd
commit bc6c4fdb31
2 changed files with 21 additions and 17 deletions

View file

@ -1787,14 +1787,12 @@ export default function DeliveryNotesPage() {
onOpenChange={(v) => setNoteEditor((prev) => ({ ...prev, open: v }))}
deliveryNoteId={noteEditor.noteId}
deliveryNoteNumber={noteEditor.number}
onSaved={(dnNumber) => {
onSaved={(dnNumber, showDocument) => {
setNoteEditor((prev) => ({ ...prev, open: false }));
// Refresh so the next quote review starts from what was
// just saved rather than the values fetched at page load,
// then bring the document back — "save, and show me what
// I just saved".
// just saved rather than the values fetched at page load.
void fetchNotes().then(() => {
if (dnNumber) setPreviewDnNumber(dnNumber);
if (showDocument && dnNumber) setPreviewDnNumber(dnNumber);
});
}}
/>

View file

@ -64,9 +64,12 @@ export interface DeliveryNoteEditorDialogProps {
onOpenChange: (open: boolean) => void;
deliveryNoteId: string;
deliveryNoteNumber: string;
/** Called after a successful save, with the DN number, so the host
* can bring the document back up for printing. */
onSaved?: (deliveryNoteNumber: string) => void;
/**
* Called after a SUCCESSFUL save, with the note number. The second
* argument is true when the operator pressed "Save & show document",
* so the host knows to bring the PDF up afterwards.
*/
onSaved?: (deliveryNoteNumber: string, showDocument: boolean) => void;
}
export function DeliveryNoteEditorDialog({
@ -152,7 +155,7 @@ export function DeliveryNoteEditorDialog({
);
};
const save = async () => {
const save = async (showDocumentAfter = false) => {
setSaving(true);
try {
// Sequential rather than parallel: these rewrite the same DN
@ -184,7 +187,12 @@ export function DeliveryNoteEditorDialog({
`Saved ${lines.length} line${lines.length === 1 ? "" : "s"} on ${deliveryNoteNumber}.`,
);
onOpenChange(false);
onSaved?.(deliveryNoteNumber);
// The host opens the document when it gets the number back.
// Passing it here rather than on the button's own click is the
// whole fix: the old "Save & show document" closed the dialog
// and showed the PDF WITHOUT saving, so the operator saw the
// old quantities and reasonably concluded the edit hadn't taken.
onSaved?.(deliveryNoteNumber, showDocumentAfter);
} catch (err: unknown) {
toast.error(
err instanceof Error ? err.message : "Failed to save the delivery note",
@ -373,21 +381,19 @@ export function DeliveryNoteEditorDialog({
>
Cancel
</Button>
{/* Close without saving, but still show the document —
most times someone opens this to LOOK, not change. */}
{/* Saves, THEN shows the document. It used to only close
and show — which looked exactly like "my change was
ignored" because the PDF still carried the old numbers. */}
<Button
variant="outline"
onClick={() => {
onOpenChange(false);
onSaved?.(deliveryNoteNumber);
}}
onClick={() => void save(true)}
disabled={saving}
data-testid="dn-editor-preview"
>
Save &amp; show document
</Button>
<Button
onClick={() => void save()}
onClick={() => void save(false)}
disabled={saving || loading || lines.length === 0}
data-testid="dn-editor-save"
>