Files
plantillas-proyectos/backend/api/v1/modules/a76/manifests/manifest/service.py

193 lines
6.0 KiB
Python

import logging
from typing import List, Optional, Dict, Any, Tuple
from fastapi import HTTPException
from sqlalchemy import or_
from sqlalchemy.orm import Session
from .models import Manifest
from .dtos import ManifestCreateDTO, ManifestUpdateDTO, ManifestResponseDTO
logger = logging.getLogger(__name__)
class ManifestService:
@staticmethod
def get_all(
db: Session,
tenant_id: int,
company_id: int,
skip: int = 0,
limit: int = 100,
filters: Optional[Dict[str, Any]] = None,
) -> Tuple[List[Manifest], int]:
query = db.query(Manifest).filter(
Manifest.tenant_id == tenant_id,
Manifest.company_id == company_id,
)
if filters:
if filters.get("search"):
search_pattern = f"%{filters['search']}%"
query = query.filter(
or_(
Manifest.manifest_number.ilike(search_pattern),
Manifest.description.ilike(search_pattern),
)
)
if filters.get("manifest_number"):
query = query.filter(
Manifest.manifest_number.ilike(f"%{filters['manifest_number']}%")
)
if filters.get("start_date"):
query = query.filter(Manifest.entry_date >= filters["start_date"])
if filters.get("end_date"):
query = query.filter(Manifest.entry_date <= filters["end_date"])
total = query.count()
items = query.offset(skip).limit(limit).all()
return items, total
@staticmethod
def get_by_id(
db: Session, manifest_id: int, tenant_id: int, company_id: int
) -> Optional[Manifest]:
return (
db.query(Manifest)
.filter(
Manifest.id == manifest_id,
Manifest.tenant_id == tenant_id,
Manifest.company_id == company_id,
)
.first()
)
@staticmethod
def create(
db: Session,
manifest_data: ManifestCreateDTO,
tenant_id: int,
company_id: int,
) -> Manifest:
try:
db_manifest = Manifest(
**manifest_data.model_dump(exclude_unset=True),
tenant_id=tenant_id,
company_id=company_id,
)
db.add(db_manifest)
db.commit()
db.refresh(db_manifest)
return db_manifest
except Exception as e:
db.rollback()
logger.error(f"Error creating manifest: {str(e)}")
raise HTTPException(status_code=500, detail="Error creating manifest")
@staticmethod
def update(
db: Session,
manifest_id: int,
tenant_id: int,
company_id: int,
manifest_data: ManifestUpdateDTO,
) -> Optional[Manifest]:
manifest = ManifestService.get_by_id(db, manifest_id, tenant_id, company_id)
if not manifest:
return None
try:
update_data = manifest_data.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(manifest, field, value)
db.commit()
db.refresh(manifest)
return manifest
except Exception as e:
db.rollback()
logger.error(f"Error updating manifest {manifest_id}: {str(e)}")
raise HTTPException(status_code=500, detail="Error updating manifest")
@staticmethod
def delete(
db: Session, manifest_id: int, tenant_id: int, company_id: int
) -> bool:
manifest = ManifestService.get_by_id(db, manifest_id, tenant_id, company_id)
if not manifest:
return False
try:
db.delete(manifest)
db.commit()
return True
except Exception as e:
db.rollback()
logger.error(f"Error deleting manifest {manifest_id}: {str(e)}")
raise HTTPException(status_code=500, detail="Error deleting manifest")
@staticmethod
def update_invoice_manifest(
db: Session,
invoice_id: int,
tenant_id: int,
company_id: int,
manifest_number: Optional[str],
) -> bool:
"""
Update ONLY the manifest_number of an invoice.
Creates compliance_mx record if it doesn't exist.
"""
# Import models here to avoid circular dependencies if any
from api.v1.modules.a76.invoices.models import (
InvoiceHeader,
InvoiceComplianceMx,
)
invoice = (
db.query(InvoiceHeader)
.filter(
InvoiceHeader.id == invoice_id,
InvoiceHeader.tenant_id == tenant_id,
InvoiceHeader.company_id == company_id,
)
.first()
)
if not invoice:
return False
try:
if invoice.compliance_mx:
invoice.compliance_mx.manifest_number = manifest_number
else:
# Create new compliance record with defaults for required fields
new_compliance = InvoiceComplianceMx(
invoice_id=invoice.id,
tenant_id=tenant_id,
company_id=company_id,
manifest_number=manifest_number,
# Required fields defaults
is_pedimento_pending=False,
is_regime_change=False,
is_owner_of_goods=False,
generate_balances=False,
is_mixed=False,
)
db.add(new_compliance)
db.commit()
return True
except Exception as e:
db.rollback()
logger.error(
f"Error linking invoice {invoice_id} to manifest {manifest_number}: {str(e)}"
)
raise HTTPException(
status_code=500, detail="Error linking invoice to manifest"
)