ocr extract

This commit is contained in:
Claude Agent
2026-01-07 14:34:07 +00:00
parent 22eca953ce
commit cc98d6f21f
24 changed files with 774 additions and 2346 deletions

View File

@@ -1,41 +1,9 @@
# Claude Learn: Backend
# Claude Learn: backend
<!-- paths: backend/**/*.py, backend/modules/**/*, requirements.txt -->
**Domain**: backend
**Last updated**: 2026-01-06
**Sessions recorded**: 1
Knowledge about FastAPI, Python services, Oracle DB, and backend architecture.
---
## Patterns
### ProfileRegistry cu Hot-Reload pentru Store Profiles
**Discovered**: 2026-01-06 (feature: ocr-store-profiles)
**Description**: Sistem de înregistrare profile OCR folosind decorator `@ProfileRegistry.register` cu hot-reload via `importlib.reload()`. Permite adăugarea/modificarea profilelor fără restart server.
**Example** (`backend/modules/data_entry/services/ocr/profiles/__init__.py`):
```python
class ProfileRegistry:
_profiles: Dict[str, Type["BaseStoreProfile"]] = {}
_instances: Dict[str, "BaseStoreProfile"] = {}
@classmethod
def register(cls, profile_class):
"""Decorator to register a store profile class."""
for cui in profile_class.CUI_LIST:
cls._profiles[cls._normalize_cui(cui)] = profile_class
return profile_class
@classmethod
def reload_all(cls):
"""Hot-reload all profile modules via importlib.reload()."""
cls._instances.clear()
for module_name in cls._get_profile_module_names():
importlib.reload(sys.modules[f"backend...profiles.{module_name}"])
```
**Usage**:
## P: ProfileRegistry cu Hot-Reload pentru Store Profiles
@2026-01-06 #registry-pattern #hot-reload #decorator | inferred:med
Sistem de înregistrare profile OCR folosind decorator `@ProfileRegistry.register` cu hot-reload via `importlib.reload()`. Permite adăugarea/modificarea profilelor fără restart server.
```python
@ProfileRegistry.register
class LidlProfile(BaseStoreProfile):
@@ -45,36 +13,12 @@ class LidlProfile(BaseStoreProfile):
# Lookup
profile = ProfileRegistry.get_profile("22891860")
# Hot-reload (endpoint)
POST /api/data-entry/ocr/profiles/reload
# Hot-reload endpoint: POST /api/data-entry/ocr/profiles/reload
```
**Tags**: registry-pattern, hot-reload, decorator, ocr, singleton
---
### Script generare cod Python din analiză PDF
**Discovered**: 2026-01-06 (feature: ocr-store-profiles)
**Description**: Script care analizează PDF-uri via OCR API, detectează pattern-uri (TVA format, date format, payment) și generează automat cod Python pentru profile noi. Include JWT auth, async polling, și verificare sintaxă.
**Example** (`scripts/generate_store_profile.py`):
```python
def analyze_tva_patterns(results: List[Dict]) -> Dict:
"""Detectează format TVA dominant din rezultatele OCR."""
tva_formats = defaultdict(int)
for text in raw_texts:
if re.search(r'TVA\s+[A-D]\s+\d{1,2}', text_upper):
tva_formats["lidl_multi_rate"] += 1
if re.search(r'BAZA\s+TVA', text_upper):
tva_formats["table"] += 1
return {"dominant_format": max(tva_formats, key=tva_formats.get)}
def generate_profile_code(store_name, cui, tva_analysis, ...):
"""Generează cod Python pentru clasa de profil."""
# Template-based generation cu OCR error variants
```
**Usage**:
## P: Script generare cod Python din analiză PDF
@2026-01-06 #code-generation #ocr #automation | inferred:med
Script care analizează PDF-uri via OCR API, detectează pattern-uri (TVA format, date format, payment) și generează automat cod Python pentru profile noi. Include JWT auth, async polling, și verificare sintaxă.
```bash
# Dry-run pentru preview
python scripts/generate_store_profile.py \
@@ -88,19 +32,19 @@ python scripts/generate_store_profile.py \
--output backend/.../profiles/magazin_nou.py
```
**Tags**: code-generation, ocr, automation, cli-tool
## G: OCR Worker Pool rulează în procese separate - restart complet necesar
@2026-01-07 #ocr #worker-pool #hot-reload | inferred:med
**P**: Modificările în fișierele de profile OCR nu sunt încărcate automat de uvicorn --reload pentru că OCR worker pool rulează în procese separate (multiprocessing).
**S**: Trebuie restart COMPLET al backend-ului cu `./start-backend.sh restart`. Hot-reload-ul uvicorn nu reîncarcă procesele worker separate.
---
## G: TOTAL_PATTERNS în profile OCR trebuie să aibă grupuri de captură
@2026-01-07 #ocr #regex #profiles | inferred:high
**P**: Pattern-uri regex în `TOTAL_PATTERNS` fără grupuri `()` cauzează `IndexError: no such group` când `super().extract_total()` încearcă `match.group(1)`.
**S**: TOTAL_PATTERNS din subclase TREBUIE să includă grupuri de captură pentru compatibilitate cu `BaseStoreProfile.extract_total()`:
```python
# GREȘIT - fără grup de captură
TOTAL_PATTERNS = [(r'SUMA\s+TOTALA\s*:', 0.98)]
## Gotchas
_(None recorded yet)_
---
## Statistics
- **Total Patterns**: 2
- **Total Gotchas**: 0
- **Last Session**: 2026-01-06
- **Sessions Recorded**: 1
# CORECT - cu grup de captură
TOTAL_PATTERNS = [(r'SUMA\s+TOTALA\s*:\s*([\d\s.,]+)', 0.98)]
```

