feature/mensajes-claros-en-eliminar-clases

This commit is contained in:
2026-05-29 11:52:32 -06:00
parent c81d5487e5
commit ff14bd3645
2 changed files with 51 additions and 11 deletions

View File

@@ -370,11 +370,46 @@ class ClassService:
def delete(db: Session, class_id: int, tenant_id: int, company_id: int) -> bool:
"""Delete a class (and its FA extension if exists)"""
from api.v1.modules.a24.fa.fa_classes.models import QClasses
from api.v1.modules.a76.items.models import LineItem
from api.v1.modules.a76.parts.models import Part
class_obj = ClassService.get_by_id(db, class_id, tenant_id, company_id)
if not class_obj:
return False
used_in_parts = (
db.query(Part.id)
.filter(
Part.part_class == class_obj.class_code,
Part.tenant_id == tenant_id,
Part.company_id == company_id,
)
.first()
is not None
)
used_in_invoices = (
db.query(LineItem.id)
.filter(
LineItem.class_id == class_id,
LineItem.tenant_id == tenant_id,
LineItem.company_id == company_id,
)
.first()
is not None
)
if used_in_parts or used_in_invoices:
reasons: list[str] = []
if used_in_parts:
reasons.append("partes")
if used_in_invoices:
reasons.append("facturas")
usage = " y ".join(reasons)
raise HTTPException(
status_code=409,
detail=f"No se puede eliminar la clase porque ya fue utilizada en {usage}.",
)
# Delete FA extension first (if exists) to avoid FK constraint violation
fa_extension = db.query(QClasses).filter(
QClasses.class_id == class_id,

View File

@@ -6,6 +6,7 @@
import FixedAssetClassForm from '$lib/components/dashboard/goods/classes/forms/FixedAssetClassForm.svelte';
import { Folder, Save, Plus, RefreshCw } from 'lucide-svelte';
import { toast } from 'svelte-sonner';
import { friendlyApiErrorParts, type ApiResponse } from '$lib/api';
import { classesApi, type A76Class } from '$lib/api/dashboard/a76/classes';
import { faClassesApi, type FAClass } from '$lib/api/dashboard/a24/fa_classes';
import { companyStore } from '$lib/stores/company.svelte';
@@ -321,29 +322,33 @@
const idsToDelete = [...selectedClassIds];
let okCount = 0;
const errors: number[] = [];
const failedResponses: ApiResponse[] = [];
for (const id of idsToDelete) {
try {
// El backend elimina automáticamente la extensión FA si existe
await classesApi.delete(id, companyId);
// El backend elimina automáticamente la extensión FA si existe
const res = await classesApi.delete(id, companyId);
if (res.status >= 400 || res.error) {
console.error(`Error deleting class ${id}:`, res.error ?? res.status);
failedResponses.push(res);
} else {
okCount++;
} catch (error) {
console.error(`Error deleting class ${id}:`, error);
errors.push(id);
}
}
if (errors.length === 0) {
if (failedResponses.length === 0) {
toast.success(
okCount === 1
? 'Clase eliminada correctamente'
: `${okCount} clases eliminadas correctamente`
);
} else if (okCount === 0) {
toast.error(`Error al eliminar ${errors.length} clase(s)`);
const { title, description } = friendlyApiErrorParts(failedResponses[0]);
toast.error(title, { description });
} else {
toast.error(`${okCount} eliminada(s), ${errors.length} con error`);
const { title, description } = friendlyApiErrorParts(failedResponses[0]);
toast.error(`${okCount} eliminada(s), ${failedResponses.length} con error`, {
description: description || title
});
}
await loadClasses();