Files
roa2web-service-auto/.claude/plans/immutable-chasing-flute.md
Claude Agent 1b9ebf1d8f feat(dashboard): Complete dashboard desktop cleanup and improvements
User Stories Completed:
- US-001: Eliminare SolduriCompactCard de pe Desktop
- US-002: Eliminare Icoane din Header-ul CollapsibleCard
- US-003: Reorganizare TreasuryDualCard - Text Înainte de Grafice
- US-004: Reorganizare ClientiBalanceCard - Text Înainte de Grafice
- US-005: Reorganizare FurnizoriBalanceCard - Text Înainte de Grafice
- US-006: Grafice Colapsabile în TreasuryDualCard
- US-007: Grafice Colapsabile în ClientiBalanceCard
- US-008: Grafice Colapsabile în FurnizoriBalanceCard
- US-009: Grafice Colapsabile în CashFlowMetricCard

Additional Improvements:
- Add cache metadata display (CacheFooter component) for all dashboard cards
- Add @cached decorators to get_monthly_flows and get_indicators_with_sparklines
- Fix financial indicators calculations and sparkline sync
- Add state reset on company change to prevent stale data
- New shared components: CacheFooter.vue, authRedirect.js
- Enhanced FinancialIndicatorsCard with sparklines and period selection

Squashed from branch: ralph/dashboard-desktop-cleanup (11 commits)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 07:27:27 +00:00

6.8 KiB

Plan: Curățare Cod ROA2WEB (High ROI, Low Risk)

Sumar Executiv

Arhitectura ROA2WEB este solidă pentru o echipă de 1-2 developeri. Nu necesită schimbări arhitecturale.

Acest plan conține doar optimizări tactice sigure cu randament mare.


Acțiuni de Curățare (Prioritizate)

1. Elimină Store Duplication

ROI: | Risc: Foarte Scăzut | Efort: 15 min

Problema: sharedStores.js identic în 2 module (42 linii duplicate)

Fișiere de șters:

  • src/modules/reports/stores/sharedStores.js
  • src/modules/data-entry/stores/sharedStores.js

Soluție: Instantiază stores direct în App.vue

// App.vue
import { createAuthStore } from '@shared/stores/auth'
import { createCompaniesStore } from '@shared/stores/companies'
import { createAccountingPeriodStore } from '@shared/stores/accountingPeriod'
import authApi from '@shared/services/authApi'

const useAuthStore = createAuthStore(authApi)
const useCompanyStore = createCompaniesStore(authApi, useAuthStore)
const useAccountingPeriodStore = createAccountingPeriodStore(authApi)

Verificare: App funcționează normal, stores disponibile în componente


2. Factory pentru API Services

ROI: | Risc: Scăzut | Efort: 30 min

Problema: api.js duplicat în module (70% cod identic, 156 linii total)

Fișier de creat: src/shared/services/createApiService.js

// createApiService.js (~50 linii)
import axios from 'axios'

export function createApiService(basePath, options = {}) {
  const api = axios.create({
    baseURL: import.meta.env.BASE_URL + `api/${basePath}`,
    headers: { 'Content-Type': 'application/json' }
  })

  api.interceptors.request.use(config => {
    const token = localStorage.getItem('access_token')
    if (token) config.headers.Authorization = `Bearer ${token}`

    if (options.injectCompany) {
      // Logic pentru X-Selected-Company header
    }

    if (config.data instanceof FormData) {
      delete config.headers['Content-Type']
    }
    return config
  })

  api.interceptors.response.use(
    response => response,
    error => {
      if (error.response?.status === 401) {
        localStorage.removeItem('access_token')
        window.location.href = '/login'
      }
      return Promise.reject(error)
    }
  )

  return api
}

Fișiere simplificate (5 linii fiecare):

// src/modules/reports/services/api.js
import { createApiService } from '@shared/services/createApiService'
export default createApiService('reports')

// src/modules/data-entry/services/api.js
import { createApiService } from '@shared/services/createApiService'
export default createApiService('data-entry', { injectCompany: true })

Verificare: Login funcționează, API calls returnează date


3. Dependențe OCR Opționale (Lazy Loading)

ROI: | Risc: Foarte Scăzut | Efort: 30 min

