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

@@ -0,0 +1,107 @@
/**
* API para gestión de Classes (Clases A76)
*/
import { api } from '$lib/api';
import type { ApiResponse } from '$lib/api';
export interface A76Class {
id: number;
tenant_id: number;
company_id: number;
client_id: number;
class_code: string;
description_es: string | null;
description_en: string | null;
material_key: string | null;
unit_of_measure: string;
fraction: string;
us_fraction: string;
sub_key: string;
physical_review: number;
iva_exempt_fraction: string;
created_at: string;
updated_at: string;
}
export interface A76ClassCreate {
company_id: number;
client_id: number;
class_code: string;
description_es?: string | null;
description_en?: string | null;
material_key?: string | null;
unit_of_measure: string;
fraction: string;
us_fraction: string;
sub_key: string;
physical_review?: number;
iva_exempt_fraction: string;
}
export interface A76ClassUpdate {
client_id?: number;
class_code?: string;
description_es?: string | null;
description_en?: string | null;
material_key?: string | null;
unit_of_measure?: string;
fraction?: string;
us_fraction?: string;
sub_key?: string;
physical_review?: number;
iva_exempt_fraction?: string;
}
export interface A76ClassListResponse {
items: A76Class[];
total: number;
page: number;
page_size: number;
}
export interface A76ClassListParams {
company_id: number;
page?: number;
page_size?: number;
}
/**
* API de Classes
*/
export const classesApi = {
/**
* Obtener lista de classes con paginación
*/
list: (params: A76ClassListParams): Promise<ApiResponse<A76ClassListResponse>> => {
const { company_id, page = 1, page_size = 50 } = params;
return api.get(`/v1/a76/classes/?company_id=${company_id}&page=${page}&page_size=${page_size}`);
},
/**
* Obtener un class por ID
*/
get: (id: number, company_id: number): Promise<ApiResponse<A76Class>> => {
return api.get(`/v1/a76/classes/${id}?company_id=${company_id}`);
},
/**
* Crear un nuevo class
*/
create: (data: A76ClassCreate, company_id: number): Promise<ApiResponse<A76Class>> => {
return api.post(`/v1/a76/classes/?company_id=${company_id}`, data);
},
/**
* Actualizar un class existente
*/
update: (id: number, data: A76ClassUpdate, company_id: number): Promise<ApiResponse<A76Class>> => {
return api.put(`/v1/a76/classes/${id}?company_id=${company_id}`, data);
},
/**
* Eliminar un class
*/
delete: (id: number, company_id: number): Promise<ApiResponse<void>> => {
return api.delete(`/v1/a76/classes/${id}?company_id=${company_id}`);
}
};

View File

@@ -0,0 +1,4 @@
/**
* Exportaciones de APIs para módulo A76
*/
export * from './classes';