View File

@@ -1,28 +1,2 @@
# Claude Learn: Database
**Domain**: database
**Last updated**: -
**Sessions recorded**: 0
Knowledge about Oracle DB, SQLite, SQLModel, migrations, and data modeling.
---
## Patterns
_(None recorded yet)_
---
## Gotchas
_(None recorded yet)_
---
## Statistics
- **Total Patterns**: 0
- **Total Gotchas**: 0
- **Last Session**: -
- **Sessions Recorded**: 0
# Claude Learn: database
<!-- paths: **/*.sql, **/models.py, **/schemas.py, backend/**/db/**/*, migrations/**/*, alembic/**/* -->

View File

@@ -1,20 +1,9 @@
# Claude Learn: Deployment
# Claude Learn: deployment
<!-- paths: deployment/**/*, public/web.config, Dockerfile*, docker-compose*.yml, *.sh, ansible/**/*, lxc/**/* -->
**Domain**: deployment
**Last updated**: 2026-01-06
**Sessions recorded**: 1
Knowledge about IIS, Docker, deployment scripts, and infrastructure.
---
## Patterns
### IIS URL Rewrite Rules for SPA with Multiple API Backends
**Discovered**: 2025-12-22 (feature: unified-app)
**Description**: Configure IIS web.config to proxy different API paths to different backend ports while serving SPA for all other routes. Enables single IIS site to route to multiple microservices.
**Example** (`public/web.config:5-28`):
## P: IIS URL Rewrite Rules for SPA with Multiple API Backends
@2025-12-22 #iis #deployment #spa | inferred:med
Configure IIS web.config to proxy different API paths to different backend ports while serving SPA for all other routes.
```xml
<rewrite>
<rules>
@@ -22,34 +11,21 @@ Knowledge about IIS, Docker, deployment scripts, and infrastructure.
<match url="^api/reports/(.*)" />
<action type="Rewrite" url="http://localhost:8001/api/{R:1}" />
</rule>
<rule name="Proxy Data Entry API" stopProcessing="true">
<match url="^api/data-entry/(.*)" />
<action type="Rewrite" url="http://localhost:8003/api/{R:1}" />
</rule>
<rule name="SPA Fallback" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<conditions><add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /></conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
```
**Tags**: iis, deployment, spa, microservices, proxy
---
## Gotchas
_(None recorded yet)_
---
## Statistics
- **Total Patterns**: 1
- **Total Gotchas**: 0
- **Last Session**: 2026-01-06
- **Sessions Recorded**: 1
## P: Scripturi pentru pornire/oprire servere ROA2WEB
@2026-01-07 #scripts #server-management | explicit:high
Serverele se pornesc și opresc DOAR cu scripturile dedicate:
- `./start-prod.sh` - pornește tot (SSH tunnel + backend + frontend) în mod producție
- `./start-test.sh` - pornește în mod test
- `./start-backend.sh restart` - restartează doar backend-ul
- `./start-frontend.sh restart` - restartează doar frontend-ul
- `./status.sh` - verifică starea serviciilor
Nu folosi: `pkill`, `fuser -k`, sau alte comenzi manuale pentru oprire.

