vueloenglobo.mx/app/Http/Controllers/Api/VuelosERPController.php

481 lines
18 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
class VuelosERPController extends Controller
{
protected int $sitio_web;
protected int $status;
public function __construct()
{
$this->sitio_web = config('sitioweb.sitio_web_erp_id', 0);
$this->status = 1; // Asumiendo que 1 es el estatus para vuelos activos
}
public function getVuelosNombresPreciosPublico()
{
$vuelos = DB::table('vuelos')
->where('id_sitio_web', $this->sitio_web)
->where('id_estatus', $this->status ?? 0)
->get();
$imagenes = DB::table('vuelos_imagenes_galeria')
->where('id_estatus', 1)
->orderBy('orden', 'asc')
->get()
->groupBy('id_vuelo');
$unidades = DB::table('unidades')
->where('id_estatus', 1)
->get()
->keyBy('id_unidad');
$vuelos->transform(function ($vuelo) use ($imagenes, $unidades) {
$vuelo->json_incluye = json_decode($vuelo->json_incluye, true);
$vuelo->precios_adicionales = collect(json_decode($vuelo->precios_adicionales, true))
->map(function ($item) use ($unidades) {
$idUnidad = (int) $item['id_unidad'];
return [
'id_unidad' => $idUnidad,
'precio' => (float) $item['precio'],
'unidad' => $unidades->has($idUnidad)
? [
'nombre_unidad' => $unidades[$idUnidad]->nombre_unidad,
'nombre_corto' => $unidades[$idUnidad]->nombre_corto,
'numero_personas_piezas' => $unidades[$idUnidad]->numero_personas_piezas,
]
: null
];
})
->values();
$vuelo->imagenes_galeria = $imagenes->get($vuelo->id_vuelo, collect())
->map(function ($img) {
return [
'id_imagen_vuelo' => $img->id_imagen_vuelo,
'ruta' => $img->ruta_imagen_vuelo,
'descripcion' => $img->descripcion_imagen_vuelo,
'orden' => $img->orden,
'imagen_destacada' => (bool) $img->imagen_destacada,
];
})
->values();
return $vuelo;
});
return response()->json(
$vuelos,
200,
[],
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
);
}
public function getServiciosAdicionales()
{
$response = Http::get('https://erp.skyballoons.mx/servicios-adicionales-webservice', [
'comercio' => 'skyballoons',
'key' => 'f093328776ae4cd210dc7b4ee4093e45',
]);
if ($response->successful()) {
$data = $response->json();
return response()->json(
$data,
200,
[],
JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE
);
} else {
return response()->json(['error' => 'No se pudieron obtener los servicios adicionales'], 500);
}
}
/*public function reservarVuelo(Request $request)
{
try {
//consultar el vuelo en globo
$vuelo = DB::table('vuelos')->where('id_vuelo', $request->id_vuelo)->first();
$data = [
// Datos del cliente
'nombre_reserva' => $request->responsable['nombres'],
'apellido_reserva' => $request->responsable['apellidos'],
'email_reserva' => $request->responsable['email'],
'tel_reserva' => preg_replace('/\D/', '', $request->responsable['telefono']),
'Lada' => 52,
'fecha_vuelo' => $request->fecha,
// Datos del vuelo
'id_vuelo' => $request->id_vuelo,
'id_unidad' => $vuelo->id_unidad,
'pasajeros' => ($request->adultos ?? 0) + ($request->ninios ?? 0),
'precio_publico' => $request->total,
// Totales
'total_compra' => $request->total,
// Pasajeros adicionales
'num_pax_adicionales' => 0,
'id_unidad_adicionales' => null,
'precio_adicional' => 0,
// Servicios adicionales
'servicios_adicionales' => collect($request->servicios ?? [])
->map(function ($servicio) {
return [
'id_servicio' => $servicio['id_servicio'],
'cantidad_solicitada' => $servicio['cantidad'] ?? 1,
'precio' => $servicio['precio'] ?? 0,
];
})
->toArray(),
];
return $data;
$resultado = $this->crearCotizacionCompleta($data);
return response()->json($resultado);
} catch (\Exception $e) {
return response()->json(['error' => 'Error al procesar la reserva: ' . $e->getMessage()], 500);
}
}*/
public function reservarVuelo(Request $request)
{
try {
// 1. BLINDAJE: Detectar si 'servicios' llegó como string JSON y parsearlo
$serviciosRaw = $request->servicios;
if (is_string($serviciosRaw)) {
$serviciosRaw = json_decode($serviciosRaw, true);
}
// Si no es un array válido tras el decode o viene vacío, asignamos un array limpio
$serviciosArray = is_array($serviciosRaw) ? $serviciosRaw : [];
// Consultar el vuelo en globo
$vuelo = DB::table('vuelos')->where('id_vuelo', $request->id_vuelo)->first();
if (!$vuelo) {
return response()->json(['error' => 'El vuelo solicitado no existe.'], 404);
}
$data = [
// Datos del cliente
'nombre_reserva' => $request->responsable['nombres'] ?? '',
'apellido_reserva' => $request->responsable['apellidos'] ?? '',
'email_reserva' => $request->responsable['email'] ?? '',
'tel_reserva' => preg_replace('/\D/', '', $request->responsable['telefono'] ?? ''),
'Lada' => 52,
'fecha_vuelo' => $request->fecha,
// Datos del vuelo
'id_vuelo' => $vuelo->id_vuelo,
'id_unidad' => $vuelo->id_unidad,
'pasajeros' => ($request->adultos ?? 0) + ($request->ninios ?? 0),
'precio_publico' => $request->total,
// Totales
'total_compra' => $request->total,
// Pasajeros adicionales
'num_pax_adicionales' => 0,
'id_unidad_adicionales' => null,
'precio_adicional' => 0,
// Servicios adicionales (procesados de forma segura)
'servicios_adicionales' => collect($serviciosArray)
->map(function ($servicio) {
return [
'id_servicio' => $servicio['id_servicio'] ?? null,
'cantidad_solicitada' => $servicio['cantidad'] ?? 1,
'precio' => $servicio['precio'] ?? 0,
];
})
->filter(fn($s) => !is_null($s['id_servicio'])) // Quita elementos mal formados
->toArray(),
];
// ⚠️ NOTA: Eliminamos el 'return $data;' para que el flujo continúe hacia la cotización real.
$id_cotizacion = $this->crearCotizacionCompleta($data);
$route = route('checkout.detalle.cotizacion.chatbot', ['cotizacion' => $id_cotizacion]);
return response()->json(['id_cotizacion' => $id_cotizacion, 'route' => $route]);
} catch (\Exception $e) {
return response()->json(['error' => 'Error al procesar la reserva: ' . $e->getMessage()], 500);
}
}
public function crearCotizacionCompleta(array $data)
{
try {
DB::beginTransaction();
// 1. Generar folio
$ultimoId = (DB::table('cotizaciones')->max('id_cotizacion') ?? 0) + 1;
$folio = "COT" . str_pad($ultimoId, 7, "0", STR_PAD_LEFT);
$vuelo = DB::table('vuelos')->where('id_vuelo', $data['id_vuelo'])->where('id_estatus', 1)->where('id_sitio_web', $this->sitio_web)->first() ?? null;
// 2. Insertar cotización principal
$id_cotizacion = DB::table('cotizaciones')->insertGetId([
'folio' => $folio,
'nombre' => $data['nombre_reserva'],
'apellidos' => $data['apellido_reserva'],
'mail' => $data['email_reserva'],
'telefono' => $data['tel_reserva'],
'iso_country_id_primary_phone' => $data['Lada'],
'subtotal' => $data['total_compra'],
'total' => $data['total_compra'],
'total_con_iva' => $data['total_compra'],
'total_neto' => $data['total_compra'],
'id_sitio_web' => $this->sitio_web,
'observaciones' => 'Cotizacion desde www.vueloenglobo.mx',
'id_user_alta' => 98,
'fecha_alta' => now(),
'fecha_vuelo' => $data['fecha_vuelo'] ?? null,
]);
// 3. Insertar vuelo principal
DB::table('vuelos_cotizaciones')->insert([
'id_cotizacion' => $id_cotizacion,
'id_vuelo' => $vuelo->id_vuelo,
'id_unidad' => $data['id_unidad'],
'cantidades' => $data['pasajeros'],
'precio_vendido_p_pax_vuelo' => $vuelo->precio_publico,
'precio_especial' => $vuelo->precio_publico,
'id_estatus' => 1,
'id_user_alta' => 98,
'fecha_alta' => now(),
]);
// 4. Pasajeros adicionales
/* if (!empty($data['num_pax_adicionales']) && $data['num_pax_adicionales'] > 0) {
DB::table('vuelos_cotizaciones')->insert([
'id_cotizacion' => $id_cotizacion,
'id_vuelo' => $data['id_vuelo'],
'id_unidad' => $data['id_unidad_adicionales'],
'cantidades' => $data['num_pax_adicionales'],
'precio_vendido_p_pax_vuelo' => $data['precio_adicional'],
'pasajero_adicional' => 1,
'id_estatus' => 1,
'id_user_alta' => 98,
'fecha_alta' => now(),
]);
}*/
// 5. Servicios adicionales
if (!empty($data['servicios_adicionales'])) {
$servicios = is_string($data['servicios_adicionales'])
? json_decode($data['servicios_adicionales'], true)
: $data['servicios_adicionales'];
foreach ($servicios as $servicio) {
DB::table('servicios_adicionales_cotizaciones')->insert([
'id_cotizacion' => $id_cotizacion,
'id_servicio_adicional' => $servicio['id_servicio'],
'cantidades' => $servicio['cantidad_solicitada'],
'precio_vendido' => $servicio['precio'],
'id_estatus' => 1,
'id_user_alta' => 98,
'fecha_alta' => now(),
]);
}
}
DB::commit();
return $id_cotizacion;
return [
'success' => true,
'id_cotizacion' => $id_cotizacion,
'folio' => $folio
];
} catch (\Exception $e) {
DB::rollBack();
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/*
public function efectuarPago(Request $request)
{
try {
$cotizacion_id = $request->id_cotizacion ?? 0;
$cotizacion = DB::table('cotizaciones')->where('id_cotizacion', $cotizacion_id)->first();
//aqui va lo del pago con clip, si se efectua entonces se generan el pase de abordar y el pedido
DB::table('pases_de_abordar')->insert([
'id_cotizacion' => $cotizacion_id,
'id_lugar_cita' => 12,
'hora_cita' => '06:00',
'id_recibo' => 0,
'id_estatus' => 1,
'id_user_alta' => 98,
'fecha_alta' => now(),
]);
DB::table('pedidos')->insert([
'id_cotizacion' => $cotizacion_id,
'foto_comprobante' => null,
'cantidad_pagada' => $cotizacion->total_neto,
'pago_confirmado' => 1,
'fecha_pago' => date('Y-m-d'),
'observaciones' => 'Transacción realizada vía Clip PAGO CON TARJETA desde vueloenglobo.mx | ' . $cotizacion->nombre . ' ' . $cotizacion->apellidos . ' - ID Cotizacion:' . $cotizacion_id,
'observaciones_logistica' => 'Transacción realizada vía Clip PAGO CON TARJETA desde vueloenglobo.mx | ' . $cotizacion->nombre . ' ' . $cotizacion->apellidos . ' - ID Cotizacion:' . $cotizacion_id,
'ultimos_digitos' => null,
'id_cuenta_bancaria' => 1,
'id_metodo_pago_cuenta_bancaria' => 9,
'id_banco' => 0,
'id_estatus' => 1,
'id_user_alta' => 98,
'fecha_alta' => now(),
]);
$url = url('https://erp.skyballoons.mx/enviar-pase/2/' . $cotizacion_id);
Http::get($url);
} catch (\Exception $e) {
return response()->json([
'success' => false,
'message' => 'Error al procesar el pago: ' . $e->getMessage()
], 500);
}
}*/
public function efectuarPago(Request $request)
{
try {
$validated = $request->validate([
'token' => 'required|string',
'id_cotizacion' => 'required|integer'
]);
$cotizacion = DB::table('cotizaciones')
->where('id_cotizacion', $validated['id_cotizacion'])
->first();
if (!$cotizacion) {
return response()->json([
'success' => false,
'message' => 'Cotización no encontrada'
], 404);
}
// ==========================
// COBRO CON CLIP
// ==========================
$payload = [
'amount' => (float) $cotizacion->total_neto,
'currency' => 'MXN',
'description' => 'Pago vuelo en globo - ' . $cotizacion->folio,
'payment_method' => [
'token' => $validated['token']
],
'customer' => [
'email' => $cotizacion->mail,
'phone' => $cotizacion->telefono
]
];
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . config('clip.api_key'),
'Content-Type' => 'application/json',
])->post(config('clip.payments_url'), $payload);
// 🔴 FALLO TOTAL: cortar flujo
if (!$response->successful()) {
return response()->json([
'success' => false,
'message' => $response->json('detail') ?? 'Pago rechazado',
'clip_response' => $response->json()
], 400);
}
$clipPayment = $response->json();
// 🔴 VALIDAR ESTATUS REAL DEL PAGO (MUY IMPORTANTE)
if (($clipPayment['status'] ?? null) !== 'approved') {
return response()->json([
'success' => false,
'message' => 'El pago no fue aprobado',
'clip_response' => $clipPayment
], 400);
}
// ==========================
// SOLO SI FUE APROBADO
// ==========================
DB::beginTransaction();
DB::table('pases_de_abordar')->insert([
'id_cotizacion' => $cotizacion->id_cotizacion,
'id_lugar_cita' => 12,
'hora_cita' => '06:00',
'id_recibo' => 0,
'id_estatus' => 1,
'id_user_alta' => 98,
'fecha_alta' => now(),
]);
DB::table('pedidos')->insert([
'id_cotizacion' => $cotizacion->id_cotizacion,
'foto_comprobante' => null,
'cantidad_pagada' => $cotizacion->total_neto,
'pago_confirmado' => 1,
'fecha_pago' => now(),
'observaciones' => 'Clip payment ID: ' . ($clipPayment['id'] ?? ''),
'observaciones_logistica' => 'Clip payment ID: ' . ($clipPayment['id'] ?? ''),
'ultimos_digitos' => $clipPayment['payment_method']['card']['last4'] ?? null,
'id_cuenta_bancaria' => 1,
'id_metodo_pago_cuenta_bancaria' => 9,
'id_banco' => 0,
'id_estatus' => 1,
'id_user_alta' => 98,
'fecha_alta' => now(),
]);
DB::commit();
Http::timeout(30)->get(
'https://erp.skyballoons.mx/enviar-pase/2/' . $cotizacion->id_cotizacion
);
return response()->json([
'success' => true,
'message' => 'Pago realizado correctamente',
'payment_id' => $clipPayment['id'] ?? null
]);
} catch (\Exception $e) {
DB::rollBack();
return response()->json([
'success' => false,
'message' => $e->getMessage()
], 500);
}
}
}