fix(uat-batch-2): external-EOI five-bug bundle (a/b/c/d) + presign filename override

Tackles the linked B4 #5 findings on the external-EOI flow. Item (e)
[Edit metadata affordance per row] is deferred to a later wave so it
can share infra with the broader signing-flow rework.

- (a) lying toast: uploadExternallySignedEoi now returns
  { stageChanged, newStage }. Client toasts conditionally so a
  Reservation+ deal that uploads paper-signing evidence no longer
  claims the stage advanced.
- (b) View downloads instead of previewing: SignedPdfActions takes an
  onView callback; InterestEoiTab lifts a single FilePreviewDialog and
  passes the callback down. Click-View opens the in-app preview rather
  than the presigned URL (which the storage backend served as
  attachment).
- (c) UUID filename on download: getDownloadUrl now passes the
  canonical filename through presignDownloadUrl; S3 backend adds a
  response-content-disposition override (filename + UTF-8 filename*)
  to the presign. Filesystem backend already passed it through.
- (d) Discarded dateEoiSigned: external-eoi service splits document-
  metadata writes (always — dateEoiSigned, eoiStatus='signed') from
  stage advance (gated on past-EOI). Also fires
  evaluateRule('eoi_signed') so berth-rules stay in sync when an EOI
  is filed manually.
- Default title for external-EOI dialog now derives
  "External EOI — <Client> — <berth range> — <date>" via the existing
  formatBerthRange helper; rep can override.

tsc clean. 1419/1419 vitest pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-21 17:01:35 +02:00
parent abbaf406ab
commit 6cdb9af6b2
5 changed files with 170 additions and 48 deletions

View File

@@ -149,7 +149,11 @@ export async function uploadFile(
export async function getDownloadUrl(id: string, portId: string) {
const file = await getFileById(id, portId);
const url = await presignDownloadUrl(file.storagePath);
// Pass the canonical filename through to the presign so MinIO/S3
// returns Content-Disposition with the original name. Without the
// override the file lands with the bare storage-key UUID (no
// extension) in every browser.
const url = await presignDownloadUrl(file.storagePath, 900, file.filename);
return { url, filename: file.filename };
}