mirror of
https://git.imnavajas.es/jjimenez/safekat.git
synced 2025-07-25 22:52:08 +00:00
Merge branch 'feat/download_zip' into 'main'
Implementada funcionalidad descarga en zip See merge request jjimenez/safekat!822
This commit is contained in:
@ -30,6 +30,8 @@ $routes->group('presupuestoadmin', ['namespace' => 'App\Controllers\Presupuestos
|
|||||||
|
|
||||||
$routes->get('presupuestosCliente', 'Presupuestoadmin::tablaClienteForm');
|
$routes->get('presupuestosCliente', 'Presupuestoadmin::tablaClienteForm');
|
||||||
$routes->get('getSumCliente/(:num)', 'Presupuestoadmin::obtenerTotalPresupuestosCliente/$1');
|
$routes->get('getSumCliente/(:num)', 'Presupuestoadmin::obtenerTotalPresupuestosCliente/$1');
|
||||||
|
|
||||||
|
$routes->post('download_zip', 'Presupuestocliente::download_zip', ['as' => 'descargarAdminArchivos']);
|
||||||
});
|
});
|
||||||
|
|
||||||
//$routes->resource('presupuestoadmin', ['namespace' => 'App\Controllers\Presupuestos', 'controller' => 'Presupuestoadmin', 'except' => 'show,new,create,update']);
|
//$routes->resource('presupuestoadmin', ['namespace' => 'App\Controllers\Presupuestos', 'controller' => 'Presupuestoadmin', 'except' => 'show,new,create,update']);
|
||||||
@ -51,6 +53,7 @@ $routes->group('presupuestocliente', ['namespace' => 'App\Controllers\Presupuest
|
|||||||
$routes->post('calcular', 'Presupuestocliente::calcular', ['as' => 'calcularPresupuesto']);
|
$routes->post('calcular', 'Presupuestocliente::calcular', ['as' => 'calcularPresupuesto']);
|
||||||
$routes->post('calcularsolapas', 'Presupuestocliente::calcularMaxSolapas', ['as' => 'calcularSolapas']);
|
$routes->post('calcularsolapas', 'Presupuestocliente::calcularMaxSolapas', ['as' => 'calcularSolapas']);
|
||||||
$routes->post('checklomo', 'Presupuestocliente::check_lomo_interior');
|
$routes->post('checklomo', 'Presupuestocliente::check_lomo_interior');
|
||||||
|
$routes->post('download_zip', 'Presupuestocliente::download_zip', ['as' => 'descargarClienteArchivos']);
|
||||||
});
|
});
|
||||||
//$routes->resource('presupuestocliente', ['namespace' => 'App\Controllers\Presupuestos', 'controller' => 'Presupuestocliente', 'except' => 'show,new,create,update']);
|
//$routes->resource('presupuestocliente', ['namespace' => 'App\Controllers\Presupuestos', 'controller' => 'Presupuestocliente', 'except' => 'show,new,create,update']);
|
||||||
|
|
||||||
|
|||||||
@ -336,8 +336,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
|
|||||||
$forzarRotativa = false;
|
$forzarRotativa = false;
|
||||||
if ($tirada[0] <= $POD && $cliente->forzar_rotativa_pod) {
|
if ($tirada[0] <= $POD && $cliente->forzar_rotativa_pod) {
|
||||||
$forzarRotativa = true;
|
$forzarRotativa = true;
|
||||||
}
|
} else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) {
|
||||||
else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) {
|
|
||||||
$excluirRotativa = true;
|
$excluirRotativa = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,8 +763,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
|
|||||||
$forzarRotativa = false;
|
$forzarRotativa = false;
|
||||||
if ($tirada[0] <= $POD && $cliente->forzar_rotativa_pod) {
|
if ($tirada[0] <= $POD && $cliente->forzar_rotativa_pod) {
|
||||||
$forzarRotativa = true;
|
$forzarRotativa = true;
|
||||||
}
|
} else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) {
|
||||||
else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) {
|
|
||||||
$excluirRotativa = true;
|
$excluirRotativa = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1341,7 +1339,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
|
|||||||
|
|
||||||
|
|
||||||
$resultado_presupuesto['info']['merma'] = isset($resultado_presupuesto['info']['num_formas']) ?
|
$resultado_presupuesto['info']['merma'] = isset($resultado_presupuesto['info']['num_formas']) ?
|
||||||
PresupuestoService::calcular_merma($selected_tirada, $POD, $resultado_presupuesto['info']['num_formas']): PresupuestoService::calcular_merma($selected_tirada, $POD);
|
PresupuestoService::calcular_merma($selected_tirada, $POD, $resultado_presupuesto['info']['num_formas']) : PresupuestoService::calcular_merma($selected_tirada, $POD);
|
||||||
|
|
||||||
$datos_presupuesto['faja'] = $faja;
|
$datos_presupuesto['faja'] = $faja;
|
||||||
|
|
||||||
@ -2084,8 +2082,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
|
|||||||
$forzarRotativa = false;
|
$forzarRotativa = false;
|
||||||
if ($tirada[$t] <= $POD && $cliente->forzar_rotativa_pod) {
|
if ($tirada[$t] <= $POD && $cliente->forzar_rotativa_pod) {
|
||||||
$forzarRotativa = true;
|
$forzarRotativa = true;
|
||||||
}
|
} else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) {
|
||||||
else if ($tirada[0] <= $POD && !$cliente->forzar_rotativa_pod) {
|
|
||||||
$excluirRotativa = true;
|
$excluirRotativa = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3586,4 +3583,29 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
|
|||||||
return $servicios;
|
return $servicios;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function download_zip()
|
||||||
|
{
|
||||||
|
$presupuesto_id = $this->request->getPost('presupuesto_id');
|
||||||
|
if (!$presupuesto_id) {
|
||||||
|
return $this->response->setStatusCode(400)->setBody('Presupuesto ID requerido');
|
||||||
|
}
|
||||||
|
|
||||||
|
$ftpClient = new \App\Libraries\SafekatFtpClient();
|
||||||
|
try {
|
||||||
|
$zipPath = $ftpClient->downloadZipPresupuesto((int) $presupuesto_id);
|
||||||
|
|
||||||
|
if ($zipPath === null || !file_exists($zipPath)) {
|
||||||
|
return $this->response->setStatusCode(404)->setBody('No se encontraron archivos');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->response
|
||||||
|
->download($zipPath, null) // null = usar nombre original del archivo
|
||||||
|
->setFileName('archivos_presupuesto_' . $presupuesto_id . '.zip');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
log_message('error', $e->getMessage());
|
||||||
|
return $this->response->setStatusCode(500)->setBody('Error interno');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,7 @@ return [
|
|||||||
"global_next" => "Siguiente",
|
"global_next" => "Siguiente",
|
||||||
"global_save_file" => "Guardar ficheros",
|
"global_save_file" => "Guardar ficheros",
|
||||||
"global_upload_files" => "Subir ficheros",
|
"global_upload_files" => "Subir ficheros",
|
||||||
|
"global_download_files" => "Descargar ficheros",
|
||||||
"global_all" => "Todos",
|
"global_all" => "Todos",
|
||||||
// LOGIN - Index
|
// LOGIN - Index
|
||||||
"login_title" => "Iniciar sesión en su cuenta",
|
"login_title" => "Iniciar sesión en su cuenta",
|
||||||
|
|||||||
@ -114,4 +114,57 @@ class SafekatFtpClient
|
|||||||
|
|
||||||
return implode('/', [$this->base_dir, 'pedidos_files', $rootIdExtern]);
|
return implode('/', [$this->base_dir, 'pedidos_files', $rootIdExtern]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function downloadZipPresupuesto(int $presupuesto_id): ?string
|
||||||
|
{
|
||||||
|
$modelPedidoLinea = model(PedidoLineaModel::class);
|
||||||
|
$model = model(PresupuestoFicheroModel::class);
|
||||||
|
|
||||||
|
$pedidoLinea = $modelPedidoLinea->findByPresupuesto($presupuesto_id);
|
||||||
|
$rootIdExtern = $this->pedido_xml_config->id_offset + $pedidoLinea->pedido_id;
|
||||||
|
|
||||||
|
$remotePath = implode('/', [$this->base_dir, 'pedidos_files', $rootIdExtern]);
|
||||||
|
|
||||||
|
$this->ftp->login(username: $this->username, password: $this->password);
|
||||||
|
|
||||||
|
if (!$this->ftp->is_dir($remotePath)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$files = $model->getFiles($presupuesto_id);
|
||||||
|
if (empty($files)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$localTempDir = WRITEPATH . 'zip_presupuestos/' . uniqid("presupuesto_");
|
||||||
|
if (!is_dir($localTempDir)) {
|
||||||
|
mkdir($localTempDir, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$originalName = $file->nombre ?? basename($file->file_path);
|
||||||
|
$localFile = $localTempDir . '/' . $originalName;
|
||||||
|
$remoteFile = $remotePath . '/' . basename($file->file_path);
|
||||||
|
$this->ftp->get($remoteFile, $localFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
$zipPath = $localTempDir . '.zip';
|
||||||
|
$zip = new \ZipArchive();
|
||||||
|
if ($zip->open($zipPath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE)) {
|
||||||
|
foreach (glob($localTempDir . '/*') as $localFile) {
|
||||||
|
$zip->addFile($localFile, basename($localFile));
|
||||||
|
}
|
||||||
|
$zip->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limpieza temporal
|
||||||
|
foreach (glob($localTempDir . '/*') as $localFile) {
|
||||||
|
unlink($localFile);
|
||||||
|
}
|
||||||
|
rmdir($localTempDir);
|
||||||
|
|
||||||
|
return $zipPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,10 @@
|
|||||||
<span class="align-middle d-sm-inline-block d-none me-sm-1"><?= lang('App.global_save_file') ?></span>
|
<span class="align-middle d-sm-inline-block d-none me-sm-1"><?= lang('App.global_save_file') ?></span>
|
||||||
<i class="ti ti-device-floppy ti-xs"></i>
|
<i class="ti ti-device-floppy ti-xs"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button id="<?= $id ?>_btnDownloadFiles" class="btn mt-3 btn-secondary btn-sm waves-effect waves-light ml-2">
|
||||||
|
<span class="align-middle d-sm-inline-block d-none me-sm-1"><?= lang('App.global_download_files') ?></span>
|
||||||
|
<i class="ti ti-device-floppy ti-xs"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -213,6 +213,10 @@
|
|||||||
<span class="align-middle d-sm-inline-block d-none me-sm-1"><?= lang('App.global_save_file') ?></span>
|
<span class="align-middle d-sm-inline-block d-none me-sm-1"><?= lang('App.global_save_file') ?></span>
|
||||||
<i class="ti ti-device-floppy ti-xs"></i>
|
<i class="ti ti-device-floppy ti-xs"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button id="download-all-files" class="btn mt-3 btn-secondary btn-submit waves-effect waves-light ml-2">
|
||||||
|
<span class="align-middle d-sm-inline-block d-none me-sm-1"><?= lang('App.global_download_files') ?></span>
|
||||||
|
<i class="ti ti-device-floppy ti-xs"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,7 @@ class FileUploadDropzone {
|
|||||||
this.modelId = this.jqElement.data('id')
|
this.modelId = this.jqElement.data('id')
|
||||||
this.btnSelectFiles = $(`#${domElement.replace('#', '')}_btnUploadFiles`)
|
this.btnSelectFiles = $(`#${domElement.replace('#', '')}_btnUploadFiles`)
|
||||||
this.btnSubmitFile = $(`#${domElement.replace('#', '')}_btnSubmitFiles`)
|
this.btnSubmitFile = $(`#${domElement.replace('#', '')}_btnSubmitFiles`)
|
||||||
|
this.btnDownloadFiles = $(`#${domElement.replace('#', '')}_btnDownloadFiles`);
|
||||||
this.dataPost = {}
|
this.dataPost = {}
|
||||||
this.nameId = nameId;
|
this.nameId = nameId;
|
||||||
this.getUri = getUri
|
this.getUri = getUri
|
||||||
@ -44,6 +45,7 @@ class FileUploadDropzone {
|
|||||||
this.btnSelectFiles.on('click', () => {
|
this.btnSelectFiles.on('click', () => {
|
||||||
this.jqElement.trigger('click')
|
this.jqElement.trigger('click')
|
||||||
})
|
})
|
||||||
|
this.btnDownloadFiles.on('click', this._handleDownloadFiles.bind(this))
|
||||||
|
|
||||||
this.dropzone = new Dropzone(this.domElement, {
|
this.dropzone = new Dropzone(this.domElement, {
|
||||||
url: this.postUri,
|
url: this.postUri,
|
||||||
@ -67,12 +69,12 @@ class FileUploadDropzone {
|
|||||||
var viewButton = Dropzone.createElement("<span class='dz-remove'>Ver</span>");
|
var viewButton = Dropzone.createElement("<span class='dz-remove'>Ver</span>");
|
||||||
file.previewElement.appendChild(viewButton);
|
file.previewElement.appendChild(viewButton);
|
||||||
// Listen to the view button click event
|
// Listen to the view button click event
|
||||||
viewButton.addEventListener("click", this.onViewButton.bind(this,file));
|
viewButton.addEventListener("click", this.onViewButton.bind(this, file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onViewButton(file) {
|
onViewButton(file) {
|
||||||
console.log(window.location.protocol + "//" + window.location.host + "/sistema/intranet/" + this.resourcePath + "/" + file.hash)
|
console.log(window.location.protocol + "//" + window.location.host + "/sistema/intranet/" + this.resourcePath + "/" + file.hash)
|
||||||
window.open(window.location.protocol + "//" + window.location.host + "/sistema/intranet/" + this.resourcePath + "/" + file.hash, '_blank');
|
window.open(window.location.protocol + "//" + window.location.host + "/sistema/intranet/" + this.resourcePath + "/" + file.hash, '_blank');
|
||||||
}
|
}
|
||||||
_getDropzoneFilesFormData() {
|
_getDropzoneFilesFormData() {
|
||||||
var files = this.dropzone.files;
|
var files = this.dropzone.files;
|
||||||
@ -134,6 +136,47 @@ class FileUploadDropzone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleDownloadFiles() {
|
||||||
|
$("#loader").modal('show');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: `/presupuestoadmin/download_zip`,
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
[this.nameId]: this.modelId
|
||||||
|
},
|
||||||
|
xhrFields: {
|
||||||
|
responseType: 'blob'
|
||||||
|
},
|
||||||
|
success: (blob, status, xhr) => {
|
||||||
|
const disposition = xhr.getResponseHeader('Content-Disposition');
|
||||||
|
let filename = "archivos.zip";
|
||||||
|
if (disposition && disposition.indexOf('attachment') !== -1) {
|
||||||
|
const match = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition);
|
||||||
|
if (match != null && match[1]) {
|
||||||
|
filename = match[1].replace(/['"]/g, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
},
|
||||||
|
error: () => {
|
||||||
|
alertWarningMessage("Error al descargar el archivo ZIP.");
|
||||||
|
},
|
||||||
|
complete: () => {
|
||||||
|
$("#loader").modal('hide');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
dropZoneUpdateFiles(files) {
|
dropZoneUpdateFiles(files) {
|
||||||
|
|
||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
|
|||||||
@ -58,6 +58,7 @@ class Resumen {
|
|||||||
this.btnPreviewCubierta = $(this.domItem.find("#btnPreviewCubierta"));
|
this.btnPreviewCubierta = $(this.domItem.find("#btnPreviewCubierta"));
|
||||||
this.btnDownloadPreviewCubierta = this.domItem.find('.download-shape');
|
this.btnDownloadPreviewCubierta = this.domItem.find('.download-shape');
|
||||||
this.submitFiles = $(this.domItem.find("#submit-all-files"));
|
this.submitFiles = $(this.domItem.find("#submit-all-files"));
|
||||||
|
this.btnDownloadAllFiles = this.domItem.find("#download-all-files");
|
||||||
|
|
||||||
this.dropzone = null;
|
this.dropzone = null;
|
||||||
this.presupuesto_id = -1;
|
this.presupuesto_id = -1;
|
||||||
@ -68,6 +69,7 @@ class Resumen {
|
|||||||
|
|
||||||
this.btnPreviewCubierta.on('click', this.#btnPreview.bind(this));
|
this.btnPreviewCubierta.on('click', this.#btnPreview.bind(this));
|
||||||
this.submitFiles.on('click', this.#btnUploadFiles.bind(this));
|
this.submitFiles.on('click', this.#btnUploadFiles.bind(this));
|
||||||
|
this.btnDownloadAllFiles.on('click', this.#downloadAllFiles.bind(this));
|
||||||
this.downloadPreviewImage()
|
this.downloadPreviewImage()
|
||||||
if (presupuesto_id != -1) {
|
if (presupuesto_id != -1) {
|
||||||
this.presupuesto_id = presupuesto_id;
|
this.presupuesto_id = presupuesto_id;
|
||||||
@ -186,6 +188,43 @@ class Resumen {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#downloadAllFiles() {
|
||||||
|
$('#loader').show();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "/presupuestocliente/download_zip",
|
||||||
|
type: 'POST',
|
||||||
|
data: { presupuesto_id: this.presupuesto_id },
|
||||||
|
xhrFields: {
|
||||||
|
responseType: 'blob' // importante para recibir un archivo binario
|
||||||
|
},
|
||||||
|
success: function (blob, status, xhr) {
|
||||||
|
const disposition = xhr.getResponseHeader('Content-Disposition');
|
||||||
|
let filename = "archivos_presupuesto.zip";
|
||||||
|
if (disposition && disposition.indexOf('attachment') !== -1) {
|
||||||
|
const match = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition);
|
||||||
|
if (match != null && match[1]) filename = match[1].replace(/['"]/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
popErrorAlert("Error al descargar el archivo ZIP");
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
$('#loader').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#btnPreview() {
|
#btnPreview() {
|
||||||
|
|
||||||
@ -384,7 +423,7 @@ class Resumen {
|
|||||||
const svgData = serializer.serializeToString(shapeSvgEl);
|
const svgData = serializer.serializeToString(shapeSvgEl);
|
||||||
const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
|
const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
|
||||||
const svgUrl = URL.createObjectURL(svgBlob);
|
const svgUrl = URL.createObjectURL(svgBlob);
|
||||||
const img = new Image(shapeSvgEl.getBoundingClientRect().width,shapeSvgEl.getBoundingClientRect().height);
|
const img = new Image(shapeSvgEl.getBoundingClientRect().width, shapeSvgEl.getBoundingClientRect().height);
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
const scaleFactor = 3; // Increase resolution (e.g., 2x, 3x)
|
const scaleFactor = 3; // Increase resolution (e.g., 2x, 3x)
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
@ -395,7 +434,7 @@ class Resumen {
|
|||||||
canvas.height = height * scaleFactor;
|
canvas.height = height * scaleFactor;
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
ctx.scale(scaleFactor, scaleFactor);
|
ctx.scale(scaleFactor, scaleFactor);
|
||||||
ctx.drawImage(img, 0,0,width,height);
|
ctx.drawImage(img, 0, 0, width, height);
|
||||||
const pngUrl = canvas.toDataURL('image/png');
|
const pngUrl = canvas.toDataURL('image/png');
|
||||||
const downloadLink = document.createElement('a');
|
const downloadLink = document.createElement('a');
|
||||||
downloadLink.href = pngUrl;
|
downloadLink.href = pngUrl;
|
||||||
|
|||||||
Reference in New Issue
Block a user