View File

@@ -1,83 +1,34 @@
# Claude Learn Domains Configuration
**Last updated**: 2026-01-06
This file defines available knowledge domains and their file path patterns.
Acest fișier definește domeniile pentru organizarea memoriei.
Fiecare domeniu are propriul fișier cu `paths` frontmatter pentru încărcare selectivă.
---
## Domains
## Domenii Definite
### frontend
**File**: `claude-learn-frontend.md`
**Patterns**:
- `src/**/*.vue`
- `src/**/*.js`
- `src/**/*.ts`
- `src/**/*.css`
- `vite.config.*`
- `package.json`
| Domain | Patterns (globs) |
|------------|------------------------------------------------------------------------------------|
| frontend | src/**/*.vue, src/**/*.js, src/**/*.ts, src/**/*.css, vite.config.*, package.json |
| backend | backend/**/*.py, backend/modules/**/*, requirements.txt |
| database | **/*.sql, **/models.py, **/schemas.py, backend/**/db/**/*, migrations/**/* |
| testing | tests/**/*, **/*.test.*, **/*.spec.*, pytest.ini, vitest.config.* |
| deployment | deployment/**/*, public/web.config, Dockerfile*, docker-compose*.yml, *.sh, ansible/**/* |
| global | * (întotdeauna încărcat) |
---
### backend
**File**: `claude-learn-backend.md`
**Patterns**:
- `backend/**/*.py`
- `backend/modules/**/*`
- `requirements.txt`
## Cum Funcționează
---
1. La `/learn:analyze`, plugin-ul detectează domeniul bazat pe fișierele din conversație
2. Memoria se salvează în `claude-learn-{domain}.md` cu frontmatter `paths:`
3. La încărcarea sesiunii, doar domeniile relevante se încarcă
### database
**File**: `claude-learn-database.md`
**Patterns**:
- `**/*.sql`
- `**/models.py`
- `**/schemas.py`
- `backend/**/db/**/*`
## Adaugă Domeniu Nou
---
Adaugă o linie în tabelul de mai sus cu formatul:
```
| nume-domeniu | pattern1, pattern2, pattern3 |
```
### testing
**File**: `claude-learn-testing.md`
**Patterns**:
- `tests/**/*`
- `**/*.test.*`
- `**/*.spec.*`
- `pytest.ini`
- `vitest.config.*`
---
### deployment
**File**: `claude-learn-deployment.md`
**Patterns**:
- `deployment/**/*`
- `public/web.config`
- `Dockerfile*`
- `docker-compose*.yml`
- `*.sh`
- `ansible/**/*`
---
### global
**File**: `claude-learn-global.md`
**Patterns**:
- `*` (catch-all for cross-cutting concerns)
---
## Statistics
| Domain | Patterns | Gotchas | Last Updated |
|--------|----------|---------|--------------|
| frontend | 8 | 10 | 2026-01-06 |
| deployment | 1 | 0 | 2026-01-06 |
| global | 0 | 1 | 2026-01-06 |
| backend | 2 | 0 | 2026-01-06 |
| database | 0 | 0 | - |
| testing | 0 | 0 | - |
**Total**: 11 patterns, 11 gotchas across 4 domains
Plugin-ul va crea automat fișierul `claude-learn-{nume-domeniu}.md`.

View File

