Commit Graph

89 Commits

Author SHA1 Message Date
Claude Agent
7dd39f9712 feat(order-detail): show CODMAT for direct SKUs + mapping validations
- Enrich order detail items with NOM_ARTICOLE data for direct SKUs
  (SKU=CODMAT) that have no ARTICOLE_TERTI entry
- Validate CODMAT exists in nomenclator before saving mapping (400)
- Block redundant self-mapping when SKU is already direct CODMAT (409)
- Show "direct" badge in CODMAT column for direct SKUs
- Show info alert in quick map modal for direct SKUs
- Display backend validation errors inline in modal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 13:10:20 +00:00
Claude Agent
f74322beab fix(dashboard): update sync card after completion + use Bucharest timezone
Sync card was showing previous run data after sync completed because the
last_run query excluded the current run_id even after it finished. Now only
excludes during active running state.

All datetime.now() and SQLite datetime('now') replaced with Europe/Bucharest
timezone to fix times displayed 2 hours behind (was using UTC).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 13:02:18 +00:00
Claude Agent
f5ef9e0811 chore: move working scripts to scripts/work/ (gitignored)
Prevents untracked file conflicts on git pull on Windows server.
Scripts are development/analysis tools, not part of the deployed app.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:34:34 +00:00
Claude Agent
06f8fa5842 cleanup: remove 5 duplicate scripts from scripts/
Removed scripts covered by more complete alternatives:
- match_by_price.py, match_invoices.py → covered by match_all.py
- compare_detail.py → covered by match_all.py
- reset_sqlite.py → covered by delete_imported.py (includes Oracle + dry-run)
- debug_match.py → one-off hardcoded debug script

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:23:40 +00:00
Claude Agent
7a2408e310 fix(import): resolve correct id_articol for duplicate CODMATs + gestiune setting
Unified id_articol selection logic in Python (resolve_codmat_ids) and PL/SQL
(resolve_id_articol): filters sters=0 AND inactiv=0, prefers article with
stock in configured gestiune, falls back to MAX(id_articol). Eliminates
mismatch where Python and PL/SQL could pick different id_articol for the
same CODMAT, causing ORA-20000 price-not-found errors.

