481 lines
18 KiB
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);
|
|
}
|
|
}
|
|
}
|