diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index 488c6d36..110b81eb 100755 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -512,15 +512,16 @@ $routes->group('pedidos', ['namespace' => 'App\Controllers\Pedidos'], function ( $routes->resource('pedidos', ['namespace' => 'App\Controllers\Pedidos', 'controller' => 'Pedido', 'except' => 'show,new,create,update']); -$routes->group('albaranes', ['namespace' => 'App\Controllers\Pedidos'], function ($routes) { - $routes->post('add', 'Albaran::add', ['as' => 'crearAlbaranesPedido']); - $routes->post('update/(:any)', 'Albaran::update/$1', ['as' => 'actualizarAlbaran']); - $routes->post('updateLinea/(:any)', 'Albaran::updateLinea/$1', ['as' => 'actualizarLineaAlbaran']); - $routes->post('deletelinea', 'Albaran::borrarlinea', ['as' => 'borrarAlbaranLinea']); - $routes->get('delete/(:any)', 'Albaran::delete/$1', ['as' => 'borrarAlbaran']); - $routes->get('getalbaranes/(:any)', 'Albaran::getAlbaranes/$1', ['as' => 'getAlbaranes']); - $routes->get('nuevalinea/(:any)', 'Albaran::addLinea/$1', ['as' => 'addAlbaranLinea']); - $routes->post('nuevalinea/(:any)', 'Albaran::addLinea/$1', ['as' => 'addIVA']); +$routes->group('albaranes', ['namespace' => 'App\Controllers\Albaranes'], function ($routes) { + $routes->post('generarAlbaran', 'Albaran::generateAlbaran', ['as' => 'generarAlbaran']); + $routes->get('albaranesEnvio', 'Albaran::getAlbaranes'); + $routes->get('datatablesAlbaranLinea', 'Albaran::datatablesLineasAlbaran'); + $routes->post('updateAlbaran', 'Albaran::updateAlbaran'); + $routes->post('borrarAlbaranLinea', 'Albaran::borrarLinea'); + $routes->post('borrarAlbaran', 'Albaran::borrarAlbaran'); + $routes->post('updateAlbaranLinea', 'Albaran::updateAlbaranLinea'); + $routes->post('addIvaAlbaran', 'Albaran::addLineasIva'); + $routes->post('nuevaLineaAlbaran', 'Albaran::addBlankLineaAlbaran'); }); $routes->resource('albaranes', ['namespace' => 'App\Controllers\Pedidos', 'controller' => 'Albaran', 'except' => 'show,new,create,update']); @@ -793,6 +794,19 @@ $routes->group('produccion', ['namespace' => 'App\Controllers\Produccion'], func $routes->group('logistica', ['namespace' => 'App\Controllers\Logistica'], function ($routes) { $routes->get('print/label/test', 'LogisticaController::print_test_label'); + $routes->get('panel', 'LogisticaController::panel', ['as' => 'LogisticaPanel']); + $routes->get('selectEnvios/(:any)', 'LogisticaController::selectorEnvios/$1', ['as' => 'selectEnvios']); + $routes->get('buscar/(:any)', 'LogisticaController::searchPedidoOrISBN/$1', ['as' => 'buscarPedidoOrISBN']); + $routes->get('datatableEnvios', 'LogisticaController::datatable_envios'); + $routes->get('datatableLineasEnvios/(:num)', 'LogisticaController::datatable_enviosEdit/$1'); + $routes->get('envio/(:num)', 'LogisticaController::editEnvio/$1'); + $routes->get('selectAddLinea', 'LogisticaController::selectAddEnvioLinea'); + $routes->get('addLineaEnvio', 'LogisticaController::addEnvioLinea'); + $routes->post('updateCajaLinea', 'LogisticaController::setCajaLinea'); + $routes->post('deleteLineasEnvio', 'LogisticaController::deleteLineas'); + $routes->post('updateLineaEnvio', 'LogisticaController::updateLineaEnvio'); + $routes->post('updateComentariosEnvio', 'LogisticaController::saveComments'); + $routes->post('updateCajasEnvio', 'LogisticaController::updateCajasEnvio'); }); /* diff --git a/ci4/app/Controllers/Albaranes/Albaran.php b/ci4/app/Controllers/Albaranes/Albaran.php new file mode 100755 index 00000000..109d00f0 --- /dev/null +++ b/ci4/app/Controllers/Albaranes/Albaran.php @@ -0,0 +1,560 @@ +request->isAJAX()) { + + $newTokenHash = csrf_hash(); + $csrfTokenName = csrf_token(); + + $model_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + $model_linea->where('albaran_id', $id)->delete(); + + $this->model->where('id', $id)->delete(); + + $data = [ + 'error' => 0, + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function addLinea($albaran_id) + { + + if ($this->request->isAJAX()) { + + $model_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + $newTokenHash = csrf_hash(); + $csrfTokenName = csrf_token(); + + // si es un post, es el iva + if ($this->request->getPost()) { + $reqData = $this->request->getPost(); + $albaran_id = $reqData['albaran_id'] ?? 0; + + $albaran = $this->model->find($albaran_id); + if ($albaran == false) { + $data = [ + 'error' => 'Albaran no encontrado', + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + } + $presupuesto_model = model('App\Models\Presupuestos\PresupuestoModel'); + $presupuesto = $presupuesto_model->find($albaran->presupuesto_id); + if ($presupuesto == false) { + $data = [ + 'error' => 'Presupuesto no encontrado', + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + } + $iva_reducido = $presupuesto->iva_reducido; + $lineas = $model_linea->where('albaran_id', $albaran_id)->findAll(); + $total = 0; + foreach ($lineas as $linea) { + $total += $linea->total; + } + $iva = $iva_reducido ? $total * 4.0 / 100 : $total * 21.0 / 100; + $data_linea = [ + 'albaran_id' => $albaran_id, + 'titulo' => $iva_reducido ? lang('Pedidos.iva4') : lang('Pedidos.iva21'), + 'cantidad' => 1, + 'precio_unidad' => round($iva, 2), + 'total' => round($iva, 2), + 'user_created_id' => auth()->user()->id, + 'user_updated_id' => auth()->user()->id + ]; + $id_linea = $model_linea->insert($data_linea); + $linea = $model_linea->find($id_linea); + $data = [ + 'error' => 0, + 'data' => $linea, + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + } else { + $linea = [ + 'albaran_id' => $albaran_id, + 'user_created_id' => auth()->user()->id, + 'user_updated_id' => auth()->user()->id + ]; + $id_linea = $model_linea->insert($linea); + $data = $model_linea->find($id_linea); + + $data = [ + 'error' => 0, + 'data' => $data, + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + } + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function add() + { + if ($this->request->isAJAX()) { + + $user = auth()->user()->id; + + $newTokenHash = csrf_hash(); + $csrfTokenName = csrf_token(); + + $reqData = $this->request->getPost(); + $pedido_id = $reqData['pedido_id'] ?? 0; + $presupuestos_id = $reqData['presupuestos_id'] ?? 0; + + $return_data = $this->model->generarAlbaranes($pedido_id, $presupuestos_id, $user); + $data = [ + 'data' => $return_data, + $csrfTokenName => $newTokenHash + ]; + + return $this->respond($data); + + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function updateAlbaran() + { + + if ($this->request->isAJAX()) { + + $fieldName = $this->request->getPost('fieldName'); + $fieldValue = $this->request->getPost('fieldValue'); + $id = $this->request->getPost('albaranId'); + + if ($id == null) { + $data = [ + 'success' => false, + 'message' => lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]), + ]; + return $this->respond($data); + } + $albaranEntity = $this->model->find($id); + + if ($albaranEntity == false) { + $data = [ + 'success' => false, + 'message' => lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]), + ]; + return $this->respond($data); + } + + if($fieldName == 'fecha_albaran'){ + if($fieldValue == null || $fieldValue == '') + $fieldValue = null; + else + $fieldValue = date('Y-m-d H:i:s', strtotime($fieldValue)); + } + + $albaranEntity->fill([ + $fieldName => $fieldValue, + 'user_updated_id' => auth()->user()->id, + ]); + $successfulResult = $this->model->skipValidation(true)->update($id, $albaranEntity); + if ($successfulResult) { + $data = [ + 'success' => true, + 'message' => lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.', + ]; + } else { + $data = [ + 'success' => false, + 'message' => lang('Basic.global.updateError', [lang('Basic.global.record')]) . '.', + ]; + } + + return $this->respond($data); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + + public function updateLinea($id = null) + { + + if ($this->request->isAJAX()) { + + $model_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + $newTokenHash = csrf_hash(); + $csrfTokenName = csrf_token(); + + if ($id == null): + $data = [ + 'error' => 2, + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + endif; + $id = filter_var($id, FILTER_SANITIZE_URL); + $albaranEntity = $model_linea->find($id); + + if ($albaranEntity == false): + $message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]); + $data = [ + 'error' => $message, + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + endif; + + if ($this->request->getPost()): + + $nullIfEmpty = true; // !(phpversion() >= '8.1'); + + $postData = $this->request->getPost(); + + $sanitizedData = $this->sanitized($postData, $nullIfEmpty); + + // JJO + $sanitizedData['user_updated_id'] = auth()->user()->id; + + $noException = true; + if ($successfulResult = $this->canValidate()): // if ($successfulResult = $this->validate($this->formValidationRules) ) : + + if ($this->canValidate()): + try { + $successfulResult = $model_linea->skipValidation(true)->update($id, $sanitizedData); + } catch (\Exception $e) { + $noException = false; + $this->dealWithException($e); + } + else: + $this->viewData['warningMessage'] = lang('Basic.global.formErr1', [mb_strtolower(lang('Pedidos.albaran'))]); + $this->session->setFlashdata('formErrors', $model_linea->errors()); + + endif; + + $albaranEntity->fill($sanitizedData); + + endif; + if ($noException && $successfulResult): + $id = $albaranEntity->id ?? $id; + $message = lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.'; + + $data = [ + 'error' => 0, + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + + endif; // $noException && $successfulResult + endif; // ($requestMethod === 'post') + + $data = [ + 'error' => 1, + $csrfTokenName => $newTokenHash + ]; + return $this->respond($data); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + + public function getAlbaranes() + { + + if ($this->request->isAJAX()) { + + $envio_id = $this->request->getGet('envio_id'); + $albaranes = $this->model->getAlbaranesEnvio($envio_id); + $data = [ + 'status' => true, + 'data' => $albaranes, + ]; + return $this->respond($data); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function generateAlbaran() + { + + if ($this->request->isAJAX()) { + + $reqData = $this->request->getPost(); + $envio_id = $reqData['envio_id'] ?? 0; + $envio_lineas = $reqData['envio_lineas'] ?? []; + $cajas = $reqData['cajas'] ?? 0; + + $response = $this->model->generarAlbaranes($envio_id, $envio_lineas, $cajas); + + return $this->respond($response); + + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function datatablesLineasAlbaran() + { + + $albaranId = $this->request->getGet('albaranId'); + $model = model('App\Models\Albaranes\AlbaranLineaModel'); + $q = $model->getDatatableQuery($albaranId); + + $result = DataTable::of($q) + ->add( + "action", + callback: function ($q) { + return ' +
+ +
+ '; + } + ) + ->edit('pedido', function ($q) { + return '' . $q->pedido . ''; + }) + ->edit('unidades', function ($q) { + if(str_contains($q->titulo, 'IVA')) + return null; + else + return ''; + }) + ->edit('titulo', function ($q) { + return ''; + }) + ->edit('total', function ($q) { + return ''; + }) + ->edit('precio_unidad', function ($q) { + if(str_contains($q->titulo, 'IVA')) + return null; + else + return ''; + }); + + + return $result->toJson(returnAsObject: true); + } + + public function updateAlbaranLinea(){ + + if ($this->request->isAJAX()) { + + $model_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + + + $fieldName = $this->request->getPost('fieldName'); + $fieldValue = $this->request->getPost('fieldValue'); + $id = $this->request->getPost('lineaId'); + + $linea = $model_linea->find($id); + if ($linea == false) { + $data = [ + 'success' => false, + 'message' => lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]), + ]; + return $this->respond($data); + } + if($fieldName == 'cantidad') { + $linea->total = round($linea->precio_unidad * intval($fieldValue), 4); + $linea->cantidad = intval($fieldValue); + } + else if($fieldName == 'precio_unidad') { + $fieldValue2 = str_replace(',', '.', $fieldValue); + $linea->total = round(round(floatval($fieldValue2), 4) * intval($linea->cantidad), 2); + $linea->precio_unidad = round(floatval($fieldValue2), 4); + } + else if($fieldName == 'total') { + $linea->total = round(floatval($fieldValue), 2); + $linea->precio_unidad = round(floatval($fieldValue) / intval($linea->cantidad), 4); + } + else{ + $linea->$fieldName = $fieldValue; + } + $linea->user_updated_id = auth()->user()->id; + $linea->updated_at = date('Y-m-d H:i:s'); + + $model_linea->update($id, $linea->toArray()); + + $data = [ + 'success' => true, + 'message' => lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.', + ]; + return $this->respond($data); + + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function addLineasIva(){ + + if ($this->request->isAJAX()) { + + $albaran_id = $this->request->getPost('albaranId'); + $model_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + + $lineas_albaran = $model_linea->where('albaran_id', $albaran_id)->findAll(); + $iva_reducido = 0; + $iva_no_reducido = 0; + foreach ($lineas_albaran as $linea) { + if($linea->iva_reducido == 1) { + $iva_reducido += round(floatval($linea->total)*0.04, 2); + } else { + $iva_no_reducido += round(floatval($linea->total)*0.21, 2); + } + } + $iva_reducido = round($iva_reducido, 2); + $iva_no_reducido = round($iva_no_reducido, 2); + if($iva_reducido > 0) { + $linea = [ + 'albaran_id' => $albaran_id, + 'titulo' => lang('Albaran.iva4'), + 'total' => round($iva_reducido, 2), + 'user_created_id' => auth()->user()->id, + 'user_updated_id' => auth()->user()->id + ]; + $model_linea->insert($linea); + } + if($iva_no_reducido > 0) { + $linea = [ + 'albaran_id' => $albaran_id, + 'titulo' => lang('Albaran.iva21'), + 'total' => round($iva_no_reducido, 2), + 'user_created_id' => auth()->user()->id, + 'user_updated_id' => auth()->user()->id + ]; + $model_linea->insert($linea); + } + $data = [ + 'success' => true, + 'message' => lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.', + ]; + return $this->respond($data); + + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function addBlankLineaAlbaran(){ + + if ($this->request->isAJAX()) { + + $albaran_id = $this->request->getPost('albaranId'); + $model_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + + $linea = [ + 'albaran_id' => $albaran_id, + 'user_created_id' => auth()->user()->id, + 'user_updated_id' => auth()->user()->id + ]; + $id_linea = $model_linea->insert($linea); + $data = $model_linea->find($id_linea); + + $data = [ + 'success' => true, + ]; + return $this->respond($data); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function borrarLinea() + { + + if ($this->request->isAJAX()) { + + $model_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + + $reqData = $this->request->getPost(); + $id = $reqData['linea'] ?? 0; + $id = filter_var($id, FILTER_SANITIZE_URL); + $albaranLineaEntity = $model_linea->find($id); + + if ($albaranLineaEntity == false): + $message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]); + $data = [ + 'success' => false, + 'error' => $message, + ]; + return $this->respond($data); + endif; + + $successfulResult = $model_linea->skipValidation(true)->update($id, ['deleted_at' => date('Y-m-d H:i:s')]); + + if ($successfulResult): + $data = [ + 'success' => true, + ]; + else: + $data = [ + 'success' => false, + 'error' => lang('Basic.global.deleteError', [lang('Basic.global.record')]) . '.', + ]; + endif; + return $this->respond($data); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function borrarAlbaran() + { + + if ($this->request->isAJAX()) { + + $id = $this->request->getPost('albaranId'); + $model_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + $model_linea->where('albaran_id', $id)->delete(); + + $this->model->where('id', $id)->delete(); + + $data = [ + 'success' => true + ]; + return $this->respond($data); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + +} diff --git a/ci4/app/Controllers/Logistica/LogisticaController.php b/ci4/app/Controllers/Logistica/LogisticaController.php index 25f5819d..1e00f72f 100755 --- a/ci4/app/Controllers/Logistica/LogisticaController.php +++ b/ci4/app/Controllers/Logistica/LogisticaController.php @@ -4,9 +4,11 @@ namespace App\Controllers\Logistica; use App\Controllers\BaseController; use App\Services\ImpresoraEtiquetaService; +use App\Services\LogisticaService; use CodeIgniter\HTTP\RequestInterface; use CodeIgniter\HTTP\ResponseInterface; use Psr\Log\LoggerInterface; +use Hermawan\DataTables\DataTable; class LogisticaController extends BaseController { @@ -15,11 +17,22 @@ class LogisticaController extends BaseController protected string $locale; protected array $viewData; + protected static $controllerSlug = 'logistica'; + protected static $viewPath = 'themes/vuexy/form/logistica/'; + public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) { $this->impresoraEtiquetaService = service('impresora_etiqueta'); $this->locale = session()->get('lang'); + $this->viewData['pageTitle'] = lang('Logistica.logistica'); + + // Breadcrumbs + $this->viewData['breadcrumb'] = [ + ['title' => lang("App.menu_logistica"), 'route' => "javascript:void(0);", 'active' => false], + ]; + + parent::initController($request, $response, $logger); } public function print_test_label() @@ -28,4 +41,282 @@ class LogisticaController extends BaseController $responseMessage = $etiquetaData["status"] ? "OK" : "ERROR"; return $this->response->setJSON(["message" => $responseMessage, "data" => $etiquetaData, "status" => $etiquetaData["status"]]); } + + public function panel() + { + $viewData = [ + 'currentModule' => static::$controllerSlug, + 'boxTitle' => lang('Logistica.panel'), + 'pageSubTitle' => 'Panel', + 'usingServerSideDataTable' => true, + ]; + + $viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class + + return view(static::$viewPath . 'viewPanelLogistica', $viewData); + } + + public function selectorEnvios($tipoEnvio = null) + { + $viewData = [ + 'currentModule' => static::$controllerSlug, + 'boxTitle' => lang('Logistica.envioSimpleMultiple'), + 'usingServerSideDataTable' => true, + 'tipoEnvio' => $tipoEnvio, + ]; + + $viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class + + return view(static::$viewPath . 'viewLogisticaSelectEnvios', $viewData); + } + + public function searchPedidoOrISBN($search = "", $envio_id = null) + { + + if (empty($search)) { + $result = [ + 'status' => false, + 'message' => lang('Logistica.errors.noDataToFind'), + ]; + return $this->response->setJSON($result); + } + $result = LogisticaService::findPedidoOrISBN($search); + return $this->response->setJSON($result); + } + + public function selectAddEnvioLinea() + { + + if ($this->request->isAJAX()) { + $query = LogisticaService::findLineaEnvioPorEnvio($this->request->getGet('envio')); + if ($this->request->getGet("q")) { + $query->groupStart() + ->orLike("p.id", $this->request->getGet("q")) + ->orLike("pr.titulo", $this->request->getGet("q")) + ->groupEnd(); + } + + + $result = $query->orderBy("name", "asc")->get()->getResultObject(); + + return $this->response->setJSON($result); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function addEnvioLinea() + { + + if ($this->request->isAJAX()) { + $pedido_id = $this->request->getGet('pedido_id'); + $envio_id = $this->request->getGet('envio_id'); + $envioModel = model('App\Models\Logistica\EnvioModel'); + $direccion = $envioModel->find($envio_id)->direccion; + + $result = LogisticaService::addLineaEnvio($envio_id, $pedido_id, $direccion); + return $this->response->setJSON($result); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function datatable_envios() + { + $model = model('App\Models\Logistica\EnvioModel'); + $q = $model->getDatatableQuery(); + + + $result = DataTable::of($q) + ->edit( + "finalizado", + function ($row, $meta) { + if ($row->finalizado == 1) + return ''; + else + return ''; + } + ) + ->add("action", callback: function ($q) { + + return ' +
+ +
+ '; + }); + + return $result->toJson(returnAsObject: true); + } + + public function editEnvio($id = null) + { + + if (empty($id)) { + return redirect()->to(base_url('logistica/selectEnvios/simple'))->with('error', lang('Logistica.errors.noEnvio')); + } + $model = model('App\Models\Logistica\EnvioModel'); + $envioEntity = $model->select('envios.*, lg_paises.nombre as pais') + ->join('lg_paises', 'lg_paises.id = envios.pais_id', 'left') + ->where('envios.id', $id) + ->first(); + if (empty($envioEntity)) { + return redirect()->to(base_url('logistica/selectEnvios/simple'))->with('error', lang('Logistica.errors.noEnvio')); + } + + $viewData = [ + 'currentModule' => static::$controllerSlug, + 'boxTitle' => '' . ' ' . lang('Logistica.envio') . ' [' . $envioEntity->id . ']: ' . $envioEntity->direccion, + 'usingServerSideDataTable' => true, + 'envioEntity' => $envioEntity, + ]; + + $viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class + + return view(static::$viewPath . 'viewEnvioEditForm', $viewData); + } + + public function updateCajasEnvio() + { + if ($this->request->isAJAX()) { + $id = $this->request->getPost('id'); + $cajas = $this->request->getPost('cajas'); + $model = model('App\Models\Logistica\EnvioModel'); + $result = $model->update($id, [ + 'cajas' => $cajas, + ]); + return $this->response->setJSON([ + "status" => $result, + ]); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function datatable_enviosEdit($idEnvio) + { + $model = model('App\Models\Logistica\EnvioLineaModel'); + $q = $model->getDatatableQuery($idEnvio); + + + $result = DataTable::of($q) + ->add( + "rowSelected", + callback: function ($q) { + return ''; + } + ) + ->edit( + "pedido", + function ($row, $meta) { + return '' . $row->pedido . ''; + } + ) + ->edit( + "presupuesto", + function ($row, $meta) { + return '' . $row->presupuesto . ''; + } + ) + ->edit( + "cajas", + function ($row, $meta) { + return ''; + } + )->edit( + "unidadesEnvio", + function ($row, $meta) { + return ''; + } + ) + ->edit('cajasRaw', function ($row) { + return is_null($row->cajas) ? '__SIN__ASIGNAR__' : $row->cajas; + }); + + return $result->toJson(returnAsObject: true); + } + + public function setCajaLinea() + { + + if ($this->request->isAJAX()) { + $id = $this->request->getPost('id'); + $caja = $this->request->getPost('caja'); + + + $model = model('App\Models\Logistica\EnvioLineaModel'); + $result = $model->update($id, [ + 'cajas' => $caja, + ]); + return $this->response->setJSON([ + "status" => $result, + ]); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function deleteLineas() + { + if ($this->request->isAJAX()) { + $ids = $this->request->getPost('ids'); + $model = model('App\Models\Logistica\EnvioLineaModel'); + $result = $model->delete($ids); + return $this->response->setJSON([ + "status" => $result, + ]); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } + + public function updateLineaEnvio() + { + $id = $this->request->getPost('id'); + $fieldName = $this->request->getPost('name'); + $fieldValue = $this->request->getPost('value'); + + if (!$id || !$fieldName || ($fieldName=='unidades_envio' && !$fieldValue)) { + return $this->response->setJSON([ + 'status' => false, + 'message' => 'Datos inválidos' + ]); + } + + $model = model('App\Models\Logistica\EnvioLineaModel'); + $updated = $model->update($id, [ + "" . $fieldName => $fieldValue==""? null: $fieldValue, + ]); + + return $this->response->setJSON([ + 'status' => $updated, + 'message' => $updated ? 'Actualizado' : 'Error al actualizar' + ]); + } + + public function saveComments() + { + $id = $this->request->getPost('id'); + $comments = $this->request->getPost('comentarios'); + + if (!$id || !$comments) { + return $this->response->setJSON([ + 'status' => false, + 'message' => 'Datos inválidos' + ]); + } + + $model = model('App\Models\Logistica\EnvioModel'); + $updated = $model->update($id, [ + 'comentarios' => $comments, + ]); + + return $this->response->setJSON([ + 'status' => $updated, + 'message' => $updated ? 'Actualizado' : 'Error al actualizar' + ]); + } + } diff --git a/ci4/app/Controllers/Pdf/PrintAlbaranes.php b/ci4/app/Controllers/Pdf/PrintAlbaranes.php index 506d9114..4ebaeb73 100755 --- a/ci4/app/Controllers/Pdf/PrintAlbaranes.php +++ b/ci4/app/Controllers/Pdf/PrintAlbaranes.php @@ -11,8 +11,8 @@ class PrintAlbaranes extends BaseController public function index($albaran_id) { - $albaranModel = model('App\Models\Pedidos\AlbaranModel'); - $lineasAlbaranModel = model('App\Models\Pedidos\AlbaranLineaModel'); + $albaranModel = model('App\Models\Albaranes\AlbaranModel'); + $lineasAlbaranModel = model('App\Models\Albaranes\AlbaranLineaModel'); $data['albaran'] = $albaranModel->getResourceForPdf($albaran_id)->get()->getRow(); $data['albaranLineas'] = $lineasAlbaranModel->getResourceForPdf($albaran_id)->get()->getResultObject(); @@ -25,14 +25,22 @@ class PrintAlbaranes extends BaseController { // Cargar modelos - $albaranModel = model('App\Models\Pedidos\AlbaranModel'); - $lineasAlbaranModel = model('App\Models\Pedidos\AlbaranLineaModel'); + $albaranModel = model('App\Models\Albaranes\AlbaranModel'); + $lineasAlbaranModel = model('App\Models\Albaranes\AlbaranLineaModel'); // Informacion del presupuesto $data['albaran'] = $albaranModel->getResourceForPdf($albaran_id)->get()->getRow(); $data['albaranLineas'] = $lineasAlbaranModel->getResourceForPdf($albaran_id)->get()->getResultObject(); + // Obtener contenido HTML de la vista + $html = view(getenv('theme.path') . 'pdfs/albaran', $data); + + // Cargar CSS desde archivo local + $css = file_get_contents(FCPATH . 'themes/vuexy/css/pdf.albaran.css'); + // Combinar CSS y HTML + $html_con_css = "" . $html; + // Crear una instancia de Dompdf $options = new \Dompdf\Options(); $options->set('isHtml5ParserEnabled', true); @@ -41,7 +49,7 @@ class PrintAlbaranes extends BaseController $dompdf = new \Dompdf\Dompdf($options); // Contenido HTML del documento - $dompdf->loadHtml(view(getenv('theme.path').'pdfs/albaran', $data)); + $dompdf->loadHtml($html_con_css); // Establecer el tamaño del papel $dompdf->setPaper('A4', 'portrait'); diff --git a/ci4/app/Controllers/Pedidos/Albaran.php b/ci4/app/Controllers/Pedidos/Albaran.php deleted file mode 100755 index f5af3504..00000000 --- a/ci4/app/Controllers/Pedidos/Albaran.php +++ /dev/null @@ -1,388 +0,0 @@ -request->isAJAX()) { - - $newTokenHash = csrf_hash(); - $csrfTokenName = csrf_token(); - - $model_linea = model('App\Models\Pedidos\AlbaranLineaModel'); - $model_linea->where('albaran_id', $id)->delete(); - - $this->model->where('id', $id)->delete(); - - $data = [ - 'error' => 0, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - } - else { - return $this->failUnauthorized('Invalid request', 403); - } - } - - public function addLinea($albaran_id){ - - if ($this->request->isAJAX()) { - - $model_linea = model('App\Models\Pedidos\AlbaranLineaModel'); - $newTokenHash = csrf_hash(); - $csrfTokenName = csrf_token(); - - // si es un post, es el iva - if($this->request->getPost()){ - $reqData = $this->request->getPost(); - $albaran_id = $reqData['albaran_id'] ?? 0; - - $albaran = $this->model->find($albaran_id); - if($albaran == false){ - $data = [ - 'error' => 'Albaran no encontrado', - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - } - $presupuesto_model = model('App\Models\Presupuestos\PresupuestoModel'); - $presupuesto = $presupuesto_model->find($albaran->presupuesto_id); - if($presupuesto == false){ - $data = [ - 'error' => 'Presupuesto no encontrado', - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - } - $iva_reducido = $presupuesto->iva_reducido; - $lineas = $model_linea->where('albaran_id', $albaran_id)->findAll(); - $total = 0; - foreach($lineas as $linea){ - $total += $linea->total; - } - $iva = $iva_reducido? $total * 4.0 / 100: $total * 21.0 / 100; - $data_linea= [ - 'albaran_id' => $albaran_id, - 'titulo' => $iva_reducido?lang('Pedidos.iva4'):lang('Pedidos.iva21'), - 'cantidad' => 1, - 'precio_unidad' => round($iva,2), - 'total' => round($iva,2), - 'user_created_id' => auth()->user()->id, - 'user_updated_id' => auth()->user()->id - ]; - $id_linea = $model_linea->insert($data_linea); - $linea = $model_linea->find($id_linea); - $data = [ - 'error' => 0, - 'data' => $linea, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - } - else{ - $linea = [ - 'albaran_id' => $albaran_id, - 'user_created_id' => auth()->user()->id, - 'user_updated_id' => auth()->user()->id - ]; - $id_linea = $model_linea->insert($linea); - $data = $model_linea->find($id_linea); - - $data = [ - 'error' => 0, - 'data' => $data, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - } - } - else { - return $this->failUnauthorized('Invalid request', 403); - } - } - - public function add() - { - if ($this->request->isAJAX()) { - - $user = auth()->user()->id; - - $newTokenHash = csrf_hash(); - $csrfTokenName = csrf_token(); - - $reqData = $this->request->getPost(); - $pedido_id = $reqData['pedido_id'] ?? 0; - $presupuestos_id = $reqData['presupuestos_id'] ?? 0; - - $return_data = $this->model->generarAlbaranes($pedido_id, $presupuestos_id, $user); - $data = [ - 'data' => $return_data, - $csrfTokenName => $newTokenHash - ]; - - return $this->respond($data); - - } - else { - return $this->failUnauthorized('Invalid request', 403); - } - } - - public function update($id = null){ - - if ($this->request->isAJAX()) { - $newTokenHash = csrf_hash(); - $csrfTokenName = csrf_token(); - - if ($id == null) : - $data = [ - 'error' => 2, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - endif; - $id = filter_var($id, FILTER_SANITIZE_URL); - $albaranEntity = $this->model->find($id); - - if ($albaranEntity == false) : - $message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]); - $data = [ - 'error' => $message, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - endif; - - if ($this->request->getPost()) : - - $nullIfEmpty = true; // !(phpversion() >= '8.1'); - - $postData = $this->request->getPost(); - - $sanitizedData = $this->sanitized($postData, $nullIfEmpty); - - // JJO - $sanitizedData['user_updated_id'] = auth()->user()->id; - - $noException = true; - if ($successfulResult = $this->canValidate()) : // if ($successfulResult = $this->validate($this->formValidationRules) ) : - - if ($this->canValidate()) : - try { - $successfulResult = $this->model->skipValidation(true)->update($id, $sanitizedData); - } catch (\Exception $e) { - $noException = false; - $this->dealWithException($e); - } - else: - $this->viewData['warningMessage'] = lang('Basic.global.formErr1', [mb_strtolower(lang('Pedidos.albaran'))]); - $this->session->setFlashdata('formErrors', $this->model->errors()); - - endif; - - $albaranEntity->fill($sanitizedData); - - endif; - if ($noException && $successfulResult) : - $id = $albaranEntity->id ?? $id; - $message = lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.'; - - $data = [ - 'error' => 0, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - - endif; // $noException && $successfulResult - endif; // ($requestMethod === 'post') - - $data = [ - 'error' => 1, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - } - else { - return $this->failUnauthorized('Invalid request', 403); - } - } - - - public function updateLinea($id = null){ - - if ($this->request->isAJAX()) { - - $model_linea = model('App\Models\Pedidos\AlbaranLineaModel'); - $newTokenHash = csrf_hash(); - $csrfTokenName = csrf_token(); - - if ($id == null) : - $data = [ - 'error' => 2, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - endif; - $id = filter_var($id, FILTER_SANITIZE_URL); - $albaranEntity = $model_linea->find($id); - - if ($albaranEntity == false) : - $message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]); - $data = [ - 'error' => $message, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - endif; - - if ($this->request->getPost()) : - - $nullIfEmpty = true; // !(phpversion() >= '8.1'); - - $postData = $this->request->getPost(); - - $sanitizedData = $this->sanitized($postData, $nullIfEmpty); - - // JJO - $sanitizedData['user_updated_id'] = auth()->user()->id; - - $noException = true; - if ($successfulResult = $this->canValidate()) : // if ($successfulResult = $this->validate($this->formValidationRules) ) : - - if ($this->canValidate()) : - try { - $successfulResult = $model_linea->skipValidation(true)->update($id, $sanitizedData); - } catch (\Exception $e) { - $noException = false; - $this->dealWithException($e); - } - else: - $this->viewData['warningMessage'] = lang('Basic.global.formErr1', [mb_strtolower(lang('Pedidos.albaran'))]); - $this->session->setFlashdata('formErrors', $model_linea->errors()); - - endif; - - $albaranEntity->fill($sanitizedData); - - endif; - if ($noException && $successfulResult) : - $id = $albaranEntity->id ?? $id; - $message = lang('Basic.global.updateSuccess', [lang('Basic.global.record')]) . '.'; - - $data = [ - 'error' => 0, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - - endif; // $noException && $successfulResult - endif; // ($requestMethod === 'post') - - $data = [ - 'error' => 1, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - } - else { - return $this->failUnauthorized('Invalid request', 403); - } - } - - public function borrarLinea(){ - if ($this->request->isAJAX()) { - - $model_linea = model('App\Models\Pedidos\AlbaranLineaModel'); - $newTokenHash = csrf_hash(); - $csrfTokenName = csrf_token(); - - $reqData = $this->request->getPost(); - $id = $reqData['id'] ?? 0; - $id = filter_var($id, FILTER_SANITIZE_URL); - $albaranLineaEntity = $model_linea->find($id); - - if ($albaranLineaEntity == false) : - $message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]); - $message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Pedidos.albaran')), $id]); - $data = [ - 'error' => $message, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - endif; - - $successfulResult = $model_linea->skipValidation(true)->update($id, ['deleted_at' => date('Y-m-d H:i:s')]); - - if ($successfulResult) : - $data = [ - 'error' => 0, - $csrfTokenName => $newTokenHash - ]; - else: - $data = [ - 'error' => 1, - $csrfTokenName => $newTokenHash - ]; - endif; - return $this->respond($data); - } - else { - return $this->failUnauthorized('Invalid request', 403); - } - } - - public function getAlbaranes($pedido_id = null){ - if ($this->request->isAJAX()) { - - $model_linea = model('App\Models\Pedidos\AlbaranLineaModel'); - $newTokenHash = csrf_hash(); - $csrfTokenName = csrf_token(); - - $returnData = []; - $albaranes = $this->model->asArray()->where('pedido_id', $pedido_id)->findAll(); - - foreach($albaranes as $albaran){ - $albaran['fecha_albaran'] = $albaran['updated_at']; - array_push($returnData, - [ - 'albaran' => $albaran, - 'lineas' => $model_linea->asArray()->where('albaran_id', $albaran['id'])->findAll()] - ); - } - - $data = [ - 'data' => $returnData, - $csrfTokenName => $newTokenHash - ]; - return $this->respond($data); - } - else { - return $this->failUnauthorized('Invalid request', 403); - } - } -} - \ No newline at end of file diff --git a/ci4/app/Controllers/Presupuestos/Presupuestoadmin.php b/ci4/app/Controllers/Presupuestos/Presupuestoadmin.php index 5039d115..5fe536da 100755 --- a/ci4/app/Controllers/Presupuestos/Presupuestoadmin.php +++ b/ci4/app/Controllers/Presupuestos/Presupuestoadmin.php @@ -382,6 +382,16 @@ class Presupuestoadmin extends \App\Controllers\BaseResourceController 'descripcion' => $linea_pedido->concepto ]); + // se actualiza el totalizador del pedido + $total_tirada = $pedidoModel + ->selectSum('cantidad') + ->where('pedido_id', $idPedido) + ->first()->cantidad; + $pedidoModel = model('App\Models\Pedidos\PedidoModel'); + $pedidoModel->update($idPedido, [ + 'total_tirada' => $total_tirada + ]); + // se actualiza la factura $linea_pedido = $this->model->generarLineaPedido($id, true, $idPedido)[0]; $facturaLineaModel = model('App\Models\Facturas\FacturaLineaModel'); diff --git a/ci4/app/Database/Migrations/2025-04-14-193000_CreateEnviosTable.php b/ci4/app/Database/Migrations/2025-04-14-193000_CreateEnviosTable.php new file mode 100644 index 00000000..3ce4cc6d --- /dev/null +++ b/ci4/app/Database/Migrations/2025-04-14-193000_CreateEnviosTable.php @@ -0,0 +1,104 @@ +forge->addField([ + 'id' => [ + 'type' => 'INT', + 'unsigned' => true, + 'auto_increment' => true, + ], + 'finalizado' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + ], + 'codigo_seguimiento' => [ + 'type' => 'VARCHAR', + 'constraint' => 100, + 'null' => true, + ], + 'proveedor_id' => [ + 'type' => 'INT', + 'unsigned' => true, + 'null' => true, + ], + 'comentarios' => [ + 'type' => 'TEXT', + 'null' => true, + ], + 'att' => [ + 'type' => 'VARCHAR', + 'constraint' => 100, + 'null' => true, + ], + 'direccion' => [ + 'type' => 'VARCHAR', + 'constraint' => 300, + 'null' => true, + ], + 'ciudad' => [ + 'type' => 'VARCHAR', + 'constraint' => 100, + 'null' => true, + ], + 'cp' => [ + 'type' => 'VARCHAR', + 'constraint' => 10, + 'null' => true, + ], + 'email' => [ + 'type' => 'VARCHAR', + 'constraint' => 150, + 'null' => true, + ], + 'telefono' => [ + 'type' => 'VARCHAR', + 'constraint' => 60, + 'null' => true, + ], + 'pais_id' => [ + 'type' => 'INT', + 'unsigned' => true, + 'null' => true, + ], + 'mostrar_precios' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + ], + 'mostrar_iva' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + ], + 'created_at' => [ + 'type' => 'TIMESTAMP', + 'null' => false, + 'default' => '0000-00-00 00:00:00', + ], + 'updated_at' => [ + 'type' => 'TIMESTAMP', + 'null' => false, + 'default' => '0000-00-00 00:00:00', + ], + ]); + + $this->forge->addKey('id', true); + $this->forge->addForeignKey('proveedor_id', 'lg_proveedores', 'id', 'SET NULL', 'SET NULL'); + $this->forge->addForeignKey('pais_id', 'lg_paises', 'id', 'SET NULL', 'SET NULL'); + + $this->forge->createTable('envios'); + } + + public function down() + { + $this->forge->dropTable('envios'); + } +} diff --git a/ci4/app/Database/Migrations/2025-04-16-193000_AddEnvioColumns.php b/ci4/app/Database/Migrations/2025-04-16-193000_AddEnvioColumns.php new file mode 100644 index 00000000..039609e1 --- /dev/null +++ b/ci4/app/Database/Migrations/2025-04-16-193000_AddEnvioColumns.php @@ -0,0 +1,29 @@ +forge->addColumn("envios", + ["multienvio" => [ + "type" => "TINYINT", + "unsigned" => true, + "null" => false, + "default" => 0, + ]] + ); + + + } + + public function down() + { + $this->forge->dropColumn("envios", ['multienvio']); + + } +} diff --git a/ci4/app/Database/Migrations/2025-04-18-100000_AddEnviosLineas.php b/ci4/app/Database/Migrations/2025-04-18-100000_AddEnviosLineas.php new file mode 100644 index 00000000..e2ce8bbf --- /dev/null +++ b/ci4/app/Database/Migrations/2025-04-18-100000_AddEnviosLineas.php @@ -0,0 +1,41 @@ +forge->addField([ + 'id' => ['type' => 'INT', 'auto_increment' => true], + 'envio_id' => ['type' => 'INT', 'unsigned' => true], + 'pedido_id' => ['type' => 'INT', 'unsigned' => true], + 'presupuesto_id' => ['type' => 'INT', 'unsigned' => true], + 'unidades_envio' => ['type' => 'INT', 'default' => 0], + 'unidades_total' => ['type' => 'INT', 'default' => 0], + 'cajas' => ['type' => 'INT', 'default' => 0], + 'unidades_cajas' => ['type' => 'INT', 'default' => 0], + 'created_at' => ['type' => 'DATETIME', 'null' => true], + 'updated_at' => ['type' => 'DATETIME', 'null' => true], + 'created_by' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + 'updated_by' => ['type' => 'INT', 'unsigned' => true, 'null' => true], + ]); + + $this->forge->addKey('id', true); // Primary Key + + // Foreign Keys + $this->forge->addForeignKey('presupuesto_id', 'presupuestos', 'id', 'CASCADE', 'CASCADE'); + $this->forge->addForeignKey('pedido_id', 'pedidos', 'id', 'CASCADE', 'CASCADE'); + $this->forge->addForeignKey('created_by', 'users', 'id', 'SET NULL', 'CASCADE'); + $this->forge->addForeignKey('updated_by', 'users', 'id', 'SET NULL', 'CASCADE'); + + $this->forge->createTable('envios_lineas'); + } + + public function down() + { + $this->forge->dropTable('envios_lineas'); + } +} diff --git a/ci4/app/Database/Migrations/2025-04-20-101500_ModifyAlbaranesAndAlbaranesLineas.php b/ci4/app/Database/Migrations/2025-04-20-101500_ModifyAlbaranesAndAlbaranesLineas.php new file mode 100644 index 00000000..ed1b8ebd --- /dev/null +++ b/ci4/app/Database/Migrations/2025-04-20-101500_ModifyAlbaranesAndAlbaranesLineas.php @@ -0,0 +1,98 @@ +forge->dropColumn('albaranes', [ + 'pedido_id', + 'presupuesto_id', + 'presupuesto_direccion_id', + 'total' + ]); + + $this->forge->addColumn('albaranes', [ + 'fecha_albaran' => [ + 'type' => 'DATE', + 'null' => true, + 'after' => 'numero_albaran' + ], + 'envio_id' => [ + 'type' => 'INT', + 'constraint' => 10, + 'unsigned' => true, + 'null' => true, + 'after' => 'fecha_albaran' + ] + ]); + + // Añadir foreign key a envios con ON DELETE SET NULL + $this->db->query('ALTER TABLE `albaranes` + ADD CONSTRAINT `fk_albaranes_envio_id` FOREIGN KEY (`envio_id`) + REFERENCES `envios`(`id`) ON DELETE SET NULL ON UPDATE CASCADE'); + + // --- Tabla albaranes_lineas --- + $this->forge->dropColumn('albaranes_lineas', ['cajas', 'ejemplares_por_caja']); + + $this->forge->addColumn('albaranes_lineas', [ + 'iva_reducido' => [ + 'type' => 'TINYINT', + 'constraint' => 1, + 'default' => 0, + 'null' => false, + 'after' => 'precio_unidad' + ] + ]); + } + + public function down() + { + // Deshacer cambios tabla albaranes + $this->forge->dropForeignKey('albaranes', 'fk_albaranes_envio_id'); + $this->forge->dropColumn('albaranes', ['envio_id', 'fecha_albaran']); + + $this->forge->addColumn('albaranes', [ + 'pedido_id' => [ + 'type' => 'INT', + 'constraint' => 10, + 'unsigned' => true, + 'null' => true, + ], + 'presupuesto_id' => [ + 'type' => 'INT', + 'constraint' => 10, + 'unsigned' => true, + 'null' => true, + ], + 'presupuesto_direccion_id' => [ + 'type' => 'INT', + 'constraint' => 10, + 'unsigned' => true, + 'null' => true, + ], + 'total' => [ + 'type' => 'DOUBLE', + 'null' => true, + ], + ]); + + // Deshacer cambios tabla albaranes_lineas + $this->forge->dropColumn('albaranes_lineas', ['iva_reducido']); + + $this->forge->addColumn('albaranes_lineas', [ + 'cajas' => [ + 'type' => 'INT', + 'null' => true, + ], + 'ejemplares_por_caja' => [ + 'type' => 'INT', + 'null' => true, + ], + ]); + } +} diff --git a/ci4/app/Database/Migrations/2025-04-20-111500_AddClienteIdToEnvios.php b/ci4/app/Database/Migrations/2025-04-20-111500_AddClienteIdToEnvios.php new file mode 100644 index 00000000..71faaf82 --- /dev/null +++ b/ci4/app/Database/Migrations/2025-04-20-111500_AddClienteIdToEnvios.php @@ -0,0 +1,29 @@ +forge->addColumn('envios', [ + 'cliente_id' => [ + 'type' => 'INT', + 'constraint' => 11, + 'unsigned' => true, // IMPORTANTE + 'null' => true, + 'after' => 'id', + ], + ]); + + $this->db->query('ALTER TABLE envios ADD CONSTRAINT fk_envios_cliente FOREIGN KEY (cliente_id) REFERENCES clientes(id) ON DELETE SET NULL ON UPDATE CASCADE'); + } + + public function down() + { + $this->db->query('ALTER TABLE envios DROP FOREIGN KEY fk_envios_cliente'); + $this->forge->dropColumn('envios', 'cliente_id'); + } +} diff --git a/ci4/app/Database/Migrations/2025-04-20-124400_RenameCajasNull.php b/ci4/app/Database/Migrations/2025-04-20-124400_RenameCajasNull.php new file mode 100644 index 00000000..c767466f --- /dev/null +++ b/ci4/app/Database/Migrations/2025-04-20-124400_RenameCajasNull.php @@ -0,0 +1,32 @@ +forge->modifyColumn('envios_lineas', [ + 'cajas' => [ + 'type' => 'INT', + 'constraint' => 11, + 'null' => true, + 'default' => null, + ], + ]); + } + + public function down() + { + $this->forge->modifyColumn('envios_lineas', [ + 'cajas' => [ + 'type' => 'INT', + 'constraint' => 11, + 'null' => false, + 'default' => 0, + ], + ]); + } +} diff --git a/ci4/app/Database/Migrations/2025-04-20-203000_update_envios_albaranes.php b/ci4/app/Database/Migrations/2025-04-20-203000_update_envios_albaranes.php new file mode 100644 index 00000000..b77e5e86 --- /dev/null +++ b/ci4/app/Database/Migrations/2025-04-20-203000_update_envios_albaranes.php @@ -0,0 +1,90 @@ +forge->dropColumn('envios_lineas', ['cajas', 'unidades_cajas']); + + // 2. Añadir columna 'cajas' en envios + $this->forge->addColumn('envios', [ + 'cajas' => [ + 'type' => 'INT', + 'constraint' => 11, + 'default' => 0, + 'after' => 'comentarios' + ] + ]); + + // 2. Quitar columna multienvio de envios + $this->forge->dropColumn('envios', 'multienvio'); + + // 3. Añadir columna 'cajas' en albaranes + $this->forge->addColumn('albaranes', [ + 'cajas' => [ + 'type' => 'INT', + 'constraint' => 11, + 'default' => 0, + 'after' => 'envio_id' + ] + ]); + + // 4. Añadir columna 'pedido_linea_id' a albaranes_lineas + $this->forge->addColumn('albaranes_lineas', [ + 'pedido_linea_id' => [ + 'type' => 'INT', + 'constraint' => 11, + 'unsigned' => true, + 'null' => true, + 'after' => 'albaran_id' + ] + ]); + + // 5. Foreign key a pedidos_lineas + $this->db->query(" + ALTER TABLE albaranes_lineas + ADD CONSTRAINT fk_albaranes_lineas_pedido_linea + FOREIGN KEY (pedido_linea_id) REFERENCES pedidos_linea(id) + ON DELETE SET NULL ON UPDATE CASCADE + "); + } + + public function down() + { + // Revertir cajas en envios_lineas + $this->forge->addColumn('envios_lineas', [ + 'cajas' => [ + 'type' => 'INT', + 'constraint' => 11, + 'null' => true, + ], + 'unidades_cajas' => [ + 'type' => 'INT', + 'constraint' => 11, + 'null' => true, + ] + ]); + + $this->forge->addColumn('envios', [ + 'multienvio' => [ + 'type' => 'TINYINT', + 'constraint' => 3, + 'unsigned' => true, + 'default' => 0 + ] + ]); + + // Quitar columnas añadidas + $this->forge->dropColumn('envios', 'cajas'); + $this->forge->dropColumn('albaranes', 'cajas'); + + // Quitar foreign y columna pedido_linea_id + $this->db->query("ALTER TABLE albaranes_lineas DROP FOREIGN KEY fk_albaranes_lineas_pedido_linea"); + $this->forge->dropColumn('albaranes_lineas', 'pedido_linea_id'); + } +} diff --git a/ci4/app/Database/Migrations/2025-04-20-210000_FixDeletedAtToDatetime .php b/ci4/app/Database/Migrations/2025-04-20-210000_FixDeletedAtToDatetime .php new file mode 100644 index 00000000..1ab51870 --- /dev/null +++ b/ci4/app/Database/Migrations/2025-04-20-210000_FixDeletedAtToDatetime .php @@ -0,0 +1,28 @@ +db->query("ALTER TABLE {$tabla} MODIFY COLUMN deleted_at DATETIME NULL"); + } + } + + public function down() + { + // Opcional: puedes restaurar como TIMESTAMP NULL si lo deseas + $tablas = ['albaranes', 'albaranes_lineas', 'envios', 'envios_lineas']; + + foreach ($tablas as $tabla) { + $this->db->query("ALTER TABLE {$tabla} MODIFY COLUMN deleted_at TIMESTAMP NULL"); + } + } +} diff --git a/ci4/app/Entities/Pedidos/AlbaranEntity.php b/ci4/app/Entities/Albaranes/AlbaranEntity.php similarity index 84% rename from ci4/app/Entities/Pedidos/AlbaranEntity.php rename to ci4/app/Entities/Albaranes/AlbaranEntity.php index bdff8334..b5928c10 100755 --- a/ci4/app/Entities/Pedidos/AlbaranEntity.php +++ b/ci4/app/Entities/Albaranes/AlbaranEntity.php @@ -1,5 +1,5 @@ null, - 'pedido_id' => null, - 'presupuesto_id' => null, - 'presupuesto_direccion_id' => null, + 'envio_id' => null, 'cliente_id' => null, 'serie_id' => null, 'numero_albaran' => null, 'mostrar_precios' => null, - 'total' => null, 'direccion_albaran' => null, 'att_albaran' => null, + 'fecha_albaran' => null, 'user_created_id' => null, 'user_updated_id' => null, 'created_at' => null, 'updated_at' => null, 'deleted_at' => null, + 'cajas' => null, ]; protected $dates = ['created_at', 'updated_at', 'deleted_at']; protected $casts = [ 'id' => 'integer', - 'pedido_id' => '?integer', + 'envio_id' => '?integer', 'presupuesto_id' => '?integer', 'presupuesto_direccion_id' => '?integer', 'cliente_id' => '?integer', @@ -40,6 +39,7 @@ class AlbaranEntity extends \CodeIgniter\Entity\Entity 'att_albaran' => '?string', 'user_created_id' => 'integer', 'user_updated_id' => 'integer', + 'fecha_albaran' => '?datetime', ]; // Agrega tus métodos personalizados aquí diff --git a/ci4/app/Entities/Pedidos/AlbaranLineaEntity.php b/ci4/app/Entities/Albaranes/AlbaranLineaEntity.php similarity index 83% rename from ci4/app/Entities/Pedidos/AlbaranLineaEntity.php rename to ci4/app/Entities/Albaranes/AlbaranLineaEntity.php index c2137df8..fc800c64 100755 --- a/ci4/app/Entities/Pedidos/AlbaranLineaEntity.php +++ b/ci4/app/Entities/Albaranes/AlbaranLineaEntity.php @@ -1,5 +1,5 @@ null, 'albaran_id' => null, + 'pedido_linea_id' => null, 'titulo' => null, 'isbn' => null, 'ref_cliente' => null, 'cantidad' => null, - 'cajas' => null, - 'ejemplares_por_caja' => null, 'precio_unidad' => null, 'total' => null, + 'iva_reducido' => null, 'user_created_id' => null, 'user_updated_id' => null, 'created_at' => null, @@ -26,14 +26,14 @@ class AlbaranLineaEntity extends \CodeIgniter\Entity\Entity protected $casts = [ 'id' => 'integer', 'albaran_id' => '?integer', + 'pedido_linea_id' => '?integer', 'titulo' => 'string', 'isbn' => '?string', 'ref_cliente' => '?string', 'cantidad' => '?integer', - 'cajas' => '?integer', - 'ejemplares_por_caja' => '?integer', 'precio_unidad' => 'float', 'total' => 'float', + 'iva_reducido' => '?boolean', 'user_created_id' => 'integer', 'user_updated_id' => 'integer', ]; diff --git a/ci4/app/Entities/Logistica/EnvioEntity.php b/ci4/app/Entities/Logistica/EnvioEntity.php new file mode 100644 index 00000000..e6bef114 --- /dev/null +++ b/ci4/app/Entities/Logistica/EnvioEntity.php @@ -0,0 +1,35 @@ + 0, + 'mostrar_precios' => 0, + 'mostrar_iva' => 0, + ]; + + protected $casts = [ + 'id' => 'int', + 'finalizado' => 'boolean', + 'codigo_seguimiento'=> 'string', + 'proveedor_id' => 'int', + 'cliente_id' => 'int', + 'comentarios' => 'string', + 'att' => 'string', + 'direccion' => 'string', + 'ciudad' => 'string', + 'cp' => 'string', + 'email' => 'string', + 'telefono' => 'string', + 'pais_id' => 'int', + 'mostrar_precios' => 'boolean', + 'mostrar_iva' => 'boolean', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'cajas' => 'int', + ]; +} diff --git a/ci4/app/Entities/Logistica/EnvioLineaEntity.php b/ci4/app/Entities/Logistica/EnvioLineaEntity.php new file mode 100644 index 00000000..2ab1a749 --- /dev/null +++ b/ci4/app/Entities/Logistica/EnvioLineaEntity.php @@ -0,0 +1,21 @@ + 'int', + 'envio_id' => 'int', + 'pedido_id' => 'int', + 'presupuesto_id' => 'int', + 'unidades_envio' => 'int', + 'unidades_total' => 'int', + 'created_by' => 'int', + 'updated_by' => 'int', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; +} diff --git a/ci4/app/Language/es/Albaran.php b/ci4/app/Language/es/Albaran.php new file mode 100644 index 00000000..31966e67 --- /dev/null +++ b/ci4/app/Language/es/Albaran.php @@ -0,0 +1,31 @@ + 'Fecha de creación', + "fechaAlbaran" => 'Fecha de albarán', + 'numEnvio' => 'Número de envío', + 'cliente' => 'Cliente', + 'albaran' => 'Albarán', + 'att' => 'Att', + 'direccion' => 'Dirección', + 'cajas' => 'Cajas', + + 'unidades' => 'Unidades', + 'titulo' => 'Título', + 'ISBN' => 'ISBN', + 'refCliente' => 'Ref. cliente', + 'precioU' => 'Precio/Unidad', + 'subtotal' => 'Subtotal', + 'pedido' => 'Pedido', + + 'mostrarPrecios' => 'Mostrar precios', + 'addIva' => 'Añadir IVA', + 'nuevaLinea' => 'Nueva línea', + 'imprimirAlbaran' => 'Imprimir albarán', + 'borrarAlbaran' => 'Borrar albarán', + 'borrarAlbaranConfirm' => '¿Está seguro de que desea borrar el albarán?', + 'borrar' => 'Borrar', + 'cancelar' => 'Cancelar', + + 'iva4' => 'IVA 4%', + 'iva21' => 'IVA 21%', +]; \ No newline at end of file diff --git a/ci4/app/Language/es/Logistica.php b/ci4/app/Language/es/Logistica.php index 3885004a..c9eaf9c2 100755 --- a/ci4/app/Language/es/Logistica.php +++ b/ci4/app/Language/es/Logistica.php @@ -9,4 +9,60 @@ return [ 'etiquetasEnvio' => 'Etiquetas de envío', 'envioFerros' => 'Envío de ferros', 'cerrarOTauto' => 'Cerrar OT automáticamente', + 'envioSimpleMultiple' => 'Envío simple/múltiple', + 'nuevoEnvio' => 'Nuevo envío', + 'buscadorPedidosTitle' => 'Código Pedido o ISBN', + 'buscadorPedidosTitle2' => 'Código Pedido o título', + 'listadoEnvios' => 'Listado de envíos', + 'idEnvio' => 'ID Envío', + 'numeroPedidos' => 'Nº Pedidos', + 'numeroLineas' => 'Nº Líneas', + 'att' => 'Att', + 'direccion' => 'Dirección', + 'ciudad' => 'Ciudad', + 'pais' => 'País', + 'cp' => 'CP', + 'email' => 'Email', + 'telefono' => 'Teléfono', + 'finalizado' => 'Finalizado', + 'acciones' => 'Acciones', + 'backToPanel' => 'Volver al panel', + 'no' => 'No', + 'si' => 'Sí', + + 'envio' => 'Envío', + 'addLineasEnvio' => 'Añadir líneas al envío', + 'addLineasText'=> 'La siguiente lista muestra los envíos del cliente a la misma dirección de envío. Si desea añadir líneas a un envío existente, seleccione el envío y haga clic en "Añadir líneas al envío". Si desea crear un nuevo envío, haga clic en "Añadir".', + 'add' => 'Añadir', + + 'datosEnvio' => 'Datos del envío', + 'lineasEnvio' => 'Líneas del envío', + 'comentariosEnvio' => 'Comentarios del envío', + 'guardar' => 'Guardar', + 'totales' => 'Totales', + 'cajas' => 'Cajas', + + 'pedido' => 'Pedido', + 'presupuesto' => 'Presupuesto', + 'unidadesEnvio' => 'Unidades envío', + 'unidadesEnviadas' => 'Unidades enviadas', + 'titulo' => 'Título', + 'unidadesTotales' => 'Total unidades', + 'eliminar' => 'Eliminar', + 'generarAlbaran' => 'Generar albarán', + 'imprimirEtiquetas' => 'Imprimir etiquetas', + 'buttonsActions' => 'Acciones sobre las filas seleccionadas', + 'addCaja' => 'Añadir caja', + 'numCaja' => 'Número de caja', + 'selectAll' => 'Seleccionar todo', + 'peso' => 'Peso (kg): ', + 'unidadesTotalesFooter' => 'Unidades:', + + 'errors' => [ + 'noEnvio' => 'No se ha encontrado el envio', + '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', + 'noAddresses' => 'El pedido no tiene direcciones de envío', + ], + ]; \ No newline at end of file diff --git a/ci4/app/Models/Albaranes/AlbaranLineaModel.php b/ci4/app/Models/Albaranes/AlbaranLineaModel.php new file mode 100755 index 00000000..0cc160d5 --- /dev/null +++ b/ci4/app/Models/Albaranes/AlbaranLineaModel.php @@ -0,0 +1,85 @@ +db + ->table($this->table . " t1") + ->select( + "t1.id, t1.titulo as titulo, t1.isbn as isbn, t1.ref_cliente as ref_cliente, + t1.cantidad as unidades, t1.precio_unidad as precio_unidad, t1.iva_reducido as iva_reducido, + t1.total as total, pedidos.id AS pedido" + ) + ->join("pedidos_linea", "t1.pedido_linea_id = pedidos_linea.id", "left") + ->join("pedidos", "pedidos_linea.pedido_id = pedidos.id", "left"); + + + $builder->where("t1.deleted_at IS NULL"); + $builder->where("t1.albaran_id", $albaran_id); + + return $builder; + } + + public function getDatatableQuery($albaran_id = null) + { + $builder = $this->db + ->table($this->table . " t1") + ->select( + "t1.id, t1.titulo as titulo, t1.isbn as isbn, t1.ref_cliente as ref_cliente, + t1.cantidad as unidades, t1.precio_unidad as precio_unidad, t1.iva_reducido as iva_reducido, + t1.total as total, pedidos.id AS pedido" + ) + ->join("pedidos_linea", "t1.pedido_linea_id = pedidos_linea.id", "left") + ->join("pedidos", "pedidos_linea.pedido_id = pedidos.id", "left"); + + $builder->where("t1.deleted_at IS NULL"); + $builder->where("t1.albaran_id", $albaran_id); + + return $builder; + } + +} \ No newline at end of file diff --git a/ci4/app/Models/Albaranes/AlbaranModel.php b/ci4/app/Models/Albaranes/AlbaranModel.php new file mode 100644 index 00000000..42b492f2 --- /dev/null +++ b/ci4/app/Models/Albaranes/AlbaranModel.php @@ -0,0 +1,206 @@ +user()->id; + + if (!$envio_id || !$envio_lineas) { + return [ + 'status' => false + ]; + } + + // el albaran es para el mismo cliente, por lo que se obtiene el cliente_id de la primera_linea + $cliente_id = $this->db->table('envios_lineas') + ->select('presupuestos.cliente_id') + ->join('presupuestos', 'presupuestos.id = envios_lineas.presupuesto_id') + ->where('envios_lineas.id', $envio_lineas[0]) + ->get() + ->getRow()->cliente_id; + + // se genera el numero de albaran + $model_series = model('App\Models\Configuracion\SeriesFacturasModel'); + $serie = $model_series->find(11); + $numero_albaran = str_replace('{number}', $serie->next, $serie->formato); + $numero_albaran = str_replace('{year}', date("Y"), $numero_albaran); + $serie->next = $serie->next + 1; + $model_series->save($serie); + + // Se genera el albaran con los datos del envio + $model_envio = model('App\Models\Logistica\EnvioModel'); + $envio = $model_envio->find($envio_id); + $data = [ + 'envio_id' => $envio->id, + 'cliente_id' => $cliente_id, + 'serie_id' => 11, // Serie de albaranes + 'numero_albaran' => $numero_albaran, + 'mostrar_precios' => 0, + 'direccion_albaran' => $envio->direccion, + 'att_albaran' => $envio->att, + 'user_created_id' => $user_id, + 'cajas' => $cajas, + ]; + $id_albaran = $this->insert($data); + if(!$id_albaran) { + return [ + 'status' => false + ]; + } + + // Se generan las lineas del albaran + $model_albaran_linea = model('App\Models\Albaranes\AlbaranLineaModel'); + $albaran_linea = []; + foreach ($envio_lineas as $linea) { + $modelLineaEnvio = model('App\Models\Logistica\EnvioLineaModel'); + $datosLinea = $this->db->table('envios_lineas') + ->select('presupuestos.titulo as titulo, presupuestos.isbn as isbn, presupuestos.referencia_cliente as ref_cliente, + envios_lineas.unidades_envio as cantidad, presupuestos.total_precio_unidad as precio_unidad, presupuestos.iva_reducido as iva_reducido, + ROUND(envios_lineas.unidades_envio * presupuestos.total_precio_unidad, 2) as total, pedidos_linea.id as pedido_linea_id') + ->join('presupuestos', 'presupuestos.id = envios_lineas.presupuesto_id') + ->join('pedidos', 'pedidos.id = envios_lineas.pedido_id') + ->join('pedidos_linea', 'pedidos_linea.pedido_id = pedidos.id') + ->where('envios_lineas.id', $linea) + ->get() + ->getRow(); + $linea = $modelLineaEnvio->find($linea); + if (!$linea) { + continue; + } + $albaran_linea = [ + 'albaran_id' => $id_albaran, + 'titulo' => $datosLinea->titulo, + 'isbn' => $datosLinea->isbn, + 'ref_cliente' => $datosLinea->ref_cliente, + 'cantidad' => $datosLinea->cantidad, + 'precio_unidad' => $datosLinea->precio_unidad, + 'iva_reducido' => $datosLinea->iva_reducido, + 'total' => $datosLinea->total, + 'user_created_id' => $user_id, + 'user_updated_id' => $user_id, + 'pedido_linea_id' => $datosLinea->pedido_linea_id, + + ]; + $model_albaran_linea->insert($albaran_linea); + } + + $albaran_data = $this->db->table('albaranes t1') + ->select(" + t1.id, + t1.att_albaran AS att, + t1.direccion_albaran AS direccion, + t1.envio_id, + t1.numero_albaran AS numero_albaran, + DATE_FORMAT(t1.created_at, '%d/%m/%Y') AS fecha_creacion, + DATE_FORMAT(t1.fecha_albaran, '%d/%m/%Y') AS fecha_albaran, + t1.mostrar_precios AS mostrar_precios, + t1.cajas AS cajas, + ") + ->where('t1.id', $id_albaran) + ->get() + ->getResultObject(); + $modelCliente = model('App\Models\Clientes\ClienteModel'); + $cliente = $modelCliente->find($cliente_id); + $albaran_data[0]->cliente = $cliente->nombre; + + return [ + 'status' => true, + 'albaran' => $albaran_data[0], + ]; + } + + public function getAlbaranesEnvio($envio_id=null){ + if (!$envio_id) { + return []; + } + + $albaran_data = $this->db->table('albaranes t1') + ->select(" + t1.id, + t1.att_albaran AS att, + t1.direccion_albaran AS direccion, + t1.envio_id, + t1.numero_albaran AS numero_albaran, + DATE_FORMAT(t1.created_at, '%d/%m/%Y') AS fecha_creacion, + DATE_FORMAT(t1.fecha_albaran, '%d/%m/%Y') AS fecha_albaran, + t1.mostrar_precios AS mostrar_precios, + t2.nombre AS cliente, + t1.cajas AS cajas + ") + ->join('clientes t2', 't1.cliente_id = t2.id', 'left') + ->where('t1.envio_id', $envio_id) + ->where('t1.deleted_at IS NULL') + ->get() + ->getResultObject(); + return $albaran_data; + } + + /** + * Get resource data for creating PDFs. + * + * @param string $search + * + * @return \CodeIgniter\Database\BaseBuilder + */ + public function getResourceForPdf($albaran_id = -1) + { + $builder = $this->db + ->table($this->table . " t1") + ->select(" + t1.id, + t1.att_albaran AS att, + t1.direccion_albaran AS direccion, + t1.envio_id, + t1.numero_albaran AS numero_albaran, + DATE_FORMAT(t1.created_at, '%d/%m/%Y') AS fecha_creacion, + DATE_FORMAT(t1.fecha_albaran, '%d/%m/%Y') AS fecha_albaran, + t1.mostrar_precios AS mostrar_precios, + t2.nombre AS cliente, + t1.cajas AS cajas + ") ; + $builder->join("clientes t2", "t1.cliente_id = t2.id", "left"); + + $builder->where("t1.deleted_at IS NULL"); + $builder->where("t1.id", $albaran_id); + + return $builder; + } +} \ No newline at end of file diff --git a/ci4/app/Models/Logistica/EnvioLineaModel.php b/ci4/app/Models/Logistica/EnvioLineaModel.php new file mode 100644 index 00000000..420b4ae6 --- /dev/null +++ b/ci4/app/Models/Logistica/EnvioLineaModel.php @@ -0,0 +1,64 @@ +db + ->table($this->table . " t1") + ->select( + "t1.id, t1.pedido_id as pedido, t3.id as presupuesto, + t3.titulo as titulo, t1.unidades_envio as unidadesEnvio, t1.unidades_envio as unidadesEnvioRaw, + t1.unidades_total as unidadesTotal, + IFNULL(( + SELECT SUM(t_sub.unidades_envio) + FROM " . $this->table . " t_sub + 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 + AND t_sub.pedido_id = t1.pedido_id + AND e.direccion = d.direccion COLLATE utf8mb3_general_ci + ), 0) as unidadesEnviadas, + IFNULL(( + SELECT ROUND(SUM(peso) / 1000, 1) + FROM presupuesto_linea + WHERE presupuesto_id = t3.id + ), 0) AS pesoUnidad" + ); + $builder->join("presupuestos t3", "t1.presupuesto_id = t3.id", "left"); + + $builder->where("t1.envio_id", $envio_id); + + return $builder; + } + + +} diff --git a/ci4/app/Models/Logistica/EnvioModel.php b/ci4/app/Models/Logistica/EnvioModel.php new file mode 100644 index 00000000..b0a60026 --- /dev/null +++ b/ci4/app/Models/Logistica/EnvioModel.php @@ -0,0 +1,56 @@ +db + ->table($this->table . " t1") + ->select( + "t1.id, GROUP_CONCAT(DISTINCT t2.pedido_id) AS pedidos, + COUNT(t2.id) AS num_lineas, + t1.att, t1.direccion, t1.ciudad, t3.nombre as pais, t1.cp, t1.email, t1.telefono, t1.finalizado" + ); + $builder->join("envios_lineas t2", "t2.envio_id = t1.id", "left"); + $builder->join("lg_paises t3", "t3.id = t1.pais_id", "left"); + + $builder->groupBy("t1.id"); + return $builder; + } +} diff --git a/ci4/app/Models/Pedidos/AlbaranLineaModel.php b/ci4/app/Models/Pedidos/AlbaranLineaModel.php deleted file mode 100755 index 9253b2a2..00000000 --- a/ci4/app/Models/Pedidos/AlbaranLineaModel.php +++ /dev/null @@ -1,66 +0,0 @@ -db - - ->table($this->table . " t1") - ->select( - "t1.id AS id, t1.albaran_id AS albaran_id, t1.titulo AS titulo, t1.isbn AS isbn, - t1.ref_cliente AS ref_cliente, t1.cantidad AS cantidad, t1.cajas AS cajas, - t1.ejemplares_por_caja AS ejemplares_por_caja, t1.precio_unidad AS precio_unidad, - t1.total AS total" - ); - - $builder->where("t1.deleted_at IS NULL"); - $builder->where("t1.albaran_id", $albaran_id); - - return $builder; - } - -} \ No newline at end of file diff --git a/ci4/app/Models/Pedidos/AlbaranModel.php b/ci4/app/Models/Pedidos/AlbaranModel.php deleted file mode 100755 index 5ac511e2..00000000 --- a/ci4/app/Models/Pedidos/AlbaranModel.php +++ /dev/null @@ -1,161 +0,0 @@ -find($presupuestos_id); - - $return_data = []; - - foreach ($presupuestos as $presupuesto) { - - $envios = $model_presupuesto_direcciones->where('presupuesto_id', $presupuesto->id)->findAll(); - - foreach($envios as $envio){ - - // se buscan los albaranes en este presupuesto con la misma direccion y con el mismo presupuesto_id en albaran - // en albaran linea para obtener la cantidad total enviada - $model_albaran = model('App\Models\Pedidos\AlbaranModel'); - $model_albaran_linea = model('App\Models\Pedidos\AlbaranLineaModel'); - $albaranes = $model_albaran->where('presupuesto_id', $presupuesto->id) - ->where('presupuesto_direccion_id', $envio->id)->findAll(); - // se suman las cantidades de los albaranes - $cantidad_enviada = 0; - foreach($albaranes as $albaran){ - $lineas = $model_albaran_linea->where('albaran_id', $albaran->id)->findAll(); - foreach($lineas as $linea){ - $cantidad_enviada += $linea->cantidad; - } - } - - if($cantidad_enviada >= intval($envio->cantidad)){ - continue; - } - // calculo precio_unidad - $precio_unidad = $presupuesto->total_aceptado/$presupuesto->tirada; - - $albaran_linea = []; - $albaran_linea = [ - 'titulo' => $presupuesto->titulo, - 'isbn' => $presupuesto->isbn, - 'ref_cliente' => $presupuesto->ref_cliente, - 'cantidad' => intval($envio->cantidad)-$cantidad_enviada, - 'cajas' => 1, - 'ejemplares_por_caja' => intval($envio->cantidad)-$cantidad_enviada, - 'precio_unidad' => $precio_unidad, - 'total' => $precio_unidad * $envio->cantidad, - 'user_created_id' => $user_id, - 'user_updated_id' => $user_id, - ]; - - - $serie = $model_series->find(11); - $numero_albaran = str_replace('{number}', $serie->next, $serie->formato); - $numero_albaran = str_replace( '{year}', date("Y"), $numero_albaran); - - $serie->next = $serie->next + 1; - $model_series->save($serie); - - $albaran = [ - 'pedido_id' => $pedido_id, - 'presupuesto_id' => $presupuesto->id, - 'presupuesto_direccion_id' => $envio->id, - 'cliente_id' => $presupuesto->cliente_id, - 'serie_id' => 11, // Serie de albaranes - 'numero_albaran' => $numero_albaran, - 'mostrar_precios' => 0, - 'total' => $albaran_linea['total'], - 'direccion_albaran' => $envio->direccion, - 'att_albaran' => $envio->att, - 'user_created_id' => $user_id, - 'user_updated_id' => $user_id, - 'fecha_albaran' => date('d/m/Y'), - ]; - - $id_albaran = $this->insert($albaran); - $model_albaran_linea = model('App\Models\Pedidos\AlbaranLineaModel'); - $albaran['id'] = $id_albaran; - $albaran_linea['albaran_id'] = $id_albaran; - $id_albaran_linea =$model_albaran_linea->insert($albaran_linea); - $albaran_linea['id'] = $id_albaran_linea; - - array_push($return_data, ["albaran"=>$albaran, "lineas" =>[$albaran_linea]]); - } - } - - return $return_data; - } - - /** - * Get resource data for creating PDFs. - * - * @param string $search - * - * @return \CodeIgniter\Database\BaseBuilder - */ - public function getResourceForPdf($albaran_id = -1) - { - $builder = $this->db - - ->table($this->table . " t1") - ->select( - "t1.id AS id, t1.pedido_id AS pedido_id, t1.presupuesto_id AS presupuesto_id, - t1.presupuesto_direccion_id AS presupuesto_direccion_id, t1.cliente_id AS cliente_id, - t1.serie_id AS serie_id, t1.numero_albaran AS numero_albaran, t1.mostrar_precios AS mostrar_precios, - t1.total AS total, t1.direccion_albaran AS direccion_albaran, t1.att_albaran AS att_albaran, - t1.user_created_id AS user_created_id, t1.user_updated_id AS user_updated_id, - t1.created_at AS created_at, t1.updated_at AS updated_at, - t2.nombre AS cliente" - ); - $builder->join("clientes t2", "t1.cliente_id = t2.id", "left"); - - $builder->where("t1.deleted_at IS NULL"); - $builder->where("t1.id", $albaran_id); - - return $builder; - } -} \ No newline at end of file diff --git a/ci4/app/Services/LogisticaService.php b/ci4/app/Services/LogisticaService.php new file mode 100644 index 00000000..3cbab564 --- /dev/null +++ b/ci4/app/Services/LogisticaService.php @@ -0,0 +1,287 @@ +builder(); + + $builder->select([ + 'pedidos.id as pedido_id', + 'pedidos_linea.id as linea_id', + 'pedidos_linea.cantidad as cantidad_linea', + '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'); + $builder->join('envios_lineas', 'envios_lineas.pedido_id = pedidos_linea.pedido_id', 'left'); + + $builder->groupStart() + ->where('pedidos.id', $search) + ->whereIn('pedidos.estado', ['finalizado']) + ->orWhere("REPLACE(presupuestos.isbn, '-', '')", $searchClean) + ->groupEnd(); + + $builder->groupBy('pedidos_linea.id'); + $builder->having('IFNULL(SUM(envios_lineas.unidades_envio), 0) < cantidad_linea', null, false); + + $result = $builder->get()->getResult(); + + if (empty($result)) { + $response = [ + 'status' => false, + 'message' => lang('Logistica.errors.notFound'), + ]; + return $response; + } + + $PresupuestoDireccionesModel = model('App\Models\Presupuestos\PresupuestoDireccionesModel'); + $numDirecciones = $PresupuestoDireccionesModel->where('presupuesto_id', $result[0]->presupuesto_id) + ->countAllResults(); + if ($numDirecciones == 0) { + $response = [ + 'status' => false, + 'message' => lang('Logistica.errors.noAddresses'), + ]; + return $response; + } else if ($numDirecciones > 1) { + $multienvio = true; + } + + $response = [ + 'status' => true, + 'data' => $result[0], + ]; + + + $response_envio = LogisticaService::generateEnvio($result[0]->pedido_id, $multienvio); + if ($response_envio['status'] == false) { + $response = [ + 'status' => false, + 'message' => $response_envio['message'], + ]; + return $response; + } else { + $response['data']->id_envio = $response_envio['data']['id_envio']; + $response['data']->multienvio = $response_envio['data']['multienvio']; + } + + return $response; + } + + + public static function findLineaEnvioPorEnvio(int $envio_id) + { + $db = \Config\Database::connect(); + $subCliente = $db->table('envios') + ->select('cliente_id') + ->where('id', $envio_id) + ->getCompiledSelect(); + + $builder = $db->table('envios e_main'); + + $builder->select(" + CONCAT('[', p.id, '] - ', pr.titulo) AS name, + 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 + $builder->join('pedidos p', 'p.id = pl.pedido_id'); + $builder->join('presupuestos pr', 'pr.id = pl.presupuesto_id'); + $builder->where('e_main.id', $envio_id); + $builder->where('p.estado', 'finalizado'); + $builder->where("pr.cliente_id = ($subCliente)", null, false); + + $builder->having('unidades_pendientes >', 0); + $builder->orderBy('name', 'ASC'); + + return $builder; + } + + + public static function addLineaEnvio($envio_id = null, $pedido_id = null, $direccion = null) + { + $modelPedido = model('App\Models\Pedidos\PedidoModel'); + + $builder = $modelPedido->builder(); + + $builder->select(" + pedidos.id as pedido_id, + pedidos_linea.id as linea_id, + pedidos_linea.cantidad as total_unidades, + ( + SELECT IFNULL(SUM(el.unidades_envio), 0) + FROM envios_lineas el + 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'); + $builder->join('envios_lineas', 'envios_lineas.pedido_id = pedidos_linea.pedido_id', 'left'); + + $builder->groupBy('pedidos_linea.id'); + $builder->having('IFNULL(SUM(envios_lineas.unidades_envio), 0) < pedidos_linea.cantidad', null, false); + $builder->where('pedidos.estado', 'finalizado'); + $builder->where('pedidos.id', $pedido_id); + + $result = $builder->get()->getResultObject(); + + if (empty($result)) { + return [ + 'status' => false, + 'message' => lang('Logistica.errors.notFound'), + ]; + } else { + $EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel'); + $EnvioLineasModel->save([ + 'envio_id' => $envio_id, + 'pedido_id' => $result[0]->pedido_id, + 'unidades_envio' => $result[0]->unidades_envio, + 'unidades_total' => $result[0]->total_unidades, + 'cajas' => null, + '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' => $result[0]->presupuesto_id, + ]); + } + + return [ + 'status' => true, + 'data' => [ + 'unidades_envio' => $result[0]->unidades_envio, + 'unidades_enviadas' => $result[0]->unidades_enviadas, + 'total_unidades' => $result[0]->total_unidades, + ] + ]; + } + + + + private static function generateEnvio($pedido_id, $multienvio = false) + { + + $presupuestoDireccionesModel = model('App\Models\Presupuestos\PresupuestoDireccionesModel'); + + if (!$multienvio) { + // 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 - IFNULL(SUM(envios_lineas.unidades_envio), 0) 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('presupuestos', 'pedidos_linea.presupuesto_id = presupuestos.id') + ->join('envios_lineas', 'envios_lineas.pedido_id = pedidos.id', 'left') + ->join('envios', 'envios.id = envios_lineas.envio_id', 'left') + ->where('pedidos.id', $pedido_id) + ->groupBy('presupuesto_direcciones.id') // Necesario por el uso de SUM + ->first(); + + + // se genera un nuevo envio con estos datos + $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 [ + 'status' => false, + 'message' => lang('Logistica.errors.noAddresses'), + ]; + } + + } +} diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php new file mode 100644 index 00000000..d9016dc6 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioEditForm.php @@ -0,0 +1,295 @@ +include("themes/_commonPartialsBs/sweetalert") ?> +include('themes/_commonPartialsBs/datatables') ?> +include("themes/_commonPartialsBs/select2bs5") ?> +extend('themes/vuexy/main/defaultlayout') ?> + + +section('content'); ?> +
+
+
+
+

+
+
+ + + + + + +
+
+

+ +

+ +
+
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+
+
+ +
+
+
+
+ +
+
+

+ +

+ +
+ +
+
+

+
+
+ +
+
+ + +
+
+ +
+
+ +
+
+
+ + +
+
+

+ +

+ +
+
+
+

+
+
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+
+ + +
+
+
+ + +
+
+ +
+ + + +
+
+
+
+
+ +
+ +
+

+ +

+ +
+
+ + +
+ +
+
+
+ + +
+
+
+
+endSection() ?> + +section('css') ?> + + + +"> + +endSection() ?> + +section('additionalExternalJs') ?> + + + + +endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioForm.php b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioForm.php new file mode 100644 index 00000000..8aee1d7a --- /dev/null +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewEnvioForm.php @@ -0,0 +1,97 @@ +include("themes/_commonPartialsBs/sweetalert") ?> +include('themes/_commonPartialsBs/datatables') ?> +extend('themes/vuexy/main/defaultlayout') ?> + +section('content'); ?> +
+
+
+
+

+
+
+ + + +
+

+ +

+ +
+
+ +
+ +
+ + +
+ +
+
+
+
+ + +
+

+ +

+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+
+ +
+
+
+endSection() ?> + + +section('css') ?> + +endSection() ?> + +section('additionalExternalJs') ?> + + +endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewLogisticaSelectEnvios.php b/ci4/app/Views/themes/vuexy/form/logistica/viewLogisticaSelectEnvios.php new file mode 100644 index 00000000..aecb0c00 --- /dev/null +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewLogisticaSelectEnvios.php @@ -0,0 +1,96 @@ +include("themes/_commonPartialsBs/sweetalert") ?> +include('themes/_commonPartialsBs/datatables') ?> +extend('themes/vuexy/main/defaultlayout') ?> + +section('content'); ?> +
+
+
+
+

+
+
+ + + +
+

+ +

+ +
+
+ +
+ +
+ + +
+ +
+
+
+
+ + +
+

+ +

+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+
+ +
+
+ endSection() ?> + + + section('css') ?> + + endSection() ?> + + section('additionalExternalJs') ?> + + + endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/vuexy/form/logistica/viewPanelLogistica.php b/ci4/app/Views/themes/vuexy/form/logistica/viewPanelLogistica.php index 419584a2..4ba6b66c 100755 --- a/ci4/app/Views/themes/vuexy/form/logistica/viewPanelLogistica.php +++ b/ci4/app/Views/themes/vuexy/form/logistica/viewPanelLogistica.php @@ -14,41 +14,43 @@
-
-
-
-
-
-
-
diff --git a/ci4/app/Views/themes/vuexy/form/pedidos/_albaranesItems.php b/ci4/app/Views/themes/vuexy/form/pedidos/_albaranesItems.php index 6a5ba19e..e69de29b 100755 --- a/ci4/app/Views/themes/vuexy/form/pedidos/_albaranesItems.php +++ b/ci4/app/Views/themes/vuexy/form/pedidos/_albaranesItems.php @@ -1,787 +0,0 @@ -
- -
-

- -

- -
-
- - -
-
- - -
- -
- - -
-
- -
-
-
-
- - -section('additionalInlineJs') ?> - - - -$('#generar_albaranes').on('click', function(){ - - var lineasPedido = $('#tableOfLineasPedido').DataTable(); - var presupuestos = lineasPedido.column(0).data().unique().toArray(); - - $.ajax({ - url: '', - type: 'POST', - data: { - pedido_id: id ?>, - presupuestos_id: presupuestos, - : v, - }, - success: function(response){ - - if(response.data.length > 0){ - Object.values(response.data).forEach(function(item){ - generarAlbaran(item); - }); - } - cambios_cantidad_albaranes(); - } - }); -}) - -const deleteLineaBtns = function(data) { - return ` - -
- -
- `; -}; - -function generarAlbaran(item){ - - // Crear los elementos necesarios - const accordion = $('
', { - class: 'accordion accordion-bordered mt-3 accordion-albaran', - id: 'accordioAlbaran' + item.albaran.id, - albaran: item.albaran.id - }); - - const card = $('
', { - class: 'card accordion-item active' - }); - - const header = $('

', { - class: 'accordion-header', - id: 'headingAlbaran' + item.albaran.id - }); - - const button = $('