- Entry created via "Inchide" flow now gets status "inchis" with closureInfo
- New DeadlineTimeline component: main deadlines as cards with progress bar,
auto-tracked sub-deadlines as milestone dots on horizontal timeline
- Auto-tracked deadlines hidden from dashboard when user deadlines exist
- Verification milestone shows "Expirat — nu se mai pot solicita clarificari"
- Parent closureInfo now includes linkedEntryId/Number of the closing act
- Removed orphaned deadline-table.tsx and use-deadline-filters.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Major UX overhaul of the "Termene legale" and thread tabs:
Deadline dashboard:
- Replace 6 KPI cards with simple summary bar (active/urgent/overdue)
- Replace flat table with grouped list by entry (cards with progress bars)
- Chain deadlines collapsed by default with expand toggle
- Auto-tracked/background deadlines hidden from main list
Flow diagram (new component):
- CSS-only horizontal flow diagram showing document chains
- Nodes with direction bar (blue=intrat, orange=iesit), number, subject, status
- Solid arrows for thread links, dashed for conex/linked entries
- Used in both "Dosare" tab (full) and detail panel (compact, max 5 nodes)
Thread explorer → Dosare:
- Renamed tab "Fire conversatie" → "Dosare"
- Each thread shown as a card with flow diagram inside
- Simplified stats (just active/finalized count)
Background tracking:
- comunicare-aviz-beneficiar marked as backgroundOnly (not shown in dashboard)
- Transmission status computed and shown in detail panel (on-time/late)
Auto-resolution:
- When closing entry via reply, matching parent deadlines auto-resolve
- Resolution note includes the reply entry number
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only the last entry in a company+year sequence can be deleted. Trying
to delete an earlier number (e.g. #2 when #3 exists) returns a 409
error with a Romanian message explaining the restriction.
Also routes UI deletes through the API (like create/update) so they
get proper audit logging and sequence recalculation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PostgreSQL JSONB value::text serializes JSON with spaces after colons
("number": "B-2026-00001") but all LIKE patterns searched for the
no-space format ("number":"B-2026-00001"), causing zero matches and
every new entry getting sequence #1.
Fixed in allocateSequenceNumber, recalculateSequence, and debug-sequences.
Added PATCH handler to migrate old-format entries (BTG/SDT/USW/GRP)
to new single-letter format (B/S/U/G).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PostgreSQL POSIX regex on the server does not support \d shorthand,
causing SUBSTRING to return NULL and every entry to get sequence 1.
Replaced all \d with [0-9] in:
- allocateSequenceNumber (new + old format queries)
- recalculateSequence (new + old format queries)
- debug-sequences endpoint (GET + POST queries)
Also added samples field to debug GET for raw number diagnostics,
and POST now handles old-format entries (BTG→B mapping) with
ON CONFLICT GREATEST for proper counter merging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New format: single-letter prefix + year + 5-digit sequence.
No direction code (IN/OUT) in the number — shown via arrow icon.
Sequence is shared across directions within the same company+year.
Changes:
- REGISTRY_COMPANY_PREFIX: BTG→B, USW→U, SDT→S, GRP→G
- OLD_COMPANY_PREFIX map for backward compat with existing entries
- allocateSequenceNumber: searches both old and new format entries
to find the actual max sequence (backward compat)
- recalculateSequence: same dual-format search
- parseRegistryNumber: supports 3 formats (current, v1, legacy)
- isNewFormat: updated regex for B-2026-00001
- CompactNumber: already used single-letter badges, just updated comment
- debug-sequences endpoint: updated for new format
- Notification test data: updated to new format
- RegistrySequence.type: now "SEQ" (shared) instead of "IN"/"OUT"
After deploy: POST /api/registratura/debug-sequences to clean up
old counters, then recreate test entries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prisma tagged template literals were mangling regex backslashes.
Switch to $queryRawUnsafe for the complex regex queries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Node 22 (from 20): ~15% faster TypeScript compilation
- BuildKit cache mount on /root/.npm: npm ci reuses cached packages
between builds instead of re-downloading from registry
- NODE_OPTIONS --max-old-space-size=2048: prevents OOM on VMs with
limited RAM during Next.js build
Requires BuildKit enabled (default in Docker 23+, or set
DOCKER_BUILDKIT=1). Portainer CE uses BuildKit by default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous fix still used MAX(actualMax, counterVal) which meant a
stale counter (from entries deleted before the fix was deployed) would
override the actual entry count. Changed to use ONLY actualMax + 1.
The RegistrySequence counter is now just a cache that gets synced —
it never overrides the actual entries count.
Also added /api/registratura/debug-sequences endpoint:
- GET: shows all counters vs actual entry max (for diagnostics)
- POST: resets all counters to match actual entries (one-time fix)
After deploy, call POST /api/registratura/debug-sequences to reset
the stale counters, then delete the BTG-2026-OUT-00004 entry and
recreate it — it will get 00001.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move prisma generate before COPY . . so it's cached when only
source files change (saves ~10-15s per build)
- Use npm ci --ignore-scripts in deps stage (postinstall scripts
not needed, prisma generate runs explicitly)
- Combine apk add + addgroup + adduser into single RUN (fewer layers)
- Expand .dockerignore to exclude .claude/, .vscode/, logs, tsbuildinfo
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The old allocateSequenceNumber blindly incremented a counter in
RegistrySequence, which drifted out of sync when entries were deleted
or moved between companies — producing wrong numbers (e.g., #6 for
the first entry of a company).
New approach:
- Uses pg_advisory_xact_lock inside a Prisma interactive transaction
to serialize concurrent allocations
- Always queries the actual MAX sequence from KeyValueStore entries
(the source of truth) before allocating the next number
- Takes MAX(actual entries, counter) + 1 so the counter can never
produce a stale/duplicate number
- Upserts the counter to the new value for consistency
- Also adds recalculateSequence to DELETE handler so the counter
stays in sync after entry deletions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add min-h-0 + overflow-hidden on ScrollArea to enable scrolling
in the detail side panel (flex child needs bounded height)
- Wrap external status badge Tooltip in TooltipProvider to fix
"Tooltip must be used within TooltipProvider" runtime crash
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The multipart body parser was using the first \r\n\r\n as the file
content start, but this could miss the actual file part. Now properly
iterates through parts to find the one with filename= header, and
uses lastIndexOf for the closing boundary to avoid false matches
inside PDF binary data.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ExternalStatusTracking types + ExternalDocStatus semantic states
- Authority catalog with Primaria Cluj-Napoca (POST scraper + HTML parser)
- Status check service: batch + single entry, change detection via hash
- API routes: cron-triggered batch (/api/registratura/status-check) +
user-triggered single (/api/registratura/status-check/single)
- Add "status-change" notification type with instant email on change
- Table badge: Radio icon color-coded by status (amber/blue/green/red)
- Detail panel: full monitoring section with status, history, manual check
- Auto-detection: prompt when recipient matches known authority
- Activation dialog: configure petitioner name + confirm registration data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Registratura: re-allocate number when company/direction changes on update,
recalculate old company's sequence counter from actual entries
- Extreme PDF: stream body to temp file instead of req.formData() to support large files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Company badges: US→U, SDT→S (B and G already single letter).
Direction: only intrat (↓ green) and iesit (↑ orange), removed intern since no longer used.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace full "BTG-0042/2026" with compact [B] ↓ 0042/2026 format:
- Colored company badge (B=blue, US=violet, SDT=green, G=gray)
- Direction arrow icon (↓ green=intrat, ↑ orange=iesit, ↔ gray=intern)
- Plain number without prefix
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copies "nr. BTG-0042/2026 din 11.03.2026" to clipboard on click.
Small icon, subtle until hover, green check feedback on copy.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
useMemo was called after early return (when deadline=null), violating
React Rules of Hooks. Moved all hooks before the conditional return.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ac-verificare (5z lucr.) now auto-track, created automatically with
any AC emitere type. Informational: authority notifies if incomplete.
- ac-emitere (30z cal.) now chains to ac-emitere-dupa-completari when
interrupted — term recalculates from completion submission date.
- ac-emitere-urgenta (7z lucr.) and ac-emitere-anexe (15z cal.) kept.
- New: ac-prelungire-emitere (15z lucr.) — authority communicates
decision on AC extension within 15 working days.
- Info box in DeadlineAddDialog for autorizare category explaining
auto-tracked verification + interruption mechanism.
- None of the autorizare deadlines have tacit approval.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously DIRECTION_CATEGORIES limited intrat to only completari+contestatie,
so cerere/aviz on intrat direction lost certificat/avize/urbanism/autorizare.
Now cerere/aviz doc types unlock all 6 categories on both directions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Typing {proiect}, {nr}, {an}, {detalii} or {text} in the subject field
now auto-transforms to template mode with the appropriate input widgets
(project dropdown, number fields, etc.).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add "Necesita analiza in comisie" toggle for avize category (mirrors CJ toggle)
- When OFF: auto-creates 5-day working limit for completari requests
- When ON: no limit (institution can request completions anytime)
- Add interruption mechanism: resolve aviz as "intrerupt" when institution
requests completions → auto-creates new 15-day deadline from completions date
- New resolution type "intrerupt" with yellow badge + chain support
- Restructure avize catalog entries:
- aviz-ac-15 (L50) and aviz-urbanism-30 (L350) now have chain to
aviz-emitere-dupa-completari for interruption flow
- aviz-mediu: updated hints about procedure closure prerequisite
- aviz-cultura-comisie: 2-phase with auto-track depunere la comisie (30 days)
- aeronautica, ISU, transport-eu: all get interruption chain
- 3 new auto-track entries: aviz-completari-limit (5zl), aviz-emitere-dupa-completari
(15zc), aviz-cultura-depunere-comisie (30zc)
- New document type: "Convocare sedinta"
- Info boxes in dialog explaining auto-track behavior + interruption mechanism
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix doc type showing "altele" after edit: preserve initial documentType
in allDocTypes map even if not in defaults or Tag Manager
- Filter deadline categories by document type: only cerere/aviz unlock
full permitting categories (CU, avize, urbanism, autorizare)
- Other doc types (scrisoare, notificare, etc.) only get completari +
contestatie as deadline categories
- Add completari to intrat direction (was missing)
- Pass documentType to DeadlineAddDialog for category filtering
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Conex button now adds to linkedEntryIds (for clarificari/solicitari)
instead of setting threadParentId
- Inchide button sets threadParentId (direct reply) + auto-closes parent
- Fix Sterge button persistence bug: threadParentId now saves as empty
string instead of undefined (which was stripped in JSON serialization)
- Card headers: "Conex cu X" (amber) vs "Raspuns la X" (blue + green)
- Add conexTo prop to RegistryEntryForm for linked entry pre-fill
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix threadParentId clear: always show "Sterge" button even when parent not found in allEntries
- Bigger clear button with text label instead of tiny X icon
- Fallback display when parent not in current list (shows truncated ID)
- Close via conex: table/detail "Inchide" now creates a new reply entry that closes the original
- Header shows "Conex la BTG-XXX" + "Inchide originala" badge when closing via conex
- After saving the new conex entry, parent is auto-closed with resolution "finalizat"
- onClose signature changed from (id: string) to (entry: RegistryEntry) across table + detail
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Conex button on table rows (Reply icon, blue) — opens new entry with threadParentId pre-set + flipped direction
- Conex button on detail panel — same behavior
- Inchide button on table rows (CheckCircle2 icon, green) — only for open entries
- replyTo prop on RegistryEntryForm: pre-sets threadParentId + direction flip (intrat→iesit, iesit→intrat)
- Card header shows "Conex la BTG-0042/2026" with blue badge when replying
- Completari moved to last position in deadline category order
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove publicitate/comunicare category entirely (AC publicity handled by AC validity tracker)
- comunicare-aviz-beneficiar moved to auto-track: created alongside any iesit deadline
- Late receipt badge on incoming aviz entries: shows "Primit cu X zile intarziere" when document date < today
- Valabilitate document + AC Validity Tracker visible only when documentType is "aviz" (act administrativ)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- CU has NO tacit approval on any entry
- Direction-dependent categories: iesiri (CU, Avize, Completari, Urbanism, Autorizare), intrari (Contestatie)
- Rename: Analiza → Urbanism (PUD/PUZ/PUG), Autorizare (AC) → Autorizare (AD/AC)
- Auto-track deadlines: cu-verificare (10zl) created automatically with CU emitere
- CJ toggle: auto-creates arhitect-sef solicita aviz (3zc) + primar emite aviz (5zc)
- Verification badge: after 10 days shows "Nu mai pot returna documentatia"
- Prelungire helper: CU issue date + 6/12/24 month calculator
- cu-prelungire-emitere changed to 30zc (practica administrativa)
- New DeadlineTypeDef fields: autoTrack, directionFilter
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add Comunicare, Instiintare under scrisoare
- Add Memoriu justificativ, Studiu de fezabilitate, Audit energetic, Caiet de sarcini under raport
- Add Aviz racordare, Acord unic under aviz
- Add Contract proiectare, PV predare-primire under contract
- Add Borderou, Fisa tehnica, Tema de proiectare, Deviz general, Conventie under altele
- Total seed templates: ~55 across 11 document types
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add SEED_TEMPLATES catalog (11 doc types x 2-4 templates = ~30 predefined patterns)
- Add {proiect} field type with mini-autocomplete from Tag Manager projects
- Pre-fill {an} fields with current year on template selection
- Dynamic placeholder changes based on documentType + direction (22 combinations)
- Dropdown on empty focus: "Sabloane recomandate" + "Recente" sections
- Direction-aware tooltip on Subiect field (intrat vs iesit examples)
- getRecommendedTemplates() merges seeds + DB-learned, DB takes priority
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>