Skip to content

[ttp1-ts] Single current-batch screen with per-file cards (TTP task 1) - #23

Merged
FranciscoMateusVG merged 3 commits into
portal-tsfrom
team/ttp1-ts/coder
Oct 9, 2026
Merged

FranciscoMateusVG merged 3 commits into
portal-tsfrom
team/ttp1-ts/coder

Conversation

@FranciscoMateusVG

Copy link
Copy Markdown
Owner

TTP task 1 (trial ttp1-ts): replace "list of orders → open one order" with one home screen showing the current print batch, against the frozen v2 contract (monorepo-incluir #1053 @ 27022467). No backend/contract change, no new dependency.

What changed

  • Port/adapters → v2: PrintApi now speaks /api/print-portal/v2 (batches, open batch, member file/quote downloads, collected/quotes/printed commands, v2 monthly closes). Zod mirror of every v2 $def (strict, plus the itemCount/unique-order/each-file-once invariants). HTTP adapter keeps the same hardening (fixed origin, no redirects, timeouts, size caps, strict parsing). Memory fake reimplements the batch rules (one current batch per supplier, queued requests, receipt/cancellation forming the next batch with previouslyCancelledIn, ETag/If-Match, idempotency replay/conflict, 428).
  • Home / = the one current batch: open via GET /batches/open, else the active collected…printed batch (open is null then). It shows the reference, status, counts, a progress bar (Pronto → Arquivos retirados → Orçamento enviado → Orçamento aprovado → Impresso) and one card per file grouped under its request (IMP-0001 · title): name, size, copies, instructions and Baixar arquivo. Unpaired legacy files get a "Sem vínculo seguro" card, and each request's residual text goes in its own "Instruções gerais" block, never merged across requests. A request with a backend previouslyCancelledIn shows a warning. With no batch, the empty state reads "Nenhum pedido aguardando".
  • Actions by state, only the allowed one is rendered. Each needs explicit confirmation (dialog + server-side confirmed=1) and sends If-Match = batch ETag and an Idempotency-Key that is kept across ambiguous retries:
    • open → "Retirei os arquivos": checkbox "Conferi todos os arquivos", and the dialog shows the file and request counts. A 412 re-renders the changed batch and requires reconfirmation.
    • files_collected / quote_rejected → one quote for the whole batch, with the rejection reason shown.
    • quote_pending / printed → waiting messages only.
    • quote_approved → "Marcar como impresso".
  • Lotes anteriores (/batches) with paginated history and a read-only detail (/batches/:id) that reuses the same cards. Notas fiscais now reads v2 closes (batch charges link to the batch; legacy orders are labelled).
  • The old /orders screens, the per-order commands and /api/print/v1 are removed. The BFF mirrors v2 at /api/print/v2 (session auth, CSRF/Origin, no browser Authorization, same upload caps).
  • data-ttp smoke markers are on the real rendered components.

Verification

  • pnpm check green locally (lint, structure, depcruise, typecheck, builds, codegen drift, 211 tests with coverage thresholds, examples, bundle smoke, hooks).

  • Acceptance tests (tests/unit/portal-batch-html.test.ts) run through the real Hono app (login form, cookies, Origin, CSRF), seeded with the frozen fixture snapshots and their real PDFs. They cover:

    • markers and contract order
    • byte-exact downloads (session only)
    • legacy residual text and the cancelled warning
    • collect without the checkbox, 412 + reconfirmation
    • 415/413 quote errors
    • 503 retries with the same key, both before and after an upstream commit (no duplicate quote)
    • printed
    • per-state actions
    • history and the empty state

    The PrintApi conformance suite runs on both the memory fake and the HTTP adapter over a real socket.

  • Ran the shared smoke helper (infra/ttp/feature_smoke.py verify) against a locally running portal over real HTTP for all 10 checkpoints (flow ×7, cancel ×2, empty-history): all pass, downloads hash-verified.

Note: infra/ is untouched. infra/ttp/fake-upstream.ts (the old in-repo v1 fake, superseded by the pinned staging/ttp-fake-v2) still imports tests/helpers/print-portal-v1.fixture.json, so that one v1 fixture file stays.

🤖 Generated with Claude Code

Francisco Mateus and others added 3 commits October 9, 2026 12:07
Move the print-shop portal from the v1 per-order API to the frozen v2
batch contract (monorepo-incluir #1053 @ 27022467):

- Home `/` is the ONE current batch (open, or the active
  collected…printed batch, since /batches/open is null then): header with
  reference/status/counts, progress bar, one card per file grouped under
  its request, residual "Instruções gerais" per request, and the backend's
  previouslyCancelledIn warning. Empty state "Nenhum pedido aguardando".
- State-driven batch actions with explicit confirmation, If-Match = batch
  ETag and an Idempotency-Key kept across ambiguous retries: "Retirei os
  arquivos" (checkbox + dialog; 412 re-renders the changed batch and needs
  reconfirmation), one quote for the whole batch, "Marcar como impresso".
  Waiting states show their message and no action.
- "Lotes anteriores" history with a read-only detail using the same cards;
  "Notas fiscais" reads v2 monthly closes (batch + legacy charges).
- Old order list/detail screens and per-order commands are removed; the
  BFF JSON API now mirrors /api/print-portal/v2 as /api/print/v2.
- Neutral data-ttp smoke markers on the real rendered components.

Tests go through the real Hono app/HTTP boundaries, seeded with the
frozen fixture and its real PDFs; the PrintApi conformance suite runs on
both the memory fake and the HTTP adapter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Quote and NF parts went upstream as untyped Blobs; the v2 upstream (and
the pinned staging fake) refuses a declared type that differs from the
sniffed content with 415, so every valid PDF quote/NF failed in staging.
The HTTP adapter now labels the part with the type its magic bytes show
(PDF/JPEG/PNG/WebP, else octet-stream so upstream still answers 415),
independent of what the browser declared.

The HTTP test fake now enforces declared == sniffed like upstream, which
turned the HTTP conformance quote/NF cases red first; a new end-to-end
test drives the HTML quote and NF forms through PrintApiHttp. The sniffer
is a pure domain function shared with the memory fake.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@FranciscoMateusVG
FranciscoMateusVG merged commit 8ab2074 into portal-ts Oct 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant