feat: Convertir módulo de clases para usar TenantCRUDRoutes

Cambios en backend:
- Actualizado ClassResponseDTO con campos de tenant y timestamps
- Agregados métodos estáticos en servicio (get_all, get_by_id, create, update, delete)
- Reemplazados endpoints de rutas con inicialización de TenantCRUDRoutes
- Corregida ruta de importación del modelo Company en security.py
- Actualizados nombres de campos en DTO para coincidir con modelo (description_es/en)
- Agregada validación para constraint de foreign key de material_key
- Agregada validación de class_code duplicado en método create
- Agregado TimestampMixin al modelo Class
- Creada migración de Alembic para agregar columnas timestamp a tabla classes
- Corregido orden de parámetros en firma del método update

Cambios en frontend:
- Actualizados componentes de UI para módulo de clases
This commit is contained in:
KevinMrkz3221
2025-11-15 20:05:29 -06:00
parent 836083b428
commit 99aff32eea
15 changed files with 1703 additions and 295 deletions

View File

@@ -3,9 +3,10 @@ DTOs (Data Transfer Objects) para módulo de clases SCAII y SCAF
Reemplaza schemas.py siguiendo enfoque DDD y estilo NestJS
"""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field
class ClassCreateDTO(BaseModel):
@@ -13,10 +14,10 @@ class ClassCreateDTO(BaseModel):
client_id: int = Field(..., description="Client key")
class_code: str = Field(..., max_length=8, description="Class code")
description_spanish: Optional[str] = Field(
description_es: Optional[str] = Field(
None, max_length=500, description="Description in Spanish"
)
description_english: Optional[str] = Field(
description_en: Optional[str] = Field(
None, max_length=500, description="Description in English"
)
material_key: Optional[str] = Field(
@@ -50,10 +51,10 @@ class ClassCreateDTO(BaseModel):
class ClassUpdateDTO(BaseModel):
"""DTO para actualizar una clase"""
description_spanish: Optional[str] = Field(
description_es: Optional[str] = Field(
None, max_length=500, description="Description in Spanish"
)
description_english: Optional[str] = Field(
description_en: Optional[str] = Field(
None, max_length=500, description="Description in English"
)
material_key: Optional[str] = Field(
@@ -87,10 +88,13 @@ class ClassUpdateDTO(BaseModel):
class ClassResponseDTO(BaseModel):
"""DTO para respuesta de clase"""
id: int
tenant_id: int
company_id: int
client_id: int
class_code: str
description_spanish: Optional[str] = None
description_english: Optional[str] = None
description_es: Optional[str] = None
description_en: Optional[str] = None
material_key: Optional[str] = None
unit_of_measure: Optional[str] = None
fraction: Optional[str] = None
@@ -98,9 +102,10 @@ class ClassResponseDTO(BaseModel):
sub_key: Optional[str] = None
physical_review: Optional[int] = None
iva_exempt_fraction: Optional[str] = None
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
model_config = ConfigDict(from_attributes=True)
class ClassBasicDTO(BaseModel):
@@ -108,8 +113,8 @@ class ClassBasicDTO(BaseModel):
client_id: int
class_code: str
description_spanish: Optional[str] = None
description_english: Optional[str] = None
description_es: Optional[str] = None
description_en: Optional[str] = None
material_key: Optional[str] = None
fraction: Optional[str] = None