@@ -1,298 +1,142 @@
# Claude Learn: Frontend
# Claude Learn: frontend
<!-- paths: src/**/*.vue, src/**/*.js, src/**/*.ts, src/**/*.css, vite.config.*, package.json -->
**Domain**: frontend
**Last updated**: 2026-01-06
**Sessions recorded**: 3
Knowledge about Vue.js, Vite, Pinia, CSS, and frontend architecture.
---
## Patterns
### Unified Vue SPA with Module Isolation via Error Boundaries
**Discovered**: 2025-12-22 (feature: unified-app)
**Description**: Consolidate multiple Vue apps into a single SPA using lazy-loaded modules wrapped in error boundaries. Each module has its own layout component with ErrorBoundary wrapper to prevent crashes from propagating across modules.
**Example** (`src/modules/reports/ReportsLayout.vue`):
## P: Unified Vue SPA with Module Isolation via Error Boundaries
@2025-12-22 #vue #spa #error-boundary | inferred:med
Consolidate multiple Vue apps into a single SPA using lazy-loaded modules wrapped in error boundaries. Each module has its own layout component with ErrorBoundary wrapper to prevent crashes from propagating.
```vue
<template>
<ErrorBoundary module-name="Rapoarte">
<router-view />
</ErrorBoundary>
</template>
<script setup>
import ErrorBoundary from '@shared/components/ErrorBoundary.vue'
</script>
```
**Tags**: vue, spa, error-boundary, module-isolation, architecture
---
### Dual API Proxy Pattern in Vite for Microservices
**Discovered**: 2025-12-22 (feature: unified-app)
**Description**: Configure Vite dev server to proxy multiple backend microservices under different paths. Allows unified frontend to communicate with separate backend services while maintaining CORS and authentication.
**Example** (`vite.config.js:38-62`):
## P: Dual API Proxy Pattern in Vite for Microservices
@2025-12-22 #vite #proxy #microservices | inferred:med
Configure Vite dev server to proxy multiple backend microservices under different paths. Allows unified frontend to communicate with separate backend services.
```javascript
proxy: {
'/api/reports': {
target: 'http://localhost:8001',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/reports/, '/api'),
configure: (proxy) => {
proxy.on('proxyReq', (proxyReq, req) => {
if (req.headers.authorization) {
proxyReq.setHeader('Authorization', req.headers.authorization);
}
});
}
},
'/api/data-entry': {
target: 'http://localhost:8003',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/data-entry/, '/api')
}
'/api/reports': { target: 'http://localhost:8001', changeOrigin: true },
'/api/data-entry': { target: 'http://localhost:8003', changeOrigin: true }
}
```
**Tags**: vite, proxy, microservices, api, configuration
---
### Pinia Store Factory Pattern for Shared Stores
**Discovered**: 2025-12-22 (feature: unified-app)
**Description**: Create shared Pinia stores as factory functions that accept API service instances. Each module instantiates the shared stores with its own API service, ensuring proper module isolation while sharing store logic.
**Example** (`src/shared/stores/auth.js:21-32`):
## P: Pinia Store Factory Pattern for Shared Stores
@2025-12-22 #pinia #stores #factory-pattern | inferred:med
Create shared Pinia stores as factory functions that accept API service instances. Each module instantiates the shared stores with its own API service.
```javascript
export function createAuthStore(apiService) {
return defineStore('auth', () => {
const accessToken = ref(localStorage.getItem('access_token'))
// ... state
const login = async (credentials) => {
const response = await apiService.post('/auth/login', credentials)
// ... handle response
}
return { login, logout, isAuthenticated, currentUser }
const login = async (credentials) => await apiService.post('/auth/login', credentials)
return { login, logout, isAuthenticated }
})
}
```
**Tags**: pinia, stores, factory-pattern, module-isolation, vue
---
### Module-Specific Shared Store Instances
**Discovered**: 2025-12-22 (feature: unified-app)
**Description**: Instantiate shared store factories in each module's dedicated file to ensure proper API service binding. Prevents import confusion and ensures each module uses its own API base URL.
**Example** (`src/modules/reports/stores/sharedStores.js:1-18`):
## P: Module-Specific Shared Store Instances
@2025-12-22 #pinia #stores #module-isolation | inferred:med
Instantiate shared store factories in each module's dedicated file to ensure proper API service binding.
```javascript
import { createAuthStore } from '@shared/stores/auth'
import { createCompaniesStore } from '@shared/stores/companies'
import { createAccountingPeriodStore } from '@shared/stores/accountingPeriod'
import api from '@reports/services/api'
// Create instances with Reports API service
export const useAuthStore = createAuthStore(api)
export const useCompanyStore = createCompaniesStore(api, useAuthStore)
export const useAccountingPeriodStore = createAccountingPeriodStore(api)
// All reports components import from this file, not directly from @shared
```
**Tags**: pinia, stores, module-isolation, api, architecture
---
### Vite Alias Strategy for Module Organization
**Discovered**: 2025-12-22 (feature: unified-app)
**Description**: Use Vite path aliases to create clear module boundaries: @shared for shared code, @reports and @data-entry for module-specific code. Makes imports explicit and prevents accidental cross-module dependencies.
**Example** (`vite.config.js:19-26`):
## P: Vite Alias Strategy for Module Organization
@2025-12-22 #vite #aliases #architecture | inferred:med
Use Vite path aliases to create clear module boundaries: @shared for shared code, @reports and @data-entry for module-specific code.
```javascript
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'@shared': fileURLToPath(new URL('./src/shared', import.meta.url)),
'@reports': fileURLToPath(new URL('./src/modules/reports', import.meta.url)),
'@data-entry': fileURLToPath(new URL('./src/modules/data-entry', import.meta.url))
},
dedupe: ['vue', 'vue-router', 'pinia', 'primevue']
'@reports': fileURLToPath(new URL('./src/modules/reports', import.meta.url))
}
}
```
**Tags**: vite, aliases, imports, module-organization, architecture
---
### Vue Watcher for Auto-Loading Dependent Data
**Discovered**: 2025-12-24 (feature: unified-app-ux)
**Description**: Use Vue watch() to automatically trigger data loading when dependent selections change. Watch company selection changes to auto-load accounting periods, ensuring UI stays synchronized without manual intervention.
**Example** (`src/App.vue:88-100`):
## P: Vue Watcher for Auto-Loading Dependent Data
@2025-12-24 #vue #watch #reactive | inferred:med
Use Vue watch() to automatically trigger data loading when dependent selections change. Watch company selection changes to auto-load accounting periods.
```javascript
watch(
() => companyStore.selectedCompany,
async (newCompany, oldCompany) => {
if (newCompany && newCompany.id_firma && newCompany !== oldCompany) {
console.log('[App] Company changed via watch, loading periods for:', newCompany.id_firma)
await periodStore.loadPeriods(newCompany.id_firma)
console.log('[App] Periods auto-loaded successfully')
}
async (newCompany) => {
if (newCompany?.id_firma) await periodStore.loadPeriods(newCompany.id_firma)
},
{ immediate: true }
)
```
**Tags**: vue, watch, reactive, auto-load, ux
---
### Axios Request Interceptor for JWT Token Injection
**Discovered**: 2025-12-24 (feature: unified-app-ux)
**Description**: Add axios request interceptor to automatically inject JWT Bearer token from localStorage into all API requests. Eliminates manual token handling in every API call and prevents 401/500 authentication errors.
**Example** (`src/App.vue:61-68`):
## P: Axios Request Interceptor for JWT Token Injection
@2025-12-24 #axios #jwt #authentication | inferred:med
Add axios request interceptor to automatically inject JWT Bearer token from localStorage into all API requests.
```javascript
authApi.interceptors.request.use(config => {
const token = localStorage.getItem('access_token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
if (token) config.headers.Authorization = `Bearer ${token}`
return config
})
```
**Tags**: axios, jwt, authentication, interceptor, api
---
### Pinia Store Factory with Lazy Instantiation
**Discovered**: 2025-12-24 (feature: unified-app-ux)
**Description**: When store factories need to access other stores, use lazy instantiation with try-catch to avoid timing issues. Access stores inside functions (not at module level) and gracefully handle cases where stores aren't ready yet.
**Example** (`src/shared/stores/accountingPeriod.js:52-64`):
## P: Pinia Store Factory with Lazy Instantiation
@2025-12-24 #pinia #stores #lazy-initialization | inferred:med
When store factories need to access other stores, use lazy instantiation with try-catch to avoid timing issues. Access stores inside functions, not at module level.
```javascript
const getStorageKey = () => {
try {
const authStore = useAuthStore();
const companyStore = useCompanyStore();
const username = authStore.user?.username;
const companyId = companyStore.selectedCompany?.id_firma;
if (!username || !companyId) return null;
return `selected_period_${username}_${companyId}`;
} catch (e) {
// Stores not yet initialized, skip localStorage
return null;
}
return `selected_period_${authStore.user?.username}`;
} catch (e) { return null; }
};
```
**Tags**: pinia, stores, lazy-initialization, try-catch, timing
## G: Import Path Hell: Default vs Named Exports
@2025-12-22 #javascript #imports #exports | inferred:med
**P**: Build failed with 'apiService is not exported' errors. Legacy code used `import { apiService }` but module uses `export default api`.
**S**: Change imports from `import { apiService }` to `import api`, then update all references.
---
## G: Pinia Store Factory Pattern Not Auto-Exported
@2025-12-22 #pinia #stores #factory-pattern | inferred:med
**P**: Build failed with 'useCompanyStore is not exported' because shared stores are factory functions, not direct exports.
**S**: Create module-specific sharedStores.js that instantiates factory functions with module's API service and exports store instances.
## Gotchas
## G: Circular Reference in API Wrapper
@2025-12-22 #javascript #naming #scope | inferred:med
**P**: 'Identifier api has already been declared' - imported api and declared `const api = { ... }` wrapper with same name.
**S**: Rename import to apiClient: `import apiClient from 'api'`, then use in wrapper.
### Import Path Hell: Default vs Named Exports
**Discovered**: 2025-12-22 (feature: unified-app)
**Problem**: Build failed with 'apiService is not exported' errors even though the module exports default api. Legacy code was using import { apiService } from 'api.js' which doesn't work with export default api.
**Solution**: Changed all imports from import { apiService } to import api, then updated all references from apiService.get to api.get. Also renamed imports to avoid conflicts (e.g., import apiClient from 'api').
## G: CSS Import Paths Breaking Build in Unified Structure
@2025-12-22 #css #imports #build-errors | inferred:med
**P**: Build failed with 'Unable to resolve @import' - CSS import paths pointed to old shared/frontend location.
**S**: Comment problematic @imports or update paths to use @shared alias or correct relative paths.
**Tags**: javascript, imports, exports, build-errors, migration
## G: Module Component Utilities Not Copied During Migration
@2025-12-22 #migration #dependencies #file-structure | inferred:med
**P**: Build failed with 'Could not resolve ../utils/exportUtils' - utils/ and components/ directories weren't copied.
**S**: Copy entire utils/ and components/ directories from source apps. Supporting files are essential dependencies.
---
## G: Vite Build Transform Count is Progress Indicator
@2025-12-22 #vite #build #debugging | inferred:low
**P**: Hard to tell if build is making progress when fixing import issues.
**S**: Watch 'transforming... N modules transformed' count - it increases with each successful fix. Use as encouragement!
### Pinia Store Factory Pattern Not Auto-Exported
**Discovered**: 2025-12-22 (feature: unified-app)
**Problem**: Build failed with 'useCompanyStore is not exported by companies.js' because the shared stores are factory functions (createCompaniesStore), not direct exports (useCompanyStore).
**Solution**: Created module-specific sharedStores.js files that instantiate the factory functions with the module's API service, then export the actual store instances. Components import from module's sharedStores.js, not from @shared directly.
## G: Menu Structure Mismatch: Flat Array vs Nested Sections
@2025-12-24 #vue #data-structure #component-contract | inferred:med
**P**: Hamburger menu appeared empty - used .flatMap() but SlideMenu expected nested structure.
**S**: Remove .flatMap() and return nested structure directly: `[{title: 'Section', items: [...]}]`.
**Tags**: pinia, stores, factory-pattern, imports, architecture
## G: TypeError: useAuthStore is not a function - Store Timing Issue
@2025-12-24 #pinia #stores #timing | inferred:high
**P**: Period store threw 'TypeError: useAuthStore is not a function' when calling useAuthStore() - timing issue.
**S**: Wrap store access in try-catch with lazy instantiation. Call inside function, not at module level. Return null if stores aren't ready.
---
## G: Missing Auth Token in API Requests Causes 500 Errors
@2025-12-24 #axios #jwt #authentication | inferred:high
**P**: Backend returned 500 - no Authorization header in requests even though JWT token existed in localStorage.
**S**: Add axios request interceptor to inject token AFTER creating axios instance but BEFORE making API calls.
### Circular Reference in API Wrapper
**Discovered**: 2025-12-22 (feature: unified-app)
**Problem**: receiptsStore.js failed to build with 'Identifier api has already been declared' because it imported api and then declared const api = { ... } wrapper object using the same name.
**Solution**: Renamed the import to apiClient (import apiClient from 'api') and used it in the wrapper: const api = { get: (url) => apiClient.get('/receipts${url}') }. This keeps the wrapper name 'api' for internal use while avoiding the conflict.
**Tags**: javascript, naming, scope, imports, build-errors
---
### CSS Import Paths Breaking Build in Unified Structure
**Discovered**: 2025-12-22 (feature: unified-app)
**Problem**: Build failed with 'Unable to resolve @import "../../../../../shared/frontend/styles/layout/header.css"' because the CSS files were copied but their import paths still pointed to old shared/frontend location.
**Solution**: Commented out the problematic @import statements in main.css since those styles are already imported in App.vue. Alternatively, could have updated paths to use @shared alias or relative paths from new location.
**Tags**: css, imports, build-errors, migration, paths
---
### Module Component Utilities Not Copied During Migration
**Discovered**: 2025-12-22 (feature: unified-app)
**Problem**: Build failed with 'Could not resolve ../utils/exportUtils' because views referenced utils/ and components/ directories that weren't copied during initial migration (only views and stores were copied).
**Solution**: Copied the entire utils/ and components/ directories from source apps to module directories. These supporting files are essential dependencies of the views and must be migrated together.
**Tags**: migration, dependencies, file-structure, build-errors
---
### Vite Build Transform Count is Progress Indicator
**Discovered**: 2025-12-22 (feature: unified-app)
**Problem**: Hard to tell if build is making progress when fixing import issues. Each fix revealed new errors, causing frustration.
**Solution**: Watch the 'transforming... N modules transformed' count - it increases with each successful fix even if build ultimately fails. Going from 200->573->1490->1492 modules meant we were getting close to success. Use this as encouragement!
**Tags**: vite, build, debugging, progress-tracking, developer-experience
---
### Menu Structure Mismatch: Flat Array vs Nested Sections
**Discovered**: 2025-12-24 (feature: unified-app-ux)
**Problem**: Hamburger menu appeared completely empty (no menu items visible) even though enabledMenuItems computed property returned data. Used .flatMap() to create flat array [{item1}, {item2}] but SlideMenu component expected nested structure [{title: 'Section', items: [...]}, ...].
**Solution**: Removed .flatMap() transformation and returned the nested structure directly from getEnabledMenuSections(). Component's v-for="section in menuItems" now properly iterates over sections, then v-for="item in section.items" shows all items.
**Tags**: vue, data-structure, component-contract, v-for, ux
---
### TypeError: useAuthStore is not a function - Store Timing Issue
**Discovered**: 2025-12-24 (feature: unified-app-ux)
**Problem**: Period store threw 'TypeError: useAuthStore is not a function' when trying to call useAuthStore() in getStorageKey() function. Stores were passed as factory parameters but weren't callable in that context/timing.
**Solution**: Wrap store access in try-catch with lazy instantiation. Call useAuthStore() inside the function that needs it, not at module level. Return null if stores aren't ready yet. This allows graceful degradation when stores haven't been initialized by Pinia yet.
**Tags**: pinia, stores, timing, initialization, error-handling
---
### Missing Auth Token in API Requests Causes 500 Errors
**Discovered**: 2025-12-24 (feature: unified-app-ux)
**Problem**: Backend returned 500 Internal Server Error when frontend tried to load accounting periods. Console showed no Authorization header in requests even though user was logged in and JWT token existed in localStorage.
**Solution**: Add axios request interceptor to automatically inject token: authApi.interceptors.request.use(config => { const token = localStorage.getItem('access_token'); if (token) config.headers.Authorization = `Bearer ${token}`; return config; }). Place this AFTER creating axios instance but BEFORE making any API calls.
**Tags**: axios, jwt, authentication, api, interceptor
---
### Period Auto-Load Never Triggered Despite Handler Exists
**Discovered**: 2025-12-24 (feature: unified-app-ux)
**Problem**: Period dropdown stayed on 'Selectare perioada' placeholder even after manually selecting company. handleCompanyChanged() function existed and logged messages, but periods.value and selectedPeriod.value remained empty. No automatic loading occurred.
**Solution**: Add Vue watch() on companyStore.selectedCompany to automatically call periodStore.loadPeriods() when company changes. Handler alone isn't enough - need reactive watcher with { immediate: true } to handle both initial load and subsequent changes. Watch triggers for ALL company changes (auto-select on login + manual selection).
**Tags**: vue, watch, reactive, auto-load, ux
---
## Statistics
- **Total Patterns**: 8
- **Total Gotchas**: 10
- **Last Session**: 2026-01-06
- **Sessions Recorded**: 3
## G: Period Auto-Load Never Triggered Despite Handler Exists
@2025-12-24 #vue #watch #reactive | inferred:high
**P**: Period dropdown stayed on placeholder - handleCompanyChanged() existed but periods never loaded.
**S**: Add Vue watch() on companyStore.selectedCompany with { immediate: true } to handle both initial load and changes.

