fix: Update Trial Balance to use real VBAL VIEW structure
After database verification, VBAL is a VIEW (not a table) that exists
in each company schema with a different structure than initially assumed.
Backend Changes:
- Updated models (trial_balance.py):
- Changed column names to match real VBAL VIEW
- CONT (account number)
- DENUMIRE (account description, not DCONT)
- PRECDEB/PRECCRED (previous balance, not SD_PREC/SC_PREC)
- RULDEB/RULCRED (monthly movement, not RD_LUNA/RC_LUNA)
- SOLDDEB/SOLDCRED (final balance, not SD_FINAL/SC_FINAL)
- Made DENUMIRE optional (can be NULL in VIEW)
- Updated router (trial_balance.py):
- Removed COD_FIRMA filter (not in VIEW)
- Query now uses: {schema}.VBAL WHERE AN = :an AND LUNA = :luna
- Fixed column names in SELECT (DENUMIRE instead of DCONT)
- Updated sort columns validation
- Fixed result processing to match new column order
Frontend Changes:
- Updated TrialBalanceView.vue:
- Changed field from 'dcont' to 'denumire' in DataTable column
Database Verification:
- VBAL VIEW confirmed in ROMFAST schema (24,217 records)
- Current data available up to November 2025
- Structure verified with 22 columns
- VIEW exists in all company schemas
Testing Notes:
- Backend endpoint ready for testing
- Frontend field names now match API response
- Ready for manual testing with real company data
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
587
features/TRIAL_BALANCE_FEATURE.md
Normal file
587
features/TRIAL_BALANCE_FEATURE.md
Normal file
@@ -0,0 +1,587 @@
|
|||||||
|
# Feature: Balanță de Verificare Sintetică (Trial Balance)
|
||||||
|
|
||||||
|
**Branch**: `feature/trial-balance`
|
||||||
|
**Status**: 📋 Planning
|
||||||
|
**Created**: 2025-11-20
|
||||||
|
**Assigned to**: Claude Code
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 Overview
|
||||||
|
|
||||||
|
Implementare pagină nouă în frontend pentru afișarea balanței de verificare sintetice simplificate din tabelul Oracle `VBAL`, cu filtrare dinamică și integrare completă în aplicație.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Business Requirements
|
||||||
|
|
||||||
|
### Functional Requirements
|
||||||
|
1. **Afișare Date Balanță de Verificare**:
|
||||||
|
- Solduri precedente (debit/credit)
|
||||||
|
- Rulaje lunare (debit/credit)
|
||||||
|
- Solduri finale (debit/credit)
|
||||||
|
- Cont contabil (cod)
|
||||||
|
- Denumire cont
|
||||||
|
|
||||||
|
2. **Filtrare și Căutare**:
|
||||||
|
- Filtrare după **număr cont** (ex: "512", "4111")
|
||||||
|
- Filtrare după **denumire cont** (căutare parțială, case-insensitive)
|
||||||
|
- Filtrare combinată (și după cont și după denumire)
|
||||||
|
- Clear filters option
|
||||||
|
|
||||||
|
3. **Navigare și UX**:
|
||||||
|
- Adăugare în meniul hamburger (secțiune Rapoarte / Reports)
|
||||||
|
- Ordonare pe coloane (ascendent/descendent)
|
||||||
|
- Paginare pentru volume mari de date
|
||||||
|
- Loading states și error handling
|
||||||
|
- Responsive design (mobile-friendly)
|
||||||
|
|
||||||
|
4. **Date Contextualizate**:
|
||||||
|
- Afișare pentru compania activă curentă
|
||||||
|
- Afișare pentru luna/anul curent (sau filtru de perioadă - opțional faza 2)
|
||||||
|
|
||||||
|
### Non-Functional Requirements
|
||||||
|
- **Performance**: Răspuns API < 2s pentru 10,000 înregistrări
|
||||||
|
- **Security**: Autentificare JWT obligatorie
|
||||||
|
- **Accessibility**: Conform design system existent
|
||||||
|
- **CSS**: Respectare strictă a arhitecturii CSS (ONBOARDING_CSS.md, CSS_PATTERNS.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🏗️ Technical Architecture
|
||||||
|
|
||||||
|
### Database Schema (Oracle `VBAL` table)
|
||||||
|
```sql
|
||||||
|
-- Structura tabelului VBAL (să fie verificată în Oracle)
|
||||||
|
SELECT
|
||||||
|
CONT, -- Număr cont contabil
|
||||||
|
DCONT, -- Denumire cont
|
||||||
|
SD_PREC, -- Sold precedent debit
|
||||||
|
SC_PREC, -- Sold precedent credit
|
||||||
|
RD_LUNA, -- Rulaj lunar debit
|
||||||
|
RC_LUNA, -- Rulaj lunar credit
|
||||||
|
SD_FINAL, -- Sold final debit
|
||||||
|
SC_FINAL, -- Sold final credit
|
||||||
|
COD_FIRMA, -- Cod firmă (pentru filtering)
|
||||||
|
LUNA, -- Luna (1-12)
|
||||||
|
AN -- An
|
||||||
|
FROM VBAL
|
||||||
|
WHERE COD_FIRMA = :cod_firma
|
||||||
|
AND AN = :an
|
||||||
|
AND LUNA = :luna
|
||||||
|
AND (CONT LIKE :cont_filter OR DCONT LIKE :denumire_filter)
|
||||||
|
ORDER BY CONT
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backend API Endpoint
|
||||||
|
|
||||||
|
**Endpoint**: `GET /api/trial-balance`
|
||||||
|
|
||||||
|
**Request Parameters**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"cod_firma": "string (required, from JWT)",
|
||||||
|
"luna": "integer (1-12, optional, default: current month)",
|
||||||
|
"an": "integer (optional, default: current year)",
|
||||||
|
"cont_filter": "string (optional, partial match)",
|
||||||
|
"denumire_filter": "string (optional, partial match, case-insensitive)",
|
||||||
|
"sort_by": "string (optional, default: 'CONT')",
|
||||||
|
"sort_order": "string (optional, 'asc' | 'desc', default: 'asc')",
|
||||||
|
"page": "integer (optional, default: 1)",
|
||||||
|
"page_size": "integer (optional, default: 50)"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Response**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"cont": "4111",
|
||||||
|
"dcont": "Furnizori interni",
|
||||||
|
"sold_precedent_debit": 0.00,
|
||||||
|
"sold_precedent_credit": 15000.00,
|
||||||
|
"rulaj_lunar_debit": 5000.00,
|
||||||
|
"rulaj_lunar_credit": 8000.00,
|
||||||
|
"sold_final_debit": 0.00,
|
||||||
|
"sold_final_credit": 18000.00
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pagination": {
|
||||||
|
"total_items": 150,
|
||||||
|
"total_pages": 3,
|
||||||
|
"current_page": 1,
|
||||||
|
"page_size": 50
|
||||||
|
},
|
||||||
|
"filters_applied": {
|
||||||
|
"luna": 11,
|
||||||
|
"an": 2025,
|
||||||
|
"cont_filter": null,
|
||||||
|
"denumire_filter": "furnizori"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Error Responses**:
|
||||||
|
- `401 Unauthorized`: Missing/invalid JWT token
|
||||||
|
- `403 Forbidden`: User doesn't have access to company
|
||||||
|
- `500 Internal Server Error`: Database connection/query error
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Frontend Architecture
|
||||||
|
|
||||||
|
**Location**: `reports-app/frontend/src/views/TrialBalanceView.vue`
|
||||||
|
|
||||||
|
**Store**: `reports-app/frontend/src/stores/trialBalanceStore.js`
|
||||||
|
|
||||||
|
**Route**: `/trial-balance` (added to `router/index.js`)
|
||||||
|
|
||||||
|
**Menu Integration**:
|
||||||
|
- Add to hamburger menu in `src/components/layout/HamburgerMenu.vue`
|
||||||
|
- Section: "Rapoarte" / "Reports"
|
||||||
|
- Icon: Calculator/Table icon (PrimeVue icon)
|
||||||
|
- Label: "Balanță de Verificare"
|
||||||
|
|
||||||
|
**Component Structure**:
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<div class="trial-balance-view">
|
||||||
|
<!-- Page Header -->
|
||||||
|
<div class="roa-page-header">
|
||||||
|
<h1>Balanță de Verificare</h1>
|
||||||
|
<p class="roa-subtitle">Luna: {{ currentMonth }}/{{ currentYear }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Filters Section -->
|
||||||
|
<div class="roa-card roa-filters-card">
|
||||||
|
<!-- Cont filter -->
|
||||||
|
<!-- Denumire filter -->
|
||||||
|
<!-- Clear filters button -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Data Table -->
|
||||||
|
<div class="roa-card">
|
||||||
|
<DataTable
|
||||||
|
:value="trialBalanceData"
|
||||||
|
:loading="loading"
|
||||||
|
paginator
|
||||||
|
:rows="50"
|
||||||
|
sortField="cont"
|
||||||
|
:sortOrder="1"
|
||||||
|
>
|
||||||
|
<!-- Columns definition -->
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Empty State / Error State -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
**CSS Patterns to Use**:
|
||||||
|
- `.roa-page-header` - Page header (CSS_PATTERNS.md)
|
||||||
|
- `.roa-card` - Card container (CSS_PATTERNS.md)
|
||||||
|
- `.roa-filters-card` - Filters section (CSS_PATTERNS.md)
|
||||||
|
- Design tokens from DESIGN_TOKENS.md (colors, spacing)
|
||||||
|
- **NO `:deep()`** - Use `src/assets/css/vendor/primevue/datatable.css` for PrimeVue overrides
|
||||||
|
|
||||||
|
**State Management** (Pinia store):
|
||||||
|
```javascript
|
||||||
|
// src/stores/trialBalanceStore.js
|
||||||
|
export const useTrialBalanceStore = defineStore('trialBalance', {
|
||||||
|
state: () => ({
|
||||||
|
trialBalanceData: [],
|
||||||
|
loading: false,
|
||||||
|
error: null,
|
||||||
|
filters: {
|
||||||
|
cont: '',
|
||||||
|
denumire: '',
|
||||||
|
luna: new Date().getMonth() + 1,
|
||||||
|
an: new Date().getFullYear()
|
||||||
|
},
|
||||||
|
pagination: {
|
||||||
|
totalItems: 0,
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 50
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
async fetchTrialBalance() { /* ... */ },
|
||||||
|
async applyFilters(filters) { /* ... */ },
|
||||||
|
clearFilters() { /* ... */ }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Implementation Plan (Phases)
|
||||||
|
|
||||||
|
### ✅ Phase 0: Preparation & Branch Setup
|
||||||
|
**Status**: 🔲 Not Started
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] Create feature branch `feature/trial-balance` from `main`
|
||||||
|
- [ ] Verify Oracle `VBAL` table structure and test queries
|
||||||
|
- [ ] Review existing code patterns (InvoicesView, DashboardView)
|
||||||
|
- [ ] Read CSS documentation (ONBOARDING_CSS.md, CSS_PATTERNS.md)
|
||||||
|
|
||||||
|
**Estimated Time**: 30 minutes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ Phase 1: Backend API Implementation
|
||||||
|
**Status**: 🔲 Not Started
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] Create Pydantic schema: `backend/app/schemas/trial_balance.py`
|
||||||
|
- `TrialBalanceItem` model
|
||||||
|
- `TrialBalanceRequest` model
|
||||||
|
- `TrialBalanceResponse` model
|
||||||
|
- [ ] Create router: `backend/app/routers/trial_balance.py`
|
||||||
|
- `GET /api/trial-balance` endpoint
|
||||||
|
- Query parameters validation
|
||||||
|
- Oracle stored procedure/query execution
|
||||||
|
- Pagination logic
|
||||||
|
- Filtering logic (cont, denumire)
|
||||||
|
- Sorting logic
|
||||||
|
- [ ] Register router in `backend/app/main.py`
|
||||||
|
- [ ] Test endpoint manually with Postman/curl
|
||||||
|
- Test with valid JWT token
|
||||||
|
- Test filtering by cont
|
||||||
|
- Test filtering by denumire
|
||||||
|
- Test pagination
|
||||||
|
- Test sorting
|
||||||
|
- Test error cases (invalid token, DB errors)
|
||||||
|
|
||||||
|
**Files to Create/Modify**:
|
||||||
|
- `reports-app/backend/app/schemas/trial_balance.py` (NEW)
|
||||||
|
- `reports-app/backend/app/routers/trial_balance.py` (NEW)
|
||||||
|
- `reports-app/backend/app/main.py` (MODIFY)
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- ✅ API returns correct data from `VBAL` table
|
||||||
|
- ✅ Filtering works for cont and denumire
|
||||||
|
- ✅ Pagination returns correct page counts
|
||||||
|
- ✅ Sorting works for all columns
|
||||||
|
- ✅ Proper error handling and status codes
|
||||||
|
|
||||||
|
**Estimated Time**: 2-3 hours
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ Phase 2: Frontend Store Implementation
|
||||||
|
**Status**: 🔲 Not Started
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] Create Pinia store: `frontend/src/stores/trialBalanceStore.js`
|
||||||
|
- State definition (data, loading, error, filters, pagination)
|
||||||
|
- `fetchTrialBalance()` action with Axios
|
||||||
|
- `applyFilters()` action
|
||||||
|
- `clearFilters()` action
|
||||||
|
- Getters for computed values
|
||||||
|
- [ ] Add API service: `frontend/src/services/trialBalanceService.js` (optional)
|
||||||
|
- [ ] Test store in browser DevTools
|
||||||
|
|
||||||
|
**Files to Create**:
|
||||||
|
- `reports-app/frontend/src/stores/trialBalanceStore.js` (NEW)
|
||||||
|
- `reports-app/frontend/src/services/trialBalanceService.js` (NEW, optional)
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- ✅ Store successfully fetches data from API
|
||||||
|
- ✅ Filters update correctly
|
||||||
|
- ✅ Loading states work properly
|
||||||
|
- ✅ Error handling displays user-friendly messages
|
||||||
|
|
||||||
|
**Estimated Time**: 1-2 hours
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ Phase 3: Frontend View Component
|
||||||
|
**Status**: 🔲 Not Started
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] Create Vue component: `frontend/src/views/TrialBalanceView.vue`
|
||||||
|
- Page header with title and period info
|
||||||
|
- Filters card (cont input, denumire input, clear button)
|
||||||
|
- PrimeVue DataTable with columns:
|
||||||
|
- Cont
|
||||||
|
- Denumire Cont
|
||||||
|
- Sold Precedent (Debit/Credit)
|
||||||
|
- Rulaj Lunar (Debit/Credit)
|
||||||
|
- Sold Final (Debit/Credit)
|
||||||
|
- Loading spinner
|
||||||
|
- Empty state (no data)
|
||||||
|
- Error state
|
||||||
|
- [ ] Use **existing CSS patterns** (NO new custom CSS unless necessary)
|
||||||
|
- `.roa-page-header`
|
||||||
|
- `.roa-card`
|
||||||
|
- `.roa-filters-card`
|
||||||
|
- Design tokens (spacing, colors)
|
||||||
|
- [ ] Implement responsive design (mobile breakpoints)
|
||||||
|
- [ ] Add number formatting (Romanian locale, 2 decimals)
|
||||||
|
|
||||||
|
**Files to Create**:
|
||||||
|
- `reports-app/frontend/src/views/TrialBalanceView.vue` (NEW)
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- ✅ Page displays correctly with data
|
||||||
|
- ✅ Filters work and update table
|
||||||
|
- ✅ Sorting on columns works
|
||||||
|
- ✅ Pagination works
|
||||||
|
- ✅ Loading/error states display correctly
|
||||||
|
- ✅ CSS follows design system (NO `:deep()`, NO custom colors)
|
||||||
|
- ✅ Responsive on mobile devices
|
||||||
|
|
||||||
|
**Estimated Time**: 3-4 hours
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ Phase 4: Routing & Navigation
|
||||||
|
**Status**: 🔲 Not Started
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] Add route in `frontend/src/router/index.js`:
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
path: '/trial-balance',
|
||||||
|
name: 'TrialBalance',
|
||||||
|
component: () => import('@/views/TrialBalanceView.vue'),
|
||||||
|
meta: { requiresAuth: true }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- [ ] Add menu item in `frontend/src/components/layout/HamburgerMenu.vue`:
|
||||||
|
- Section: "Rapoarte"
|
||||||
|
- Icon: `pi-calculator` or `pi-table`
|
||||||
|
- Label: "Balanță de Verificare"
|
||||||
|
- Route: `/trial-balance`
|
||||||
|
- [ ] Test navigation from menu
|
||||||
|
|
||||||
|
**Files to Modify**:
|
||||||
|
- `reports-app/frontend/src/router/index.js` (MODIFY)
|
||||||
|
- `reports-app/frontend/src/components/layout/HamburgerMenu.vue` (MODIFY)
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- ✅ Route is accessible at `/trial-balance`
|
||||||
|
- ✅ Menu item appears in hamburger menu
|
||||||
|
- ✅ Clicking menu item navigates to page
|
||||||
|
- ✅ Auth guard prevents unauthorized access
|
||||||
|
|
||||||
|
**Estimated Time**: 30 minutes
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ Phase 5: Testing & Refinement
|
||||||
|
**Status**: 🔲 Not Started
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] Manual testing:
|
||||||
|
- Test with different companies
|
||||||
|
- Test with different date ranges
|
||||||
|
- Test filtering edge cases (empty results, special characters)
|
||||||
|
- Test sorting on all columns
|
||||||
|
- Test pagination with large datasets
|
||||||
|
- Test on mobile devices (responsive)
|
||||||
|
- Test error scenarios (API down, invalid token)
|
||||||
|
- [ ] Add Playwright E2E tests (optional, recommended):
|
||||||
|
- `frontend/tests/e2e/trial-balance/trial-balance.spec.js`
|
||||||
|
- Test navigation
|
||||||
|
- Test filtering
|
||||||
|
- Test data display
|
||||||
|
- [ ] Code review & refinement:
|
||||||
|
- Check CSS adherence (no `:deep()`, use patterns)
|
||||||
|
- Check error handling
|
||||||
|
- Check loading states
|
||||||
|
- Check accessibility (keyboard navigation, screen readers)
|
||||||
|
- [ ] Performance testing:
|
||||||
|
- Test with 10,000+ rows
|
||||||
|
- Check API response time
|
||||||
|
- Check frontend rendering performance
|
||||||
|
|
||||||
|
**Files to Create** (optional):
|
||||||
|
- `reports-app/frontend/tests/e2e/trial-balance/trial-balance.spec.js` (NEW)
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- ✅ All manual tests pass
|
||||||
|
- ✅ E2E tests pass (if implemented)
|
||||||
|
- ✅ Performance benchmarks met (API < 2s)
|
||||||
|
- ✅ Code follows project conventions
|
||||||
|
- ✅ CSS follows design system strictly
|
||||||
|
|
||||||
|
**Estimated Time**: 2-3 hours
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ Phase 6: Documentation & PR
|
||||||
|
**Status**: 🔲 Not Started
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [ ] Update `README.md` - add Trial Balance to features list
|
||||||
|
- [ ] Update `CLAUDE.md` - add Trial Balance to documentation index (if needed)
|
||||||
|
- [ ] Add API documentation in backend README
|
||||||
|
- [ ] Create PR from `feature/trial-balance` to `main`:
|
||||||
|
- Title: "feat: Add Trial Balance (Balanță de Verificare) page"
|
||||||
|
- Description: Link to this feature file, list phases completed
|
||||||
|
- Screenshots of UI
|
||||||
|
- API endpoint documentation
|
||||||
|
- [ ] Request code review
|
||||||
|
- [ ] Address review comments
|
||||||
|
- [ ] Merge to `main`
|
||||||
|
|
||||||
|
**Acceptance Criteria**:
|
||||||
|
- ✅ All documentation updated
|
||||||
|
- ✅ PR created with complete description
|
||||||
|
- ✅ Code review approved
|
||||||
|
- ✅ Branch merged successfully
|
||||||
|
|
||||||
|
**Estimated Time**: 1 hour
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Progress Tracking
|
||||||
|
|
||||||
|
### Overall Progress
|
||||||
|
- **Phase 0**: 🔲 Not Started (0%)
|
||||||
|
- **Phase 1**: 🔲 Not Started (0%)
|
||||||
|
- **Phase 2**: 🔲 Not Started (0%)
|
||||||
|
- **Phase 3**: 🔲 Not Started (0%)
|
||||||
|
- **Phase 4**: 🔲 Not Started (0%)
|
||||||
|
- **Phase 5**: 🔲 Not Started (0%)
|
||||||
|
- **Phase 6**: 🔲 Not Started (0%)
|
||||||
|
|
||||||
|
**Total Progress**: 0% Complete
|
||||||
|
|
||||||
|
### Status Legend
|
||||||
|
- 🔲 Not Started
|
||||||
|
- 🔄 In Progress
|
||||||
|
- ✅ Completed
|
||||||
|
- ⚠️ Blocked
|
||||||
|
- ❌ Cancelled
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 Getting Started
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
1. SSH tunnel running (`./ssh_tunnel.sh status`)
|
||||||
|
2. Backend running (`cd reports-app/backend && uvicorn app.main:app --reload --port 8001`)
|
||||||
|
3. Frontend running (`cd reports-app/frontend && npm run dev`)
|
||||||
|
4. Valid JWT token for testing API
|
||||||
|
|
||||||
|
### Starting Development
|
||||||
|
```bash
|
||||||
|
# 1. Create feature branch
|
||||||
|
git checkout main
|
||||||
|
git pull origin main
|
||||||
|
git checkout -b feature/trial-balance
|
||||||
|
|
||||||
|
# 2. Verify Oracle VBAL table
|
||||||
|
# Connect to Oracle and run:
|
||||||
|
# SELECT * FROM VBAL WHERE ROWNUM <= 10;
|
||||||
|
|
||||||
|
# 3. Start backend (Phase 1)
|
||||||
|
cd reports-app/backend
|
||||||
|
# Create schemas/trial_balance.py
|
||||||
|
# Create routers/trial_balance.py
|
||||||
|
# Test with curl/Postman
|
||||||
|
|
||||||
|
# 4. Start frontend (Phases 2-4)
|
||||||
|
cd reports-app/frontend
|
||||||
|
# Create stores/trialBalanceStore.js
|
||||||
|
# Create views/TrialBalanceView.vue
|
||||||
|
# Update router and menu
|
||||||
|
|
||||||
|
# 5. Test and refine (Phase 5)
|
||||||
|
# Manual testing
|
||||||
|
# E2E tests (optional)
|
||||||
|
|
||||||
|
# 6. Create PR (Phase 6)
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: Add Trial Balance page with filtering and pagination"
|
||||||
|
git push origin feature/trial-balance
|
||||||
|
# Create PR on GitHub/GitLab
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Reference Documentation
|
||||||
|
|
||||||
|
**MUST READ before coding**:
|
||||||
|
- `docs/ONBOARDING_CSS.md` - CSS quick start (5 min read)
|
||||||
|
- `docs/CSS_PATTERNS.md` - All available CSS patterns
|
||||||
|
- `docs/DESIGN_TOKENS.md` - Colors, spacing, typography
|
||||||
|
- `reports-app/frontend/README.md` - Frontend architecture
|
||||||
|
- `reports-app/backend/README.md` - Backend architecture
|
||||||
|
|
||||||
|
**Similar implementations to reference**:
|
||||||
|
- `reports-app/frontend/src/views/InvoicesView.vue` - Table + filters pattern
|
||||||
|
- `reports-app/frontend/src/views/DashboardView.vue` - Cards + data display
|
||||||
|
- `reports-app/backend/app/routers/invoices.py` - API with filtering/pagination
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ Important Notes
|
||||||
|
|
||||||
|
### CSS Architecture Compliance
|
||||||
|
**CRITICAL**: This feature MUST follow the established CSS architecture:
|
||||||
|
|
||||||
|
✅ **DO**:
|
||||||
|
- Use existing `.roa-*` patterns from `CSS_PATTERNS.md`
|
||||||
|
- Use design tokens (`var(--color-primary)`, `var(--spacing-4)`)
|
||||||
|
- Use vendor overrides in `src/assets/css/vendor/primevue/` for PrimeVue
|
||||||
|
- Keep component styles minimal and semantic
|
||||||
|
- Follow BEM naming if creating new components
|
||||||
|
|
||||||
|
❌ **DON'T**:
|
||||||
|
- Use `:deep()` in Vue components
|
||||||
|
- Hardcode colors or spacing values
|
||||||
|
- Duplicate existing patterns
|
||||||
|
- Create custom CSS without checking patterns first
|
||||||
|
- Override PrimeVue styles in component `<style>` blocks
|
||||||
|
|
||||||
|
### Database Considerations
|
||||||
|
- **Performance**: Use indexes on `VBAL(COD_FIRMA, AN, LUNA, CONT)`
|
||||||
|
- **Data Volume**: Consider pagination for companies with many accounts
|
||||||
|
- **Filters**: Use Oracle `LIKE` with wildcards efficiently: `CONT LIKE :cont || '%'`
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- **JWT Auth**: Required for all API calls
|
||||||
|
- **Company Access**: Verify user has access to `cod_firma` in request
|
||||||
|
- **SQL Injection**: Use parameterized queries (`:param` syntax)
|
||||||
|
|
||||||
|
### Future Enhancements (Not in Initial Scope)
|
||||||
|
- Export to Excel/PDF
|
||||||
|
- Drill-down to account details (sold și rulaj pe luni)
|
||||||
|
- Comparison between periods (current vs previous month/year)
|
||||||
|
- Charts/visualizations (rulaj pe conturi)
|
||||||
|
- Advanced filters (by account class/category)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Known Issues / Risks
|
||||||
|
|
||||||
|
1. **Oracle VBAL table structure unknown**: Verify column names and types in Phase 0
|
||||||
|
2. **Performance with large datasets**: Monitor query performance, add indexes if needed
|
||||||
|
3. **Decimal precision**: Ensure proper handling of Romanian decimal separator (comma vs dot)
|
||||||
|
4. **Company switching**: Ensure data refreshes when user switches active company
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 Support
|
||||||
|
|
||||||
|
For questions or blockers, refer to:
|
||||||
|
- **Architecture**: `docs/ARCHITECTURE_SCHEMA.md`, `docs/MICROSERVICES_GUIDE.md`
|
||||||
|
- **CSS Issues**: `docs/ONBOARDING_CSS.md`, `docs/STYLING_GUIDELINES.md`
|
||||||
|
- **Backend Issues**: `reports-app/backend/README.md`, `README.md` (troubleshooting)
|
||||||
|
- **Frontend Issues**: `reports-app/frontend/README.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated**: 2025-11-20
|
||||||
|
**Feature Owner**: Claude Code
|
||||||
|
**Reviewers**: TBD
|
||||||
106
features/TRIAL_BALANCE_PROMPT.md
Normal file
106
features/TRIAL_BALANCE_PROMPT.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# 🎯 Prompt pentru Implementare Balanță de Verificare
|
||||||
|
|
||||||
|
## Promptul de folosit:
|
||||||
|
|
||||||
|
```
|
||||||
|
Implementează feature-ul "Balanță de Verificare" conform specificațiilor din features/TRIAL_BALANCE_FEATURE.md.
|
||||||
|
|
||||||
|
Cerințe:
|
||||||
|
1. Creează branch nou: feature/trial-balance
|
||||||
|
2. Implementează toate fazele (0-6) în ordine
|
||||||
|
3. Urmărește progresul actualizând statusul fazelor în TRIAL_BALANCE_FEATURE.md
|
||||||
|
4. Respectă STRICT arhitectura CSS (ONBOARDING_CSS.md, CSS_PATTERNS.md) - fără :deep(), doar pattern-uri existente
|
||||||
|
5. Testează manual după fiecare fază înainte de a trece la următoarea
|
||||||
|
|
||||||
|
Prioritate: Phases 0-4 (backend + frontend + navigare)
|
||||||
|
Phases 5-6 (testing + PR) - opțional pentru MVP
|
||||||
|
|
||||||
|
Start cu Phase 0: Preparation & Branch Setup.
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sau versiunea extinsă:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Task: Implementare completă Balanță de Verificare (Trial Balance)
|
||||||
|
|
||||||
|
## Context
|
||||||
|
Implementează o pagină nouă în frontend pentru afișarea balanței de verificare sintetice din Oracle VBAL cu filtrare, paginare și integrare completă în aplicație.
|
||||||
|
|
||||||
|
## Specificații
|
||||||
|
Vezi: features/TRIAL_BALANCE_FEATURE.md
|
||||||
|
|
||||||
|
## Plan de lucru
|
||||||
|
1. **Phase 0**: Setup branch feature/trial-balance + verificare VBAL table
|
||||||
|
2. **Phase 1**: Backend API (schemas + router + endpoint GET /api/trial-balance)
|
||||||
|
3. **Phase 2**: Frontend Store (Pinia trialBalanceStore)
|
||||||
|
4. **Phase 3**: Frontend View (TrialBalanceView.vue cu DataTable)
|
||||||
|
5. **Phase 4**: Routing + Menu (router.js + HamburgerMenu.vue)
|
||||||
|
6. **Phase 5**: Testing manual + E2E (opțional)
|
||||||
|
7. **Phase 6**: Documentation + PR
|
||||||
|
|
||||||
|
## Reguli CRITICE
|
||||||
|
✅ Respectă CSS architecture: DOAR pattern-uri din CSS_PATTERNS.md, FĂRĂ :deep()
|
||||||
|
✅ Folosește design tokens (var(--color-primary), var(--spacing-4))
|
||||||
|
✅ Testează manual după fiecare fază
|
||||||
|
✅ Actualizează progresul în TRIAL_BALANCE_FEATURE.md la finalul fiecărei faze
|
||||||
|
|
||||||
|
## Start
|
||||||
|
Începe cu Phase 0 și confirmă structura tabelului VBAL înainte de a trece la Phase 1.
|
||||||
|
|
||||||
|
Urmărește progresul în features/TRIAL_BALANCE_FEATURE.md actualizând:
|
||||||
|
- Status fază: 🔲 → 🔄 → ✅
|
||||||
|
- Checkboxes task-uri: [ ] → [x]
|
||||||
|
- Overall Progress: X% Complete
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Alternative scurte pentru faze individuale:
|
||||||
|
|
||||||
|
### Pentru Phase 1 (Backend):
|
||||||
|
```
|
||||||
|
Implementează Phase 1 din features/TRIAL_BALANCE_FEATURE.md:
|
||||||
|
- Creează schemas/trial_balance.py (TrialBalanceItem, Request, Response)
|
||||||
|
- Creează routers/trial_balance.py (GET /api/trial-balance cu filtering/pagination)
|
||||||
|
- Testează cu curl/Postman
|
||||||
|
- Marchează task-urile ca [x] în feature file
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pentru Phase 3 (Frontend View):
|
||||||
|
```
|
||||||
|
Implementează Phase 3 din features/TRIAL_BALANCE_FEATURE.md:
|
||||||
|
- Creează TrialBalanceView.vue
|
||||||
|
- Folosește DOAR pattern-uri CSS existente (.roa-card, .roa-page-header)
|
||||||
|
- FĂRĂ :deep(), FĂRĂ custom CSS
|
||||||
|
- DataTable cu coloane: Cont, Denumire, Sold Prec (D/C), Rulaj Lunar (D/C), Sold Final (D/C)
|
||||||
|
- Marchează task-urile ca [x] în feature file
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tips pentru urmărire progres:
|
||||||
|
|
||||||
|
Actualizează manual în TRIAL_BALANCE_FEATURE.md:
|
||||||
|
```markdown
|
||||||
|
### ✅ Phase 1: Backend API Implementation
|
||||||
|
**Status**: ✅ Completed
|
||||||
|
|
||||||
|
**Tasks**:
|
||||||
|
- [x] Create Pydantic schema
|
||||||
|
- [x] Create router
|
||||||
|
- [x] Register router in main.py
|
||||||
|
- [x] Test endpoint manually
|
||||||
|
```
|
||||||
|
|
||||||
|
Apoi actualizează Overall Progress:
|
||||||
|
```markdown
|
||||||
|
### Overall Progress
|
||||||
|
- **Phase 0**: ✅ Completed (100%)
|
||||||
|
- **Phase 1**: ✅ Completed (100%)
|
||||||
|
- **Phase 2**: 🔄 In Progress (50%)
|
||||||
|
...
|
||||||
|
|
||||||
|
**Total Progress**: 35% Complete
|
||||||
|
```
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
Pydantic models for Trial Balance (Balanță de Verificare)
|
Pydantic models for Trial Balance (Balanță de Verificare)
|
||||||
Maps to Oracle VBAL table
|
Maps to Oracle VBAL VIEW (exists in each company schema)
|
||||||
"""
|
"""
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
from typing import Optional, List
|
from typing import Optional, List
|
||||||
@@ -8,16 +8,22 @@ from decimal import Decimal
|
|||||||
|
|
||||||
class TrialBalanceItem(BaseModel):
|
class TrialBalanceItem(BaseModel):
|
||||||
"""
|
"""
|
||||||
Individual trial balance record from VBAL table
|
Individual trial balance record from VBAL VIEW
|
||||||
|
Real structure from Oracle:
|
||||||
|
- CONT: account number
|
||||||
|
- DENUMIRE: account description
|
||||||
|
- PRECDEB/PRECCRED: previous balance debit/credit
|
||||||
|
- RULDEB/RULCRED: monthly movement debit/credit
|
||||||
|
- SOLDDEB/SOLDCRED: final balance debit/credit
|
||||||
"""
|
"""
|
||||||
cont: str = Field(description="Număr cont contabil")
|
cont: str = Field(description="Număr cont contabil (CONT)")
|
||||||
dcont: str = Field(description="Denumire cont")
|
denumire: Optional[str] = Field(default="", description="Denumire cont (DENUMIRE)")
|
||||||
sold_precedent_debit: Decimal = Field(description="Sold precedent debit", decimal_places=2)
|
sold_precedent_debit: Decimal = Field(description="Sold precedent debit (PRECDEB)", decimal_places=2)
|
||||||
sold_precedent_credit: Decimal = Field(description="Sold precedent credit", decimal_places=2)
|
sold_precedent_credit: Decimal = Field(description="Sold precedent credit (PRECCRED)", decimal_places=2)
|
||||||
rulaj_lunar_debit: Decimal = Field(description="Rulaj lunar debit", decimal_places=2)
|
rulaj_lunar_debit: Decimal = Field(description="Rulaj lunar debit (RULDEB)", decimal_places=2)
|
||||||
rulaj_lunar_credit: Decimal = Field(description="Rulaj lunar credit", decimal_places=2)
|
rulaj_lunar_credit: Decimal = Field(description="Rulaj lunar credit (RULCRED)", decimal_places=2)
|
||||||
sold_final_debit: Decimal = Field(description="Sold final debit", decimal_places=2)
|
sold_final_debit: Decimal = Field(description="Sold final debit (SOLDDEB)", decimal_places=2)
|
||||||
sold_final_credit: Decimal = Field(description="Sold final credit", decimal_places=2)
|
sold_final_credit: Decimal = Field(description="Sold final credit (SOLDCRED)", decimal_places=2)
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|||||||
@@ -64,8 +64,9 @@ async def get_trial_balance(
|
|||||||
sort_order = 'asc'
|
sort_order = 'asc'
|
||||||
|
|
||||||
# Validează sort_by (previne SQL injection)
|
# Validează sort_by (previne SQL injection)
|
||||||
valid_sort_columns = ['CONT', 'DCONT', 'SD_PREC', 'SC_PREC', 'RD_LUNA',
|
# Real column names from VBAL VIEW
|
||||||
'RC_LUNA', 'SD_FINAL', 'SC_FINAL']
|
valid_sort_columns = ['CONT', 'DENUMIRE', 'PRECDEB', 'PRECCRED',
|
||||||
|
'RULDEB', 'RULCRED', 'SOLDDEB', 'SOLDCRED']
|
||||||
if sort_by.upper() not in valid_sort_columns:
|
if sort_by.upper() not in valid_sort_columns:
|
||||||
sort_by = 'CONT'
|
sort_by = 'CONT'
|
||||||
|
|
||||||
@@ -90,25 +91,25 @@ async def get_trial_balance(
|
|||||||
|
|
||||||
schema = schema_result[0]
|
schema = schema_result[0]
|
||||||
|
|
||||||
# Construiește query-ul de bază pentru VBAL
|
# Construiește query-ul de bază pentru VBAL VIEW
|
||||||
|
# VBAL este un VIEW în fiecare schemă de companie
|
||||||
|
# Structura reală: CONT, DENUMIRE, AN, LUNA, PRECDEB, PRECCRED, RULDEB, RULCRED, SOLDDEB, SOLDCRED
|
||||||
base_query = f"""
|
base_query = f"""
|
||||||
SELECT
|
SELECT
|
||||||
CONT,
|
CONT,
|
||||||
DCONT,
|
NVL(DENUMIRE, '') as DENUMIRE,
|
||||||
NVL(SD_PREC, 0) as SD_PREC,
|
NVL(PRECDEB, 0) as PRECDEB,
|
||||||
NVL(SC_PREC, 0) as SC_PREC,
|
NVL(PRECCRED, 0) as PRECCRED,
|
||||||
NVL(RD_LUNA, 0) as RD_LUNA,
|
NVL(RULDEB, 0) as RULDEB,
|
||||||
NVL(RC_LUNA, 0) as RC_LUNA,
|
NVL(RULCRED, 0) as RULCRED,
|
||||||
NVL(SD_FINAL, 0) as SD_FINAL,
|
NVL(SOLDDEB, 0) as SOLDDEB,
|
||||||
NVL(SC_FINAL, 0) as SC_FINAL
|
NVL(SOLDCRED, 0) as SOLDCRED
|
||||||
FROM {schema}.VBAL
|
FROM {schema}.VBAL
|
||||||
WHERE COD_FIRMA = :cod_firma
|
WHERE AN = :an
|
||||||
AND AN = :an
|
|
||||||
AND LUNA = :luna
|
AND LUNA = :luna
|
||||||
"""
|
"""
|
||||||
|
|
||||||
params = {
|
params = {
|
||||||
'cod_firma': company,
|
|
||||||
'an': an,
|
'an': an,
|
||||||
'luna': luna
|
'luna': luna
|
||||||
}
|
}
|
||||||
@@ -119,7 +120,7 @@ async def get_trial_balance(
|
|||||||
params['cont_filter'] = f"{cont_filter}%"
|
params['cont_filter'] = f"{cont_filter}%"
|
||||||
|
|
||||||
if denumire_filter:
|
if denumire_filter:
|
||||||
base_query += " AND UPPER(DCONT) LIKE UPPER(:denumire_filter)"
|
base_query += " AND UPPER(DENUMIRE) LIKE UPPER(:denumire_filter)"
|
||||||
params['denumire_filter'] = f"%{denumire_filter}%"
|
params['denumire_filter'] = f"%{denumire_filter}%"
|
||||||
|
|
||||||
# Count total pentru paginare
|
# Count total pentru paginare
|
||||||
@@ -148,11 +149,13 @@ async def get_trial_balance(
|
|||||||
rows = cursor.fetchall()
|
rows = cursor.fetchall()
|
||||||
|
|
||||||
# Procesează rezultatele
|
# Procesează rezultatele
|
||||||
|
# Index columns: CONT(0), DENUMIRE(1), PRECDEB(2), PRECCRED(3),
|
||||||
|
# RULDEB(4), RULCRED(5), SOLDDEB(6), SOLDCRED(7), rnum(8)
|
||||||
items = []
|
items = []
|
||||||
for row in rows:
|
for row in rows:
|
||||||
item = TrialBalanceItem(
|
item = TrialBalanceItem(
|
||||||
cont=row[0] or '',
|
cont=row[0] or '',
|
||||||
dcont=row[1] or '',
|
denumire=row[1] or '',
|
||||||
sold_precedent_debit=Decimal(str(row[2] or 0)),
|
sold_precedent_debit=Decimal(str(row[2] or 0)),
|
||||||
sold_precedent_credit=Decimal(str(row[3] or 0)),
|
sold_precedent_credit=Decimal(str(row[3] or 0)),
|
||||||
rulaj_lunar_debit=Decimal(str(row[4] or 0)),
|
rulaj_lunar_debit=Decimal(str(row[4] or 0)),
|
||||||
|
|||||||
@@ -119,7 +119,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</Column>
|
</Column>
|
||||||
|
|
||||||
<Column field="dcont" header="Denumire Cont" sortable :style="{ width: '25%' }" />
|
<Column field="denumire" header="Denumire Cont" sortable :style="{ width: '25%' }" />
|
||||||
|
|
||||||
<Column header="Sold Precedent" :style="{ width: '15%' }">
|
<Column header="Sold Precedent" :style="{ width: '15%' }">
|
||||||
<template #body="slotProps">
|
<template #body="slotProps">
|
||||||
|
|||||||
Reference in New Issue
Block a user