// ROCA GOLF — v2.0 · Administrador de Proyecto // Presupuesto total editable + Conciliación de presupuesto + Proyecciones de costo // (grupos modulares de claves de insumo). Espejo de la hoja "ADMINISTRADOR DE PROYECTOS". function money(n) { try { return '$' + fmtMoney(Number(n) || 0); } catch { return '$' + (Number(n)||0).toFixed(2); } } // Conceptos fijos de la Proyección de Utilidad (la fila "Ajustes por ahorro" y // "Total" se calculan aparte, no se capturan). const UTIL_CONCEPTS = ['Utilidad Original', 'Utilidad Orden de Cambio', 'Bono de finalización', 'Daños y Perjuicios', 'Ahorros con cliente']; function buildUtilRows(saved) { const byName = {}; (Array.isArray(saved) ? saved : []).forEach(r => { if (r && r.concepto) byName[r.concepto] = r; }); return UTIL_CONCEPTS.map(c => { const r = byName[c] || {}; return { concepto: c, original: r.original || 0, revisado: r.revisado || 0, pendiente: r.pendiente || 0, proyectado: r.proyectado || 0 }; }); } // ── Modal: crear / editar proyección (grupo modular) ────────────────────────── function ProyeccionModal({ open, onClose, proyectoid, initial, onSaved }) { const editing = !!initial; const [nombre, setNombre] = useState(''); const [revisado, setRevisado] = useState(''); const [final, setFinal] = useState(''); const [desc, setDesc] = useState(''); const [saving, setSaving] = useState(false); useEffect(() => { if (!open) return; setNombre(initial?.nombre || ''); setRevisado(initial ? String(initial.presupuesto_revisado) : ''); setFinal(initial ? String(initial.proyectado_final) : ''); setDesc(initial?.descripcion || ''); }, [open, initial]); async function save() { if (!nombre.trim()) { toast.error('El nombre es requerido'); return; } setSaving(true); try { if (editing) { await apiFetch('proyecciones.php?id=' + initial.id, 'PUT', { nombre: nombre.trim(), presupuesto_revisado: parseFloat(revisado) || 0, proyectado_final: parseFloat(final) || 0, descripcion: desc, }); toast.success('Proyección actualizada'); } else { await apiFetch('proyecciones.php', 'POST', { accion: 'crear', proyectoid, nombre: nombre.trim(), presupuesto_revisado: parseFloat(revisado) || 0, proyectado_final: parseFloat(final) || 0, descripcion: desc, }); toast.success('Proyección creada'); } onSaved(); onClose(); } catch (e) { toast.error(e.message); } finally { setSaving(false); } } return ( }>
setNombre(e.target.value)} placeholder="Material"/>
setRevisado(e.target.value)} placeholder="0.00"/>
setFinal(e.target.value)} placeholder="0.00"/>