diff --git a/backend/api/v1/modules/a76/aduanal/dto.py b/backend/api/v1/modules/a76/aduanal/dto.py new file mode 100644 index 00000000..f4574fb1 --- /dev/null +++ b/backend/api/v1/modules/a76/aduanal/dto.py @@ -0,0 +1,68 @@ +from pydantic import BaseModel +from typing import Optional, List + +class CustomsBrokerDTO(BaseModel): + type: Optional[str] + broker_key: str + name: Optional[str] + address: Optional[str] + postal_code: Optional[str] + city: Optional[str] + state: Optional[str] + phone: Optional[str] + fax: Optional[str] + email: Optional[str] + country: Optional[str] + tax_id: Optional[str] + personal_id: Optional[str] + position: Optional[str] + license: Optional[str] + company: Optional[str] + contact: Optional[str] + tenant_id: str + company_id: str + + class Config: + orm_mode = True + + +class CustomsBrokerVUCreateDTO(BaseModel): + certificate_path: Optional[str] + key_path: Optional[str] + access_key: Optional[str] + fiel_format: Optional[str] + signature_read_path: Optional[str] + archive_path: Optional[str] + fiel_access_key: Optional[str] + web_service_user: Optional[str] + web_service_access_key: Optional[str] + vu_email: Optional[str] + vu_figure_type: Optional[str] + xml_files_path: Optional[str] + query_tax_id: Optional[str] + doda_certificate_path: Optional[str] + doda_key_path: Optional[str] + doda_web_service_user: Optional[str] + doda_web_service_access_key: Optional[str] + doda_fiel_access_key: Optional[str] + doda_xml_files_path: Optional[str] + + class Config: + orm_mode = True + + +class CustomsBrokerPersonnelDTO(BaseModel): + broker_key: str + line: int + name: Optional[str] + tax_id: Optional[str] + personal_id: Optional[str] + position: Optional[str] + license: Optional[str] + first_name: Optional[str] + last_name: Optional[str] + middle_name: Optional[str] + email: Optional[str] + + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/api/v1/modules/a76/aduanal/models.py b/backend/api/v1/modules/a76/aduanal/models.py new file mode 100644 index 00000000..933c29bb --- /dev/null +++ b/backend/api/v1/modules/a76/aduanal/models.py @@ -0,0 +1,74 @@ +from sqlalchemy import Column, String, Integer, ForeignKey +from sqlalchemy.orm import relationship +from core.database import Base + +class CustomsBroker(Base): + __tablename__ = "GAAduanal" + + type = Column(String(9), nullable=True) + broker_key = Column(String(5), primary_key=True, nullable=False) + name = Column(String(80), nullable=True) + address = Column(String(1500), nullable=True) + postal_code = Column(String(15), nullable=True) + city = Column(String(30), nullable=True) + state = Column(String(30), nullable=True) + phone = Column(String(30), nullable=True) + fax = Column(String(30), nullable=True) + email = Column(String(100), nullable=True) + country = Column(String(3), nullable=True) + tax_id = Column(String(30), nullable=True) + personal_id = Column(String(20), nullable=True) + position = Column(String(30), nullable=True) + license = Column(String(4), nullable=True) + company = Column(String(200), nullable=True) + contact = Column(String(80), nullable=True) + tenant_id = Column(String(36), nullable=False) + company_id = Column(String(36), nullable=False) + + vu = relationship("CustomsBrokerVU", back_populates="customs_broker", cascade="all, delete") + personnel = relationship("CustomsBrokerPersonnel", back_populates="customs_broker", cascade="all, delete") + + +class CustomsBrokerVU(Base): + __tablename__ = "GAAduanal_VU" + + broker_key = Column(String(5), ForeignKey("GAAduanal.broker_key", ondelete="CASCADE"), primary_key=True) + certificate_path = Column(String(1499), nullable=True) + key_path = Column(String(1499), nullable=True) + access_key = Column(String(50), nullable=True) + fiel_format = Column(String(19), nullable=True) + signature_read_path = Column(String(1499), nullable=True) + archive_path = Column(String(1499), nullable=True) + fiel_access_key = Column(String(50), nullable=True) + web_service_user = Column(String(100), nullable=True) + web_service_access_key = Column(String(100), nullable=True) + vu_email = Column(String(800), nullable=True) + vu_figure_type = Column(String(29), nullable=True) + xml_files_path = Column(String(1499), nullable=True) + query_tax_id = Column(String(30), nullable=True) + doda_certificate_path = Column(String(1499), nullable=True) + doda_key_path = Column(String(1499), nullable=True) + doda_web_service_user = Column(String(100), nullable=True) + doda_web_service_access_key = Column(String(100), nullable=True) + doda_fiel_access_key = Column(String(50), nullable=True) + doda_xml_files_path = Column(String(1499), nullable=True) + + customs_broker = relationship("CustomsBroker", back_populates="vu") + + +class CustomsBrokerPersonnel(Base): + __tablename__ = "GAAduanalPersonal" + + broker_key = Column(String(5), ForeignKey("GAAduanal.broker_key", ondelete="CASCADE"), primary_key=True) + line = Column(Integer, primary_key=True, nullable=False) + name = Column(String(80), nullable=True) + tax_id = Column(String(30), nullable=True) + personal_id = Column(String(20), nullable=True) + position = Column(String(30), nullable=True) + license = Column(String(4), nullable=True) + first_name = Column(String(80), nullable=True) + last_name = Column(String(80), nullable=True) + middle_name = Column(String(80), nullable=True) + email = Column(String(100), nullable=True) + + customs_broker = relationship("CustomsBroker", back_populates="personnel") \ No newline at end of file diff --git a/backend/api/v1/modules/a76/aduanal/routes.py b/backend/api/v1/modules/a76/aduanal/routes.py new file mode 100644 index 00000000..d4493cd2 --- /dev/null +++ b/backend/api/v1/modules/a76/aduanal/routes.py @@ -0,0 +1,38 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from . import services, dto +from core.database import get_db + +router = APIRouter() + +@router.get("/customs-broker/{broker_key}", response_model=dto.CustomsBrokerDTO) +def get_customs_broker(broker_key: str, db: Session = Depends(get_db)): + broker = services.CustomsBrokerService.get_by_broker_key(db, broker_key) + if not broker: + raise HTTPException(status_code=404, detail="Customs Broker not found") + return broker + +@router.post("/customs-broker", response_model=dto.CustomsBrokerDTO) +def create_customs_broker(broker_data: dto.CustomsBrokerDTO, db: Session = Depends(get_db)): + return services.CustomsBrokerService.create_customs_broker(db, broker_data) + +@router.delete("/customs-broker/{broker_key}", response_model=dto.CustomsBrokerDTO) +def delete_customs_broker(broker_key: str, db: Session = Depends(get_db)): + broker = services.CustomsBrokerService.delete_customs_broker(db, broker_key) + if not broker: + raise HTTPException(status_code=404, detail="Customs Broker not found") + return broker + +@router.put("/customs-broker-vu/{broker_key}", response_model=dto.CustomsBrokerVUCreateDTO) +def update_customs_broker_vu(broker_key: str, vu_data: dto.CustomsBrokerVUCreateDTO, db: Session = Depends(get_db)): + updated_vu = services.CustomsBrokerVUService.update_vu(db, broker_key, vu_data) + if not updated_vu: + raise HTTPException(status_code=404, detail="Customs Broker VU not found") + return updated_vu + +@router.put("/customs-broker-personnel/{broker_key}/{line}", response_model=dto.CustomsBrokerPersonnelDTO) +def update_customs_broker_personnel(broker_key: str, line: int, personnel_data: dto.CustomsBrokerPersonnelDTO, db: Session = Depends(get_db)): + updated_personnel = services.CustomsBrokerPersonnelService.update_personnel(db, broker_key, line, personnel_data) + if not updated_personnel: + raise HTTPException(status_code=404, detail="Customs Broker Personnel not found") + return updated_personnel \ No newline at end of file diff --git a/backend/api/v1/modules/a76/aduanal/services.py b/backend/api/v1/modules/a76/aduanal/services.py new file mode 100644 index 00000000..5d90a0a7 --- /dev/null +++ b/backend/api/v1/modules/a76/aduanal/services.py @@ -0,0 +1,90 @@ +from sqlalchemy.orm import Session +from . import models, dto + +class CustomsBrokerService: + @staticmethod + def get_by_broker_key(db: Session, broker_key: str): + return db.query(models.CustomsBroker).filter(models.CustomsBroker.broker_key == broker_key).first() + + @staticmethod + def create_customs_broker(db: Session, broker_data: dto.CustomsBrokerDTO): + new_broker = models.CustomsBroker(**broker_data.dict()) + db.add(new_broker) + db.commit() + db.refresh(new_broker) + return new_broker + + @staticmethod + def delete_customs_broker(db: Session, broker_key: str): + broker = CustomsBrokerService.get_by_broker_key(db, broker_key) + if broker: + db.delete(broker) + db.commit() + return broker + + +class CustomsBrokerVUService: + @staticmethod + def get_by_broker_key(db: Session, broker_key: str): + return db.query(models.CustomsBrokerVU).filter(models.CustomsBrokerVU.broker_key == broker_key).first() + + @staticmethod + def create_vu(db: Session, vu_data: dto.CustomsBrokerVUCreateDTO): + new_vu = models.CustomsBrokerVU(**vu_data.dict()) + db.add(new_vu) + db.commit() + db.refresh(new_vu) + return new_vu + + @staticmethod + def update_vu(db: Session, broker_key: str, vu_data: dto.CustomsBrokerVUCreateDTO): + vu = CustomsBrokerVUService.get_by_broker_key(db, broker_key) + if vu: + for key, value in vu_data.dict(exclude_unset=True).items(): + setattr(vu, key, value) + db.commit() + db.refresh(vu) + return vu + + @staticmethod + def delete_vu(db: Session, broker_key: str): + vu = CustomsBrokerVUService.get_by_broker_key(db, broker_key) + if vu: + db.delete(vu) + db.commit() + return vu + + +class CustomsBrokerPersonnelService: + @staticmethod + def get_by_broker_key_and_line(db: Session, broker_key: str, line: int): + return db.query(models.CustomsBrokerPersonnel).filter( + models.CustomsBrokerPersonnel.broker_key == broker_key, + models.CustomsBrokerPersonnel.line == line + ).first() + + @staticmethod + def create_personnel(db: Session, personnel_data: dto.CustomsBrokerPersonnelDTO): + new_personnel = models.CustomsBrokerPersonnel(**personnel_data.dict()) + db.add(new_personnel) + db.commit() + db.refresh(new_personnel) + return new_personnel + + @staticmethod + def update_personnel(db: Session, broker_key: str, line: int, personnel_data: dto.CustomsBrokerPersonnelDTO): + personnel = CustomsBrokerPersonnelService.get_by_broker_key_and_line(db, broker_key, line) + if personnel: + for key, value in personnel_data.dict(exclude_unset=True).items(): + setattr(personnel, key, value) + db.commit() + db.refresh(personnel) + return personnel + + @staticmethod + def delete_personnel(db: Session, broker_key: str, line: int): + personnel = CustomsBrokerPersonnelService.get_by_broker_key_and_line(db, broker_key, line) + if personnel: + db.delete(personnel) + db.commit() + return personnel \ No newline at end of file diff --git a/backend/api/v1/modules/a76/drivers/dto.py b/backend/api/v1/modules/a76/drivers/dto.py new file mode 100644 index 00000000..1a9f81c7 --- /dev/null +++ b/backend/api/v1/modules/a76/drivers/dto.py @@ -0,0 +1,37 @@ +from pydantic import BaseModel +from typing import Optional + +class DriverBaseDTO(BaseModel): + transporter_key: str + line: int + driver_name: Optional[str] + license_number: Optional[str] + express_line_id: Optional[str] + ace_id: Optional[str] + birth_date: Optional[int] + gender: Optional[str] + birth_country: Optional[str] + hazardous_material_auth: Optional[str] + hazardous_material_state: Optional[str] + first_name: Optional[str] + last_name: Optional[str] + id_key1: Optional[str] + id_number1: Optional[str] + id_state1: Optional[str] + id_country1: Optional[str] + id_key2: Optional[str] + id_number2: Optional[str] + id_state2: Optional[str] + id_country2: Optional[str] + badge_number: Optional[str] + class_type: Optional[str] + unique_badge_number: Optional[str] + company_id: str + tenant_id: str + +class DriverCreateDTO(DriverBaseDTO): + pass + +class DriverResponseDTO(DriverBaseDTO): + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/api/v1/modules/a76/drivers/models.py b/backend/api/v1/modules/a76/drivers/models.py new file mode 100644 index 00000000..fbdd42eb --- /dev/null +++ b/backend/api/v1/modules/a76/drivers/models.py @@ -0,0 +1,33 @@ +from sqlalchemy import Column, String, Integer, ForeignKey +from core.database import Base + +class Driver(Base): + __tablename__ = "driver" + __table_args__ = {"schema": "a76"} + + transporter_key = Column(String(5), ForeignKey("a76.transporter.transporter_key", ondelete="CASCADE"), primary_key=True, nullable=False) + line = Column(Integer, primary_key=True, nullable=False) + driver_name = Column(String(80), nullable=True) + license_number = Column(String(29), nullable=True) + express_line_id = Column(String(17), nullable=True) + ace_id = Column(String(20), nullable=True) + birth_date = Column(Integer, nullable=True) + gender = Column(String(1), nullable=True) + birth_country = Column(String(3), nullable=True) + hazardous_material_auth = Column(String(2), nullable=True) + hazardous_material_state = Column(String(30), nullable=True) + first_name = Column(String(20), nullable=True) + last_name = Column(String(20), nullable=True) + id_key1 = Column(String(40), nullable=True) + id_number1 = Column(String(20), nullable=True) + id_state1 = Column(String(30), nullable=True) + id_country1 = Column(String(3), nullable=True) + id_key2 = Column(String(40), nullable=True) + id_number2 = Column(String(20), nullable=True) + id_state2 = Column(String(30), nullable=True) + id_country2 = Column(String(3), nullable=True) + badge_number = Column(String(20), nullable=True) + class_type = Column(String(1), nullable=True) + unique_badge_number = Column(String(100), nullable=True) + company_id = Column(String, ForeignKey("a76.company.id"), nullable=False) + tenant_id = Column(String, ForeignKey("a76.tenants.id"), nullable=False) \ No newline at end of file diff --git a/backend/api/v1/modules/a76/drivers/routes.py b/backend/api/v1/modules/a76/drivers/routes.py new file mode 100644 index 00000000..5a2a661e --- /dev/null +++ b/backend/api/v1/modules/a76/drivers/routes.py @@ -0,0 +1,48 @@ +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.orm import Session +from typing import List + +from core.database import get_core_db +from core.security import get_current_user +from .dto import DriverCreateDTO, DriverResponseDTO +from .services import DriverService + +router = APIRouter(prefix="/drivers", tags=["Drivers"]) + +@router.get("/", response_model=List[DriverResponseDTO]) +async def list_drivers( + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + return db.query(DriverService).all() + +@router.get("/{transporter_key}/{line}", response_model=DriverResponseDTO) +async def read_driver( + transporter_key: str, + line: int, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + driver = DriverService.get_driver_by_key_and_line(db, transporter_key, line) + if not driver: + raise HTTPException(status_code=404, detail="Driver not found") + return driver + +@router.post("/", response_model=DriverResponseDTO, status_code=status.HTTP_201_CREATED) +async def create_driver( + driver_data: DriverCreateDTO, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + return DriverService.create_driver(db, driver_data) + +@router.delete("/{transporter_key}/{line}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_driver( + transporter_key: str, + line: int, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + driver = DriverService.delete_driver(db, transporter_key, line) + if not driver: + raise HTTPException(status_code=404, detail="Driver not found") \ No newline at end of file diff --git a/backend/api/v1/modules/a76/drivers/services.py b/backend/api/v1/modules/a76/drivers/services.py new file mode 100644 index 00000000..6f1f1099 --- /dev/null +++ b/backend/api/v1/modules/a76/drivers/services.py @@ -0,0 +1,26 @@ +from sqlalchemy.orm import Session +from . import models, dto + +class DriverService: + @staticmethod + def get_driver_by_key_and_line(db: Session, transporter_key: str, line: int): + return db.query(models.Driver).filter( + models.Driver.transporter_key == transporter_key, + models.Driver.line == line + ).first() + + @staticmethod + def create_driver(db: Session, driver_data: dto.DriverCreateDTO): + new_driver = models.Driver(**driver_data.dict()) + db.add(new_driver) + db.commit() + db.refresh(new_driver) + return new_driver + + @staticmethod + def delete_driver(db: Session, transporter_key: str, line: int): + driver = DriverService.get_driver_by_key_and_line(db, transporter_key, line) + if driver: + db.delete(driver) + db.commit() + return driver \ No newline at end of file diff --git a/backend/api/v1/modules/a76/router.py b/backend/api/v1/modules/a76/router.py index 25ddcbb3..25305015 100644 --- a/backend/api/v1/modules/a76/router.py +++ b/backend/api/v1/modules/a76/router.py @@ -20,6 +20,14 @@ from .seal.routes import router as seal_router from .fraction_rule_octave.routes import router as fraction_rule_octave_router from .country_rule_oct.routes import router as country_rule_oct_router from .exchange_rate.routes import router as exchange_rate_router +from .transport_types.routes import router as transport_types_router +from .trailers.routes import router as trailers_router +from .trailer_types.routes import router as trailer_types_router +from .transport_modes.routes import router as transport_modes_router +from .aduanal.routes import router as customs_broker_router +from .drivers.routes import router as drivers_router +from .transporters.routes import router as transporters_router +from .vehicles.routes import router as vehicles_router # Router principal router = APIRouter() @@ -40,4 +48,12 @@ router.include_router(seal_router, prefix="/a76", tags=["a76 / Seal"]) router.include_router(fraction_rule_octave_router, prefix="/a76", tags=["a76 / FractionRuleOctave"]) router.include_router(country_rule_oct_router, prefix="/a76", tags=["a76 / CountryRuleOct"]) router.include_router(exchange_rate_router, prefix="/a76", tags=["a76 / ExchangeRate"]) +router.include_router(transport_types_router, prefix="/a76", tags=["a76 / TransportTypes"]) +router.include_router(trailers_router, prefix="/a76", tags=["a76 / Trailers"]) +router.include_router(trailer_types_router, prefix="/a76", tags=["a76 / TrailerTypes"]) +router.include_router(transport_modes_router, prefix="/a76", tags=["a76 / TransportModes"]) +router.include_router(customs_broker_router, prefix="/a76", tags=["a76 / CustomsBroker"]) +router.include_router(drivers_router, prefix="/a76", tags=["a76 / Drivers"]) +router.include_router(transporters_router, prefix="/a76", tags=["a76 / Transporters"]) +router.include_router(vehicles_router, prefix="/a76", tags=["a76 / Vehicles"]) diff --git a/backend/api/v1/modules/a76/trailer_types/dto.py b/backend/api/v1/modules/a76/trailer_types/dto.py new file mode 100644 index 00000000..9318cb15 --- /dev/null +++ b/backend/api/v1/modules/a76/trailer_types/dto.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from typing import Optional + +class TrailerTypeBaseDTO(BaseModel): + trailer_type_key: str + description: Optional[str] + company_id: str + tenant_id: str + +class TrailerTypeCreateDTO(TrailerTypeBaseDTO): + pass + +class TrailerTypeResponseDTO(TrailerTypeBaseDTO): + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/api/v1/modules/a76/trailer_types/models.py b/backend/api/v1/modules/a76/trailer_types/models.py new file mode 100644 index 00000000..1f115fea --- /dev/null +++ b/backend/api/v1/modules/a76/trailer_types/models.py @@ -0,0 +1,11 @@ +from sqlalchemy import Column, String, ForeignKey +from core.database import Base + +class TrailerType(Base): + __tablename__ = "trailer_type" + __table_args__ = {"schema": "a76"} + + trailer_type_key = Column(String(2), primary_key=True, nullable=False) + description = Column(String(100), nullable=True) + company_id = Column(String, ForeignKey("a76.company.id"), nullable=False) + tenant_id = Column(String, ForeignKey("a76.tenants.id"), nullable=False) \ No newline at end of file diff --git a/backend/api/v1/modules/a76/trailer_types/routes.py b/backend/api/v1/modules/a76/trailer_types/routes.py new file mode 100644 index 00000000..d930f2fd --- /dev/null +++ b/backend/api/v1/modules/a76/trailer_types/routes.py @@ -0,0 +1,24 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from . import services, dto +from core.database import get_db + +router = APIRouter() + +@router.get("/trailer-types/{trailer_type_key}", response_model=dto.TrailerTypeDTO) +def get_trailer_type(trailer_type_key: str, db: Session = Depends(get_db)): + trailer_type = services.TrailerTypeService.get_trailer_type_by_key(db, trailer_type_key) + if not trailer_type: + raise HTTPException(status_code=404, detail="Trailer type not found") + return trailer_type + +@router.post("/trailer-types", response_model=dto.TrailerTypeDTO) +def create_trailer_type(trailer_type_data: dto.TrailerTypeCreateDTO, db: Session = Depends(get_db)): + return services.TrailerTypeService.create_trailer_type(db, trailer_type_data) + +@router.delete("/trailer-types/{trailer_type_key}", response_model=dto.TrailerTypeDTO) +def delete_trailer_type(trailer_type_key: str, db: Session = Depends(get_db)): + trailer_type = services.TrailerTypeService.delete_trailer_type(db, trailer_type_key) + if not trailer_type: + raise HTTPException(status_code=404, detail="Trailer type not found") + return trailer_type \ No newline at end of file diff --git a/backend/api/v1/modules/a76/trailer_types/services.py b/backend/api/v1/modules/a76/trailer_types/services.py new file mode 100644 index 00000000..55ea05a2 --- /dev/null +++ b/backend/api/v1/modules/a76/trailer_types/services.py @@ -0,0 +1,23 @@ +from sqlalchemy.orm import Session +from . import models, dto + +class TrailerTypeService: + @staticmethod + def get_trailer_type_by_key(db: Session, trailer_type_key: str): + return db.query(models.TrailerType).filter(models.TrailerType.trailer_type_key == trailer_type_key).first() + + @staticmethod + def create_trailer_type(db: Session, trailer_type_data: dto.TrailerTypeCreateDTO): + new_trailer_type = models.TrailerType(**trailer_type_data.dict()) + db.add(new_trailer_type) + db.commit() + db.refresh(new_trailer_type) + return new_trailer_type + + @staticmethod + def delete_trailer_type(db: Session, trailer_type_key: str): + trailer_type = TrailerTypeService.get_trailer_type_by_key(db, trailer_type_key) + if trailer_type: + db.delete(trailer_type) + db.commit() + return trailer_type \ No newline at end of file diff --git a/backend/api/v1/modules/a76/trailers/dto.py b/backend/api/v1/modules/a76/trailers/dto.py new file mode 100644 index 00000000..313713a5 --- /dev/null +++ b/backend/api/v1/modules/a76/trailers/dto.py @@ -0,0 +1,22 @@ +from pydantic import BaseModel +from typing import Optional + +class TrailerBaseDTO(BaseModel): + trailer_number: str + ace_trailer_number: Optional[str] + trailer_type_key: Optional[str] + seal: Optional[str] + entity_code: Optional[str] + plate_number: Optional[str] + state: Optional[str] + country: Optional[str] + container_key: Optional[str] + company_id: str + tenant_id: str + +class TrailerCreateDTO(TrailerBaseDTO): + pass + +class TrailerResponseDTO(TrailerBaseDTO): + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/api/v1/modules/a76/trailers/models.py b/backend/api/v1/modules/a76/trailers/models.py new file mode 100644 index 00000000..c41454f9 --- /dev/null +++ b/backend/api/v1/modules/a76/trailers/models.py @@ -0,0 +1,18 @@ +from sqlalchemy import Column, String, ForeignKey +from core.database import Base + +class Trailer(Base): + __tablename__ = "trailer" + __table_args__ = {"schema": "a76"} + + trailer_number = Column(String(20), primary_key=True, nullable=False) + ace_trailer_number = Column(String(10), nullable=True) + trailer_type_key = Column(String(2), ForeignKey("a76.trailer_type.trailer_type_key"), nullable=True) + seal = Column(String(15), nullable=True) + entity_code = Column(String(1), nullable=True) + plate_number = Column(String(17), nullable=True) + state = Column(String(30), nullable=True) + country = Column(String(3), nullable=True) + container_key = Column(String(3), nullable=True) + company_id = Column(String, ForeignKey("a76.company.id"), nullable=False) + tenant_id = Column(String, ForeignKey("a76.tenants.id"), nullable=False) \ No newline at end of file diff --git a/backend/api/v1/modules/a76/trailers/routes.py b/backend/api/v1/modules/a76/trailers/routes.py new file mode 100644 index 00000000..9f0218bc --- /dev/null +++ b/backend/api/v1/modules/a76/trailers/routes.py @@ -0,0 +1,24 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from . import services, dto +from core.database import get_db + +router = APIRouter() + +@router.get("/trailers/{trailer_number}", response_model=dto.TrailerDTO) +def get_trailer(trailer_number: str, db: Session = Depends(get_db)): + trailer = services.TrailerService.get_trailer_by_number(db, trailer_number) + if not trailer: + raise HTTPException(status_code=404, detail="Trailer not found") + return trailer + +@router.post("/trailers", response_model=dto.TrailerDTO) +def create_trailer(trailer_data: dto.TrailerCreateDTO, db: Session = Depends(get_db)): + return services.TrailerService.create_trailer(db, trailer_data) + +@router.delete("/trailers/{trailer_number}", response_model=dto.TrailerDTO) +def delete_trailer(trailer_number: str, db: Session = Depends(get_db)): + trailer = services.TrailerService.delete_trailer(db, trailer_number) + if not trailer: + raise HTTPException(status_code=404, detail="Trailer not found") + return trailer \ No newline at end of file diff --git a/backend/api/v1/modules/a76/trailers/services.py b/backend/api/v1/modules/a76/trailers/services.py new file mode 100644 index 00000000..2629fd4a --- /dev/null +++ b/backend/api/v1/modules/a76/trailers/services.py @@ -0,0 +1,23 @@ +from sqlalchemy.orm import Session +from . import models, dto + +class TrailerService: + @staticmethod + def get_trailer_by_number(db: Session, trailer_number: str): + return db.query(models.Trailer).filter(models.Trailer.trailer_number == trailer_number).first() + + @staticmethod + def create_trailer(db: Session, trailer_data: dto.TrailerCreateDTO): + new_trailer = models.Trailer(**trailer_data.dict()) + db.add(new_trailer) + db.commit() + db.refresh(new_trailer) + return new_trailer + + @staticmethod + def delete_trailer(db: Session, trailer_number: str): + trailer = TrailerService.get_trailer_by_number(db, trailer_number) + if trailer: + db.delete(trailer) + db.commit() + return trailer \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transport_modes/dto.py b/backend/api/v1/modules/a76/transport_modes/dto.py new file mode 100644 index 00000000..53ffa3bb --- /dev/null +++ b/backend/api/v1/modules/a76/transport_modes/dto.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from typing import Optional + +class TransportModeBaseDTO(BaseModel): + mode_key: str + mode_description: Optional[str] + company_id: str + tenant_id: str + +class TransportModeCreateDTO(TransportModeBaseDTO): + pass + +class TransportModeResponseDTO(TransportModeBaseDTO): + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transport_modes/models.py b/backend/api/v1/modules/a76/transport_modes/models.py new file mode 100644 index 00000000..77e8ce4c --- /dev/null +++ b/backend/api/v1/modules/a76/transport_modes/models.py @@ -0,0 +1,11 @@ +from sqlalchemy import Column, String, ForeignKey +from core.database import Base + +class TransportMode(Base): + __tablename__ = "transport_mode" + __table_args__ = {"schema": "a76"} + + mode_key = Column(String(3), primary_key=True, nullable=False) + mode_description = Column(String(30), nullable=True) + company_id = Column(String, ForeignKey("a76.company.id"), nullable=False) + tenant_id = Column(String, ForeignKey("a76.tenants.id"), nullable=False) \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transport_modes/routes.py b/backend/api/v1/modules/a76/transport_modes/routes.py new file mode 100644 index 00000000..1526611f --- /dev/null +++ b/backend/api/v1/modules/a76/transport_modes/routes.py @@ -0,0 +1,24 @@ +from fastapi import APIRouter, Depends, HTTPException +from sqlalchemy.orm import Session +from . import services, dto +from core.database import get_db + +router = APIRouter() + +@router.get("/transport-modes/{mode_key}", response_model=dto.TransportModeDTO) +def get_transport_mode(mode_key: str, db: Session = Depends(get_db)): + transport_mode = services.TransportModeService.get_transport_mode_by_key(db, mode_key) + if not transport_mode: + raise HTTPException(status_code=404, detail="Transport mode not found") + return transport_mode + +@router.post("/transport-modes", response_model=dto.TransportModeDTO) +def create_transport_mode(transport_mode_data: dto.TransportModeCreateDTO, db: Session = Depends(get_db)): + return services.TransportModeService.create_transport_mode(db, transport_mode_data) + +@router.delete("/transport-modes/{mode_key}", response_model=dto.TransportModeDTO) +def delete_transport_mode(mode_key: str, db: Session = Depends(get_db)): + transport_mode = services.TransportModeService.delete_transport_mode(db, mode_key) + if not transport_mode: + raise HTTPException(status_code=404, detail="Transport mode not found") + return transport_mode \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transport_modes/services.py b/backend/api/v1/modules/a76/transport_modes/services.py new file mode 100644 index 00000000..e5650e6e --- /dev/null +++ b/backend/api/v1/modules/a76/transport_modes/services.py @@ -0,0 +1,23 @@ +from sqlalchemy.orm import Session +from . import models, dto + +class TransportModeService: + @staticmethod + def get_transport_mode_by_key(db: Session, mode_key: str): + return db.query(models.TransportMode).filter(models.TransportMode.mode_key == mode_key).first() + + @staticmethod + def create_transport_mode(db: Session, transport_mode_data: dto.TransportModeCreateDTO): + new_transport_mode = models.TransportMode(**transport_mode_data.dict()) + db.add(new_transport_mode) + db.commit() + db.refresh(new_transport_mode) + return new_transport_mode + + @staticmethod + def delete_transport_mode(db: Session, mode_key: str): + transport_mode = TransportModeService.get_transport_mode_by_key(db, mode_key) + if transport_mode: + db.delete(transport_mode) + db.commit() + return transport_mode \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transport_types/dto.py b/backend/api/v1/modules/a76/transport_types/dto.py new file mode 100644 index 00000000..4a794759 --- /dev/null +++ b/backend/api/v1/modules/a76/transport_types/dto.py @@ -0,0 +1,15 @@ +from pydantic import BaseModel +from typing import Optional + +class TransportTypeBaseDTO(BaseModel): + transport_type_key: str + description: Optional[str] + company_id: str + tenant_id: str + +class TransportTypeCreateDTO(TransportTypeBaseDTO): + pass + +class TransportTypeResponseDTO(TransportTypeBaseDTO): + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transport_types/models.py b/backend/api/v1/modules/a76/transport_types/models.py new file mode 100644 index 00000000..ab706632 --- /dev/null +++ b/backend/api/v1/modules/a76/transport_types/models.py @@ -0,0 +1,11 @@ +from sqlalchemy import Column, String, ForeignKey +from core.database import Base + +class TransportType(Base): + __tablename__ = "transport_type" + __table_args__ = {"schema": "a76"} + + transport_type_key = Column(String(2), primary_key=True, nullable=False) + description = Column(String(100), nullable=True) + company_id = Column(String, ForeignKey("a76.company.id"), nullable=False) + tenant_id = Column(String, ForeignKey("a76.tenants.id"), nullable=False) \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transport_types/routes.py b/backend/api/v1/modules/a76/transport_types/routes.py new file mode 100644 index 00000000..5ac1a15e --- /dev/null +++ b/backend/api/v1/modules/a76/transport_types/routes.py @@ -0,0 +1,46 @@ +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.orm import Session +from typing import List + +from core.database import get_core_db +from core.security import get_current_user +from .dto import TransportTypeCreateDTO, TransportTypeResponseDTO +from .services import TransportTypeService + +router = APIRouter(prefix="/transport-types", tags=["TransportTypes"]) + +@router.get("/", response_model=List[TransportTypeResponseDTO]) +async def list_transport_types( + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + return db.query(TransportTypeService).all() + +@router.get("/{transport_type_key}", response_model=TransportTypeResponseDTO) +async def read_transport_type( + transport_type_key: str, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + transport_type = TransportTypeService.get_transport_type_by_key(db, transport_type_key) + if not transport_type: + raise HTTPException(status_code=404, detail="TransportType not found") + return transport_type + +@router.post("/", response_model=TransportTypeResponseDTO, status_code=status.HTTP_201_CREATED) +async def create_transport_type( + transport_type_data: TransportTypeCreateDTO, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + return TransportTypeService.create_transport_type(db, transport_type_data) + +@router.delete("/{transport_type_key}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_transport_type( + transport_type_key: str, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + transport_type = TransportTypeService.delete_transport_type(db, transport_type_key) + if not transport_type: + raise HTTPException(status_code=404, detail="TransportType not found") \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transport_types/services.py b/backend/api/v1/modules/a76/transport_types/services.py new file mode 100644 index 00000000..b7f40bae --- /dev/null +++ b/backend/api/v1/modules/a76/transport_types/services.py @@ -0,0 +1,23 @@ +from sqlalchemy.orm import Session +from . import models, dto + +class TransportTypeService: + @staticmethod + def get_transport_type_by_key(db: Session, transport_type_key: str): + return db.query(models.TransportType).filter(models.TransportType.transport_type_key == transport_type_key).first() + + @staticmethod + def create_transport_type(db: Session, transport_type_data: dto.TransportTypeCreateDTO): + new_transport_type = models.TransportType(**transport_type_data.dict()) + db.add(new_transport_type) + db.commit() + db.refresh(new_transport_type) + return new_transport_type + + @staticmethod + def delete_transport_type(db: Session, transport_type_key: str): + transport_type = TransportTypeService.get_transport_type_by_key(db, transport_type_key) + if transport_type: + db.delete(transport_type) + db.commit() + return transport_type \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transporters/dto.py b/backend/api/v1/modules/a76/transporters/dto.py new file mode 100644 index 00000000..4c6e644d --- /dev/null +++ b/backend/api/v1/modules/a76/transporters/dto.py @@ -0,0 +1,32 @@ +from pydantic import BaseModel +from typing import Optional + +class TransporterBaseDTO(BaseModel): + transporter_key: str + name: Optional[str] + short_name: Optional[str] + responsible: Optional[str] + rfc: Optional[str] + streets: Optional[str] + postal_code: Optional[str] + city: Optional[str] + state: Optional[str] + country: Optional[str] + loader_code: Optional[str] + caat_code: Optional[str] + transport_code: Optional[str] + transport_interface_type: Optional[str] + ftp_server: Optional[str] + ftp_user: Optional[str] + ftp_password: Optional[str] + ftp_directory: Optional[str] + filler_code: Optional[str] + company_id: str + tenant_id: str + +class TransporterCreateDTO(TransporterBaseDTO): + pass + +class TransporterResponseDTO(TransporterBaseDTO): + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transporters/models.py b/backend/api/v1/modules/a76/transporters/models.py new file mode 100644 index 00000000..f43d6830 --- /dev/null +++ b/backend/api/v1/modules/a76/transporters/models.py @@ -0,0 +1,28 @@ +from sqlalchemy import Column, String, ForeignKey +from core.database import Base + +class Transporter(Base): + __tablename__ = "transporter" + __table_args__ = {"schema": "a76"} + + transporter_key = Column(String(5), primary_key=True, nullable=False) + name = Column(String(256), nullable=True) + short_name = Column(String(10), nullable=True) + responsible = Column(String(100), nullable=True) + rfc = Column(String(30), nullable=True) + streets = Column(String(100), nullable=True) + postal_code = Column(String(15), nullable=True) + city = Column(String(30), nullable=True) + state = Column(String(30), nullable=True) + country = Column(String(3), nullable=True) + loader_code = Column(String(9), nullable=True) + caat_code = Column(String(49), nullable=True) + transport_code = Column(String(8), nullable=True) + transport_interface_type = Column(String(20), nullable=True) + ftp_server = Column(String(200), nullable=True) + ftp_user = Column(String(200), nullable=True) + ftp_password = Column(String(100), nullable=True) + ftp_directory = Column(String(1000), nullable=True) + filler_code = Column(String(4), nullable=True) + company_id = Column(String, ForeignKey("a76.company.id"), nullable=False) + tenant_id = Column(String, ForeignKey("a76.tenants.id"), nullable=False) \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transporters/routes.py b/backend/api/v1/modules/a76/transporters/routes.py new file mode 100644 index 00000000..9d1bd1f4 --- /dev/null +++ b/backend/api/v1/modules/a76/transporters/routes.py @@ -0,0 +1,46 @@ +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.orm import Session +from typing import List + +from core.database import get_core_db +from core.security import get_current_user +from .dto import TransporterCreateDTO, TransporterResponseDTO +from .services import TransporterService + +router = APIRouter(prefix="/transporters", tags=["Transporters"]) + +@router.get("/", response_model=List[TransporterResponseDTO]) +async def list_transporters( + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + return db.query(TransporterService).all() + +@router.get("/{transporter_key}", response_model=TransporterResponseDTO) +async def read_transporter( + transporter_key: str, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + transporter = TransporterService.get_transporter_by_key(db, transporter_key) + if not transporter: + raise HTTPException(status_code=404, detail="Transporter not found") + return transporter + +@router.post("/", response_model=TransporterResponseDTO, status_code=status.HTTP_201_CREATED) +async def create_transporter( + transporter_data: TransporterCreateDTO, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + return TransporterService.create_transporter(db, transporter_data) + +@router.delete("/{transporter_key}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_transporter( + transporter_key: str, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + transporter = TransporterService.delete_transporter(db, transporter_key) + if not transporter: + raise HTTPException(status_code=404, detail="Transporter not found") \ No newline at end of file diff --git a/backend/api/v1/modules/a76/transporters/services.py b/backend/api/v1/modules/a76/transporters/services.py new file mode 100644 index 00000000..ce1cb8c5 --- /dev/null +++ b/backend/api/v1/modules/a76/transporters/services.py @@ -0,0 +1,23 @@ +from sqlalchemy.orm import Session +from . import models, dto + +class TransporterService: + @staticmethod + def get_transporter_by_key(db: Session, transporter_key: str): + return db.query(models.Transporter).filter(models.Transporter.transporter_key == transporter_key).first() + + @staticmethod + def create_transporter(db: Session, transporter_data: dto.TransporterCreateDTO): + new_transporter = models.Transporter(**transporter_data.dict()) + db.add(new_transporter) + db.commit() + db.refresh(new_transporter) + return new_transporter + + @staticmethod + def delete_transporter(db: Session, transporter_key: str): + transporter = TransporterService.get_transporter_by_key(db, transporter_key) + if transporter: + db.delete(transporter) + db.commit() + return transporter \ No newline at end of file diff --git a/backend/api/v1/modules/a76/vehicles/dto.py b/backend/api/v1/modules/a76/vehicles/dto.py new file mode 100644 index 00000000..afecc2f0 --- /dev/null +++ b/backend/api/v1/modules/a76/vehicles/dto.py @@ -0,0 +1,39 @@ +from pydantic import BaseModel +from typing import Optional + +class VehicleBaseDTO(BaseModel): + vehicle_key: str + ace_vehicle_key: Optional[str] + transporter_key: Optional[str] + transport_identifier: Optional[str] + transport_type: Optional[str] + entity_code: Optional[str] + transponder_number: Optional[str] + dot_number: Optional[str] + plate_number: Optional[str] + city: Optional[str] + state: Optional[str] + country: Optional[str] + seal: Optional[str] + insurance_company_name: Optional[str] + insurance_number: Optional[str] + insurance_amount: Optional[float] + insurance_date: Optional[int] + box_number: Optional[str] + brand: Optional[str] + year: Optional[str] + series: Optional[str] + description: Optional[str] + engine_number: Optional[str] + sct_permission: Optional[str] + color: Optional[str] + container_key: Optional[str] + company_id: str + tenant_id: str + +class VehicleCreateDTO(VehicleBaseDTO): + pass + +class VehicleResponseDTO(VehicleBaseDTO): + class Config: + orm_mode = True \ No newline at end of file diff --git a/backend/api/v1/modules/a76/vehicles/models.py b/backend/api/v1/modules/a76/vehicles/models.py new file mode 100644 index 00000000..f20eb42a --- /dev/null +++ b/backend/api/v1/modules/a76/vehicles/models.py @@ -0,0 +1,35 @@ +from sqlalchemy import Column, String, DECIMAL, Integer, ForeignKey +from core.database import Base + +class Vehicle(Base): + __tablename__ = "vehicle" + __table_args__ = {"schema": "a76"} + + vehicle_key = Column(String(14), primary_key=True, nullable=False) + ace_vehicle_key = Column(String(10), nullable=True) + transporter_key = Column(String(23), nullable=True) + transport_identifier = Column(String(30), nullable=True) + transport_type = Column(String(2), nullable=True) + entity_code = Column(String(1), nullable=True) + transponder_number = Column(String(16), nullable=True) + dot_number = Column(String(8), nullable=True) + plate_number = Column(String(17), nullable=True) + city = Column(String(30), nullable=True) + state = Column(String(30), nullable=True) + country = Column(String(3), nullable=True) + seal = Column(String(49), nullable=True) + insurance_company_name = Column(String(30), nullable=True) + insurance_number = Column(String(20), nullable=True) + insurance_amount = Column(DECIMAL(13, 2), nullable=True) + insurance_date = Column(Integer, nullable=True) + box_number = Column(String(300), nullable=True) + brand = Column(String(20), nullable=True) + year = Column(String(4), nullable=True) + series = Column(String(30), nullable=True) + description = Column(String(100), nullable=True) + engine_number = Column(String(50), nullable=True) + sct_permission = Column(String(40), nullable=True) + color = Column(String(20), nullable=True) + container_key = Column(String(3), nullable=True) + company_id = Column(String, ForeignKey("a76.company.id"), nullable=False) + tenant_id = Column(String, ForeignKey("a76.tenants.id"), nullable=False) \ No newline at end of file diff --git a/backend/api/v1/modules/a76/vehicles/routes.py b/backend/api/v1/modules/a76/vehicles/routes.py new file mode 100644 index 00000000..13dbc83f --- /dev/null +++ b/backend/api/v1/modules/a76/vehicles/routes.py @@ -0,0 +1,46 @@ +from fastapi import APIRouter, Depends, HTTPException, status +from sqlalchemy.orm import Session +from typing import List + +from core.database import get_core_db +from core.security import get_current_user +from .dto import VehicleCreateDTO, VehicleResponseDTO +from .services import VehicleService + +router = APIRouter(prefix="/vehicles", tags=["Vehicles"]) + +@router.get("/", response_model=List[VehicleResponseDTO]) +async def list_vehicles( + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + return db.query(VehicleService).all() + +@router.get("/{vehicle_key}", response_model=VehicleResponseDTO) +async def read_vehicle( + vehicle_key: str, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + vehicle = VehicleService.get_vehicle_by_key(db, vehicle_key) + if not vehicle: + raise HTTPException(status_code=404, detail="Vehicle not found") + return vehicle + +@router.post("/", response_model=VehicleResponseDTO, status_code=status.HTTP_201_CREATED) +async def create_vehicle( + vehicle_data: VehicleCreateDTO, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + return VehicleService.create_vehicle(db, vehicle_data) + +@router.delete("/{vehicle_key}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_vehicle( + vehicle_key: str, + db: Session = Depends(get_core_db), + current_user: dict = Depends(get_current_user) +): + vehicle = VehicleService.delete_vehicle(db, vehicle_key) + if not vehicle: + raise HTTPException(status_code=404, detail="Vehicle not found") \ No newline at end of file diff --git a/backend/api/v1/modules/a76/vehicles/services.py b/backend/api/v1/modules/a76/vehicles/services.py new file mode 100644 index 00000000..5aae3a0f --- /dev/null +++ b/backend/api/v1/modules/a76/vehicles/services.py @@ -0,0 +1,23 @@ +from sqlalchemy.orm import Session +from . import models, dto + +class VehicleService: + @staticmethod + def get_vehicle_by_key(db: Session, vehicle_key: str): + return db.query(models.Vehicle).filter(models.Vehicle.vehicle_key == vehicle_key).first() + + @staticmethod + def create_vehicle(db: Session, vehicle_data: dto.VehicleCreateDTO): + new_vehicle = models.Vehicle(**vehicle_data.dict()) + db.add(new_vehicle) + db.commit() + db.refresh(new_vehicle) + return new_vehicle + + @staticmethod + def delete_vehicle(db: Session, vehicle_key: str): + vehicle = VehicleService.get_vehicle_by_key(db, vehicle_key) + if vehicle: + db.delete(vehicle) + db.commit() + return vehicle \ No newline at end of file