feat: add pricing_config, catalog_items and budget input fields to schema
This commit is contained in:
@@ -9,6 +9,8 @@ import {
|
||||
timestamp,
|
||||
jsonb,
|
||||
index,
|
||||
doublePrecision,
|
||||
uniqueIndex,
|
||||
} from 'drizzle-orm/pg-core';
|
||||
|
||||
// Estado comercial del lead — RF-D-03. Lo que el reformista gestiona a mano.
|
||||
@@ -42,6 +44,17 @@ export const tipoReforma = pgEnum('tipo_reforma', [
|
||||
'otro',
|
||||
]);
|
||||
|
||||
export const calidad = pgEnum('calidad', ['basica', 'media', 'premium']);
|
||||
|
||||
export const categoriaMaterial = pgEnum('categoria_material', [
|
||||
'suelo',
|
||||
'pared',
|
||||
'pintura',
|
||||
'mobiliario',
|
||||
]);
|
||||
|
||||
export const unidadMedida = pgEnum('unidad_medida', ['m2', 'ml', 'ud']);
|
||||
|
||||
// Reformista (cliente del SaaS). MVP = "Reformas Ejemplo" hardcoded.
|
||||
// Multi-tenant real es F1.5; la tabla ya queda lista para ello.
|
||||
export const tenants = pgTable('tenants', {
|
||||
@@ -91,6 +104,17 @@ export const leads = pgTable(
|
||||
audioUrl: text('audio_url'),
|
||||
|
||||
notas: text('notas'),
|
||||
|
||||
// Inputs del motor de presupuesto (capturados de menos a más en el funnel)
|
||||
m2Suelo: doublePrecision('m2_suelo'),
|
||||
alturaTecho: doublePrecision('altura_techo'),
|
||||
calidadGlobal: calidad('calidad_global'),
|
||||
estructural: boolean('estructural').notNull().default(false),
|
||||
materialSelections: jsonb('material_selections')
|
||||
.$type<Record<string, string>>()
|
||||
.notNull()
|
||||
.default({}),
|
||||
desgloseSnapshot: jsonb('desglose_snapshot'),
|
||||
},
|
||||
(table) => [
|
||||
index('leads_tenant_created_idx').on(table.tenantId, table.createdAt),
|
||||
@@ -144,6 +168,42 @@ export const precisionHistory = pgTable('precision_history', {
|
||||
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
});
|
||||
|
||||
// Configuración de precios del reformista (1 fila por tenant). RF-D-07.
|
||||
export const pricingConfig = pgTable('pricing_config', {
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
tenantId: uuid('tenant_id')
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: 'cascade' })
|
||||
.unique(),
|
||||
alturaTechoDefault: doublePrecision('altura_techo_default').notNull().default(2.5),
|
||||
factorZona: jsonb('factor_zona').$type<Record<string, number>>().notNull().default({}),
|
||||
manoObra: jsonb('mano_obra').$type<Record<string, number>>().notNull().default({}),
|
||||
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
||||
});
|
||||
|
||||
// Catálogo de materiales del reformista. Importable por CSV.
|
||||
export const catalogItems = pgTable(
|
||||
'catalog_items',
|
||||
{
|
||||
id: uuid('id').primaryKey().defaultRandom(),
|
||||
tenantId: uuid('tenant_id')
|
||||
.notNull()
|
||||
.references(() => tenants.id, { onDelete: 'cascade' }),
|
||||
categoria: categoriaMaterial('categoria').notNull(),
|
||||
nombre: text('nombre').notNull(),
|
||||
calidad: calidad('calidad').notNull(),
|
||||
precioUnit: integer('precio_unit').notNull(), // céntimos por unidad
|
||||
unidad: unidadMedida('unidad').notNull(),
|
||||
descriptorRender: text('descriptor_render').notNull().default(''),
|
||||
esDefault: boolean('es_default').notNull().default(false),
|
||||
sku: text('sku').notNull(),
|
||||
},
|
||||
(table) => [
|
||||
index('catalog_tenant_idx').on(table.tenantId),
|
||||
uniqueIndex('catalog_tenant_sku_idx').on(table.tenantId, table.sku),
|
||||
]
|
||||
);
|
||||
|
||||
export type Tenant = typeof tenants.$inferSelect;
|
||||
export type Lead = typeof leads.$inferSelect;
|
||||
export type NewLead = typeof leads.$inferInsert;
|
||||
@@ -151,3 +211,6 @@ export type LeadFoto = typeof leadFotos.$inferSelect;
|
||||
export type LeadEstadoHistory = typeof leadEstadoHistory.$inferSelect;
|
||||
export type LeadPipelineEvento = typeof leadPipelineEventos.$inferSelect;
|
||||
export type PrecisionHistory = typeof precisionHistory.$inferSelect;
|
||||
export type PricingConfigRow = typeof pricingConfig.$inferSelect;
|
||||
export type CatalogItemRow = typeof catalogItems.$inferSelect;
|
||||
export type NewCatalogItem = typeof catalogItems.$inferInsert;
|
||||
|
||||
Reference in New Issue
Block a user