View File

@@ -1,33 +1,7 @@
# Claude Learn: Global
# Claude Learn: global
<!-- paths: * -->
**Domain**: global
**Last updated**: 2026-01-06
**Sessions recorded**: 1
Cross-cutting knowledge applicable to multiple domains (scripting, tooling, workflow).
---
## Patterns
_(None recorded yet)_
---
## Gotchas
### Sed Command Quote Mismatch in Bulk Find-Replace
**Discovered**: 2025-12-22 (feature: unified-app)
**Problem**: Bulk sed commands using single quotes in pattern didn't match imports using double quotes, and vice versa. Commands like sed 's|from '@/stores/'|...' didn't replace from "@/stores/" lines.
**Solution**: Always use the quote style that matches the target files. For Vue/JS files with ESLint using double quotes, use double quotes in sed patterns. Better yet: use find -exec with separate sed for each file to handle both quote styles.
**Tags**: sed, regex, scripting, find-replace, migration
---
## Statistics
- **Total Patterns**: 0
- **Total Gotchas**: 1
- **Last Session**: 2026-01-06
- **Sessions Recorded**: 1
## G: Sed Command Quote Mismatch in Bulk Find-Replace
@2025-12-22 #sed #regex #scripting | inferred:med
**P**: Bulk sed commands using single quotes in pattern didn't match imports using double quotes. Commands like `sed 's|from '@/stores/'|...'` didn't replace `from "@/stores/"` lines.
**S**: Use quote style that matches target files. For Vue/JS files with ESLint using double quotes, use double quotes in sed patterns. Or use find -exec with separate sed for each quote style.

View File

@@ -1,28 +1,2 @@
# Claude Learn: Testing
**Domain**: testing
**Last updated**: -
**Sessions recorded**: 0
Knowledge about pytest, Vitest, test patterns, and validation strategies.
---
## Patterns
_(None recorded yet)_
---
## Gotchas
_(None recorded yet)_
---
## Statistics
- **Total Patterns**: 0
- **Total Gotchas**: 0
- **Last Session**: -
- **Sessions Recorded**: 0
# Claude Learn: testing
<!-- paths: tests/**/*, **/*.test.*, **/*.spec.*, pytest.ini, vitest.config.* -->