- Add resolve_codmat_ids helper in validation_service.py (single batch query)
- Refactor validate_skus/validate_prices/ensure_prices to use it
- Add resolve_id_articol function in PL/SQL package body
- Add p_id_gestiune parameter to importa_comanda (spec + body)
- Add /api/settings/gestiuni endpoint and id_gestiune setting
- Add gestiune dropdown in settings UI

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:18:18 +00:00
Claude Agent
09a5403f83 add: handoff notes for SKU mapping discovery session
Documents what was tried, what worked (order-invoice matching),
what failed (line item matching by price), and proposed strategy
for next session (subset → confirm → generalize).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:06:23 +00:00
Claude Agent
3d73d9e422 add: scripts for invoice-order matching and SKU discovery
Analysis scripts to match GoMag orders with Oracle invoices by
date/client/total, then compare line items by price to discover
SKU → id_articol mappings. Generates SQL for nom_articole codmat
updates and CSV for ARTICOLE_TERTI repackaging/set mappings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 12:01:51 +00:00
Claude Agent
dafc2df0d4 feat(dashboard): auto-refresh after sync, configurable polling, extra filters
- Detect missed sync completions via last_run.run_id comparison
- Load polling interval from settings (dashboard_poll_seconds, default 5s)
- Add 1min/3min scheduler interval options
- Add 1zi/2zile period filter options
- New Dashboard settings card for polling interval

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 11:48:29 +00:00
Claude Agent
5e01fefd4c feat(sync): handle cancelled GoMag orders (status Anulata / statusId 7)
- Add web_status column to orders table (generic name for platform status)
- Filter cancelled orders during sync, record as CANCELLED in SQLite
- Soft-delete previously-imported cancelled orders in Oracle (if not invoiced)
- Add CANCELLED filter pill + badge in dashboard UI
- New soft_delete_order_in_roa() and mark_order_cancelled() functions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 21:50:38 +00:00
Claude Agent
8020b2d14b fix(dashboard): renderClientCell shows customer_name (partner) as primary
renderClientCell was showing shipping_name (person) instead of
customer_name (company/partner). Now shows customer_name with tooltip
for shipping person when different (e.g. company orders).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:28:35 +00:00
Claude Agent
172debdbdb fix(dashboard): show customer_name (partner) instead of shipping_name
Dashboard list was prioritizing shipping_name over customer_name,
so company orders showed the person instead of the company name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:25:56 +00:00
Claude Agent
ecb4777a35 fix(sqlite): update customer_name on upsert, not just on insert
customer_name was only set on INSERT but not updated on ON CONFLICT,
so re-synced orders kept the old (wrong) customer name.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:18:21 +00:00
Claude Agent
cc872cfdad fix(sync): customer_name reflects invoice partner (company or shipping person)
When billing is on a company, customer_name now uses billing.company_name
instead of shipping person name. This aligns SQLite customer_name with the
partner created in ROA by import_service, making order-invoice correlation
possible in the dashboard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 19:14:48 +00:00
Claude Agent
8d58e97ac6 fix(sync): clean old JSON files before downloading new orders
Previous sync runs left JSON files in the output directory, causing
order_reader to accumulate orders from multiple downloads instead of
only processing the latest batch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 18:29:07 +00:00
Claude Agent
b930b2bc85 documentatie 2026-03-16 18:18:45 +00:00
Claude Agent
5dfd795908 fix(sync): detect deleted orders and invoices in ROA
Previously, orders deleted from Oracle (sters=1) remained as IMPORTED
in SQLite, and deleted invoices kept stale cache data. Now the refresh
button and sync cycle re-verify all imported orders against Oracle:
- Deleted orders → marked DELETED_IN_ROA with cleared id_comanda
- Deleted invoices → invoice cache fields cleared
- New status badge for DELETED_IN_ROA in dashboard and logs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 18:18:36 +00:00
Claude Agent
27af22d241 update 2026-03-16 17:56:09 +00:00
Claude Agent
35e3881264 update 2026-03-16 17:55:32 +00:00
Claude Agent
2ad051efbc update 2026-03-16 17:54:09 +00:00
Claude Agent
e9cc41b282 update 2026-03-16 17:53:05 +00:00
Claude Agent
7241896749 update 2026-03-16 17:51:53 +00:00
Claude Agent
9ee61415cf feat(deploy): smart update script with skip-if-no-changes and silent mode
Only pulls and restarts the service when new commits exist.
Supports -Silent flag for Task Scheduler (logs to update.log).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 17:47:24 +00:00
Claude Agent
3208804966 style(ui): move invoice info to right column, single line, no bold
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 17:43:23 +00:00
Claude Agent
8827782aca fix(invoice): require factura_data in cache to avoid missing invoice date
Orders cached before the factura_data column was populated show "-"
for invoice date. Now both detail and dashboard endpoints require
factura_data to be present before using SQLite cache, falling through
to Oracle live query which fetches and caches the date.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 17:40:30 +00:00
Claude Agent
84b24b1434 feat(invoice+import): refresh facturi, detalii factura, fix duplicate CODMAT + rollback
- PL/SQL: handle duplicate CODMAT in nom_articole with MAX(id_articol)
- import_service: add explicit conn.rollback() on Oracle errors
- sync_service: auto-fix stale ERROR orders that exist in Oracle
- invoice_service: add data_act (invoice date) from vanzari table
- sync router: new POST /api/dashboard/refresh-invoices endpoint
- order detail: enrich with invoice data (serie, numar, data factura)
- dashboard: refresh invoices button (desktop + mobile icon)
- quick map modal: compact single-row layout, pre-populate existing mappings
- quick map: link on SKU column instead of CODMAT

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 17:30:23 +00:00
Claude Agent
43327c4a70 feat(oracle): support per-article id_pol in PACK_IMPORT_COMENZI + deploy docs
- PACK_IMPORT_COMENZI: reads optional "id_pol" per article from JSON, uses it
  via NVL(v_id_pol_articol, p_id_pol) — enables separate price policy for
  transport/discount articles vs regular order articles
- README.md: add Windows deploy section (deploy.ps1, update.ps1, .env example)
- CLAUDE.md: add reference to Windows deploy docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:42:41 +00:00
Claude Agent
227dabd6d4 feat(settings): add GoMag API config, Oracle dropdowns, compact 2x2 layout
- Remove ID_GESTIUNE from config (unused)
- Add GoMag API settings (key, shop, days_back, limit) to SQLite — editable without restart
- sync_service reads GoMag settings from SQLite before download
- gomag_client.download_orders accepts api_key/api_shop/limit overrides
- New GET /api/settings/sectii and /api/settings/politici endpoints for Oracle dropdowns
  (nom_sectii.sectie, crm_politici_preturi.nume_lista_preturi)
