parece terminado los envios

This commit is contained in:
2025-04-24 00:32:53 +02:00
parent 8b949a3173
commit f7b9c23f69
9 changed files with 426 additions and 236 deletions

View File

@ -806,6 +806,7 @@ $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], functi
$routes->post('updateCodigoSeguimiento', 'LogisticaController::updateCodigoSeguimiento'); $routes->post('updateCodigoSeguimiento', 'LogisticaController::updateCodigoSeguimiento');
$routes->post('updateProveedorEnvio', 'LogisticaController::updateProveedorEnvio'); $routes->post('updateProveedorEnvio', 'LogisticaController::updateProveedorEnvio');
$routes->post('finalizarEnvio', 'LogisticaController::finalizarEnvio'); $routes->post('finalizarEnvio', 'LogisticaController::finalizarEnvio');
$routes->post('generateEnvio', 'LogisticaController::generarEnvio');
}); });
/* /*

View File

@ -83,6 +83,20 @@ class LogisticaController extends BaseController
return $this->response->setJSON($result); return $this->response->setJSON($result);
} }
public function generarEnvio()
{
if ($this->request->isAJAX()) {
$pedido_id = $this->request->getPost('pedido_id');
$direccion = $this->request->getPost('direccion');
$result = LogisticaService::generateEnvio($pedido_id, $direccion);
return $this->response->setJSON($result);
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function selectAddEnvioLinea() public function selectAddEnvioLinea()
{ {
@ -209,20 +223,6 @@ class LogisticaController extends BaseController
$id = $this->request->getPost('id') ?? null; $id = $this->request->getPost('id') ?? null;
$finalizar_ots = $this->request->getPost('finalizar_ots') ?? false; $finalizar_ots = $this->request->getPost('finalizar_ots') ?? false;
$result = LogisticaService::finalizarEnvio($id);
return $this->response->setJSON($result);
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function finalizarEnvioYOts()
{
if ($this->request->isAJAX()) {
$id = $this->request->getPost('id') ?? null;
$finalizar_ots = $this->request->getPost('finalizar_ots') ?? false;
$result = LogisticaService::finalizarEnvio($id, $finalizar_ots); $result = LogisticaService::finalizarEnvio($id, $finalizar_ots);
return $this->response->setJSON($result); return $this->response->setJSON($result);
} else { } else {
@ -230,6 +230,7 @@ class LogisticaController extends BaseController
} }
} }
public function datatable_enviosEdit($idEnvio) public function datatable_enviosEdit($idEnvio)
{ {
$model = model('App\Models\Logistica\EnvioLineaModel'); $model = model('App\Models\Logistica\EnvioLineaModel');

View File

@ -65,11 +65,12 @@ return [
'noEnvio' => 'No se ha encontrado el envio', 'noEnvio' => 'No se ha encontrado el envio',
'noEnvioLineas' => 'No se han encontrado líneas de envío', 'noEnvioLineas' => 'No se han encontrado líneas de envío',
'noDataToFind' => 'No se ha introducido ningún dato para buscar', 'noDataToFind' => 'No se ha introducido ningún dato para buscar',
'notFound' => 'No se encuentra el pedido o ISBN, el pedido aún no se ha finalizado o no tiene envíos pendientes', 'notFound' => 'No se encuentra el pedido o ISBN, el pedido no está en producción o finalizado o no tiene envíos pendientes',
'noAddresses' => 'El pedido no tiene direcciones de envío', 'noAddresses' => 'El pedido no tiene direcciones de envío',
], ],
'success' => [ 'success' => [
'finalizado' => 'El envío se ha finalizado correctamente', 'finalizado' => 'El envío se ha finalizado correctamente',
'finalizadoOTs' => 'El envío se ha finalizado correctamente.\nSe han creado las OTs siguientes OTs: {ots}',
], ],
]; ];

View File

@ -40,19 +40,16 @@ class EnvioLineaModel extends Model
t1.unidades_total as unidadesTotal, t1.unidades_total as unidadesTotal,
IFNULL(( IFNULL((
SELECT SUM(t_sub.unidades_envio) SELECT SUM(t_sub.unidades_envio)
FROM " . $this->table . " t_sub FROM envios_lineas t_sub
JOIN envios e ON e.id = t_sub.envio_id JOIN envios e ON e.id = t_sub.envio_id
JOIN presupuesto_direcciones d ON d.presupuesto_id = t_sub.presupuesto_id
WHERE e.finalizado = 1 WHERE e.finalizado = 1
AND t_sub.pedido_id = t1.pedido_id AND t_sub.pedido_id = t1.pedido_id
AND e.direccion = d.direccion COLLATE utf8mb3_general_ci AND e.direccion = t2.direccion COLLATE utf8mb3_general_ci
AND ( AND (
t_sub.envio_id <> t1.envio_id t_sub.envio_id <> t1.envio_id
OR (t_sub.envio_id = t1.envio_id AND ( OR (t_sub.envio_id = t1.envio_id AND e.finalizado = 1)
SELECT finalizado FROM envios WHERE id = t1.envio_id
) = 1)
) )
), 0) as unidadesEnviadas, ), 0) AS unidadesEnviadas,
IFNULL(( IFNULL((
SELECT ROUND(SUM(peso) / 1000, 1) SELECT ROUND(SUM(peso) / 1000, 1)
FROM presupuesto_linea FROM presupuesto_linea

View File

@ -10,6 +10,7 @@ class LogisticaService
public static function findPedidoOrISBN($search) public static function findPedidoOrISBN($search)
{ {
$multienvio = false; $multienvio = false;
$direcciones = [];
$modelPedido = model('App\Models\Pedidos\PedidoModel'); $modelPedido = model('App\Models\Pedidos\PedidoModel');
@ -32,13 +33,14 @@ class LogisticaService
$builder->groupStart() $builder->groupStart()
->where('pedidos.id', $search) ->where('pedidos.id', $search)
->whereIn('pedidos.estado', ['finalizado']) ->whereIn('pedidos.estado', ['finalizado', 'produccion'])
->orWhere("REPLACE(presupuestos.isbn, '-', '')", $searchClean) ->orWhere("REPLACE(presupuestos.isbn, '-', '')", $searchClean)
->groupEnd(); ->groupEnd();
$builder->groupBy('pedidos_linea.id'); $builder->groupBy('pedidos_linea.id');
$builder->having('IFNULL(SUM(envios_lineas.unidades_envio), 0) < cantidad_linea', null, false); $builder->having('IFNULL(SUM(envios_lineas.unidades_envio), 0) < cantidad_linea', null, false);
$result = $builder->get()->getResult(); $result = $builder->get()->getResult();
if (empty($result)) { if (empty($result)) {
@ -60,6 +62,21 @@ class LogisticaService
return $response; return $response;
} else if ($numDirecciones > 1) { } else if ($numDirecciones > 1) {
$multienvio = true; $multienvio = true;
$dirs = $PresupuestoDireccionesModel->select('direccion')->where('presupuesto_id', $result[0]->presupuesto_id)
->findAll();
foreach ($dirs as $key => $direccion) {
$modelEnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');
$unidades_en_direccion = $modelEnvioLineasModel->select('SUM(envios_lineas.unidades_envio) as unidades_enviadas,
envios_lineas.unidades_total')
->join('envios', 'envios.id = envios_lineas.envio_id')
->where('pedido_id', $result[0]->pedido_id)
->where('envios.direccion', $direccion->direccion)
->where('envios.finalizado', 1)
->groupBy('pedido_id')->get()->getResult();
if (count($unidades_en_direccion) == 0 || $unidades_en_direccion[0]->unidades_enviadas < $unidades_en_direccion[0]->unidades_total) {
array_push($direcciones, $direccion->direccion);
}
}
} }
$response = [ $response = [
@ -67,8 +84,18 @@ class LogisticaService
'data' => $result[0], 'data' => $result[0],
]; ];
if ($multienvio) {
$response_envio = [
'status' => true,
'multienvio' => true,
'direcciones' => $direcciones,
'pedido_id' => $result[0]->pedido_id,
];
return $response_envio;
}
$response_envio = LogisticaService::generateEnvio($result[0]->pedido_id, $multienvio);
$response_envio = LogisticaService::generateEnvio($result[0]->pedido_id);
if ($response_envio['status'] == false) { if ($response_envio['status'] == false) {
$response = [ $response = [
'status' => false, 'status' => false,
@ -84,84 +111,113 @@ class LogisticaService
} }
public static function findLineaEnvioPorEnvio(int $envio_id) public static function findLineaEnvioPorEnvio(int $envio_id)
{ {
$db = \Config\Database::connect(); $db = \Config\Database::connect();
$subCliente = $db->table('envios')
->select('cliente_id')
->where('id', $envio_id)
->getCompiledSelect();
$builder = $db->table('envios e_main'); // 1. Obtener dirección del envío actual
$envio = $db->table('envios')->select('direccion')->where('id', $envio_id)->get()->getRow();
if (!$envio) {
return [];
}
$builder->select(" $direccionNormalizada = str_replace(' ', '', strtolower(trim($envio->direccion)));
CONCAT('[', p.id, '] - ', pr.titulo) AS name, $direccionSQL = $db->escape($direccionNormalizada);
pl.id AS id,
pl.cantidad,
(
SELECT IFNULL(SUM(el.unidades_envio), 0)
FROM envios_lineas el
JOIN envios e ON e.id = el.envio_id
WHERE el.pedido_id = p.id
AND e.direccion = e_main.direccion
AND pr.cliente_id = ($subCliente)
) AS unidades_enviadas,
(
pl.cantidad - (
SELECT IFNULL(SUM(el2.unidades_envio), 0)
FROM envios_lineas el2
JOIN envios e2 ON e2.id = el2.envio_id
WHERE el2.pedido_id = p.id
AND e2.direccion = e_main.direccion
AND pr.cliente_id = ($subCliente)
)
) AS unidades_pendientes
");
$builder->join('pedidos_linea pl', '1=1'); // para incluir líneas sin envío aún // 2. Obtener los presupuesto_id asociados a esa dirección
$builder->join('pedidos p', 'p.id = pl.pedido_id'); $presupuestosConEsaDireccion = $db->table('presupuesto_direcciones')
$builder->join('presupuestos pr', 'pr.id = pl.presupuesto_id'); ->select('presupuesto_id')
$builder->where('e_main.id', $envio_id); ->where("REPLACE(LOWER(TRIM(direccion)), ' ', '') = $direccionSQL", null, false)
$builder->where('p.estado', 'finalizado'); ->get()
$builder->where("pr.cliente_id = ($subCliente)", null, false); ->getResultArray();
$builder->having('unidades_pendientes >', 0); $presupuestoIds = array_column($presupuestosConEsaDireccion, 'presupuesto_id');
if (empty($presupuestoIds)) {
return [];
}
// 3. Subconsulta principal con unidades pendientes
$subBuilder = $db->table('pedidos_linea pl')
->select("
pl.id AS id,
CONCAT('[', p.id, '] - ', pr.titulo) AS name,
(
SELECT IFNULL(SUM(el.unidades_envio), 0)
FROM envios_lineas el
JOIN envios e ON e.id = el.envio_id
WHERE el.pedido_id = p.id
AND el.presupuesto_id = pr.id
AND REPLACE(LOWER(TRIM(e.direccion)), ' ', '') = $direccionSQL
AND (e.finalizado = 1 OR e.id = $envio_id)
) AS unidades_enviadas,
pd.cantidad AS cantidad
")
->join('pedidos p', 'p.id = pl.pedido_id')
->join('presupuestos pr', 'pr.id = pl.presupuesto_id')
->join('presupuesto_direcciones pd', 'pd.presupuesto_id = pr.id')
->whereIn('pr.id', $presupuestoIds)
->whereIn('p.estado', ['finalizado', 'produccion'])
->where("REPLACE(LOWER(TRIM(pd.direccion)), ' ', '') = $direccionSQL", null, false)
->groupBy('pl.id');
// 4. Envolver y filtrar por unidades pendientes reales
$builder = $db->table("({$subBuilder->getCompiledSelect(false)}) AS sub");
$builder->select('id, name');
$builder->where('cantidad > unidades_enviadas');
$builder->orderBy('name', 'ASC'); $builder->orderBy('name', 'ASC');
return $builder; return $builder;
} }
public static function addLineaEnvio($envio_id = null, $pedido_id = null, $direccion = null) public static function addLineaEnvio($envio_id = null, $pedido_id = null, $direccion = null)
{ {
$modelPedido = model('App\Models\Pedidos\PedidoModel'); $db = \Config\Database::connect();
$builder = $modelPedido->builder(); $direccionNormalizada = strtolower(trim($direccion));
$builder->select(" // 1. Obtener presupuesto_id y cantidad desde presupuesto_direcciones
pedidos.id as pedido_id, $builder = $db->table('pedidos_linea pl')
pedidos_linea.id as linea_id, ->select("
pedidos_linea.cantidad as total_unidades, p.id AS pedido_id,
( pl.id AS linea_id,
SELECT IFNULL(SUM(el.unidades_envio), 0) pr.id AS presupuesto_id,
FROM envios_lineas el pd.cantidad AS total_unidades,
JOIN envios e ON e.id = el.envio_id
WHERE el.pedido_id = pedidos.id
AND e.finalizado = 1
AND TRIM(e.direccion) = '" . addslashes(trim($direccion)) . "'
) as unidades_enviadas,
pedidos_linea.cantidad - IFNULL(SUM(envios_lineas.unidades_envio), 0) as unidades_envio,
presupuestos.id as presupuesto_id
");
$builder->join('pedidos_linea', 'pedidos_linea.pedido_id = pedidos.id', 'left'); (
$builder->join('presupuestos', 'presupuestos.id = pedidos_linea.presupuesto_id', 'left'); SELECT IFNULL(SUM(el.unidades_envio), 0)
$builder->join('envios_lineas', 'envios_lineas.pedido_id = pedidos_linea.pedido_id', 'left'); FROM envios_lineas el
JOIN envios e ON e.id = el.envio_id
WHERE el.pedido_id = p.id
AND el.presupuesto_id = pr.id
AND TRIM(LOWER(e.direccion)) = '$direccionNormalizada'
AND (e.finalizado = 1 OR e.id = $envio_id)
) AS unidades_enviadas,
$builder->groupBy('pedidos_linea.id'); (
$builder->having('IFNULL(SUM(envios_lineas.unidades_envio), 0) < pedidos_linea.cantidad', null, false); pd.cantidad - (
$builder->where('pedidos.estado', 'finalizado'); SELECT IFNULL(SUM(el2.unidades_envio), 0)
$builder->where('pedidos.id', $pedido_id); FROM envios_lineas el2
JOIN envios e2 ON e2.id = el2.envio_id
WHERE el2.pedido_id = p.id
AND el2.presupuesto_id = pr.id
AND TRIM(LOWER(e2.direccion)) = '$direccionNormalizada'
AND (e2.finalizado = 1 OR e2.id = $envio_id)
)
) AS unidades_envio
")
->join('pedidos p', 'p.id = pl.pedido_id')
->join('presupuestos pr', 'pr.id = pl.presupuesto_id')
->join('presupuesto_direcciones pd', 'pd.presupuesto_id = pr.id')
->where('p.id', $pedido_id)
->whereIn('p.estado', ['finalizado', 'produccion'])
->where("TRIM(LOWER(pd.direccion)) = '$direccionNormalizada'", null, false)
->groupBy('pl.id');
$result = $builder->get()->getResultObject(); $result = $builder->get()->getResultObject();
@ -170,122 +226,132 @@ class LogisticaService
'status' => false, 'status' => false,
'message' => lang('Logistica.errors.notFound'), 'message' => lang('Logistica.errors.notFound'),
]; ];
} else { }
$r = $result[0];
// 2. Insertar solo si hay unidades a enviar
if ($r->unidades_envio > 0) {
$EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel'); $EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');
$EnvioLineasModel->save([ $EnvioLineasModel->save([
'envio_id' => $envio_id, 'envio_id' => $envio_id,
'pedido_id' => $result[0]->pedido_id, 'pedido_id' => $r->pedido_id,
'unidades_envio' => $result[0]->unidades_envio, 'presupuesto_id' => $r->presupuesto_id,
'unidades_total' => $result[0]->total_unidades, 'unidades_envio' => $r->unidades_envio,
'unidades_total' => $r->total_unidades,
'cajas' => null, 'cajas' => null,
'unidades_cajas' => 1, 'unidades_cajas' => 1,
'created_at' => date('Y-m-d H:i:s'), 'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'),
'created_by' => auth()->user()->id, 'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id, 'updated_by' => auth()->user()->id,
'presupuesto_id' => $result[0]->presupuesto_id,
]); ]);
} }
return [ return [
'status' => true, 'status' => true,
'data' => [ 'data' => [
'unidades_envio' => $result[0]->unidades_envio, 'unidades_envio' => $r->unidades_envio,
'unidades_enviadas' => $result[0]->unidades_enviadas, 'unidades_enviadas' => $r->unidades_enviadas,
'total_unidades' => $result[0]->total_unidades, 'total_unidades' => $r->total_unidades,
] ]
]; ];
} }
private static function generateEnvio($pedido_id, $multienvio = false) public static function generateEnvio($pedido_id, $direccion = null)
{ {
$presupuestoDireccionesModel = model('App\Models\Presupuestos\PresupuestoDireccionesModel'); $presupuestoDireccionesModel = model('App\Models\Presupuestos\PresupuestoDireccionesModel');
$direccionNormalizada = strtolower(trim($direccion));
if (!$multienvio) { // Consulta con cálculo exacto de unidades pendientes por dirección
// solo hay una dirección, se obtiene de los albaranes $datosEnvio = $presupuestoDireccionesModel
->select("
presupuestos.id as presupuesto_id,
presupuesto_direcciones.att,
presupuesto_direcciones.direccion,
presupuesto_direcciones.provincia as ciudad,
presupuesto_direcciones.cp,
presupuesto_direcciones.telefono,
presupuesto_direcciones.email,
presupuesto_direcciones.pais_id,
presupuesto_direcciones.cantidad as cantidad_total,
presupuestos.cliente_id as cliente_id,
$datosEnvio = $presupuestoDireccionesModel (
->select(' presupuesto_direcciones.cantidad - IFNULL((
presupuestos.id as presupuesto_id, SELECT SUM(el.unidades_envio)
presupuesto_direcciones.att, FROM envios_lineas el
presupuesto_direcciones.direccion, JOIN envios e ON e.id = el.envio_id
presupuesto_direcciones.provincia as ciudad, WHERE el.pedido_id = pedidos.id
presupuesto_direcciones.cp, AND el.presupuesto_id = presupuestos.id
presupuesto_direcciones.telefono, AND TRIM(LOWER(e.direccion)) = '$direccionNormalizada'
presupuesto_direcciones.email, AND e.finalizado = 1
presupuesto_direcciones.pais_id, ), 0)
presupuesto_direcciones.cantidad - IFNULL(SUM(envios_lineas.unidades_envio), 0) as cantidad, ) as cantidad
presupuesto_direcciones.cantidad as cantidad_total, ")
presupuestos.cliente_id as cliente_id ->join('pedidos_linea', 'pedidos_linea.presupuesto_id = presupuesto_direcciones.presupuesto_id')
') ->join('pedidos', 'pedidos.id = pedidos_linea.pedido_id')
->join('pedidos_linea', 'pedidos_linea.presupuesto_id = presupuesto_direcciones.presupuesto_id') ->join('presupuestos', 'pedidos_linea.presupuesto_id = presupuestos.id')
->join('pedidos', 'pedidos.id = pedidos_linea.pedido_id') ->where('pedidos.id', $pedido_id)
->join('presupuestos', 'pedidos_linea.presupuesto_id = presupuestos.id') ->where("TRIM(LOWER(presupuesto_direcciones.direccion)) = '$direccionNormalizada'", null, false)
->join('envios_lineas', 'envios_lineas.pedido_id = pedidos.id', 'left') ->groupBy('presupuesto_direcciones.id')
->join('envios', 'envios.id = envios_lineas.envio_id', 'left') ->first();
->where('pedidos.id', $pedido_id)
->groupBy('presupuesto_direcciones.id') // Necesario por el uso de SUM
->first();
// Validación si no hay datos o no quedan unidades
// se genera un nuevo envio con estos datos if (empty($datosEnvio) || $datosEnvio->cantidad <= 0) {
$EnvioModel = model('App\Models\Logistica\EnvioModel');
$EnvioModel->set('cliente_id', $datosEnvio->cliente_id);
$EnvioModel->set('att', $datosEnvio->att);
$EnvioModel->set('direccion', $datosEnvio->direccion);
$EnvioModel->set('ciudad', $datosEnvio->ciudad);
$EnvioModel->set('cp', $datosEnvio->cp);
$EnvioModel->set('telefono', $datosEnvio->telefono);
$EnvioModel->set('email', $datosEnvio->email);
$EnvioModel->set('pais_id', $datosEnvio->pais_id);
$EnvioModel->set('cantidad', $datosEnvio->cantidad);
$EnvioModel->set('cajas', 1);
$EnvioModel->set('multienvio', $multienvio ? 1 : 0);
$EnvioModel->set('created_at', date('Y-m-d H:i:s'));
$EnvioModel->set('updated_at', date('Y-m-d H:i:s'));
$EnvioModel->insert();
$idEnvio = $EnvioModel->insertID();
// se genera la linea de envio
$EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');
$EnvioLineasModel->save([
'envio_id' => $idEnvio,
'pedido_id' => $pedido_id,
'unidades_envio' => $datosEnvio->cantidad,
'unidades_total' => $datosEnvio->cantidad_total,
'cajas' => 1,
'unidades_cajas' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id,
'presupuesto_id' => (int) $datosEnvio->presupuesto_id
]);
return [
'status' => true,
'data' => [
'id_envio' => $idEnvio,
'multienvio' => false,
],
];
}
if (empty($datosEnvio)) {
return [ return [
'status' => false, 'status' => false,
'message' => lang('Logistica.errors.noAddresses'), 'message' => lang('Logistica.errors.noAddresses') . ' o no hay unidades pendientes.',
]; ];
} }
// Crear envío
$EnvioModel = model('App\Models\Logistica\EnvioModel');
$EnvioModel->set([
'cliente_id' => $datosEnvio->cliente_id,
'att' => $datosEnvio->att,
'direccion' => $datosEnvio->direccion,
'ciudad' => $datosEnvio->ciudad,
'cp' => $datosEnvio->cp,
'telefono' => $datosEnvio->telefono,
'email' => $datosEnvio->email,
'pais_id' => $datosEnvio->pais_id,
'cantidad' => $datosEnvio->cantidad,
'cajas' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
$EnvioModel->insert();
$idEnvio = $EnvioModel->insertID();
// Crear línea de envío
$EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');
$EnvioLineasModel->save([
'envio_id' => $idEnvio,
'pedido_id' => $pedido_id,
'unidades_envio' => $datosEnvio->cantidad,
'unidades_total' => $datosEnvio->cantidad_total,
'cajas' => 1,
'unidades_cajas' => 1,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
'created_by' => auth()->user()->id,
'updated_by' => auth()->user()->id,
'presupuesto_id' => (int) $datosEnvio->presupuesto_id
]);
return [
'status' => true,
'data' => [
'id_envio' => $idEnvio,
],
];
} }
public static function finalizarEnvio($envio_id, $finalizar_ot = false) public static function finalizarEnvio($envio_id, $finalizar_ot = false)
{ {
// hay que comprobar que para todas las lineas de envio de este envio // hay que comprobar que para todas las lineas de envio de este envio
@ -337,7 +403,7 @@ class LogisticaService
$cantidad_enviada = $cantidad_enviada[0]->unidades_enviadas; $cantidad_enviada = $cantidad_enviada[0]->unidades_enviadas;
} }
if ($cantidad_enviada + $linea->unidades_envio == $linea->unidades_total) { if ($cantidad_enviada + $linea->unidades_envio == $pedido->total_tirada) {
$otModel = model('App\Models\OrdenTrabajo\OrdenTrabajoModel'); $otModel = model('App\Models\OrdenTrabajo\OrdenTrabajoModel');
$ot = $otModel->where('pedido_id', $linea->pedido_id) $ot = $otModel->where('pedido_id', $linea->pedido_id)
->first(); ->first();
@ -365,6 +431,9 @@ class LogisticaService
]; ];
if ($finalizar_ot) { if ($finalizar_ot) {
$data_return['message'] = lang('Logistica.success.finalizadoOTs', [
'ots' => implode(', ', $ots)
]);
$data_return['ots'] = $ots; $data_return['ots'] = $ots;
} }
return $data_return; return $data_return;

View File

@ -144,7 +144,7 @@ class PresupuestoService extends BaseService
$maquina->velocidad $maquina->velocidad
); );
$tiempo = round($tiempo, 2); $tiempo = round($tiempo, 2);
[$precio_hora, $margen_precio_hora] = $clientePreciosModel->get_precio_hora($cliente_id, $config, $tiempo); [$precio_hora, $margen_precio_hora] = $clientePreciosModel->get_precio_hora($cliente_id, $config, round($tiempo, 2));
if (is_null($precio_hora)) { if (is_null($precio_hora)) {

View File

@ -9,7 +9,7 @@
<div class="col-12"> <div class="col-12">
<div class="card"> <div class="card">
<div class="card-header"> <div class="card-header">
<h4><?= $boxTitle ?> <span class="badge text-bg-success fw-lg">FINALIZADO</span></h4> <h4><?= $boxTitle ?> <?= ($envioEntity->finalizado == 0)?'':'<span class="badge text-bg-success fw-lg">FINALIZADO</span>' ?></h4>
</div> </div>
<div class="card-body"> <div class="card-body">

View File

@ -1,27 +1,30 @@
import Ajax from '../../components/ajax.js'; import Ajax from '../../components/ajax.js';
$(()=>{ $(() => {
$('#buscadorPedidos').on('keydown', function(e) { $('#buscadorPedidos').on('keydown', function (e) {
if (e.key === 'Enter' || e.keyCode === 13) { if (e.key === 'Enter' || e.keyCode === 13) {
e.preventDefault(); // Evita el submit si está dentro de un form e.preventDefault(); // Evita el submit si está dentro de un form
let search = $(this).val().trim(); let search = $(this).val().trim();
new Ajax( new Ajax(
'/logistica/buscar/'+search, '/logistica/buscar/' + search,
{}, {},
{}, {},
function(response) { function (response) {
if(!response.status){ if (!response.status) {
popErrorAlert(response.message); popErrorAlert(response.message);
} }
if(response.data){ if (response.multienvio) {
mostrarSwalDirecciones(response);
}
else if (response.data) {
window.open(`${window.location.origin}/logistica/envio/${response.data.id_envio}`); window.open(`${window.location.origin}/logistica/envio/${response.data.id_envio}`);
} }
}, },
function(xhr, status, error) { function (xhr, status, error) {
if(status == 'error' && typeof(error)== 'string') if (status == 'error' && typeof (error) == 'string')
popErrorAlert(error); popErrorAlert(error);
else else
popErrorAlert(error.responseJSON.message); popErrorAlert(error.responseJSON.message);
@ -79,4 +82,51 @@ $(()=>{
window.location.href = '/logistica/envio/' + $(this).attr('data-id'); window.location.href = '/logistica/envio/' + $(this).attr('data-id');
}); });
function mostrarSwalDirecciones(response) {
// Crear el select como HTML
let options = response.direcciones.map((dir, index) =>
`<option value="${index}">${dir}</option>`
).join("");
Swal.fire({
title: 'Múltiples direcciones',
html: `
<p>El pedido tiene múltiples direcciones. Debe seleccionar una dirección:</p>
<select id="swal-select-direccion" class="form-select" style="width: 100%; margin-top: 1rem;">
${options}
</select>
`,
confirmButtonText: 'Aceptar',
cancelButtonText: 'Cancelar',
customClass: {
confirmButton: 'swal2-confirm btn btn-primary',
cancelButton: 'swal2-cancel btn btn-secondary' // Estilo gris
},
preConfirm: () => {
const select = document.getElementById('swal-select-direccion');
if (!select.value) {
Swal.showValidationMessage('Debe seleccionar una dirección');
return false;
}
return response.direcciones[select.value]; // Devuelve la dirección seleccionada
}
}).then((result) => {
if (result.isConfirmed) {
const direccionSeleccionada = result.value;
$.post('/logistica/generateEnvio', {
pedido_id: response.pedido_id,
direccion: direccionSeleccionada
}, function (response) {
if (response.status) {
window.open(`${window.location.origin}/logistica/envio/${response.data.id_envio}`);
} else {
popErrorAlert(response.message);
}
}).fail(function (xhr, status, error) {
popErrorAlert(error);
});
}
});
}
}); });

View File

@ -29,14 +29,14 @@ class EnvioEdit {
this.btnbtnSelectAll = $("#btnSelectAll"); this.btnbtnSelectAll = $("#btnSelectAll");
this.cajas = $("#cajas"); this.cajas = $("#cajas");
this.codigoSeguimiento = $("#codigoSeguimiento"); this.codigoSeguimiento = $("#codigoSeguimiento");
if($("#empresaMensajeriaInput").length) { if (!$("#empresaMensajeriaInput").length) {
this.proveedor = new ClassSelect($("#empresaMensajeria"), '/compras/proveedores/getProveedores', "", true, { 'tipo_id': 2 }); this.proveedor = new ClassSelect($("#empresaMensajeria"), '/compras/proveedores/getProveedores', "", true, { 'tipo_id': 2 });
} }
} }
init() { init() {
if($("#empresaMensajeriaInput").length) { if (!$("#empresaMensajeriaInput").length) {
this.proveedor.init(); this.proveedor.init();
} }
@ -254,17 +254,32 @@ class EnvioEdit {
); );
}); });
this.proveedor.onChange((e) => { if (!$("#empresaMensajeriaInput").length) {
this.proveedor.onChange((e) => {
const value = this.proveedor.getVal(); const value = this.proveedor.getVal();
$.post('/logistica/updateProveedorEnvio', { $.post('/logistica/updateProveedorEnvio', {
id: $('#id').val(), id: $('#id').val(),
proveedor_id: value proveedor_id: value
}, function (response) { }, function (response) {
if (!response.status) { if (!response.status) {
Swal.fire({
title: 'Error',
text: response.message,
icon: 'error',
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
this.proveedor.setVal(0);
}
}).fail(() => {
Swal.fire({ Swal.fire({
title: 'Error', title: 'Error',
text: response.message, text: 'No se pudo actualizar el proveedor.',
icon: 'error', icon: 'error',
confirmButtonColor: '#3085d6', confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok', confirmButtonText: 'Ok',
@ -275,47 +290,15 @@ class EnvioEdit {
}); });
this.proveedor.setVal(0); this.proveedor.setVal(0);
} }
}).fail(() => { );
Swal.fire({ });
title: 'Error', }
text: 'No se pudo actualizar el proveedor.',
icon: 'error',
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
this.proveedor.setVal(0);
}
);
});
$('.btn-finalizar').on('click', (e) => { $('#finalizarEnvio').on('click', (e) => {
let data = {
id : $('#id').val(); if (!this._checkDatosFinalizar())
};
let url = '/logistica/finalizarEnvio';
if(e.currentTarget.id() != "finalizarEnvio"){
let url = '/logistica/finalizarEnvioYOts';
data.finalizar_ots = true;
}
if(this.codigoSeguimiento.val().length <= 0 || this.proveedor.getVal() <= 0) {
Swal.fire({
title: 'Atención!',
text: 'Debe seleccionar un proveedor y un código de seguimiento antes de finalizar el envío.',
icon: 'info',
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
return; return;
}
////////////////////
Swal.fire({ Swal.fire({
title: 'Finalizar envío', title: 'Finalizar envío',
text: '¿Está seguro de que desea finalizar el envío?', text: '¿Está seguro de que desea finalizar el envío?',
@ -343,6 +326,75 @@ class EnvioEdit {
confirmButton: 'btn btn-primary me-1', confirmButton: 'btn btn-primary me-1',
}, },
buttonsStyling: false buttonsStyling: false
}).then(() => {
window.location.reload();
});
} else {
Swal.fire({
title: 'Error',
text: response.message,
icon: 'error',
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
}
}).fail(() => {
Swal.fire({
title: 'Error',
text: 'No se pudo finalizar el envío.',
icon: 'error',
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
});
}
});
});
$('#finalizarEnvioYOTs').on('click', (e) => {
if (!this._checkDatosFinalizar())
return;
Swal.fire({
title: 'Finalizar envío y las OTs',
text: '¿Está seguro de que desea finalizar el envío y las OTs de las líneas de envío?',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Sí',
cancelButtonText: 'Cancelar',
customClass: {
confirmButton: 'btn btn-danger me-1',
cancelButton: 'btn btn-secondary'
},
buttonsStyling: false
}).then((result) => {
if (result.isConfirmed) {
$.post('/logistica/finalizarEnvio', {
id: $('#id').val(),
finalizar_ots: true
}, function (response) {
if (response.status) {
Swal.fire({
text: response.message,
icon: 'success',
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
}).then(() => {
window.location.reload();
}); });
} else { } else {
Swal.fire({ Swal.fire({
@ -377,6 +429,25 @@ class EnvioEdit {
this._getAlbaranes(); this._getAlbaranes();
} }
_checkDatosFinalizar() {
if (this.codigoSeguimiento.val().length <= 0 || this.proveedor.getVal() <= 0) {
Swal.fire({
title: 'Atención!',
text: 'Debe seleccionar un proveedor y un código de seguimiento antes de finalizar el envío.',
icon: 'info',
confirmButtonColor: '#3085d6',
confirmButtonText: 'Ok',
customClass: {
confirmButton: 'btn btn-primary me-1',
},
buttonsStyling: false
});
return false;
}
return true;
}
_getAlbaranes() { _getAlbaranes() {
$.get('/albaranes/albaranesEnvio', { $.get('/albaranes/albaranesEnvio', {
envio_id: $('#id').val(), envio_id: $('#id').val(),