TVA BREAKDOWN
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
"""CRUD operations for receipts."""
|
"""CRUD operations for receipts."""
|
||||||
|
|
||||||
|
import json
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
from typing import Optional, List, Tuple
|
from decimal import Decimal
|
||||||
|
from typing import Optional, List, Tuple, Any
|
||||||
from sqlalchemy import select, func, or_
|
from sqlalchemy import select, func, or_
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
from sqlalchemy.orm import selectinload
|
from sqlalchemy.orm import selectinload
|
||||||
@@ -10,6 +12,31 @@ from app.db.models.receipt import Receipt, ReceiptStatus
|
|||||||
from app.schemas.receipt import ReceiptCreate, ReceiptUpdate, ReceiptFilter
|
from app.schemas.receipt import ReceiptCreate, ReceiptUpdate, ReceiptFilter
|
||||||
|
|
||||||
|
|
||||||
|
def _serialize_tva_breakdown(tva_breakdown: Optional[List[Any]]) -> Optional[str]:
|
||||||
|
"""Serialize TVA breakdown list to JSON string for SQLite storage."""
|
||||||
|
if tva_breakdown is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Convert Decimal to float for JSON serialization
|
||||||
|
serializable = []
|
||||||
|
for entry in tva_breakdown:
|
||||||
|
if hasattr(entry, 'model_dump'):
|
||||||
|
# Pydantic model
|
||||||
|
item = entry.model_dump()
|
||||||
|
elif isinstance(entry, dict):
|
||||||
|
item = entry.copy()
|
||||||
|
else:
|
||||||
|
item = dict(entry)
|
||||||
|
|
||||||
|
# Convert Decimal to float
|
||||||
|
if 'amount' in item and isinstance(item['amount'], Decimal):
|
||||||
|
item['amount'] = float(item['amount'])
|
||||||
|
|
||||||
|
serializable.append(item)
|
||||||
|
|
||||||
|
return json.dumps(serializable)
|
||||||
|
|
||||||
|
|
||||||
class ReceiptCRUD:
|
class ReceiptCRUD:
|
||||||
"""CRUD operations for Receipt model."""
|
"""CRUD operations for Receipt model."""
|
||||||
|
|
||||||
@@ -20,8 +47,12 @@ class ReceiptCRUD:
|
|||||||
created_by: str,
|
created_by: str,
|
||||||
) -> Receipt:
|
) -> Receipt:
|
||||||
"""Create a new receipt."""
|
"""Create a new receipt."""
|
||||||
|
# Get data as dict and serialize tva_breakdown to JSON string
|
||||||
|
receipt_data = data.model_dump()
|
||||||
|
receipt_data['tva_breakdown'] = _serialize_tva_breakdown(receipt_data.get('tva_breakdown'))
|
||||||
|
|
||||||
receipt = Receipt(
|
receipt = Receipt(
|
||||||
**data.model_dump(),
|
**receipt_data,
|
||||||
created_by=created_by,
|
created_by=created_by,
|
||||||
status=ReceiptStatus.DRAFT,
|
status=ReceiptStatus.DRAFT,
|
||||||
)
|
)
|
||||||
@@ -132,6 +163,10 @@ class ReceiptCRUD:
|
|||||||
"""Update receipt fields."""
|
"""Update receipt fields."""
|
||||||
update_data = data.model_dump(exclude_unset=True)
|
update_data = data.model_dump(exclude_unset=True)
|
||||||
|
|
||||||
|
# Serialize tva_breakdown to JSON string if present
|
||||||
|
if 'tva_breakdown' in update_data:
|
||||||
|
update_data['tva_breakdown'] = _serialize_tva_breakdown(update_data['tva_breakdown'])
|
||||||
|
|
||||||
for field, value in update_data.items():
|
for field, value in update_data.items():
|
||||||
setattr(receipt, field, value)
|
setattr(receipt, field, value)
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
"""Pydantic schemas for receipts API."""
|
"""Pydantic schemas for receipts API."""
|
||||||
|
|
||||||
|
import json
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from typing import Optional, List
|
from typing import Optional, List, Any, Union
|
||||||
from pydantic import BaseModel, Field, ConfigDict
|
from pydantic import BaseModel, Field, ConfigDict, field_validator
|
||||||
|
|
||||||
from app.db.models.receipt import ReceiptType, ReceiptDirection, ReceiptStatus
|
from app.db.models.receipt import ReceiptType, ReceiptDirection, ReceiptStatus
|
||||||
from app.db.models.accounting_entry import EntryType
|
from app.db.models.accounting_entry import EntryType
|
||||||
@@ -148,6 +149,21 @@ class ReceiptResponse(ReceiptBase):
|
|||||||
attachments: List[AttachmentResponse] = []
|
attachments: List[AttachmentResponse] = []
|
||||||
entries: List[AccountingEntryResponse] = []
|
entries: List[AccountingEntryResponse] = []
|
||||||
|
|
||||||
|
@field_validator('tva_breakdown', mode='before')
|
||||||
|
@classmethod
|
||||||
|
def parse_tva_breakdown(cls, v: Any) -> Optional[List[dict]]:
|
||||||
|
"""Deserialize tva_breakdown from JSON string if needed."""
|
||||||
|
if v is None:
|
||||||
|
return None
|
||||||
|
if isinstance(v, str):
|
||||||
|
try:
|
||||||
|
return json.loads(v)
|
||||||
|
except (json.JSONDecodeError, TypeError):
|
||||||
|
return None
|
||||||
|
if isinstance(v, list):
|
||||||
|
return v
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class ReceiptListResponse(BaseModel):
|
class ReceiptListResponse(BaseModel):
|
||||||
"""Schema for paginated receipt list response."""
|
"""Schema for paginated receipt list response."""
|
||||||
|
|||||||
Reference in New Issue
Block a user