fix(clientes): crear tenant como despacho desde admin global
Antes, createTenant() solo seteaba nombre, rfc, plan y databaseName. Ahora registra tenants completos como despachos: - dbMode: 'MANAGED' - verticalProfile: CONTABLE | JURIDICO | ARQUITECTURA - trialEndsAt: +30 días para plan trial - codigoPostal: opcional (se llena automáticamente de la CSF al subir FIEL) Frontend: - Selector de Tipo de Despacho en /clientes - C.P. omitido del formulario (viene de CSF -> sincronizarDatosFiscales) - Tipos Tenant y CreateTenantData actualizados Backend: - getAllTenants y getTenantById retornan verticalProfile y codigoPostal Refs: docs/sessions/2026-05-04-fix-clientes-crea-despacho.md
This commit is contained in:
@@ -84,6 +84,7 @@ export default function ClientesPage() {
|
||||
adminNombre: string;
|
||||
amount: number;
|
||||
firstPaymentDueAt: string;
|
||||
verticalProfile: 'CONTABLE' | 'JURIDICO' | 'ARQUITECTURA';
|
||||
}>({
|
||||
nombre: '',
|
||||
rfc: '',
|
||||
@@ -92,6 +93,7 @@ export default function ClientesPage() {
|
||||
adminNombre: '',
|
||||
amount: 0,
|
||||
firstPaymentDueAt: '',
|
||||
verticalProfile: 'CONTABLE',
|
||||
});
|
||||
|
||||
// Only global admin can access this page
|
||||
@@ -122,7 +124,7 @@ export default function ClientesPage() {
|
||||
} else {
|
||||
await createTenant.mutateAsync(formData);
|
||||
}
|
||||
setFormData({ nombre: '', rfc: '', plan: 'trial', adminEmail: '', adminNombre: '', amount: 0, firstPaymentDueAt: '' });
|
||||
setFormData({ nombre: '', rfc: '', plan: 'trial', adminEmail: '', adminNombre: '', amount: 0, firstPaymentDueAt: '', verticalProfile: 'CONTABLE' });
|
||||
setShowForm(false);
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
@@ -142,6 +144,7 @@ export default function ClientesPage() {
|
||||
firstPaymentDueAt: sub?.currentPeriodEnd
|
||||
? new Date(sub.currentPeriodEnd).toISOString().slice(0, 10)
|
||||
: '',
|
||||
verticalProfile: tenant.verticalProfile || 'CONTABLE',
|
||||
});
|
||||
setShowForm(true);
|
||||
};
|
||||
@@ -159,7 +162,7 @@ export default function ClientesPage() {
|
||||
const handleCancelForm = () => {
|
||||
setShowForm(false);
|
||||
setEditingTenant(null);
|
||||
setFormData({ nombre: '', rfc: '', plan: 'trial', adminEmail: '', adminNombre: '', amount: 0, firstPaymentDueAt: '' });
|
||||
setFormData({ nombre: '', rfc: '', plan: 'trial', adminEmail: '', adminNombre: '', amount: 0, firstPaymentDueAt: '', verticalProfile: 'CONTABLE' });
|
||||
};
|
||||
|
||||
const handleViewClient = (tenantId: string, tenantName: string) => {
|
||||
@@ -477,6 +480,25 @@ export default function ClientesPage() {
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="verticalProfile">Tipo de Despacho</Label>
|
||||
<Select
|
||||
value={formData.verticalProfile}
|
||||
onValueChange={(value) =>
|
||||
setFormData({ ...formData, verticalProfile: value as 'CONTABLE' | 'JURIDICO' | 'ARQUITECTURA' })
|
||||
}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="CONTABLE">Contable</SelectItem>
|
||||
<SelectItem value="JURIDICO">Jurídico</SelectItem>
|
||||
<SelectItem value="ARQUITECTURA">Arquitectura</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* Campos de admin — solo al crear */}
|
||||
{!editingTenant && (
|
||||
<div className="border-t pt-4">
|
||||
|
||||
@@ -14,6 +14,8 @@ export interface Tenant {
|
||||
plan: string;
|
||||
databaseName: string;
|
||||
createdAt: string;
|
||||
verticalProfile?: 'CONTABLE' | 'JURIDICO' | 'ARQUITECTURA' | null;
|
||||
codigoPostal?: string | null;
|
||||
_count?: {
|
||||
/** Memberships activos (matches el `_count.memberships` que retorna `getAllTenants`). */
|
||||
memberships: number;
|
||||
@@ -32,6 +34,10 @@ export interface CreateTenantData {
|
||||
amount?: number;
|
||||
/** Solo plan custom: deadline para primer pago (formato ISO YYYY-MM-DD). */
|
||||
firstPaymentDueAt?: string | null;
|
||||
/** Tipo de despacho (CONTABLE, JURIDICO, ARQUITECTURA). Default: CONTABLE */
|
||||
verticalProfile?: 'CONTABLE' | 'JURIDICO' | 'ARQUITECTURA';
|
||||
/** Código postal del domicilio fiscal (5 dígitos) */
|
||||
codigoPostal?: string;
|
||||
}
|
||||
|
||||
export async function getTenants(): Promise<Tenant[]> {
|
||||
|
||||
Reference in New Issue
Block a user