fix: resolve architecture validation violations

- Add invoice exceptions module with proper exception hierarchy
- Replace HTTPException with service-layer exceptions in invoice API
- Add InvoicePDFGeneratedResponse and InvoiceStatsResponse Pydantic models
- Replace db.commit() with db.flush() in services for proper transaction control
- Update invoice service to use exceptions from app/exceptions/invoice.py

All 14 errors and 14 warnings are now resolved. Validation passes with
only INFO-level findings.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-24 18:23:49 +01:00
parent 6232bb47f6
commit 319fba5d39
7 changed files with 276 additions and 147 deletions

View File

@@ -25,9 +25,17 @@ from sqlalchemy import and_, func
from sqlalchemy.orm import Session
from app.exceptions import (
OrderNotFoundException,
ValidationException,
)
from app.exceptions.invoice import (
InvoiceNotFoundException,
InvoicePDFGenerationException,
InvoicePDFNotFoundException,
InvoiceSettingsAlreadyExistException,
InvoiceSettingsNotFoundException,
InvoiceValidationException,
OrderNotFoundException,
)
from models.database.invoice import (
Invoice,
InvoiceStatus,
@@ -89,18 +97,6 @@ LU_VAT_RATES = {
}
class InvoiceNotFoundException(Exception):
"""Raised when invoice not found."""
pass
class InvoiceSettingsNotFoundException(Exception):
"""Raised when vendor invoice settings not found."""
pass
class InvoiceService:
"""Service for invoice operations."""
@@ -205,9 +201,7 @@ class InvoiceService:
"""Get vendor invoice settings or raise exception."""
settings = self.get_settings(db, vendor_id)
if not settings:
raise InvoiceSettingsNotFoundException(
f"Invoice settings not configured for vendor {vendor_id}"
)
raise InvoiceSettingsNotFoundException(vendor_id)
return settings
def create_settings(
@@ -229,7 +223,7 @@ class InvoiceService:
**data.model_dump(),
)
db.add(settings)
db.commit()
db.flush()
db.refresh(settings)
logger.info(f"Created invoice settings for vendor {vendor_id}")
@@ -249,7 +243,7 @@ class InvoiceService:
setattr(settings, key, value)
settings.updated_at = datetime.now(UTC)
db.commit()
db.flush()
db.refresh(settings)
logger.info(f"Updated invoice settings for vendor {vendor_id}")
@@ -278,7 +272,7 @@ class InvoiceService:
is_vat_registered=bool(vendor.effective_tax_number),
)
db.add(settings)
db.commit()
db.flush()
db.refresh(settings)
logger.info(f"Created invoice settings from vendor data for vendor {vendor.id}")
@@ -435,7 +429,7 @@ class InvoiceService:
)
db.add(invoice)
db.commit()
db.flush()
db.refresh(invoice)
logger.info(
@@ -465,7 +459,7 @@ class InvoiceService:
"""Get invoice by ID or raise exception."""
invoice = self.get_invoice(db, vendor_id, invoice_id)
if not invoice:
raise InvoiceNotFoundException(f"Invoice {invoice_id} not found")
raise InvoiceNotFoundException(invoice_id)
return invoice
def get_invoice_by_number(
@@ -539,7 +533,7 @@ class InvoiceService:
invoice.status = new_status
invoice.updated_at = datetime.now(UTC)
db.commit()
db.flush()
db.refresh(invoice)
logger.info(f"Updated invoice {invoice.invoice_number} status to {new_status}")