Problema: PaddleOCR + pytesseract se instalează și încarcă mereu, chiar dacă nu sunt folosite

Soluție: Fă-le opționale via .env și lazy loading

Fișier .env - adaugă:

# OCR Engines (true = instalează și încarcă, false = skip)
OCR_ENABLE_PADDLEOCR=false
OCR_ENABLE_TESSERACT=false

Fișier backend/requirements.txt - mută în secțiune opțională:

# Required OCR
python-doctr[torch]>=0.8.0

# Optional OCR (install only if needed)
# paddleocr>=2.7.0      # Uncomment if OCR_ENABLE_PADDLEOCR=true
# paddlepaddle>=2.5.0   # Uncomment if OCR_ENABLE_PADDLEOCR=true
# pytesseract>=0.3.10   # Uncomment if OCR_ENABLE_TESSERACT=true

SAU creează requirements-ocr-optional.txt:

paddleocr>=2.7.0
paddlepaddle>=2.5.0
pytesseract>=0.3.10

Fișier OCR service - lazy import:

# backend/modules/data_entry/services/ocr_service.py
import os
from functools import lru_cache

@lru_cache()
def get_paddleocr():
    if os.getenv('OCR_ENABLE_PADDLEOCR', 'false').lower() == 'true':
        from paddleocr import PaddleOCR
        return PaddleOCR(use_angle_cls=True, lang='ro')
    return None

@lru_cache()
def get_tesseract():
    if os.getenv('OCR_ENABLE_TESSERACT', 'false').lower() == 'true':
        import pytesseract
        return pytesseract
    return None

Beneficiu:

  • Păstrează alternativele pentru viitor
  • Nu se instalează/încarcă dacă nu sunt necesare
  • Startup mai rapid când sunt dezactivate
  • ~500MB saved când false

Verificare:

  • Cu false: App pornește fără PaddleOCR/Tesseract instalate
  • Cu true: OCR fallback funcționează

4. Consolidare Design Tokens CSS

ROI: | Risc: Scăzut | Efort: 1 oră

Problema: 3 fișiere cu tokens overlap: variables.css, tokens.css, md3-tokens.css

Soluție: Consolidează în src/assets/css/core/design-tokens.css

Pași:

  1. Creează design-tokens.css unificat
  2. Migrează variabilele din cele 3 fișiere
  3. Actualizează importurile în main.css
  4. Șterge fișierele vechi

Verificare: Testează light mode ȘI dark mode pe toate paginile


Acțiuni Opționale (Dacă Ai Timp)

5. Split receiptStore (Opțional)

ROI: | Risc: Mediu | Efort: 2-3 ore

Problema: 606 linii într-un singur store

Soluție: Split în 3 stores (receipts, workflow, nomenclatures)

De făcut doar dacă: Lucrezi frecvent pe data-entry module


6. Simplificare Cache (Opțional)

ROI: | Risc: Mediu | Efort: 2-3 ore

Problema: 7 fișiere cache, unele nefolosite

Soluție: Reduce la 3 fișiere

De făcut doar dacă: Ai nevoie să modifici cache logic


Impact Total (Acțiuni 1-4)

Metrică Înainte După Diferență
Linii cod duplicat ~200 ~50 -150
OCR deps obligatorii 3 0 opționale via .env
Fișiere CSS tokens 3 1 -2
Store duplication 42 linii 0 -42
Startup time (OCR off) ~5s ~2s -3s
Timp total - - ~2.5 ore

Ordinea Recomandată

  1. [15 min] Elimină store duplication
  2. [30 min] Factory pentru API services
  3. [30 min] OCR dependencies opționale (lazy loading)
  4. [1 oră] Consolidare CSS tokens

Total: ~2.5 ore pentru toate 4 acțiunile principale


Verificare Finală

După fiecare acțiune:

  • App pornește fără erori
  • Login funcționează
  • Un raport se încarcă
  • O chitanță se creează
  • Dark mode arată corect

Ce NU Schimbăm

  • Arhitectura Layered - potrivită pentru echipa de 1-2 devs
  • Module isolation (reports, data-entry, telegram)
  • Router/Store Factory patterns
  • Auth middleware
  • Cache decorator @cached
  • Oracle pool singleton

Plan simplificat: doar curățare cod cu randament mare și risc minim.