feat: Add PWA support and consolidate CSS design system
- Add PWA manifest, icons (192x192, 512x512), and service worker - Register service worker in index.html with Apple mobile web app support - Consolidate CSS variables and design tokens documentation - Update PrimeVue overrides for consistent theming - Refactor data-entry components to use shared CSS patterns - Add frontend-style-auditor agent for style consistency checks - Minor OCR validation and job worker improvements - Update start-prod.sh configuration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -353,9 +353,9 @@ async def start_job_worker() -> bool:
|
||||
logger.info("[JobWorker] Pre-warming OCR worker pool (background)...")
|
||||
warmup_success = await ocr_worker_pool.prewarm(timeout=90.0)
|
||||
if warmup_success:
|
||||
logger.info("[JobWorker] ✅ OCR worker pool pre-warmed successfully")
|
||||
logger.info("[JobWorker] OCR worker pool pre-warmed successfully")
|
||||
else:
|
||||
logger.warning("[JobWorker] ⚠️ Worker pool pre-warm failed, first request will be slower")
|
||||
logger.warning("[JobWorker] Worker pool pre-warm failed, first request will be slower")
|
||||
|
||||
asyncio.create_task(_background_prewarm())
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ class PaymentSumRule(ValidationRule):
|
||||
return ValidationResult(
|
||||
is_valid=False,
|
||||
confidence_penalty=0.4,
|
||||
message=f"Payment sum {payment_sum:.2f} RON ≠ Total {total:.2f} RON (diff: {diff:.2f} RON). Consider auto-correction.",
|
||||
message=f"Payment sum {payment_sum:.2f} RON != Total {total:.2f} RON (diff: {diff:.2f} RON). Consider auto-correction.",
|
||||
severity="error"
|
||||
)
|
||||
|
||||
@@ -299,7 +299,7 @@ class TVAEntriesSumRule(ValidationRule):
|
||||
return ValidationResult(
|
||||
is_valid=False,
|
||||
confidence_penalty=0.2,
|
||||
message=f"TVA entries sum {entries_sum:.2f} RON ≠ TVA total {tva_total:.2f} RON (diff: {diff:.2f} RON)",
|
||||
message=f"TVA entries sum {entries_sum:.2f} RON != TVA total {tva_total:.2f} RON (diff: {diff:.2f} RON)",
|
||||
severity="warning"
|
||||
)
|
||||
|
||||
@@ -783,7 +783,7 @@ class OCRValidationEngine:
|
||||
else:
|
||||
warnings.append(msg)
|
||||
|
||||
print(f" ❌ {msg}", flush=True)
|
||||
print(f" [X] {msg}", flush=True)
|
||||
|
||||
# Track confidence penalty for the relevant field based on rule
|
||||
if result.confidence_penalty > 0:
|
||||
@@ -797,7 +797,7 @@ class OCRValidationEngine:
|
||||
if f in extraction_result:
|
||||
confidence_adjustments[f] = result.confidence_penalty
|
||||
else:
|
||||
print(f" ✅ {rule.rule_name}: {result.message}", flush=True)
|
||||
print(f" [OK] {rule.rule_name}: {result.message}", flush=True)
|
||||
|
||||
# Step 2: Cross-field validation
|
||||
print("\n[Validation] Step 2: Cross-field validation...", flush=True)
|
||||
@@ -812,7 +812,7 @@ class OCRValidationEngine:
|
||||
else:
|
||||
warnings.append(msg)
|
||||
|
||||
print(f" ❌ {msg}", flush=True)
|
||||
print(f" [X] {msg}", flush=True)
|
||||
|
||||
# Track confidence penalty for the relevant field based on rule
|
||||
if result.confidence_penalty > 0:
|
||||
@@ -826,7 +826,7 @@ class OCRValidationEngine:
|
||||
if f in extraction_result:
|
||||
confidence_adjustments[f] = result.confidence_penalty
|
||||
else:
|
||||
print(f" ✅ {rule.rule_name}: {result.message}", flush=True)
|
||||
print(f" [OK] {rule.rule_name}: {result.message}", flush=True)
|
||||
|
||||
# Step 3: Inter-OCR consistency checks
|
||||
if light_result and medium_result:
|
||||
@@ -845,7 +845,7 @@ class OCRValidationEngine:
|
||||
if not result.is_valid:
|
||||
msg = f"[Inter-OCR] {result.message}"
|
||||
warnings.append(msg)
|
||||
print(f" ❌ {msg}", flush=True)
|
||||
print(f" [X] {msg}", flush=True)
|
||||
|
||||
# Store ratio for metadata
|
||||
ratio = max(
|
||||
@@ -854,7 +854,7 @@ class OCRValidationEngine:
|
||||
) / min(light_result["amount"], medium_result["amount"])
|
||||
inter_ocr_ratios["amount"] = ratio
|
||||
else:
|
||||
print(f" ✅ {result.message}", flush=True)
|
||||
print(f" [OK] {result.message}", flush=True)
|
||||
|
||||
# Determine if manual review is needed
|
||||
# Only flag for review if there are errors OR high-severity warnings
|
||||
|
||||
@@ -124,7 +124,7 @@ class OCRService:
|
||||
|
||||
# Check if memory is high - force GC before processing
|
||||
if mem_before > self._memory_threshold_mb:
|
||||
print(f"[OCR Service] ⚠️ Memory high ({mem_before:.0f}MB > {self._memory_threshold_mb}MB), forcing GC...", flush=True)
|
||||
print(f"[OCR Service] WARNING: Memory high ({mem_before:.0f}MB > {self._memory_threshold_mb}MB), forcing GC...", flush=True)
|
||||
gc.collect()
|
||||
mem_after_gc = get_memory_usage_mb()
|
||||
print(f"[OCR Service] Memory after pre-GC: {mem_after_gc:.0f}MB", flush=True)
|
||||
@@ -188,7 +188,7 @@ class OCRService:
|
||||
extraction.raw_text = "\n\n".join(raw_texts)
|
||||
elapsed_ms = int((time.time() - start_time) * 1000)
|
||||
extraction.processing_time_ms = elapsed_ms
|
||||
print(f"[OCR] ✓✓✓ EARLY EXIT at Step 1 - All fields found! ({elapsed_ms}ms) ✓✓✓", flush=True)
|
||||
print(f"[OCR] *** EARLY EXIT at Step 1 - All fields found! ({elapsed_ms}ms) ***", flush=True)
|
||||
# Cleanup before return
|
||||
del image
|
||||
if images:
|
||||
@@ -244,7 +244,7 @@ class OCRService:
|
||||
extraction.ocr_engine = "paddle-adaptive"
|
||||
elapsed_ms = int((time.time() - start_time) * 1000)
|
||||
extraction.processing_time_ms = elapsed_ms
|
||||
print(f"[OCR] ✓✓✓ EARLY EXIT at Step 2 - All fields found after merge! ({elapsed_ms}ms) ✓✓✓", flush=True)
|
||||
print(f"[OCR] *** EARLY EXIT at Step 2 - All fields found after merge! ({elapsed_ms}ms) ***", flush=True)
|
||||
# Cleanup before return
|
||||
del image
|
||||
if images:
|
||||
@@ -399,7 +399,7 @@ class OCRService:
|
||||
print(f" - Needs Manual Review: {extraction.needs_manual_review}", flush=True)
|
||||
if extraction.validation_warnings:
|
||||
for warning in extraction.validation_warnings:
|
||||
print(f" ⚠️ {warning}", flush=True)
|
||||
print(f" [!] {warning}", flush=True)
|
||||
|
||||
return True, message, extraction
|
||||
|
||||
@@ -611,7 +611,7 @@ class OCRService:
|
||||
print(f"[OCR] Missing: {', '.join(missing)} - continuing", flush=True)
|
||||
return False
|
||||
|
||||
print(f"[OCR] ✓ All 5 fields found with {ext.overall_confidence:.0%} confidence", flush=True)
|
||||
print(f"[OCR] OK: All 5 fields found with {ext.overall_confidence:.0%} confidence", flush=True)
|
||||
return True
|
||||
|
||||
def _complement_extraction(
|
||||
|
||||
@@ -157,7 +157,7 @@ class EventMonitor:
|
||||
# Changes detected!
|
||||
logger.info(
|
||||
f"Schema {schema} (company {company_id}): "
|
||||
f"id_act changed {cached_watermark} → {current_max}"
|
||||
f"id_act changed {cached_watermark} -> {current_max}"
|
||||
)
|
||||
|
||||
# Update watermark
|
||||
|
||||
Reference in New Issue
Block a user