Merge pull request 'feature/tablas_nuevas_partes_2' (#226) from feature/tablas_nuevas_partes_2 into development
Reviewed-on: ADUANASOFT/anexo76#226
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
from pydantic import BaseModel, ConfigDict, field_validator
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import date
|
||||
|
||||
|
||||
class AphisCatalogDTO(BaseModel):
|
||||
id: Optional[int] = None
|
||||
|
||||
# --- Pestaña 1: General ---
|
||||
program_code: Optional[str] = None
|
||||
processing_code: Optional[str] = None
|
||||
aphis_type: Optional[str] = None
|
||||
disclaimer: Optional[str] = None
|
||||
electronic_image: Optional[str] = None
|
||||
confidential: Optional[str] = None
|
||||
global_product_id: Optional[str] = None
|
||||
intended_use_code: Optional[str] = None
|
||||
intended_use_description: Optional[str] = None
|
||||
item_type: Optional[str] = None
|
||||
product_code: Optional[str] = None
|
||||
product_code_2: Optional[str] = None
|
||||
product_code_3: Optional[str] = None
|
||||
scientific_genus_name: Optional[str] = None
|
||||
scientific_species_name: Optional[str] = None
|
||||
scientific_sub_species_name: Optional[str] = None
|
||||
common_name_specific: Optional[str] = None
|
||||
common_name_general: Optional[str] = None
|
||||
signed_doc: Optional[str] = None
|
||||
signed_doc_date: Optional[date] = None
|
||||
signed_doc_id: Optional[str] = None
|
||||
invoice_number: Optional[str] = None
|
||||
quantity_1: Optional[str] = None
|
||||
quantity_2: Optional[str] = None
|
||||
quantity_3: Optional[str] = None
|
||||
inspection: Optional[str] = None
|
||||
inspection_date: Optional[date] = None
|
||||
inspection_loc_date: Optional[date] = None
|
||||
inspection_location: Optional[str] = None
|
||||
country_production: Optional[str] = None
|
||||
country_source: Optional[str] = None
|
||||
|
||||
# --- Pestañas 2-7: Detalles (Listas de objetos) ---
|
||||
characteristics: Optional[List[Dict[str, Any]]] = []
|
||||
pitems: Optional[List[Dict[str, Any]]] = []
|
||||
lpcos: Optional[List[Dict[str, Any]]] = []
|
||||
entities: Optional[List[Dict[str, Any]]] = []
|
||||
containers: Optional[List[Dict[str, Any]]] = []
|
||||
routing: Optional[List[Dict[str, Any]]] = []
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@field_validator("signed_doc_date", "inspection_date", "inspection_loc_date", mode="before")
|
||||
@classmethod
|
||||
def empty_to_none(cls, v):
|
||||
if v == "":
|
||||
return None
|
||||
return v
|
||||
@@ -0,0 +1,61 @@
|
||||
from typing import Optional, List, Dict, Any
|
||||
from datetime import date
|
||||
from sqlalchemy import Integer, String, Date, PrimaryKeyConstraint, JSON
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from core.database import Base
|
||||
|
||||
|
||||
class AphisCatalog(Base):
|
||||
"""
|
||||
Catálogo global de registros APHIS por empresa.
|
||||
Soporta las 7 pestañas de información (General + 6 detalles via JSON).
|
||||
"""
|
||||
__tablename__ = "inv_aphis_catalog"
|
||||
__table_args__ = (
|
||||
PrimaryKeyConstraint("id", name="inv_aphis_catalog_pkey"),
|
||||
{"schema": "a24", "extend_existing": True},
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
company_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
|
||||
|
||||
# --- Pestaña 1: General (Campos principales) ---
|
||||
program_code: Mapped[Optional[str]] = mapped_column(String(10))
|
||||
processing_code: Mapped[Optional[str]] = mapped_column(String(10))
|
||||
aphis_type: Mapped[Optional[str]] = mapped_column(String(10))
|
||||
disclaimer: Mapped[Optional[str]] = mapped_column(String(10))
|
||||
electronic_image: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
confidential: Mapped[Optional[str]] = mapped_column(String(1))
|
||||
global_product_id: Mapped[Optional[str]] = mapped_column(String(100))
|
||||
intended_use_code: Mapped[Optional[str]] = mapped_column(String(10))
|
||||
intended_use_description: Mapped[Optional[str]] = mapped_column(String(200))
|
||||
item_type: Mapped[Optional[str]] = mapped_column(String(20))
|
||||
product_code: Mapped[Optional[str]] = mapped_column(String(20))
|
||||
product_code_2: Mapped[Optional[str]] = mapped_column(String(20))
|
||||
product_code_3: Mapped[Optional[str]] = mapped_column(String(20))
|
||||
scientific_genus_name: Mapped[Optional[str]] = mapped_column(String(100))
|
||||
scientific_species_name: Mapped[Optional[str]] = mapped_column(String(100))
|
||||
scientific_sub_species_name: Mapped[Optional[str]] = mapped_column(String(100))
|
||||
common_name_specific: Mapped[Optional[str]] = mapped_column(String(200))
|
||||
common_name_general: Mapped[Optional[str]] = mapped_column(String(200))
|
||||
signed_doc: Mapped[Optional[str]] = mapped_column(String(100))
|
||||
signed_doc_date: Mapped[Optional[date]] = mapped_column(Date)
|
||||
signed_doc_id: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
invoice_number: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
quantity_1: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
quantity_2: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
quantity_3: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
inspection: Mapped[Optional[str]] = mapped_column(String(200))
|
||||
inspection_date: Mapped[Optional[date]] = mapped_column(Date)
|
||||
inspection_loc_date: Mapped[Optional[date]] = mapped_column(Date)
|
||||
inspection_location: Mapped[Optional[str]] = mapped_column(String(200))
|
||||
country_production: Mapped[Optional[str]] = mapped_column(String(3))
|
||||
country_source: Mapped[Optional[str]] = mapped_column(String(3))
|
||||
|
||||
# --- Pestañas 2-7: Detalles (Almacenados como JSON por flexibilidad) ---
|
||||
characteristics: Mapped[Optional[List[Dict[str, Any]]]] = mapped_column(JSON, default=list)
|
||||
pitems: Mapped[Optional[List[Dict[str, Any]]]] = mapped_column(JSON, default=list)
|
||||
lpcos: Mapped[Optional[List[Dict[str, Any]]]] = mapped_column(JSON, default=list)
|
||||
entities: Mapped[Optional[List[Dict[str, Any]]]] = mapped_column(JSON, default=list)
|
||||
containers: Mapped[Optional[List[Dict[str, Any]]]] = mapped_column(JSON, default=list)
|
||||
routing: Mapped[Optional[List[Dict[str, Any]]]] = mapped_column(JSON, default=list)
|
||||
@@ -0,0 +1,62 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.orm import Session
|
||||
from typing import List
|
||||
from core.database import get_core_db
|
||||
from .models import AphisCatalog
|
||||
from .dto import AphisCatalogDTO
|
||||
|
||||
router = APIRouter(prefix="/aphis-catalog", tags=["APHIS Catalog"])
|
||||
|
||||
|
||||
@router.get("/", response_model=List[AphisCatalogDTO])
|
||||
def list_aphis_catalog(company_id: int, db: Session = Depends(get_core_db)):
|
||||
records = (
|
||||
db.query(AphisCatalog)
|
||||
.filter(AphisCatalog.company_id == company_id)
|
||||
.order_by(AphisCatalog.id)
|
||||
.all()
|
||||
)
|
||||
return records
|
||||
|
||||
|
||||
@router.post("/", response_model=AphisCatalogDTO)
|
||||
def create_aphis_catalog(data: AphisCatalogDTO, company_id: int, db: Session = Depends(get_core_db)):
|
||||
payload = data.model_dump(exclude={"id"})
|
||||
record = AphisCatalog(**payload, company_id=company_id)
|
||||
db.add(record)
|
||||
db.commit()
|
||||
db.refresh(record)
|
||||
return record
|
||||
|
||||
|
||||
@router.put("/{record_id}", response_model=AphisCatalogDTO)
|
||||
def update_aphis_catalog(
|
||||
record_id: int, data: AphisCatalogDTO, company_id: int, db: Session = Depends(get_core_db)
|
||||
):
|
||||
record = (
|
||||
db.query(AphisCatalog)
|
||||
.filter(AphisCatalog.id == record_id, AphisCatalog.company_id == company_id)
|
||||
.first()
|
||||
)
|
||||
if not record:
|
||||
raise HTTPException(status_code=404, detail="Registro no encontrado")
|
||||
|
||||
for field, value in data.model_dump(exclude={"id"}).items():
|
||||
setattr(record, field, value)
|
||||
|
||||
db.commit()
|
||||
db.refresh(record)
|
||||
return record
|
||||
|
||||
|
||||
@router.delete("/{record_id}", status_code=204)
|
||||
def delete_aphis_catalog(record_id: int, company_id: int, db: Session = Depends(get_core_db)):
|
||||
record = (
|
||||
db.query(AphisCatalog)
|
||||
.filter(AphisCatalog.id == record_id, AphisCatalog.company_id == company_id)
|
||||
.first()
|
||||
)
|
||||
if not record:
|
||||
raise HTTPException(status_code=404, detail="Registro no encontrado")
|
||||
db.delete(record)
|
||||
db.commit()
|
||||
@@ -8,6 +8,10 @@ from fastapi import APIRouter
|
||||
from .fa.fa_classes.routes import router as fa_classes_router
|
||||
from .fa.fa_item_lines.routes import router as fa_item_lines_router
|
||||
from .inv.part_countries.routes import router as part_countries_router
|
||||
from .inv.inv_aphis.inv_aphis_catalog.router import router as aphis_catalog_router
|
||||
|
||||
# Importar modelo para que SQLAlchemy cree la tabla automáticamente
|
||||
import api.v1.modules.a24.inv.inv_aphis.inv_aphis_catalog.models # noqa: F401
|
||||
|
||||
|
||||
# Router principal de A24
|
||||
@@ -21,3 +25,5 @@ router.include_router(
|
||||
|
||||
# Registrar routers de INV (Inventory)
|
||||
router.include_router(part_countries_router, prefix="/a24", tags=["a24 / inv / part-countries"])
|
||||
router.include_router(aphis_catalog_router, prefix="/a24", tags=["a24 / inv / aphis-catalog"])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user