// factura-express.jsx - Link directo C09 para verificar factura sin login. function FacturaExpressScreen({ facturaId, vendedoraId }) { const T = window.T; const { ProductTile } = window; const [loading, setLoading] = React.useState(true); const [error, setError] = React.useState(''); const [data, setData] = React.useState(null); const [mode, setMode] = React.useState('review'); const [nota, setNota] = React.useState(''); const [producto, setProducto] = React.useState({ codigo: '', nombre: '', cantidad: 1 }); const [submitting, setSubmitting] = React.useState(false); const [pagoModal, setPagoModal] = React.useState(false); const reload = React.useCallback(async () => { setLoading(true); setError(''); try { const result = await window.pedidosApi.obtenerFacturaExpress({ facturaId, vendedoraId }); setData(result); } catch (e) { console.error('factura express load', e); setError(e.message || 'No pude abrir la factura'); } finally { setLoading(false); } }, [facturaId, vendedoraId]); React.useEffect(() => { reload(); }, [reload]); if (loading) { return (
Abriendo tu factura...
); } if (error || !data?.factura) { return (
No pude abrir esta factura
{error || 'Pide a Inova que te envie el link nuevamente.'}
); } const factura = data.factura; const vendedora = data.vendedora || { id: vendedoraId, nombre: 'Vendedora' }; const resolvedVendedoraId = vendedora?.id || vendedoraId; const pagos = data.pagos || []; const feedback = data.feedback || window.pedidosApi.latestFacturaFeedback?.(factura); const productos = (factura.productosFinales && factura.productosFinales.length) ? factura.productosFinales : (factura.productosOriginales || []); const saldo = window.facturaSaldo ? window.facturaSaldo(factura, pagos) : Math.max(0, +factura.aPagar || 0); const isProcesada = window.facturaEsCobrable ? window.facturaEsCobrable(factura) : factura.estado === 'procesada'; const resumenPagos = window.facturaPagosResumen ? window.facturaPagosResumen(factura, pagos) : { montoVerificado: 0, montoPendiente: 0, saldoConPendientes: saldo }; const hasIssue = feedback && feedback.respuesta !== 'aceptada'; const accepted = feedback?.respuesta === 'aceptada'; const paymentPlan = window.getPaymentPlanForCampaign ? window.getPaymentPlanForCampaign(factura.campaignId) : null; const paymentPlanLabel = paymentPlan?.label || factura.campaignId || 'esta campana'; async function submitFeedback(tipo) { if (submitting) return; setSubmitting(true); setError(''); try { const cleanProduct = { codigo: String(producto.codigo || '').trim(), nombre: String(producto.nombre || '').trim(), cantidad: Math.max(1, parseInt(producto.cantidad, 10) || 1), }; if (tipo === 'falta_producto' && !cleanProduct.codigo && !cleanProduct.nombre) { setError('Indica al menos el codigo o el nombre del producto que falta.'); setSubmitting(false); return; } const result = await window.pedidosApi.enviarFeedbackFacturaExpress({ facturaId: factura.id || facturaId, vendedoraId: resolvedVendedoraId, tipo, nota, producto: tipo === 'falta_producto' ? cleanProduct : null, }); setData(prev => ({ ...prev, factura: result.factura, feedback: result.feedback })); setMode('sent'); } catch (e) { console.error('factura express feedback', e); setError(e.message || 'No pude guardar tu respuesta'); } finally { setSubmitting(false); } } const feedbackLabel = { aceptada: 'Factura aceptada', falta_producto: 'Reporto producto faltante', producto_sobra: 'Reporto producto de mas', cambio_cantidad: 'Reporto cantidad incorrecta', identidad_incorrecta: 'Reporto que esta factura no es suya', }[feedback?.respuesta]; return (
Verificacion {factura.campaignId || ''}
Revisa tu factura
{vendedora.nombre}, confirma si estos son los productos correctos. Si falta algo o ves algo de mas, avisanos aqui.
Para esta campana no necesitas clave ni descargar la app. Usa este link para revisar tu factura.
{isProcesada ? 'Factura final' : 'En revision antes de cerrar'}
${(+factura.aPagar || 0).toFixed(2)}
A pagar a Inova · total pedido ${(+factura.total || 0).toFixed(2)}
Tu 20%
${(+factura.ganancia || 0).toFixed(2)}
{feedbackLabel && (
{feedbackLabel}
)}
{isProcesada && (resumenPagos.montoVerificado > 0.01 || resumenPagos.montoPendiente > 0.01 || saldo > 0.01) && (
)} {window.PaymentPlanCard && (
)} {isProcesada && (
)}
Productos
{productos.map((p, i) => { const unavailable = !!p.no_disponible; return (
{p.codigo} · {p.catalogo || 'Catalogo'}
{p.nombre}
{p.tono && (
{p.tono}
)} {unavailable && (
{p.motivo_no_disponible === 'recepcion_venezuela' ? 'No llego a Venezuela / no se cobra' : 'Agotado / no se cobra'}
)}
x{p.cantidad}
${((+p.precio || 0) * (+p.cantidad || 0)).toFixed(2)}
); })}
{!isProcesada && mode !== 'sent' && (
)} {!isProcesada && mode === 'missing' && ( submitFeedback('falta_producto')} /> )} {!isProcesada && mode === 'extra' && ( submitFeedback('producto_sobra')} simple /> )} {mode === 'sent' && (
Respuesta guardada. Inova la vera en el admin antes de cerrar la factura.
)} {isProcesada && (
)} {isProcesada && mode === 'identity' && ( submitFeedback('identidad_incorrecta')} simple placeholder="Ej. este link no es mio / estos productos no son de mi pedido" /> )} {error && (
{error}
)} {pagoModal && ( setPagoModal(false)} onSaved={() => { setPagoModal(false); reload(); }} /> )}
); } function FeedbackForm({ T, title, producto, setProducto, nota, setNota, submitting, onSubmit, simple, placeholder }) { return (
{title}
{!simple && (
setProducto({ ...producto, codigo: e.target.value })} placeholder="Codigo" style={inputStyle(T)} /> setProducto({ ...producto, nombre: e.target.value })} placeholder="Producto" style={inputStyle(T)} /> setProducto({ ...producto, cantidad: e.target.value })} type="number" min="1" style={inputStyle(T)} />
)}