diff --git a/CLAUDE.md b/CLAUDE.md index 4fdbcf5..18c5fcf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -106,6 +106,13 @@ python3 scripts/sync_vending_to_mariusm.py --apply --yes Sincronizează via SSH din VENDING (prod Windows) în MARIUSM_AUTO (dev ROA_CENTRAL): nom_articole (noi by codmat, codmat updatat) + articole_terti (noi, modificate, soft-delete). +## Design System + +Always read DESIGN.md before making any visual or UI decisions. +All font choices, colors, spacing, and aesthetic direction are defined there. +Do not deviate without explicit user approval. +In QA mode, flag any code that doesn't match DESIGN.md. + ## Deploy Windows Vezi [README.md](README.md#deploy-windows) diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 0000000..61a94b4 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,318 @@ +# Design System — GoMag Vending + +## Product Context +- **What this is:** Internal admin dashboard for importing web orders from GoMag e-commerce into ROA Oracle ERP +- **Who it's for:** Ops/admin team who monitor order sync daily, fix SKU mappings, check import errors +- **Space/industry:** Internal tools, B2B operations, ERP integration +- **Project type:** Data-heavy admin dashboard (tables, status indicators, sync controls) + +## Aesthetic Direction +- **Direction:** Industrial/Utilitarian — function-first, data-dense, quietly confident +- **Decoration level:** Minimal — typography and color do the work. No illustrations, gradients, or decorative elements. The data IS the decoration. +- **Mood:** Command console. This tool says "built by someone who respects the operator." Serious, efficient, warm. +- **Anti-patterns:** No purple gradients, no 3-column icon grids, no centered-everything layouts, no decorative blobs, no stock-photo heroes + +## Typography + +### Font Stack +- **Display/Headings:** Space Grotesk — geometric, slightly techy, distinctive `a` and `g`. Says "engineered." +- **Body/UI:** DM Sans — clean, excellent readability, good tabular-nums for inline numbers +- **Data/Tables:** JetBrains Mono — order IDs, CODMATs, status codes align perfectly. Tables become scannable. +- **Code:** JetBrains Mono + +### Loading +```html + + + +``` + +### CSS Variables +```css +--font-display: 'Space Grotesk', sans-serif; +--font-body: 'DM Sans', sans-serif; +--font-data: 'JetBrains Mono', monospace; +``` + +### Type Scale +| Level | Size | Weight | Font | Usage | +|-------|------|--------|------|-------| +| Page title | 18px | 600 | Display | "Panou de Comanda" | +| Section title | 16px | 600 | Display | Card headers | +| Label/uppercase | 12px | 500 | Display | Column headers, section labels (letter-spacing: 0.04em) | +| Body | 14px | 400 | Body | Paragraphs, descriptions | +| UI/Button | 13px | 500 | Body | Buttons, nav links, form labels | +| Data cell | 13px | 400 | Data | Table cells, order IDs | +| Data small | 12px | 400 | Data | Timestamps, secondary data | +| Code/mono | 11px | 400 | Data | Inline code, debug info | + +## Color + +### Approach: Restrained with warm accent +Every admin tool is blue. This one uses amber — reads as "operational" and "attention-worthy." + +### Light Mode (default) +```css +:root { + /* Surfaces */ + --bg: #F8F7F5; /* warm off-white, not clinical gray */ + --surface: #FFFFFF; + --surface-raised: #F3F2EF; /* hover states, table headers */ + --card-shadow: 0 1px 3px rgba(28,25,23,0.1), 0 1px 2px rgba(28,25,23,0.06); + + /* Text */ + --text-primary: #1C1917; /* warm black */ + --text-secondary: #57534E; /* warm gray */ + --text-muted: #78716C; /* labels, timestamps */ + + /* Borders */ + --border: #E7E5E4; + --border-subtle: #F0EFED; + + /* Accent — amber */ + --accent: #D97706; + --accent-hover: #B45309; + --accent-light: #FEF3C7; /* amber backgrounds */ + --accent-text: #92400E; /* text on amber bg */ + + /* Semantic */ + --success: #16A34A; + --success-light: #DCFCE7; + --success-text: #166534; + + --warning: #CA8A04; + --warning-light: #FEF9C3; + --warning-text: #854D0E; + + --error: #DC2626; + --error-light: #FEE2E2; + --error-text: #991B1B; + + --info: #2563EB; + --info-light: #DBEAFE; + --info-text: #1E40AF; + + --cancelled: #78716C; + --cancelled-light: #F5F5F4; +} +``` + +### Dark Mode +Strategy: invert surfaces, reduce accent saturation ~15%, keep semantic colors recognizable. + +```css +[data-theme="dark"] { + --bg: #121212; + --surface: #1E1E1E; + --surface-raised: #2A2A2A; + --card-shadow: 0 1px 3px rgba(0,0,0,0.4), 0 1px 2px rgba(0,0,0,0.3); + + --text-primary: #E8E4DD; /* warm bone white */ + --text-secondary: #A8A29E; + --text-muted: #78716C; + + --border: #333333; + --border-subtle: #262626; + + --accent: #F59E0B; + --accent-hover: #D97706; + --accent-light: rgba(245,158,11,0.12); + --accent-text: #FCD34D; + + --success: #16A34A; + --success-light: rgba(22,163,74,0.15); + --success-text: #4ADE80; + + --warning: #CA8A04; + --warning-light: rgba(202,138,4,0.15); + --warning-text: #FACC15; + + --error: #DC2626; + --error-light: rgba(220,38,38,0.15); + --error-text: #FCA5A5; + + --info: #2563EB; + --info-light: rgba(37,99,235,0.15); + --info-text: #93C5FD; + + --cancelled: #78716C; + --cancelled-light: rgba(120,113,108,0.15); +} +``` + +### Status Color Mapping +| Status | Dot Color | Badge BG | Glow | +|--------|-----------|----------|------| +| IMPORTED | `--success` | `--success-light` | none (quiet when healthy) | +| ERROR | `--error` | `--error-light` | `0 0 8px 2px rgba(220,38,38,0.35)` | +| SKIPPED | `--warning` | `--warning-light` | `0 0 6px 2px rgba(202,138,4,0.3)` | +| ALREADY_IMPORTED | `--info` | `--info-light` | none | +| CANCELLED | `--cancelled` | `--cancelled-light` | none | +| DELETED_IN_ROA | `--cancelled` | `--cancelled-light` | none | + +**Design rule:** Problems glow, success is calm. The operator's eye is pulled to rows that need action. + +## Spacing +- **Base unit:** 4px +- **Density:** Comfortable — not cramped, not wasteful +- **Scale:** + +| Token | Value | Usage | +|-------|-------|-------| +| 2xs | 2px | Tight internal gaps | +| xs | 4px | Icon-text gap, badge padding | +| sm | 8px | Compact card padding, table cell padding | +| md | 16px | Standard card padding, section gaps | +| lg | 24px | Section spacing | +| xl | 32px | Major section gaps | +| 2xl | 48px | Page-level spacing | +| 3xl | 64px | Hero spacing (rarely used) | + +## Layout + +### Approach: Grid-disciplined, full-width +Tables with 8+ columns and hundreds of rows need every pixel of width. + +- **Nav:** Horizontal top bar, fixed, 48px height. Active tab has amber underline (2px). +- **Content max-width:** None on desktop (full-width for tables), 1200px for non-table content +- **Grid:** Single-column layout, cards stack vertically +- **Breakpoints:** + +| Name | Width | Columns | Behavior | +|------|-------|---------|----------| +| Desktop | >= 1024px | Full width | All features visible | +| Tablet | 768-1023px | Full width | Nav labels abbreviated, tables scroll horizontally | +| Mobile | < 768px | Single column | Bottom nav, cards stack, condensed views | + +### Border Radius +| Token | Value | Usage | +|-------|-------|-------| +| sm | 4px | Buttons, inputs, badges, status dots | +| md | 8px | Cards, dropdowns, modals | +| lg | 12px | Large containers, mockup frames | +| full | 9999px | Pills, avatar circles | + +## Motion +- **Approach:** Minimal-functional — only transitions that aid comprehension +- **Easing:** enter(ease-out) exit(ease-in) move(ease-in-out) +- **Duration:** + +| Token | Value | Usage | +|-------|-------|-------| +| micro | 50-100ms | Button hover, focus ring | +| short | 150-250ms | Dropdown open, tab switch, color transitions | +| medium | 250-400ms | Modal open/close, page transitions | +| long | 400-700ms | Only for sync pulse animation | + +- **Sync pulse:** The live sync dot uses a 2s infinite pulse (opacity 1 → 0.4 → 1) +- **No:** entrance animations, scroll effects, decorative motion + +## Mobile Design + +### Navigation +- **Bottom tab bar** replaces top horizontal nav on screens < 768px +- 5 tabs: Dashboard, Mapari, Lipsa, Jurnale, Setari +- Each tab: icon (Bootstrap Icons) + short label below +- Active tab: amber accent color, inactive: `--text-muted` +- Height: 56px, safe-area padding for notched devices +- Fixed position bottom, with `padding-bottom: env(safe-area-inset-bottom)` + +```css +@media (max-width: 767px) { + .top-navbar { display: none; } + .bottom-nav { + position: fixed; + bottom: 0; + left: 0; + right: 0; + height: 56px; + padding-bottom: env(safe-area-inset-bottom); + background: var(--surface); + border-top: 1px solid var(--border); + display: flex; + justify-content: space-around; + align-items: center; + z-index: 1000; + } + .main-content { + padding-bottom: 72px; /* clear bottom nav */ + padding-top: 8px; /* no top navbar */ + } +} +``` + +### Dashboard — Mobile +- **Sync card:** Full width, stacked vertically + - Status + controls row wraps to 2 lines + - Sync button full-width at bottom of card + - Last sync info wraps naturally +- **Orders table:** Condensed card view instead of horizontal table + - Each order = a compact card showing: status dot + ID + client name + total + - Tap to expand: shows date, factura, full details + - Swipe left on card: quick action (view error details) +- **Filter bar:** Horizontal scrollable chips instead of dropdowns + - Period selector: pill chips (1zi, 7zi, 30zi, Toate) + - Status filter: colored chips matching status colors +- **Touch targets:** Minimum 44x44px for all interactive elements + +### Orders Mobile Card Layout +``` +┌────────────────────────────────┐ +│ ● CMD-47832 2,450.00 RON│ +│ SC Automate Express SRL │ +│ 27.03.2026 · FCT-2026-1847 │ +└────────────────────────────────┘ +``` +- Status dot (8px, left-aligned with glow for errors) +- Order ID in JetBrains Mono, amount right-aligned +- Client name in DM Sans +- Date + factura in muted data font + +### SKU Mappings — Mobile +- Each mapping = expandable card +- Collapsed: SKU + product name + type badge (KIT/SIMPLU) +- Expanded: Full CODMAT list with quantities +- Search: Full-width sticky search bar at top +- Filter: Horizontal scrollable type chips + +### Logs — Mobile +- Timeline view instead of table +- Each log entry = timestamp + status icon + summary +- Tap to expand full log details +- Infinite scroll with date separators + +### Settings — Mobile +- Standard stacked form layout +- Full-width inputs +- Toggle switches for boolean settings (min 44px touch target) +- Save button sticky at bottom + +### Gestures +- **Pull to refresh** on Dashboard: triggers sync status check +- **Swipe left** on order card: reveal quick actions +- **Long press** on SKU mapping: copy CODMAT to clipboard +- **No swipe navigation** between pages (use bottom tabs) + +### Mobile Typography Adjustments +| Level | Desktop | Mobile | +|-------|---------|--------| +| Page title | 18px | 16px | +| Body | 14px | 14px (no change) | +| Data cell | 13px | 13px (no change) | +| Data small | 12px | 12px (no change) | +| Table header | 12px | 11px | + +### Responsive Images & Icons +- Use Bootstrap Icons throughout (already loaded via CDN) +- Icon size: 16px desktop, 20px mobile (larger touch targets) +- No images in the admin interface (data-only) + +## Decisions Log +| Date | Decision | Rationale | +|------|----------|-----------| +| 2026-03-27 | Initial design system created | Created by /design-consultation. Industrial/utilitarian aesthetic with amber accent, Space Grotesk + DM Sans + JetBrains Mono. | +| 2026-03-27 | Amber accent over blue | Every admin tool is blue. Amber reads as "operational" and gives the tool its own identity. Confirmed by Claude subagent ("Control Room Noir" also converged on amber). | +| 2026-03-27 | JetBrains Mono for data tables | Both primary analysis and subagent independently recommended monospace for data tables. Scannability win outweighs the ~15% wider columns. | +| 2026-03-27 | Warm tones throughout | Off-white (#F8F7F5) instead of clinical gray. Warm black text instead of blue-gray. Makes the tool feel handcrafted. | +| 2026-03-27 | Glowing status dots for errors | Problems glow (box-shadow), success is calm. Operator's eye is pulled to rows that need action. Inspired by subagent's "LED indicator" concept. | +| 2026-03-27 | Full mobile design | Bottom nav, card-based order views, touch-optimized gestures. Supports quick-glance usage from phone. | diff --git a/api/database-scripts/06_pack_import_comenzi.pck b/api/database-scripts/06_pack_import_comenzi.pck index 931e918..36d634e 100644 --- a/api/database-scripts/06_pack_import_comenzi.pck +++ b/api/database-scripts/06_pack_import_comenzi.pck @@ -1,74 +1,3 @@ --- ==================================================================== --- PACK_IMPORT_COMENZI --- Package pentru importul comenzilor din platforme web (GoMag, etc.) --- in sistemul ROA Oracle. --- --- Dependinte: --- Packages: PACK_COMENZI (adauga_comanda, adauga_articol_comanda) --- pljson (pljson_list, pljson) - instalat in CONTAFIN_ORACLE, --- accesat prin PUBLIC SYNONYM --- Tabele: ARTICOLE_TERTI (mapari SKU -> CODMAT) --- NOM_ARTICOLE (nomenclator articole ROA) --- COMENZI (verificare duplicat comanda_externa) --- CRM_POLITICI_PRETURI (flag PRETURI_CU_TVA per politica) --- CRM_POLITICI_PRET_ART (preturi componente kituri) --- --- Proceduri publice: --- --- importa_comanda(...) --- Importa o comanda completa: creeaza comanda + adauga articolele. --- p_json_articole accepta: --- - array JSON: [{"sku":"X","quantity":"1","price":"10","vat":"19"}, ...] --- - obiect JSON: {"sku":"X","quantity":"1","price":"10","vat":"19"} --- Optional per articol: "id_pol":"5" — politica de pret specifica --- (pentru transport/discount cu politica separata de cea a comenzii) --- Valorile sku, quantity, price, vat sunt extrase ca STRING si convertite. --- Daca comanda exista deja (comanda_externa), nu se dubleaza. --- La eroare ridica RAISE_APPLICATION_ERROR(-20001, mesaj). --- Returneaza v_id_comanda (OUT) = ID-ul comenzii create. --- --- Parametri kit pricing: --- p_kit_mode — 'distributed' | 'separate_line' | NULL --- distributed: discountul fata de suma componentelor se distribuie --- proportional in pretul fiecarei componente --- separate_line: componentele se insereaza la pret plin + --- linii discount separate per-kit sub componente, grupate pe cota TVA --- p_id_pol_productie — politica de pret pentru articole de productie --- (cont in 341/345); NULL = nu se foloseste --- p_kit_discount_codmat — CODMAT-ul articolului discount (Mode separate_line) --- p_kit_discount_id_pol — id_pol pentru liniile discount (Mode separate_line) --- --- Logica cautare articol per SKU: --- 1. Mapari speciale din ARTICOLE_TERTI (reimpachetare, seturi compuse) --- - daca SKU are >1 rand si p_kit_mode IS NOT NULL: kit pricing logic --- - altfel (1 rand sau kit_mode NULL): pret web / cantitate_roa direct --- 2. Fallback: cautare directa in NOM_ARTICOLE dupa CODMAT = SKU --- --- get_last_error / clear_error --- Management erori pentru orchestratorul VFP. --- --- Exemplu utilizare: --- DECLARE --- v_id NUMBER; --- BEGIN --- PACK_IMPORT_COMENZI.importa_comanda( --- p_nr_comanda_ext => '479317993', --- p_data_comanda => SYSDATE, --- p_id_partener => 1424, --- p_json_articole => '[{"sku":"5941623003366","quantity":"1.00","price":"40.99","vat":"21"}]', --- p_id_pol => 39, --- v_id_comanda => v_id); --- DBMS_OUTPUT.PUT_LINE('ID comanda: ' || v_id); --- END; --- 20.03.2026 - dual policy vanzare/productie, kit pricing distributed/separate_line, SKU→CODMAT via ARTICOLE_TERTI --- 20.03.2026 - kit discount deferred cross-kit (separate_line, merge-on-collision) --- 20.03.2026 - merge_or_insert_articol: merge cantitati cand kit+individual au acelasi articol/pret --- 20.03.2026 - kit pricing extins pt reambalari single-component (cantitate_roa > 1) --- 21.03.2026 - diagnostic detaliat discount kit (id_pol, id_art, codmat in eroare) --- 21.03.2026 - fix discount amount: v_disc_amt e per-kit, nu se imparte la v_cantitate_web --- 25.03.2026 - skip negative kit discount (markup), ROUND prices to nzecimale_pretv --- 25.03.2026 - kit discount inserat per-kit sub componente (nu deferred cross-kit) --- ==================================================================== CREATE OR REPLACE PACKAGE PACK_IMPORT_COMENZI AS -- Variabila package pentru ultima eroare (pentru orchestrator VFP) @@ -98,6 +27,31 @@ END PACK_IMPORT_COMENZI; / CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_COMENZI AS + -- ==================================================================== + -- PACK_IMPORT_COMENZI + -- Package pentru importul comenzilor din platforme web (GoMag, etc.) + -- in sistemul ROA Oracle. + -- + -- Dependinte: + -- Packages: PACK_COMENZI (adauga_comanda, adauga_articol_comanda) + -- pljson (pljson_list, pljson) - instalat in CONTAFIN_ORACLE, + -- accesat prin PUBLIC SYNONYM + -- Tabele: ARTICOLE_TERTI (mapari SKU -> CODMAT) + -- NOM_ARTICOLE (nomenclator articole ROA) + -- COMENZI (verificare duplicat comanda_externa) + -- CRM_POLITICI_PRETURI (flag PRETURI_CU_TVA per politica) + -- CRM_POLITICI_PRET_ART (preturi componente kituri) + + -- 20.03.2026 - dual policy vanzare/productie, kit pricing distributed/separate_line, SKU→CODMAT via ARTICOLE_TERTI + -- 20.03.2026 - kit discount deferred cross-kit (separate_line, merge-on-collision) + -- 20.03.2026 - merge_or_insert_articol: merge cantitati cand kit+individual au acelasi articol/pret + -- 20.03.2026 - kit pricing extins pt reambalari single-component (cantitate_roa > 1) + -- 21.03.2026 - diagnostic detaliat discount kit (id_pol, id_art, codmat in eroare) + -- 21.03.2026 - fix discount amount: v_disc_amt e per-kit, nu se imparte la v_cantitate_web + -- 25.03.2026 - skip negative kit discount (markup), ROUND prices to nzecimale_pretv + -- 25.03.2026 - kit discount inserat per-kit sub componente (nu deferred cross-kit) + -- ==================================================================== + -- Constante pentru configurare c_id_util CONSTANT NUMBER := -3; -- Sistem c_interna CONSTANT NUMBER := 2; -- Comenzi de la client (web)