all()); $request->validate([ 'pedido_id' => 'required|string', 'monto_consumo' => 'required|numeric', 'monto_propina' => 'nullable|numeric', 'mesero_id' => 'nullable|string', 'metodo' => 'required|string|in:TARJETA_POS,YAPE_POS', ]); try { $resultado = $this->registrarPagoTarjetaUC->ejecutar( $request->input('pedido_id'), (float) $request->input('monto_consumo'), (float) ($request->input('monto_propina') ?? 0), $request->input('mesero_id'), $request->input('metodo') ); return response()->json($resultado, 200); } catch (\Exception $e) { Log::error('❌ [POS] ERROR en registrarPagoPOS: ' . $e->getMessage()); return response()->json(['error' => $e->getMessage()], 500); } } public function crear(Request $request) { $request->validate([ 'pedido_id' => 'required|string', 'monto' => 'required|numeric', 'cliente_email' => 'nullable|email', 'cliente_nombre' => 'nullable|string', 'descripcion' => 'nullable|string', ]); try { $pagoDto = $this->crearPagoUC->ejecutar($request->all()); return response()->json($pagoDto->toArray(), 201); } catch (\Exception $e) { Log::error('❌ Error al crear pago: ' . $e->getMessage()); Log::error('❌ Trace: ' . $e->getTraceAsString()); return response()->json(['error' => 'No se pudo iniciar el proceso de pago: ' . $e->getMessage()], 500); } } public function registrarPagoEfectivo(Request $request) { Log::info('🏧 [CHISMOSO BACK] Iniciando registrarPagoEfectivo', $request->all()); $request->validate([ 'pedido_id' => 'required|string', 'monto' => 'required|numeric', 'mesero_id' => 'nullable|string', // [NEW] ]); try { Log::info('🏧 [CHISMOSO BACK] Llamando al UseCase...'); $resultado = $this->registrarPagoEfectivoUC->ejecutar( $request->input('pedido_id'), (float) $request->input('monto'), $request->input('mesero_id') // [NEW] ); Log::info('✅ [CHISMOSO BACK] Pago registrado correctamente', $resultado); return response()->json($resultado, 200); } catch (\Exception $e) { Log::error('❌ [CHISMOSO BACK] ERROR en registrarPagoEfectivo: ' . $e->getMessage()); Log::error('❌ [CHISMOSO BACK] TRACE: ' . $e->getTraceAsString()); return response()->json([ 'error' => 'No se pudo registrar el pago: ' . $e->getMessage(), 'trace' => $e->getTraceAsString() // Solo para depuración en este momento ], 500); } } public function solicitarPagoEfectivo(Request $request) { Log::info('📩 [Caja] Solicitando pago en efectivo...', $request->all()); $request->validate([ 'pedido_id' => 'required|string', 'propina' => 'nullable|numeric', 'billing_type' => 'nullable|integer', 'document_number' => 'nullable|string', 'client_name' => 'nullable|string', 'direccion' => 'nullable|string', ]); try { $comprobanteTipo = 'BOLETA'; if ($request->input('billing_type') == 2) { $comprobanteTipo = 'FACTURA'; } else if ($request->input('billing_type') == 0) { $comprobanteTipo = 'N/A'; } $comprobanteDatos = [ 'documento_numero' => $request->input('document_number'), 'razon_social' => $request->input('client_name'), 'direccion' => $request->input('direccion'), ]; $resultado = $this->solicitarPagoEfectivoUC->ejecutar( $request->input('pedido_id'), Auth::id(), // Pass triggering user ID (float) $request->input('propina', 0), // Pass propina $comprobanteTipo, $comprobanteDatos ); return response()->json($resultado, 200); } catch (\Exception $e) { Log::error('❌ ERROR en solicitarPagoEfectivo: ' . $e->getMessage()); return response()->json(['error' => $e->getMessage()], 500); } } public function consultar(string $id) { $pago = $this->repositorio->obtenerPorId($id); if (!$pago) { return response()->json(['error' => 'Pago no encontrado'], 404); } return response()->json([ 'id' => $pago->getId(), 'pedido_id' => $pago->getPedidoId(), 'estado' => $pago->getEstado(), 'monto' => $pago->getMonto(), 'init_point' => $pago->getInitPoint() ]); } /** * Puente para el Webhook (llamado desde Node.js o directamente) */ public function webhook(Request $request) { // El webhook real será procesado en una fase posterior. // Por ahora registramos la llamada. Log::info('📩 Pago Webhook recibido', $request->all()); return response()->json(['status' => 'received']); } /** * [NEW] Registra pago y emite comprobante en una sola operación combinada. */ public function registrarPagoYFacturar(Request $request) { $pedidoId = $request->input('pedido_id'); $monto = (float) $request->input('monto'); $montoPropina = (float) $request->input('monto_propina', 0); $metodo = $request->input('metodo', 'EFECTIVO'); $meseroId = $request->input('mesero_id'); try { // --- 1. CAPTURA DE ITEMS CONSOLIDADOS (TODA LA MESA) --- $ordenBase = \Illuminate\Support\Facades\DB::table('Ventas_Ordenes')->where('id_ordenes', $pedidoId)->first(); if ($ordenBase && $ordenBase->recurso_id) { $items = \Illuminate\Support\Facades\DB::table('Ventas_Detalle_Orden as d') ->join('Ventas_Ordenes as o', 'd.orden_id', '=', 'o.id_ordenes') ->leftJoin('Ventas_Productos as p', 'd.producto_id', '=', 'p.id_producto') ->where('o.recurso_id', $ordenBase->recurso_id) ->whereIn('o.estado', ['PENDIENTE', 'POR_CONFIRMAR', 'POR_REVISAR', 'EN_PREPARACION', 'LISTO', 'ENTREGADO']) ->select('d.*', 'p.nombre as producto_nombre') ->get(); } else { // Fallback a solo la orden si no es una mesa o no se encuentra el recurso $items = \Illuminate\Support\Facades\DB::table('Ventas_Detalle_Orden as d') ->leftJoin('Ventas_Productos as p', 'd.producto_id', '=', 'p.id_producto') ->where('d.orden_id', $pedidoId) ->select('d.*', 'p.nombre as producto_nombre') ->get(); } if ($items->isEmpty()) { Log::warning("⚠️ [BILLING] No se encontraron items para la mesa del pedido $pedidoId antes de procesar pago."); } $mappedItems = $items->map(function ($det) { return [ 'codigo' => 'PROD', 'descripcion' => $det->producto_nombre ?? 'Producto', 'unidad' => 'NIU', 'cantidad' => (float)($det->cantidad ?? 1), 'mto_precio_unitario' => (float)($det->precio_aplicado ?? 0.0), 'porcentaje_igv' => 18.0, 'tip_afe_igv' => '10' ]; })->toArray(); // Agregar Propina como ítem si existe if ($montoPropina > 0) { $mappedItems[] = [ 'codigo' => 'PROPINA', 'descripcion' => 'PROPINA/SERVICIO', 'unidad' => 'ZZ', 'cantidad' => 1, 'mto_precio_unitario' => (float)$montoPropina, 'porcentaje_igv' => 0, 'tip_afe_igv' => '30' ]; } // --- 2. REGISTRO DEL PAGO --- $resultadoPago = null; if ($metodo === 'EFECTIVO') { $resultadoPago = $this->registrarPagoEfectivoUC->ejecutar($pedidoId, $monto, $montoPropina, $meseroId); $montoRecibido = (float)$request->input('monto_recibido', 0); $montoVuelto = (float)$request->input('monto_vuelto', 0); if ($montoRecibido > 0) { $descExtra = " (Recibido: S/ " . number_format($montoRecibido, 2, '.', '') . " • Vuelto: S/ " . number_format($montoVuelto, 2, '.', '') . ")"; \Illuminate\Support\Facades\DB::table('Ventas_Pagos') ->where('pedido_id', $pedidoId) ->where('metodo_pago', 'EFECTIVO') ->orderBy('creado_at', 'desc') ->limit(1) ->update([ 'descripcion' => \Illuminate\Support\Facades\DB::raw("CONCAT(COALESCE(descripcion, 'Pago en efectivo'), '{$descExtra}')") ]); } } else { $resultadoPago = $this->registrarPagoTarjetaUC->ejecutar($pedidoId, $monto, $montoPropina, $meseroId, $metodo); } // --- 3. FACTURACIÓN LOCAL (SIN ENVÍO AUTOMÁTICO) --- $resultadoFactura = null; if ($request->has('datos_facturacion') && (int)$request->input('datos_facturacion.tipo_documento_id') !== 0) { $datosFact = $request->input('datos_facturacion'); $orden = \Illuminate\Support\Facades\DB::table('Ventas_Ordenes') ->where('id_ordenes', $pedidoId) ->select('sucursal_id') ->first(); $tipoMetodo = 'EFEC'; if ($metodo === 'TARJETA_POS') $tipoMetodo = 'POS'; else if ($metodo === 'YAPE_POS') $tipoMetodo = 'YAPE'; else if ($metodo === 'PLIN_POS') $tipoMetodo = 'PLIN'; $resultadoFactura = $this->billingService->emitirComprobante([ 'orden_id' => $pedidoId, 'sucursal_id' => $orden->sucursal_id ?? $datosFact['sucursal_id'], 'tipo_documento_id' => (int)$datosFact['tipo_documento_id'], 'total' => $monto + $montoPropina, 'envio_automatico' => false, // [MANUAL] No enviar a SUNAT inmediatamente 'medios_pago' => [ [ 'tipo' => $tipoMetodo, 'monto' => $monto + $montoPropina, 'referencia' => '-' ] ] ], $datosFact['cliente'], $mappedItems); } if ($resultadoFactura && isset($resultadoFactura['success']) && $resultadoFactura['success'] === false) { return response()->json([ 'success' => true, 'facturacion_success' => false, 'message' => 'Pago registrado correctamente, pero falló la facturación: ' . ($resultadoFactura['message'] ?? 'Error desconocido'), 'pago' => $resultadoPago, 'comprobante' => $resultadoFactura ]); } return response()->json([ 'success' => true, 'facturacion_success' => true, 'message' => 'Proceso completado exitosamente (Manual)', 'pago' => $resultadoPago, 'comprobante' => $resultadoFactura ]); } catch (\Exception $e) { Log::error('❌ [Comb] ERROR en registrarPagoYFacturar: ' . $e->getMessage()); return response()->json(['error' => $e->getMessage()], 500); } } }