- id_pol, id_sectie, transport_id_pol, discount_id_pol now use select dropdowns
- order_reader extracts discount_vat from GoMag JSON discounts[].vat
- import_service uses GoMag discount_vat as primary, settings as fallback
- settings.html redesigned to compact 2x2 grid (GoMag API | Import ROA / Transport | Discount)
- settings.js v2: loadDropdowns() sequential before loadSettings()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:39:59 +00:00
Claude Agent
a0649279cf log 2026-03-16 15:51:15 +00:00
Claude Agent
db29822a5b fix(js): add ROOT_PATH to window.location navigations
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:25:43 +00:00
Claude Agent
49471e9f34 fix(js): patch fetch to prepend ROOT_PATH for IIS reverse proxy
All relative /api/... calls automatically get /gomag prefix via
global fetch wrapper in shared.js. ROOT_PATH injected from template.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:19:50 +00:00
Claude Agent
ced6c0a2d4 fix(templates): use root_path for static assets instead of url_for
url_for generates absolute URLs with internal host (localhost:5003)
which browsers block via ERR_BLOCKED_BY_ORB. Using root_path prefix
generates correct relative paths (/gomag/static/...).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:15:56 +00:00
Claude Agent
843378061a feat(deploy): add update.ps1 for Windows server updates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:07:13 +00:00
Claude Agent
a9d0cead79 chore: commit all pending changes including deploy scripts and Windows config
- deploy.ps1, iis-web.config: Windows Server deployment scripts
- api/app/routers/sync.py, dashboard.py: router updates
- api/app/services/import_service.py, sync_service.py: service updates
- api/app/static/css/style.css, js/*.js: UI updates
- api/database-scripts/08_PACK_FACTURARE.pck: Oracle package
- .gitignore: add .gittoken
- CLAUDE.md, agent configs: documentation updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:05:04 +00:00
Claude Agent
ee60a17f00 fix(templates): use url_for for static assets and root_path for nav links
Fixes 404 errors for CSS/JS when served behind IIS reverse proxy with
/gomag prefix. Replaces hardcoded /static/ paths with request.url_for()
and nav links with request.scope root_path prefix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:04:03 +00:00
Claude Agent
926543a2e4 fix(mappings): resolve 409 error on multi-CODMAT edit and make SKU editable
Batch create after soft-delete was rejected because create_mapping()
treated soft-deleted records as conflicts. Added auto_restore param
that restores+updates instead of 409 when called from edit flow.
Also removed readOnly on SKU input in edit modal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 13:31:03 +00:00
Claude Agent
25aa9e544c feat(sync): add delivery cost, discount tracking and import settings
Parse delivery.total and discounts[] from GoMag JSON into new
delivery_cost/discount_total fields. Add app_settings table for
configuring transport/discount CODMAT codes. When configured,
transport and discount are appended as extra articles in the
Oracle import JSON. Reorder Total column in dashboard/logs tables
and show transport/discount breakdown in order detail modals.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 10:15:17 +00:00
Claude Agent
137c4a8b0b feat(ui): order totals, decimals, mobile modal cards, set editing
- Dashboard/Logs: Total column with 2 decimals (order_total)
- Order detail modal: totals summary row (items total + order total)
- Order detail modal mobile: compact article cards (d-md-none)
- Mappings: openEditModal loads all CODMATs for SKU, saveMapping
  replaces entire set via delete-all + batch POST
- Add project-specific team agents: ui-templates, ui-js, ui-verify,
  backend-api
- CLAUDE.md: mandatory preview approval before implementation,
  fix-loop after verification, server must start via start.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 21:55:58 +00:00
Claude Agent
ac8a01eb3e chore: add .playwright-mcp to gitignore
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:21:17 +00:00
Claude Agent
c4fa643eca feat(sync): add order_total field to SQLite tracking
Parse order total from GoMag JSON, store in SQLite orders table,
and expose via sync run API. Enables total display in mobile flat rows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:20:57 +00:00
Claude Agent
9a6bec33ff docs: rewrite CLAUDE.md and README.md, remove VFP references
- Remove all Visual FoxPro references (VFP fully replaced by Python)
- Add TeamCreate workflow for parallel UI development
- Document before/preview/after visual verification with Playwright
- Add mandatory rule: use TeamCreate, not superpowers subagents
- Update architecture, tech stack, project structure to current state
- Update import flow to reference Python services

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:20:36 +00:00
Claude Agent
680f670037 feat(ui): mobile UI polish with segmented controls and responsive navbar
- Replace filter pills with btn-group segmented controls on mobile (all pages)
- Add renderMobileSegmented() shared utility with colored count badges
- Compact sync card and logs run selector on mobile
- Unified flat-row format: dot + date + name + count (0.875rem throughout)
- Responsive navbar with short labels on mobile (Acasa/Mapari/Lipsa/Jurnale)
- Vertical dots icon (bi-three-dots-vertical) without dropdown caret
- Shorter "Mapare" button text on mobile, Re-scan in context menu
- Top pagination on logs page, hide per-page selector on mobile
- Cache-bust static assets to v=5

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:20:24 +00:00
Claude Agent
5a0ea462e5 fix(validation): remove non-existent find_new_orders call
Replace broken asyncio.to_thread call with len(importable)
which already represents orders ready to process.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:59:05 +00:00
Claude Agent
452dc9b9f0 feat(mappings): strict validation + silent CSV skip for missing CODMAT
Add Pydantic validators and service-level checks that reject empty SKU/CODMAT
on create/edit (400). CSV import now silently skips rows without CODMAT and
counts them in skipped_no_codmat instead of treating them as errors.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:46:59 +00:00
Claude Agent
9cacc19d15 fix(ui): fix set pct badge logic and compact CODMAT form layout
- Fix is_complete check: use abs(pct-100)<=0.01 instead of >=99.99
  so sets with >100% total are correctly shown as incomplete
- Show pct badge with 2 decimals (e.g. "⚠️ 200.00%")
- Remove product name pre-fill in missing SKUs map modal CODMAT field
- Compact CODMAT lines to single row with placeholders instead of labels

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:21:49 +00:00
Claude Agent
15ccbe028a fix(dashboard): fix pill counts and Bootstrap UI cleanup
- IMPORTED pill now includes ALREADY_IMPORTED orders in count
- UNINVOICED filter includes ALREADY_IMPORTED orders
- Pill counts (Toate/Importate/Omise/Erori/Nefacturate) always reflect
  full period+search, independent of active status filter
- Nefacturate count computed from SQLite cache across full period,
  not just current page
- Bootstrap UI: design tokens, soft badge pills, consistent font sizes,
  purge inline styles from templates, move badge-pct to style.css

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:05:43 +00:00
Claude Agent
b69b5e7104 feat(sync): add GoMag API client with Phase 0 auto-download
- New gomag_client.py service: async httpx client that downloads orders
  from GoMag API with full pagination and 1s rate-limit sleep
- config.py: add GOMAG_API_KEY, GOMAG_API_SHOP, GOMAG_ORDER_DAYS_BACK,
  GOMAG_LIMIT, GOMAG_API_URL settings
- sync_service.py: Phase 0 downloads fresh orders before reading JSONs;
  graceful skip if API keys not configured
- start.sh: auto-detect INSTANTCLIENTPATH from .env, fallback to thin mode
- .env.example: document GoMag API variables

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 23:03:39 +00:00
2e65855fe2 feat(sync): already_imported tracking, invoice cache, path fixes, remove vfp
- Track already_imported/new_imported counts separately in sync_runs
  and surface them in status API + dashboard last-run card
- Cache invoice data in SQLite orders table (factura_* columns);
  dashboard falls back to Oracle only for uncached imported orders
- Resolve JSON_OUTPUT_DIR and SQLITE_DB_PATH relative to known
  anchored roots in config.py, independent of CWD (fixes WSL2 start)
- Use single Oracle connection for entire validation phase (perf)
- Batch upsert web_products instead of one-by-one
- Remove stale VFP scripts (replaced by gomag-vending.prg workflow)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 00:15:37 +02:00
8681a92eec fix(logs): use status_at_run for per-run order counts and filtering
orders.status preserves IMPORTED over ALREADY_IMPORTED to avoid
overwriting historical data, so per-run journal views must use
sync_run_orders.status_at_run to show what actually happened in
that specific run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 00:12:10 +02:00
f52c504c2b chore: ignore SQLite auxiliary files (journal, wal, shm)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 18:02:08 +02:00
77a89f4b16 docs: update README and .env.example for project root start convention
Fix start command (python -m uvicorn api.app.main:app from project root),
correct JSON_OUTPUT_DIR path (vfp/output not ../vfp/output), document
all env variables with descriptions, add dashboard features overview,
business rules, and WSL2 notes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 17:59:58 +02:00