Parte C del plan: el baremo mínimo de rentabilidad es ahora un valor configurable del reformista, solo informativo. Los agentes NO lo usan para decidir nada. - schema: pricing_config.baremo_minimo (céntimos, nullable) + migración 0012. - pricing-queries / budget types: exponen baremoMinimo. - panel/precios: sección "Baremo de rentabilidad" + action actualizarBaremo (vacío = sin baremo). - panel/[id]: el presupuesto estimado se muestra en rojo con aviso "Por debajo de tu baremo (X €)" cuando no alcanza el baremo del tenant. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
81 lines
2.3 KiB
TypeScript
81 lines
2.3 KiB
TypeScript
import { eq } from 'drizzle-orm';
|
|
import { db } from './index';
|
|
import { pricingConfig, catalogItems, tenants } from './schema';
|
|
import type { PricingConfig, CatalogItem, ManoObraKey } from '@/budget/types';
|
|
import { getCurrentTenantId as getTenantId } from '@/lib/auth/current-user';
|
|
|
|
export type EnvioMode = (typeof tenants.envioPresupuesto.enumValues)[number];
|
|
|
|
export async function getEnvioModeFor(tenantId: string): Promise<EnvioMode> {
|
|
const [row] = await db
|
|
.select({ modo: tenants.envioPresupuesto })
|
|
.from(tenants)
|
|
.where(eq(tenants.id, tenantId))
|
|
.limit(1);
|
|
return row?.modo ?? 'automatico';
|
|
}
|
|
|
|
export async function getEnvioMode(): Promise<EnvioMode> {
|
|
return getEnvioModeFor(await getTenantId());
|
|
}
|
|
|
|
const MANO_OBRA_DEFAULT: Record<ManoObraKey, number> = {
|
|
demolicion: 0,
|
|
impermeabilizacion: 0,
|
|
fontaneria: 0,
|
|
electricidad: 0,
|
|
mano_de_obra: 0,
|
|
};
|
|
|
|
const EXTRAS_DEFAULT = { tuberias: 0, boletin: 0, distribucion: 0 };
|
|
|
|
export async function getPricingConfigFor(tenantId: string): Promise<PricingConfig> {
|
|
const [row] = await db
|
|
.select()
|
|
.from(pricingConfig)
|
|
.where(eq(pricingConfig.tenantId, tenantId))
|
|
.limit(1);
|
|
|
|
if (!row) {
|
|
return {
|
|
alturaTechoDefault: 2.5,
|
|
factorZona: {},
|
|
manoObra: { ...MANO_OBRA_DEFAULT },
|
|
extras: { ...EXTRAS_DEFAULT },
|
|
baremoMinimo: null,
|
|
};
|
|
}
|
|
return {
|
|
alturaTechoDefault: row.alturaTechoDefault,
|
|
factorZona: row.factorZona,
|
|
manoObra: { ...MANO_OBRA_DEFAULT, ...(row.manoObra as Record<ManoObraKey, number>) },
|
|
extras: { ...EXTRAS_DEFAULT, ...(row.extras ?? {}) },
|
|
baremoMinimo: row.baremoMinimo ?? null,
|
|
};
|
|
}
|
|
|
|
export async function getPricingConfig(): Promise<PricingConfig> {
|
|
return getPricingConfigFor(await getTenantId());
|
|
}
|
|
|
|
export async function getCatalogFor(tenantId: string): Promise<CatalogItem[]> {
|
|
const rows = await db.select().from(catalogItems).where(eq(catalogItems.tenantId, tenantId));
|
|
return rows.map((r) => ({
|
|
id: r.id,
|
|
categoria: r.categoria,
|
|
nombre: r.nombre,
|
|
calidad: r.calidad,
|
|
precioUnit: r.precioUnit,
|
|
unidad: r.unidad,
|
|
descriptorRender: r.descriptorRender,
|
|
esDefault: r.esDefault,
|
|
sku: r.sku,
|
|
}));
|
|
}
|
|
|
|
export async function getCatalog(): Promise<CatalogItem[]> {
|
|
return getCatalogFor(await getTenantId());
|
|
}
|
|
|
|
export { getTenantId };
|