#!/usr/bin/env python3 """Genera apps/cotizador/src/data/unidades-{dev}.ts desde reference/cotizadores/{DEV}.json. - Prefija el código con el desarrollo (ATELIER-10, ESTANZA-52, SENDA-411-1-7, SOLANA-6) para que sea único en todo el ecosistema (board Monday compartido). - En desarrollos de precio único, precioSinAcabados/precioConAcabados replican precioLista (el tipo los requiere numéricos; el flag precioUnico del desarrollo es el que manda en la UI). """ import json import re import sys ROOT = '/root/frasa-ecosystem' def num(v): return v if isinstance(v, (int, float)) else None def ts_num(v): return 'null' if v is None else repr(float(v)).rstrip('0').rstrip('.') if isinstance(v, float) and v == int(v) else repr(v) def ts_str(v): if v is None: return 'null' s = str(v).replace('\\', '\\\\').replace("'", "\\'") return f"'{s}'" def slug(codigo): return re.sub(r'[^A-Za-z0-9]+', '_', str(codigo)).strip('_') def extras_ts(pairs): items = ', '.join(f'{k}: {ts_str(v) if isinstance(v, str) or v is None else ts_num(v)}' for k, v in pairs) return '{ ' + items + ' }' def gen(dev, codigo_fn, map_fn, nota): data = json.load(open(f'{ROOT}/reference/cotizadores/{dev}.json')) unidades = data['unidades'] lines = [ "import type { Unidad } from '../types'", '', f'// Inventario {dev} — {len(unidades)} unidades. {nota}', f'// Generado desde reference/cotizadores/{dev}.json (NO editar a mano; regenerar con scripts/generar-seeds.py).', f'// Precio único por unidad: precioSinAcabados/precioConAcabados replican precioLista.', f'export const UNIDADES_{dev}: Unidad[] = [', ] for u in unidades: precio = map_fn('precio', u) campos = { 'codigo': ts_str(codigo_fn(u)), 'modelo': ts_str(u.get('modelo') or ''), 'desarrollo': ts_str(dev), 'fechaEntrega': ts_str(u.get('fechaEntrega')), 'supEstacionamiento': ts_num(num(u.get('supEstacionamiento'))), 'supConstruccion': ts_num(num(u.get('supConstruccion'))), 'supExcedente': ts_num(num(u.get('supExcedente'))), 'precioSinAcabados': ts_num(precio if precio is not None else 0), 'precioConAcabados': ts_num(precio if precio is not None else 0), 'precioLista': ts_num(precio), 'status': ts_str(u.get('status')), 'mesesParaFirma': ts_num(num(map_fn('mesesParaFirma', u))), 'extras': extras_ts(map_fn('extras', u)), } body = ', '.join(f'{k}: {v}' for k, v in campos.items() if v is not None) lines.append(f' {{ {body} }},') lines.append(']') lines.append('') out = f'{ROOT}/apps/cotizador/src/data/unidades-{dev.lower()}.ts' open(out, 'w').write('\n'.join(lines)) print(f'{out}: {len(unidades)} unidades') def precio_de(u, *claves): ex = u.get('extras') or {} for c in claves: v = ex.get(c) if isinstance(v, (int, float)): return v return None gen( 'ATELIER', lambda u: f"ATELIER-{u['codigo']}", lambda k, u: { 'precio': precio_de(u, 'precioLista'), 'mesesParaFirma': None, 'extras': [('prototipo', u['extras'].get('prototipo')), ('manzana', u['extras'].get('manzana')), ('lote', u['extras'].get('lote')), ('cajones', u['extras'].get('cajones'))], }[k], 'Departamentos, MZA 32 LOTE 1.', ) gen( 'ESTANZA', lambda u: f"ESTANZA-{str(u['codigo']).replace('CASA-', '')}", lambda k, u: { 'precio': precio_de(u, 'precioLista'), 'mesesParaFirma': None, 'extras': [('manzana', u['extras'].get('manzana')), ('lote', u['extras'].get('lote')), ('cajones', u['extras'].get('cajones'))], }[k], 'Casas DUPLO A/B, MZA 92 LOTE 32.', ) gen( 'SENDA', lambda u: f"SENDA-{u['codigo']}", lambda k, u: { 'precio': precio_de(u, 'precioPreventa'), 'mesesParaFirma': None, 'extras': [('prototipo', u['extras'].get('prototipo')), ('manzana', u['extras'].get('manzana')), ('lote', u['extras'].get('lote')), ('cajones', u['extras'].get('cajones'))], }[k], 'Casas; fechaEntrega null cuando la unidad no está en la tabla TERM (mensualidades no calculables).', ) gen( 'SOLANA', lambda u: f"SOLANA-{u['codigo']}", lambda k, u: { 'precio': precio_de(u, 'precioPreventa'), 'mesesParaFirma': u['extras'].get('mesesParaFirma'), 'extras': [('prototipo', u['extras'].get('prototipo')), ('etapa', u['extras'].get('etapa')), ('cajones', u['extras'].get('cajones'))], }[k], 'Casas etapas SOLANA I/II; mesesParaFirma (1-4) es el plazo de mensualidades.', )