feat: undo mistaken moves, numbered pagination, and quieter Kanban messages
All checks were successful
Build and deploy / Validate source (push) Successful in 6s
Build and deploy / Integration suite on a real stack (push) Successful in 2m33s
Build and deploy / Secret scan and release gate (push) Successful in 7s
Build and deploy / Publish images (push) Successful in 1m48s

Moves: an order can go back one stage (BACK in app/runtime.py) with an
internal reason, flagged in the history as movements.back. The customer is
not notified and approved finals stay; "production started" and "ready" are
now enqueued once per order, so undoing and redoing a move sends nothing
twice. Dragging only goes forward and highlights the allowed column. Move
errors are in Portuguese.

Lists: the send log, payments (open, resolved as history, all) and quotes
are paged on the server with a total, 20 rows by default (10/20/50/100),
first/previous/page/next/last. The send log filters by destination, status,
event and order. Older finished orders load on demand. The board no longer
carries the send log or payment rows, only the open-payment count.

Kanban: Pagamentos and Integrações are separate tabs; messages are brief,
bottom notifications that clear themselves; wording is shorter.

Full CI integration sequence passes locally, with new checks for undo, paging
and filters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cauê Faleiros
2026-09-24 16:01:31 -03:00
parent 99a558ddd9
commit 2e03b0362b
12 changed files with 434 additions and 127 deletions

View File

@@ -138,6 +138,15 @@ try{
await kanban.click(`[data-order="${oid}"] [data-move="${state}"]`);
await waitFor(()=>kanban.eval(`board.orders.find(o=>o.id==='${oid}').state==='${state}'`),'transition '+state);
}
// Undo a mistaken move from the panel: one stage back with an internal reason.
await waitFor(()=>kanban.eval(`!!document.querySelector('[data-order="${oid}"] [data-back="imp"]')`),'back button');
await kanban.click(`[data-order="${oid}"] [data-back="imp"]`);
await kanban.fill(`[data-order="${oid}"] form.reason input`,'Movido por engano (teste)');
await kanban.eval(`document.querySelector('[data-order="${oid}"] form.reason input').closest('form').requestSubmit()`);
await waitFor(()=>kanban.eval(`board.orders.find(o=>o.id==='${oid}').state==='imp'`),'undo to Imprimindo');
await waitFor(()=>kanban.eval(`!!document.querySelector('[data-order="${oid}"] [data-move="fin"]')`),'move to Finalizado again');
await kanban.click(`[data-order="${oid}"] [data-move="fin"]`);
await waitFor(()=>kanban.eval(`board.orders.find(o=>o.id==='${oid}').state==='fin'`),'finished again');
// Reload proves the board is persisted on the backend.
await kanban.call('Page.reload');
await waitFor(()=>kanban.eval(`typeof board!=='undefined' && !!board && board.orders.some(o=>o.id==='${oid}'&&o.state==='fin')`),'persisted board');