Optimize PDF export layout with compact columns and more space for partner names. Add accounting period display to invoices matching Trial Balance format. Fix date filtering to use local timezone instead of UTC. Update invoice ordering to chronological sequence (DATAACT, NRACT, NUME). **Backend changes:** - Add accounting period query from calendar table - Add currency (valuta) and cont filter support - Change invoice ordering to chronological (DATAACT ASC, NRACT ASC, NUME) - Add accounting_period field to InvoiceListResponse model **Frontend changes:** - Optimize PDF column widths (37% for partner names, compact numeric columns) - Add custom column width support in exportUtils - Fix date conversion from UTC to local timezone (prevents day shift) - Add accounting period display in PDF exports - Enhance E2E test coverage **Cleanup:** - Remove obsolete Trial Balance feature documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
77 lines
3.4 KiB
Python
77 lines
3.4 KiB
Python
"""
|
|
Modele Pydantic pentru facturi - Compatibile cu aplicația Flask existentă
|
|
"""
|
|
from pydantic import BaseModel, Field, validator
|
|
from datetime import date
|
|
from typing import Optional, List, Literal
|
|
from decimal import Decimal
|
|
|
|
class InvoiceBase(BaseModel):
|
|
"""Model de bază pentru factură - mapează exact pe rezultatul query-ului Flask"""
|
|
nume: str = Field(description="Numele partenerului")
|
|
nract: int = Field(description="Numărul actului")
|
|
dataact: Optional[date] = Field(description="Data actului")
|
|
datascad: Optional[date] = Field(description="Data scadentă")
|
|
contract: Optional[str] = Field(description="Numărul contractului")
|
|
cod_fiscal: Optional[str] = Field(description="Codul fiscal")
|
|
reg_comert: Optional[str] = Field(description="Registrul comerțului")
|
|
cont: Optional[str] = Field(description="Contul contabil")
|
|
valuta: str = Field(default="RON", description="Valuta (RON, EUR, USD, etc.)")
|
|
|
|
class Invoice(InvoiceBase):
|
|
"""Model complet pentru factură cu calcule financiare"""
|
|
totctva: Decimal = Field(description="Total cu TVA", decimal_places=2)
|
|
achitat: Decimal = Field(description="Suma achitată", decimal_places=2)
|
|
soldfinal: Decimal = Field(description="Soldul final", decimal_places=2)
|
|
css_class: Literal["", "invoice-paid", "invoice-overdue"] = Field(
|
|
default="", description="Clasa CSS pentru stilizare"
|
|
)
|
|
|
|
@validator('css_class', always=True)
|
|
def determine_css_class(cls, v, values):
|
|
"""Determină automat clasa CSS bazată pe status factură"""
|
|
if 'soldfinal' in values and 'datascad' in values:
|
|
sold = values['soldfinal']
|
|
data_scad = values['datascad']
|
|
|
|
if sold < 1:
|
|
return 'invoice-paid'
|
|
elif data_scad and data_scad < date.today() and sold != 0:
|
|
return 'invoice-overdue'
|
|
return ''
|
|
|
|
class InvoiceFilter(BaseModel):
|
|
"""Filtru pentru căutarea facturilor"""
|
|
company: str = Field(description="Codul firmei (schema Oracle)")
|
|
partner_type: Literal["CLIENTI", "FURNIZORI"] = Field(description="Tipul partenerului")
|
|
date_from: Optional[date] = Field(description="Data de început")
|
|
date_to: Optional[date] = Field(description="Data de sfârșit")
|
|
partner_name: Optional[str] = Field(description="Filtru după nume")
|
|
cont: Optional[str] = Field(description="Filtru după cont contabil")
|
|
only_unpaid: bool = Field(default=True, description="Doar neachitate")
|
|
min_amount: Optional[Decimal] = Field(description="Suma minimă")
|
|
max_amount: Optional[Decimal] = Field(description="Suma maximă")
|
|
page: int = Field(default=1, ge=1, description="Pagina")
|
|
page_size: int = Field(default=50, ge=1, le=10000000, description="Mărimea paginii")
|
|
|
|
class InvoiceListResponse(BaseModel):
|
|
"""Răspuns pentru lista de facturi"""
|
|
invoices: List[Invoice]
|
|
total_count: int
|
|
filtered_count: int
|
|
total_amount: Decimal
|
|
page: int
|
|
page_size: int
|
|
has_more: bool
|
|
accounting_period: Optional[dict] = Field(default=None, description="Perioada contabilă (an, luna)")
|
|
|
|
class InvoiceSummary(BaseModel):
|
|
"""Rezumat pentru facturi - pentru dashboard"""
|
|
company: str
|
|
partner_type: str
|
|
total_invoices: int
|
|
total_amount: Decimal
|
|
paid_amount: Decimal
|
|
outstanding_amount: Decimal
|
|
overdue_amount: Decimal
|
|
overdue_count: int |