Add merge a BudgetInputs y aplicación de extras/ajustes al presupuesto
This commit is contained in:
72
mvp/b2c/tests/voice/apply.test.ts
Normal file
72
mvp/b2c/tests/voice/apply.test.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { applyPreferences, mergeIntoBudgetInputs } from '@/lib/voice/apply';
|
||||
import type { AbstractedPreferences } from '@/lib/voice/preferences';
|
||||
import type { BudgetResult } from '@/budget/types';
|
||||
|
||||
function prefs(partial: Partial<AbstractedPreferences>): AbstractedPreferences {
|
||||
return {
|
||||
calidadGlobal: 'media',
|
||||
materialSelections: {},
|
||||
estructural: false,
|
||||
urgencia: null,
|
||||
presupuestoTarget: null,
|
||||
elementos: [],
|
||||
estiloRender: [],
|
||||
ajustes: [],
|
||||
confianza: 'media',
|
||||
resumen: '',
|
||||
camposFaltantes: [],
|
||||
...partial,
|
||||
};
|
||||
}
|
||||
|
||||
const base: BudgetResult = {
|
||||
partidas: [{ key: 'mano_de_obra', label: 'Mano de obra', importe: 100000 }],
|
||||
subtotal: 100000,
|
||||
factorZona: 1,
|
||||
total: 100000,
|
||||
rango: { min: 85000, max: 115000 },
|
||||
confianza: 'media',
|
||||
materialesRender: ['suelo cerámico gris'],
|
||||
avisos: [],
|
||||
};
|
||||
|
||||
describe('applyPreferences', () => {
|
||||
it('añade elementos y ajustes fijos como partidas y recalcula totales', () => {
|
||||
const r = applyPreferences(base, prefs({
|
||||
elementos: [{ key: 'isla_cocina', label: 'Isla de cocina', importe: 120000 }],
|
||||
ajustes: [{ label: 'Encimera de piedra natural', tipo: 'fijo', valor: 50000, motivo: 'cuarzo' }],
|
||||
estiloRender: ['estilo nórdico'],
|
||||
}));
|
||||
const byKey = Object.fromEntries(r.partidas.map((p) => [p.key, p.importe]));
|
||||
expect(byKey.isla_cocina).toBe(120000);
|
||||
expect(r.partidas.some((p) => p.label === 'Encimera de piedra natural' && p.importe === 50000)).toBe(true);
|
||||
expect(r.subtotal).toBe(270000);
|
||||
expect(r.total).toBe(270000);
|
||||
expect(r.rango.min).toBe(229500); // round(85000 * 2.7)
|
||||
expect(r.rango.max).toBe(310500); // round(115000 * 2.7)
|
||||
expect(r.materialesRender).toContain('estilo nórdico');
|
||||
});
|
||||
|
||||
it('un ajuste tipo factor se aplica sobre el subtotal original como partida explícita', () => {
|
||||
const r = applyPreferences(base, prefs({
|
||||
ajustes: [{ label: 'Acabado premium global', tipo: 'factor', valor: 1.1, motivo: 'premium' }],
|
||||
}));
|
||||
expect(r.partidas.some((p) => p.label === 'Acabado premium global' && p.importe === 10000)).toBe(true);
|
||||
expect(r.subtotal).toBe(110000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mergeIntoBudgetInputs', () => {
|
||||
it('vuelca preferencias y datos del lead en BudgetInputs', () => {
|
||||
const inputs = mergeIntoBudgetInputs(
|
||||
prefs({ calidadGlobal: 'premium', materialSelections: { suelo: 'suelo-p' }, estructural: true }),
|
||||
{ tipoReforma: 'cocina', m2Suelo: 16, alturaTecho: null, provincia: 'Madrid' },
|
||||
);
|
||||
expect(inputs.calidadGlobal).toBe('premium');
|
||||
expect(inputs.materialSelections.suelo).toBe('suelo-p');
|
||||
expect(inputs.estructural).toBe(true);
|
||||
expect(inputs.m2Suelo).toBe(16);
|
||||
expect(inputs.provincia).toBe('Madrid');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user