falta preview resumen

This commit is contained in:
2024-10-16 03:45:10 +02:00
parent 2c5ea4d7ba
commit b5924dceb5
19 changed files with 1132 additions and 126 deletions

View File

@ -410,6 +410,8 @@ $routes->group('clienteusuarios', ['namespace' => 'App\Controllers\Clientes'], f
$routes->group('misdirecciones', ['namespace' => 'App\Controllers\Clientes'], function ($routes) {
$routes->get('', 'Clientedirecciones::index', ['as' => 'clientedireccionesIndex']);
$routes->get('get/(:num)', 'Clientedirecciones::get/$1', ['as' => 'get']);
$routes->post('add', 'Clientedirecciones::add', ['as' => 'newClientedirecciones']);
$routes->get('getSelect2', 'Clientedirecciones::getSelect2', ['as' => 'listaClientedirecciones']);
});

View File

@ -82,7 +82,7 @@ class Clientedirecciones extends \App\Controllers\BaseResourceController
$att = $reqData['att'] ?? "";
$email = $reqData['email'] ?? "";
$direccion = $reqData['direccion'] ?? "";
$pais_id = $reqData['paisId'] ?? -1;
$pais_id = $reqData['pais_id'] ?? -1;
$provincia = $reqData['provincia'] ?? "";
$municipio = $reqData['municipio'] ?? "";
$cp = $reqData['cp'] ?? "";
@ -103,11 +103,8 @@ class Clientedirecciones extends \App\Controllers\BaseResourceController
];
$response = $this->model->insert($data);
$newTokenHash = csrf_hash();
$csrfTokenName = csrf_token();
$data_ret = [
'data' => $response,
$csrfTokenName => $newTokenHash
];
return $this->respond($data_ret);
} else {
@ -140,6 +137,34 @@ class Clientedirecciones extends \App\Controllers\BaseResourceController
}
public function getSelect2()
{
if ($this->request->isAJAX()) {
$cliente_id = $this->request->getGet('cliente_id');
$query = $this->model->builder()->select(
[
"id",
"alias as name"
]
)
->where("cliente_id", $cliente_id)
->orderBy("alias", "asc");
if ($this->request->getGet("q")) {
$query->groupStart()
->orLike("clientes.nombre", $this->request->getGet("q"))
->groupEnd();
}
return $this->response->setJSON($query->get()->getResultObject());
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function datatable()
{
if ($this->request->isAJAX()) {

View File

@ -320,7 +320,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
$tipo = $reqData['tipo'];
$paginasCuadernillo = $reqData['paginasCuadernillo'] ?? null;
$papelInteriorDiferente = $reqData['papelInteriorDiferente'] ?? null;
$papelInteriorDiferente = intval($reqData['papelInteriorDiferente']) ?? null;
$isColor = intval($reqData['isColor']) ?? 0;
$isHq = intval($reqData['isHq']) ?? 0;
@ -331,16 +331,26 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
$guardas = $reqData['guardas'] ?? [];
$faja = $reqData['faja'] ?? [];
$excluirRotativa = $reqData['excluirRotativa'] ?? 0;
$ivaReducido = $reqData['ivaReducido'] ?? 0;
$ivaReducido = intval($reqData['ivaReducido']) ?? 0;
$direcciones = $reqData['direcciones'] ?? [];
$tipo_impresion_id = $this->getTipoImpresion($tipo, $cubierta['tipoCubierta']);
if($papelInteriorDiferente){
$papel['negro'] = $modelPapelGenerico->getIdFromCode($interior['papelInterior']['negro']);
$papel['color'] = $modelPapelGenerico->getIdFromCode($interior['papelInterior']['color']);
$gramaje['negro'] = intval($interior['gramajeInterior']['negro']);
$gramaje['color'] = intval($interior['gramajeInterior']['color']);
}
else{
$papel = $modelPapelGenerico->getIdFromCode($interior['papelInterior']);
$gramaje = intval($interior['gramajeInterior']);
}
// Interior
$interior = [
'papel_generico' => $modelPapelGenerico->getIdFromCode($interior['papelInterior']),
'gramaje' => intval($interior['gramajeInterior']),
'papel_generico' => $papel,
'gramaje' => $gramaje,
'excluirRotativa' => $excluirRotativa == "false" ? false : true,
'paginas' => $paginas,
'paginas_color' => $paginas_color,
@ -396,7 +406,11 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
);
$return_data = $this->calcular_presupuesto($datos_presupuesto, 0, false); //TRUE FOR DEBUG
if(array_key_exists('exception', $return_data)){
return $this->failServerError(
$return_data['exception'] . ' - ' .
$return_data['file'] . ' - ' . $return_data['line']);
}
if(count($direcciones) > 1){
for ($i=0; $i<count($tirada); $i++){

View File

@ -54,7 +54,7 @@ class ClienteDireccionesModel extends \App\Models\BaseModel
],
"email" => [
"label" => "ClienteDirecciones.email",
"rules" => "trim|max_length[100]|valid_email",
"rules" => "trim|max_length[100]",
],
"cp" => [
"label" => "ClienteDirecciones.cp",

View File

@ -24,7 +24,6 @@ class PresupuestoClienteService extends BaseService
$total_plana = -1;
$hay_plana = false;
$papelInteriorDiferente = $data['papelInteriorDiferente'];
if ($data['isColor']) {
if ($data['datosPedido']->paginas == $data['paginas_color'])
$total_plana += floatval($plana[1]['total_impresion']);
@ -297,8 +296,6 @@ class PresupuestoClienteService extends BaseService
return $result;
}
);
$linea_negro_plana = $linea_negro_plana[0]['fields'];
$linea_negro_plana['tipo_linea'] = $isHq ? 'lp_bnhq' : 'lp_bn';
}
}
@ -308,6 +305,10 @@ class PresupuestoClienteService extends BaseService
$datosPedido->paginas = $paginas_color;
for ($i = 0; $i < 2; $i++) {
if ($data['papelInteriorDiferente'] == true){
$papel_generico = $papel_generico_color;
$gramaje = $gramaje_color;
}
$lineas = PresupuestoService::obtenerComparadorPlana([
'uso' => $uso,
'tipo_impresion_id' => $tipo_impresion_id,
@ -337,10 +338,57 @@ class PresupuestoClienteService extends BaseService
return $result;
}
);
}
}
// Si hay negro y color, y se hace con el mismo papel, hay que buscar la combinación
// más económica con la misma máquna
if (
$paginas_negro > 0 && $paginas_color > 0 && $data['papelInteriorDiferente'] == 0 &&
count($linea_negro_plana) > 0 && count($linea_color_plana) > 0
) {
$mejor_combinacion = null;
$coste_menor = PHP_INT_MAX;
// Iteramos ambos arrays
foreach ($linea_color_plana as $color_item) {
foreach ($linea_negro_plana as $negro_item) {
// Comparar si tienen el mismo 'maquina_id'
if ($color_item['fields']['maquina_id'] == $negro_item['fields']['maquina_id']) {
// Sumar los 'total_impresion' de ambas líneas
$costo_total = $color_item['fields']['total_impresion'] + $negro_item['fields']['total_impresion'];
// Verificar si es la combinación más barata hasta ahora
if ($costo_total < $coste_menor) {
$coste_menor = $costo_total;
$mejor_combinacion = [
'maquina_id' => $color_item['fields']['maquina_id'],
'costo_total' => $costo_total,
'color_item' => $color_item,
'negro_item' => $negro_item,
];
}
}
}
// Retornar la mejor combinación encontrada
if ($mejor_combinacion !== null) {
return [$mejor_combinacion['negro_item']['fields'], $mejor_combinacion['color_item']['fields']];
} else {
return [];
}
}
}
else{
if (count($linea_negro_plana) > 0) {
$linea_negro_plana = $linea_negro_plana[0]['fields'];
$linea_negro_plana['tipo_linea'] = $isHq ? 'lp_bnhq' : 'lp_bn';
}
if (count($linea_color_plana) > 0) {
$linea_color_plana = $linea_color_plana[0]['fields'];
$linea_color_plana['tipo_linea'] = $isHq ? 'lp_colorhq' : 'lp_color';
}
}
return [$linea_negro_plana, $linea_color_plana];
}

View File

@ -0,0 +1,114 @@
<div id="addressModal" action='create' class="modal fade addModal">
<div class="modal-dialog modal-lg modal-simple">
<div class="modal-content">
<div class="modal-header">
<h4 id="labelTitleConfirmDialog" class="modal-title"><?= lang('ClienteDirecciones.direccionTitle') ?></h4>
</div>
<div class="modal-body">
<div class="texto-error d-none">
Rellene los campos obligatorios
</div>
<div class="mb-3">
<label for="add_alias" class="form-label">
<?= lang('ClienteDirecciones.alias') ?>*
</label>
<input type="text" id="add_alias" tabindex="1" maxLength="100" class="form-control">
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_att" class="form-label">
<?= lang('ClienteDirecciones.att') ?>*
</label>
<input type="text" id="add_att" tabindex="1" maxLength="100" class="form-control">
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_email" class="form-label">
<?= lang('ClienteDirecciones.email') ?>
</label>
<input type="text" id="add_email" tabindex="2" maxLength="100" class="form-control">
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_direccion" class="form-label">
<?= lang('ClienteDirecciones.direccion') ?>*
</label>
<input type="text" id="add_direccion" tabindex="3" maxLength="255" class="form-control">
</div><!--//.mb-3 -->
<div class='row'>
<div id='divPais' class="col-md-12 col-lg-12 pl-4">
<div class="mb-3">
<label for="add_pais_id" class="form-label">
<?= lang('ClienteDirecciones.pais') ?>*
</label>
<select id="add_pais_id" tabindex="4" class="form-control select2bs" style="width: 100%;">
<option value="" disabled selected><?= lang('ClienteDirecciones.selectPais') ?></option>
<?php foreach ($paisList as $item) : ?>
<option value="<?= $item->id ?>">
<?= $item->nombre ?>
</option>
<?php endforeach; ?>
</select>
</div><!--//.mb-3 -->
</div>
</div> <!-- //.row -->
<div class='row'>
<div id='divMunicipio' class="col-md-12 col-lg-12 pl-4">
<div class="mb-3">
<label for="add_municipio" class="form-label">
<?= lang('ClienteDirecciones.municipio') ?>*
</label>
<input type="text" id="add_municipio" tabindex="6" maxLength="100" class="form-control">
</div><!--//.mb-3 -->
</div>
<div class="col-md-12 col-lg-6 pl-4 spain-data" style="display: none;">
<div class="mb-3">
<label for="add_provincia" class="form-label">
<?= lang('ClienteDirecciones.provincia') ?>
</label>
<input type="text" id="add_provincia" tabindex="7" maxLength="100" class="form-control">
</div><!--//.mb-3 -->
</div>
</div> <!-- //.row -->
<div class='row'>
<div class="col-md-12 col-lg-6 pl-4">
<div class="mb-3">
<label for="add_cp" class="form-label">
<?= lang('ClienteDirecciones.cp') ?>*
</label>
<input type="text" id="add_cp" tabindex="8" maxLength="100" class="form-control">
</div><!--//.mb-3 -->
</div>
<div class="col-md-12 col-lg-6 pl-4">
<div class="mb-3">
<label for="add_telefono" class="form-label">
<?= lang('ClienteDirecciones.telefono') ?>
</label>
<input type="text" id="add_telefono" tabindex="9" maxLength="100" class="form-control"></input>
</div><!--//.mb-3 -->
</div>
</div> <!-- //.row -->
</div>
<div class="modal-footer">
<button id="saveAdd"
type="button"
class="btn btn-primary">Guardar</button>
<button id="cancelAdd"
type="button"
class="btn btn-secondary">Cancelar</button>
</div>
</div>
</div>
</div>

View File

@ -10,7 +10,7 @@
<div id="divInputDirecciones" name="div_input_direcciones" class="row col-sm-12 mb-5 justify-content-center">
<div id="containerTiradasEnvios" class="row mb-3">
<div id="containerTiradasEnvios" class="row mb-3 justify-content-center">
</div>
<div class="row mb-3 justify-content-center">
@ -47,6 +47,15 @@
</div>
</div>
<div class="row mb-3 justify-content-center">
<div class="col-sm-2 mb-3 mt-auto mb-0">
<button id="nuevaDireccion" type="button"
class="btn btn-secondary waves-effect waves-light">Nueva Dirección</button>
</div>
</div>
<div id="divErrorEnvios" name="div_error_envios" class="col-sm-10 mb-3 justify-content-center"></div>
<div id="divDirecciones" class="calcular-presupuesto col-sm-12 d-flex flex-column align-items-center">
</div>

View File

@ -0,0 +1,143 @@
<div id="addressForm" action='create' class="modal fade addModal">
<div class="modal-dialog modal-lg modal-simple">
<div class="modal-content">
<div class="modal-header">
<h4 id="labelTitleConfirmDialog" class="modal-title"><?= lang('PresupuestosDirecciones.direccionTitle') ?></h4>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="add_clientedAdd" class="form-label">
<?= lang('PresupuestosDirecciones.clientedAdd') ?>*
</label>
<select id="add_clientedAdd" class="form-control select2bs" style="width: 100%;">
</select>
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_cantidad" class="form-label">
<?= lang('PresupuestosDirecciones.cantidad') ?>*
</label>
<input type="number" id="add_cantidad" class="form-control">
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_att" class="form-label">
<?= lang('PresupuestosDirecciones.att') ?>*
</label>
<input type="text" id="add_att" maxLength="100" class="form-control new-address">
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_email" class="form-label">
<?= lang('PresupuestosDirecciones.email') ?>*
</label>
<input type="text" id="add_email" maxLength="100" class="form-control new-address">
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_direccion" class="form-label">
<?= lang('PresupuestosDirecciones.direccion') ?>*
</label>
<input type="text" id="add_direccion" maxLength="255" class="form-control new-address">
</div><!--//.mb-3 -->
<div class="mb-3">
<label for="add_pais_id" class="form-label">
<?= lang('PresupuestosDirecciones.pais') ?>*
</label>
<select id="add_pais_id" class="form-control select2bs new-address" style="width: 100%;">
<option value="" disabled selected><?= lang('PresupuestosDirecciones.selectPais') ?></option>
<?php foreach ($paisList as $item) : ?>
<option value="<?= $item->id ?>" <?= $item->id == 1 ? ' selected' : '' ?>>
<?= $item->nombre ?>
</option>
<?php endforeach; ?>
</select>
</div><!--//.mb-3 -->
<div class='row'>
<div id='divMunicipio' class="col-md-12 col-lg-12 pl-4">
<div class="mb-3">
<label for="add_municipio" class="form-label">
<?= lang('PresupuestosDirecciones.municipio') ?>*
</label>
<input type="text" id="add_municipio" maxLength="100" class="form-control new-address">
</div><!--//.mb-3 -->
</div>
<div class="col-md-12 col-lg-6 pl-4 spain-data" style="display: none;">
<div class="mb-3">
<label for="add_provincia" class="form-label">
<?= lang('PresupuestosDirecciones.provincia') ?>*
</label>
<input type="text" id="add_provincia" maxLength="100" class="form-control new-address">
</div><!--//.mb-3 -->
</div>
</div> <!-- //.row -->
<div class='row'>
<div class="col-md-12 col-lg-6 pl-4">
<div class="mb-3">
<label for="add_cp" class="form-label">
<?= lang('PresupuestosDirecciones.cp') ?>*
</label>
<input type="text" id="add_cp" maxLength="100" class="form-control new-address">
</div><!--//.mb-3 -->
</div>
<div class="col-md-12 col-lg-6 pl-4">
<div class="mb-3">
<label for="add_telefono" class="form-label">
<?= lang('PresupuestosDirecciones.telefono') ?>*
</label>
<input type="text" id="add_telefono" maxLength="100" class="form-control new-address"></input>
</div><!--//.mb-3 -->
</div>
</div> <!-- //.row -->
<div class="col-md-12 col-lg-6 pl-4">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="add_entregaPieCalle" name="add_entregaPieCalle" value="1">
<label class="form-check-label" for="add_entregaPieCalle"><?= lang('PresupuestosDirecciones.entregaPieCalle') ?></label>
</div>
</div>
<div class="col-md-12 col-lg-6 pl-4">
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="add_saveDirection" name="add_saveDirection" value="1">
<label class="form-check-label" for="add_saveDirection"><?= lang('PresupuestosDirecciones.saveDirection') ?></label>
</div>
</div>
<div class="mb-3">
<label style="display:none" for="add_alias" class="form-label save-alias">
<?= lang('PresupuestosDirecciones.alias') ?>*
</label>
<input type="text" id="add_alias" maxLength="100" class="form-control new-address save-alias" style='display: none;'>
</div><!--//.mb-3 -->
</div>
<div class="modal-footer">
<button id="saveDireccionEnvio"
type="button"
class="btn btn-primary">Guardar</button>
<button id="cancelAdd"
type="button"
class="btn btn-default">Cancelar</button>
</div>
</div>
</div>
</div>
<?= $this->section("additionalExternalJs") ?>
<?= $this->endSection() ?>

View File

@ -0,0 +1,174 @@
<div class="col-12 d-flex flex-column align-items-center">
<h3 class="mb-1 fw-bold">Resumen del presupuesto</h3>
<div class="line mb-4"></div>
<div class="col-sm-8 mb-3 d-flex flex-column align-items-center">
<h5 class="mb-1 "> Precio unidad: <span id="resumenPrecioU"></span> </h5>
<h4 class="mb-1 "> Total base: <span id="resumenTotalBase"></span> </h>
<h4 class="mb-1 "> Iva (<span id="resumenIvaPorcentaje"></span>%): <span id="resumenIva"></span> </h>
<h3 class="mb-1 fw-bold"> Total: <span id="resumenTotal"></span> </h>
</div><!--//.mb-3 -->
<div class="table-responsive col-10 mb-3">
<table class="table table-bordered">
<thead class="table-dark">
<tr>
<th colspan="2">Datos generales</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col-item-resumen-table">Titulo</td>
<td id="resumenTitulo">Albert Cook</td>
</tr>
<tr>
<td class="col-item-resumen-table">Tipo libro</td>
<td id="resumenTipoLibro"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Formato</td>
<td id="resumenFormato"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Páginas negro</td>
<td id="resumenPaginasNegro"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Páginas color</td>
<td id="resumenPaginasColor"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Páginas en total</td>
<td id="resumenPaginas"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Tirada</td>
<td id="resumenTirada"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Prototipo</td>
<td id="resumenPrototipo"></td>
</tr>
</tbody>
</table>
</div>
<div class="table-responsive col-10 mb-3">
<table class="table table-bordered">
<thead class="table-dark">
<tr>
<th colspan="2">Interior</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col-item-resumen-table">Impresion</td>
<td id="resumenImpresion"></td>
</tr>
<tr class="mismoInterior">
<td class="col-item-resumen-table">Papel</td>
<td id="resumenPapelInterior"></td>
</tr>
<tr class="mismoInterior">
<td class="col-item-resumen-table">Gramaje</td>
<td id="resumenGramajeInterior"></td>
</tr>
<tr class="diferenteInterior d-none">
<td class="col-item-resumen-table">Papel B&N</td>
<td id="resumenPapelInteriorNegro"></td>
</tr>
<tr class="diferenteInterior d-none">
<td class="col-item-resumen-table">Gramaje B&N</td>
<td id="resumenGramajeInteriorNegro"></td>
</tr>
<tr class="diferenteInterior d-none">
<td class="col-item-resumen-table">Papel Color</td>
<td id="resumenPapelInteriorColor"></td>
</tr>
<tr class="diferenteInterior d-none">
<td class="col-item-resumen-table">Gramaje Color</td>
<td id="resumenGramajeInteriorColor"></td>
</tr>
</tbody>
</table>
</div>
<div class="table-responsive col-10 mb-3">
<table class="table table-bordered">
<thead class="table-dark">
<tr>
<th colspan="2">Cubierta</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col-item-resumen-table">Tipo</td>
<td id="resumenCubiertaTipo"></td>
</tr>
<tr class="cubierta-tapa-blanda d-none">
<td class="col-item-resumen-table">Caras impresas</td>
<td id="resumenCarasCubierta"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Papel</td>
<td id="resumenPapelCubierta"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Gramaje</td>
<td id="resumenGramajeCubierta"></td>
</tr>
<tr class="cubierta-tapa-blanda d-none">
<td class="col-item-resumen-table">Solapas</td>
<td id="resumenSolapasCubierta"></td>
</tr>
<tr class="cubierta-tapa-dura d-none">
<td class="col-item-resumen-table">Papel de guardas</td>
<td id="resumenPapelGuardas"></td>
</tr>
<tr class="cubierta-tapa-dura d-none">
<td class="col-item-resumen-table">Guardas impresas</td>
<td id="resumenGuardasImpresas"></td>
</tr>
<tr class="cubierta-tapa-dura d-none">
<td class="col-item-resumen-table">Cabezada</td>
<td id="resumenCabezada"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Acabados</td>
<td id="resumenCubiertaAcabados"></td>
</tr>
</tbody>
</table>
</div>
<div id="divResumenSobrecubierta" class="table-responsive col-10 mb-3 d-none">
<table class="table table-bordered">
<thead class="table-dark">
<tr>
<th colspan="2">Sobrecubierta</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col-item-resumen-table">Papel</td>
<td id="resumenPapelSobrecubierta">Estucado Mate</td>
</tr>
<tr class="d-none">
<td class="col-item-resumen-table">Gramaje</td>
<td id="resumenGramajeSobrecubierta"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Tamaño solapas</td>
<td id="resumenSolapaSobrecubierta"></td>
</tr>
<tr>
<td class="col-item-resumen-table">Plastificado</td>
<td id="resumenPlastificadoSobreCubierta"></td>
</tr>
</tbody>
</table>
</div>
</div>

View File

@ -9,6 +9,7 @@
<?= view("themes/vuexy/form/clientes/cliente/_clienteDireccionesForm") ?>
<?= view("themes/_commonPartialsBs/_modalInput") ?>
<?= view("themes/vuexy/components/modals/modalDireccion") ?>
<div class="container-xxl flex-grow-1 container-p-y">
<div class="col-12">
@ -60,6 +61,15 @@
</button>
</div>
<div class="step" data-target="#resumen-libro">
<button type="button" class="step-trigger" aria-selected="false" disabled="disabled">
<span class="bs-stepper-circle"><i class="ti ti-checkbox ti-sm"></i></span>
<span class="bs-stepper-label">
<span class="bs-stepper-title">Resumen del presupuesto</span>
</span>
</button>
</div>
<div class="line"></div>
<div id='divTiradasPrecio'></div>
@ -70,8 +80,6 @@
<div class="bs-stepper-content">
<form id="presupuesto-cliente-form" onsubmit="return false">
<!-- Tipo Libro -->
<div id="datos-generales" class="content active dstepper-block fv-plugins-bootstrap5 fv-plugins-framework">
<div class="row g-3">
@ -97,6 +105,12 @@
</div>
</div>
<div id="resumen-libro" class="content fv-plugins-bootstrap5 fv-plugins-framework">
<div class="row g-3">
<?= view("themes/vuexy/form/presupuestos/cliente/items/_resumen") ?>
</div>
</div>
<?= view("themes/vuexy/form/presupuestos/cliente/items/_buttons") ?>