fix(impuestos): desactivar JIT en queries con subplans correlacionados
- Agrega helper withJitOff en impuestos.service.ts - Ejecuta getResumenIva, getIvaMensual y readResumenIvaFromCache con SET LOCAL jit = off - Evita compilación JIT de ~17s en queries con costo estimado alto feat(contribuyentes): auto-asignar a cartera del supervisor - Al crear contribuyente con supervisorUserId, se agrega automáticamente a todas las carteras top-level del supervisor feat(permisos): restricciones de UI por rol en contribuyentes - Oculta botón Add-ons para roles distintos de owner/cfo - Oculta botón Eliminar contribuyente para no-owner - Oculta botón Agregar RFC para auxiliar/visor/cliente/contador feat(cfdi): ver CFDI desde conceptos y forma de pago en Excel - Agrega botón Ver CFDI en cada fila de la tabla de Conceptos - Agrega columna Forma de Pago en export Excel de CFDIs - Agrega columna Forma de Pago en export individual de CFDI chore(migraciones): índices GIN para relaciones de activos - 048: índices btree parciales para activos - 049: índices GIN para cfdis_relacionados y uuid_relacionado
This commit is contained in:
@@ -88,6 +88,8 @@ export default function ContribuyentesPage() {
|
||||
setShowDialog(true);
|
||||
};
|
||||
|
||||
const canCreate = user?.role === 'owner' || user?.role === 'cfo' || user?.role === 'supervisor';
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6 max-w-7xl mx-auto">
|
||||
<div className="flex items-center justify-between">
|
||||
@@ -95,14 +97,16 @@ export default function ContribuyentesPage() {
|
||||
<h1 className="text-2xl font-bold">Contribuyentes</h1>
|
||||
<p className="text-sm text-muted-foreground">RFCs que gestiona tu despacho · {rfcCounterText}</p>
|
||||
</div>
|
||||
<Button
|
||||
onClick={() => { resetForm(); setShowDialog(true); }}
|
||||
disabled={trialAtLimit}
|
||||
title={trialAtLimit ? TRIAL_LIMIT_TOOLTIP : undefined}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<Plus className="h-4 w-4" /> Agregar RFC
|
||||
</Button>
|
||||
{canCreate && (
|
||||
<Button
|
||||
onClick={() => { resetForm(); setShowDialog(true); }}
|
||||
disabled={trialAtLimit}
|
||||
title={trialAtLimit ? TRIAL_LIMIT_TOOLTIP : undefined}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
<Plus className="h-4 w-4" /> Agregar RFC
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isLoading ? <p className="text-muted-foreground">Cargando...</p> : !contribuyentes || contribuyentes.length === 0 ? (
|
||||
@@ -110,13 +114,15 @@ export default function ContribuyentesPage() {
|
||||
<Building2 className="h-12 w-12 text-muted-foreground mb-4" />
|
||||
<h3 className="text-lg font-semibold">Sin contribuyentes</h3>
|
||||
<p className="text-sm text-muted-foreground mt-1 mb-4">Agrega el primer RFC para empezar.</p>
|
||||
<Button
|
||||
onClick={() => { resetForm(); setShowDialog(true); }}
|
||||
disabled={trialAtLimit}
|
||||
title={trialAtLimit ? TRIAL_LIMIT_TOOLTIP : undefined}
|
||||
>
|
||||
Agregar primer RFC
|
||||
</Button>
|
||||
{canCreate && (
|
||||
<Button
|
||||
onClick={() => { resetForm(); setShowDialog(true); }}
|
||||
disabled={trialAtLimit}
|
||||
title={trialAtLimit ? TRIAL_LIMIT_TOOLTIP : undefined}
|
||||
>
|
||||
Agregar primer RFC
|
||||
</Button>
|
||||
)}
|
||||
</CardContent></Card>
|
||||
) : (
|
||||
<div className="grid gap-3 lg:grid-cols-2 3xl:grid-cols-3 4xl:grid-cols-4">{contribuyentes.map((c) => (
|
||||
@@ -127,9 +133,13 @@ export default function ContribuyentesPage() {
|
||||
{c.regimenFiscal && <p className="text-xs text-muted-foreground mt-1">Régimen: {c.regimenFiscal}</p>}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="ghost" size="sm" onClick={() => setAddonsTarget({ id: c.id, nombre: c.nombre })} title="Add-ons"><Sparkles className="h-4 w-4" /></Button>
|
||||
{(user?.role === 'owner' || user?.role === 'cfo') && (
|
||||
<Button variant="ghost" size="sm" onClick={() => setAddonsTarget({ id: c.id, nombre: c.nombre })} title="Add-ons"><Sparkles className="h-4 w-4" /></Button>
|
||||
)}
|
||||
<Button variant="ghost" size="sm" onClick={() => openEdit(c)}><Pencil className="h-4 w-4" /></Button>
|
||||
<Button variant="ghost" size="sm" onClick={() => handleDeactivate(c.id, c.rfc)} className="text-destructive hover:text-destructive"><Trash2 className="h-4 w-4" /></Button>
|
||||
{user?.role === 'owner' && (
|
||||
<Button variant="ghost" size="sm" onClick={() => handleDeactivate(c.id, c.rfc)} className="text-destructive hover:text-destructive"><Trash2 className="h-4 w-4" /></Button>
|
||||
)}
|
||||
</div>
|
||||
</CardContent></Card>
|
||||
))}</div>
|
||||
|
||||
Reference in New Issue
Block a user