Files
roa2web-service-auto/reports-app/backend/app/models/invoice.py
Marius Mutu c75e896a84 feat: Add accounting period selector for all views
- Add PeriodSelectorMini component for global period selection
- Add accountingPeriod store for shared period state
- Add calendar service/router/model for available periods API
- Update Dashboard, Invoices, Trial Balance, Bank/Cash Register views
  to respect selected period
- Fix Trial Balance navigation sync bug (period now syncs on mount)
- Update backend services to accept luna/an parameters

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 12:14:35 +02:00

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")
luna: Optional[int] = Field(default=None, ge=1, le=12, description="Luna contabilă (1-12)")
an: Optional[int] = Field(default=None, ge=2000, le=2100, description="Anul contabil")
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