Merge branch 'feat/add_edit_factura' into 'main'

Feat/add edit factura

See merge request jjimenez/safekat!286
This commit is contained in:
2024-07-15 09:24:15 +00:00
36 changed files with 1775 additions and 73 deletions

View File

@ -76,7 +76,7 @@ $routes->group('configuracion', ['namespace' => 'App\Controllers\Configuracion']
$routes->match(['get', 'post'], 'edit/(:num)', 'SeriesFacturas::edit/$1', ['as' => 'seriesFacturasEdit']); $routes->match(['get', 'post'], 'edit/(:num)', 'SeriesFacturas::edit/$1', ['as' => 'seriesFacturasEdit']);
$routes->get('delete/(:num)', 'SeriesFacturas::delete/$1', ['as' => 'seriesFacturasDelete']); $routes->get('delete/(:num)', 'SeriesFacturas::delete/$1', ['as' => 'seriesFacturasDelete']);
$routes->post('datatable', 'SeriesFacturas::datatable', ['as' => 'seriesFacturasDT']); $routes->post('datatable', 'SeriesFacturas::datatable', ['as' => 'seriesFacturasDT']);
$routes->post('menuitemsFacturas', 'SeriesFacturas::menuItemsFacturas', ['as' => 'menuItemsOfSeriesFacturas']);
}); });
}); });
@ -652,8 +652,19 @@ $routes->group('facturas', ['namespace' => 'App\Controllers\Facturacion'], funct
$routes->get('list', 'Facturas::list', ['as' => 'facturasList']); $routes->get('list', 'Facturas::list', ['as' => 'facturasList']);
$routes->post('datatable', 'Facturas::datatable', ['as' => 'dataTableOfFacturas']); $routes->post('datatable', 'Facturas::datatable', ['as' => 'dataTableOfFacturas']);
$routes->get('add', 'Facturas::add', ['as' => 'newFactura']);
$routes->post('add', 'Facturas::add', ['as' => 'createFactura']);
$routes->get('edit/(:any)', 'Facturas::edit/$1', ['as' => 'editarFactura']);
$routes->post('update/(:any)', 'Facturas::update/$1', ['as' => 'actualizarFactura']);
$routes->post('datatable/(:any)', 'FacturasLineas::datatable/$1', ['as' => 'dataTableOfLineasFacturas']);
$routes->post('menuPedidosPendientes/(:num)', 'Facturas::menuPedidosPendientes/$1', ['as' => 'menuPedidosPendientesImpresion']);
$routes->post('addLineaPedidoImpresion/(:num)', 'Facturas::addLineaPedidoImpresion/$1', ['as' => 'addLineaPedidoImpresion2Factura']);
$routes->post('addLineaPedidoImpresion/(:num)', 'Facturas::addLineaPedidoImpresion/$1', ['as' => 'addLineaPedidoImpresion2Factura']);
$routes->get('deleteLinea/(:any)', 'FacturasLineas::deleteLinea/$1', ['as' => 'deleteLineaFactura']);
$routes->post('editorLineas', 'FacturasLineas::datatable_editor', ['as' => 'editorOfLineasFacturas']);
}); });
$routes->group( $routes->group(
'printpresupuestos', 'printpresupuestos',
['namespace' => 'App\Controllers\Pdf'], ['namespace' => 'App\Controllers\Pdf'],

View File

@ -312,10 +312,6 @@ class Cliente extends \App\Controllers\BaseResourceController
$onlyActiveOnes = false; $onlyActiveOnes = false;
try{ try{
$menu = $this->model->getSelect2MenuItems($columns2select, $columns2select[1], $onlyActiveOnes, $searchStr); $menu = $this->model->getSelect2MenuItems($columns2select, $columns2select[1], $onlyActiveOnes, $searchStr);
$nonItem = new \stdClass;
$nonItem->id = '';
$nonItem->text = '- ' . lang('Basic.global.None') . ' -';
array_unshift($menu, $nonItem);
} }
catch(Exception $e){ catch(Exception $e){
$menu = []; $menu = [];

View File

@ -238,10 +238,24 @@ class SeriesFacturas extends BaseResourceController
$onlyActiveOnes = false; $onlyActiveOnes = false;
$menu = $this->model->getSelect2MenuItems($columns2select, $columns2select[1], $onlyActiveOnes, $searchStr); $menu = $this->model->getSelect2MenuItems($columns2select, $columns2select[1], $onlyActiveOnes, $searchStr);
$nonItem = new \stdClass; $nonItem = new \stdClass;
$nonItem->id = '';
$nonItem->text = '- ' . lang('Basic.global.None') . ' -'; $newTokenHash = csrf_hash();
array_unshift($menu, $nonItem); $csrfTokenName = csrf_token();
$data = [
'menu' => $menu,
$csrfTokenName => $newTokenHash
];
return $this->respond($data);
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function menuItemsFacturas()
{
if ($this->request->isAJAX()) {
$menu = $this->model->getMenuItemsFacturas();
$newTokenHash = csrf_hash(); $newTokenHash = csrf_hash();
$csrfTokenName = csrf_token(); $csrfTokenName = csrf_token();
$data = [ $data = [

View File

@ -3,6 +3,8 @@
namespace App\Controllers\Facturacion; namespace App\Controllers\Facturacion;
use App\Models\Facturas\FacturaModel; use App\Models\Facturas\FacturaModel;
use App\Entities\Facturas\FacturaEntity;
use App\Models\Clientes\ClienteModel;
use App\Models\Collection; use App\Models\Collection;
@ -22,14 +24,14 @@ class Facturas extends \App\Controllers\BaseResourceController
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger) public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{ {
$this->viewData['pageTitle'] = lang('Pedidos.moduleTitle'); $this->viewData['pageTitle'] = lang('Facturas.facturas');
// Se indica que este controlador trabaja con soft_delete // Se indica que este controlador trabaja con soft_delete
$this->viewData = ['usingServerSideDataTable' => true]; $this->viewData = ['usingServerSideDataTable' => true];
// Breadcrumbs // Breadcrumbs
$this->viewData['breadcrumb'] = [ $this->viewData['breadcrumb'] = [
['title' => lang("App.menu_pedidos"), 'route' => "javascript:void(0);", 'active' => false], ['title' => lang("App.menu_facturas"), 'route' => "javascript:void(0);", 'active' => false],
]; ];
parent::initController($request, $response, $logger); parent::initController($request, $response, $logger);
@ -51,10 +53,9 @@ class Facturas extends \App\Controllers\BaseResourceController
$viewData = [ $viewData = [
'currentModule' => static::$controllerSlug, 'currentModule' => static::$controllerSlug,
'pageSubTitle' => lang('Basic.global.ManageAllRecords', [lang('Pedidos.pedido')]), 'pageSubTitle' => lang('Basic.global.ManageAllRecords', [lang('Facturas.facturas')]),
'usingServerSideDataTable' => true, 'usingServerSideDataTable' => true,
'pageTitle' => lang('Facturas.facturas'), 'pageTitle' => lang('Facturas.facturas'),
'estadoPedidos' => 'todos',
['title' => lang("App.menu_facturas"), 'route' => site_url('facturas/list'), 'active' => true] ['title' => lang("App.menu_facturas"), 'route' => site_url('facturas/list'), 'active' => true]
]; ];
@ -66,6 +67,117 @@ class Facturas extends \App\Controllers\BaseResourceController
return view(static::$viewPath . 'viewFacturasList', $viewData); return view(static::$viewPath . 'viewFacturasList', $viewData);
} }
public function add()
{
if ($this->request->getPost()) :
$nullIfEmpty = true; // !(phpversion() >= '8.1');
$postData = $this->request->getPost();
$noException = true;
$allData = true;
if( !isset($postData['cliente_id']) || !isset($postData['serie_id']) ) {
$this->viewData['errorMessage'] = lang('Facturas.errors.requiredFields');
$this->session->setFlashdata('formErrors', $this->model->errors());
$allData = false;
$noException = false;
}
try {
$clienteModel = model('App\Models\Clientes\ClienteModel');
$datosCliente = $clienteModel->getClienteDataFacturas($postData['cliente_id']);
if(count($datosCliente)>0){
// add array data datosCliente to postData
$postData = array_merge($postData, $datosCliente[0]);
}
} catch (\Exception $e) {
$noException = false;
$this->dealWithException($e);
}
$sanitizedData = $this->sanitized($postData, $nullIfEmpty);
$sanitizedData['user_updated_id'] = auth()->user()->id;
$sanitizedData['user_created_id'] = auth()->user()->id;
if ($allData && $successfulResult = $this->canValidate()) : // if ($successfulResult = $this->validate($this->formValidationRules) ) :
if ($this->canValidate()) :
try {
$successfulResult = $this->model->skipValidation(true)->save($sanitizedData);
} catch (\Exception $e) {
$noException = false;
$this->dealWithException($e);
}
else:
$this->viewData['errorMessage'] = lang('Basic.global.formErr1', [lang('Basic.global.record')]);
$this->session->setFlashdata('formErrors', $this->model->errors());
endif;
endif;
if ($noException && $successfulResult) :
$id = $this->model->db->insertID();
$message = lang('Basic.global.saveSuccess', [lang('Basic.global.record')]) . '.';
return redirect()->to(route_to('editarFactura', $id))->with('sweet-success', $message);
endif; // $noException && $successfulResult
endif; // ($requestMethod === 'post')
$this->viewData['factura'] = isset($sanitizedData) ? new FacturaEntity($sanitizedData) : new FacturaEntity();
$this->viewData['formAction'] = route_to('createFactura');
$this->viewData['boxTitle'] = lang('Basic.global.addNew') . ' ' . lang('Facturas.facturas') . ' ' . lang('Basic.global.addNewSuffix');
helper('form');
$this->viewData['usingSelect2'] = true;
$validation = \Config\Services::validation();
$this->viewData['validation'] = $validation;
$viewFilePath = static::$viewPath . 'viewAddFactura';
return view($viewFilePath, $this->viewData);
} // end function add()
public function edit($id=null){
if ($id == null) :
return $this->redirect2listView();
endif;
$id = filter_var($id, FILTER_SANITIZE_URL);
$factura = $this->model->find($id);
if ($factura == false) :
$message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Facturas.factura')), $id]);
return $this->redirect2listView('sweet-error', $message);
endif;
$this->obtenerDatosFormulario($factura);
$this->viewData['facturaEntity'] = $factura;
$this->viewData['boxTitle'] = lang('Basic.global.edit2') . ' ' . lang('Facturas.factura') . ' ' . lang('Basic.global.edit3');
return $this->displayForm(__METHOD__, $id);
}
public function datatable(){ public function datatable(){
if ($this->request->isAJAX()) { if ($this->request->isAJAX()) {
@ -87,13 +199,217 @@ class Facturas extends \App\Controllers\BaseResourceController
return $this->respond(Collection::datatable( return $this->respond(Collection::datatable(
$resourceData, $resourceData,
$model_linea->getResource("")->countAllResults(), $this->model->getResource("")->countAllResults(),
$model_linea->getResource($search)->countAllResults() $this->model->getResource($search)->countAllResults()
)); ));
} else { } else {
return $this->failUnauthorized('Invalid request', 403); 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);
$facturaEntity = $this->model->find($id);
if ($facturaEntity == false) :
$message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Factura.factura')), $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('Facturas.factura'))]);
$this->session->setFlashdata('formErrors', $this->model->errors());
endif;
$facturaEntity->fill($sanitizedData);
endif;
if ($noException && $successfulResult) :
$id = $facturaEntity->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 menuPedidosPendientes($cliente_id){
if ($this->request->isAJAX()) {
$model = model('\App\Models\Pedidos\PedidoLineaModel');
$pedidos = [];
try{
$pedidos = $model->obtenerLineasPedidoSinFacturar($cliente_id);
}
catch(Exception $e){
}
$newTokenHash = csrf_hash();
$csrfTokenName = csrf_token();
$data = [
'menu' => $pedidos,
$csrfTokenName => $newTokenHash
];
return $this->respond($data);
}
else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function addLineaPedidoImpresion($factura_id){
if ($this->request->isAJAX()) {
$model_pedido_linea = model('\App\Models\Pedidos\PedidoLineaModel');
$model_presupuesto = model('\App\Models\Presupuestos\PresupuestoModel');
$model_factura_linea = model('\App\Models\Facturas\FacturaLineaModel');
try{
$pedido_linea_id = $this->request->getPost('lineaPedido') ?? 0;
$linea = $model_pedido_linea->find($pedido_linea_id);
if($linea){
$presupuesto = $model_presupuesto->find($linea->presupuesto_id);
if($presupuesto){
// Se añade la linea de factura
$descripcion = $model_presupuesto->generarLineaPedido($presupuesto->id, true, $linea->pedido_id);
$cantidad = intval($presupuesto->tirada) - intval($this->model->getCantidadLineaPedidoFacturada($linea->id));
$base = $cantidad * floatval($presupuesto->total_precio_unidad);
$total_iva = $base * ($presupuesto->iva_reducido==1 ? 0.04 : 0.21);
// se redondea a dos decimales
$total_iva = round($total_iva, 2);
$total = $base + $total_iva;
$data = (object)[
'factura_id'=>$factura_id,
'pedido_linea_impresion_id'=>$linea->pedido_id,
'descripcion'=>$descripcion[0]->concepto,
'cantidad'=>$cantidad,
'precio_unidad'=>$presupuesto->total_precio_unidad,
'iva' => $presupuesto->iva_reducido==1 ? 4 : 21,
'base' => $base,
'total_iva' => $total_iva,
'total' => $total,
'user_updated_id' => auth()->user()->id,
];
$model_factura_linea->insert($data);
$id = $model_factura_linea->getInsertID();
if($id){
$model_factura_linea->addFacturaPedidoLinea($factura_id, $linea->id, $cantidad);
$newTokenHash = csrf_hash();
$csrfTokenName = csrf_token();
$data = [
'error' => 0,
'id' => $id,
$csrfTokenName => $newTokenHash
];
return $this->respond($data);
}
}
}
}
catch(Exception $e){
}
$newTokenHash = csrf_hash();
$csrfTokenName = csrf_token();
$data = [
$csrfTokenName => $newTokenHash
];
return $this->respond($data);
}
else {
return $this->failUnauthorized('Invalid request', 403);
}
}
/*************************************
* FUNCIONES AUXILIARES
************************************/
private function obtenerDatosFormulario(&$factura){
if($factura->estado == 'borrador'){
$serieModel = model('App\Models\Configuracion\SeriesFacturasModel');
$serie = $serieModel->find($factura->serie_id);
if($serie){
$factura->numero = str_replace("{numero}", $serie->next, $serie->formato);
}
}
$clienteModel = model('App\Models\Clientes\ClienteModel');
$cliente = $clienteModel->find($factura->cliente_id);
$factura->cliente_alias = $cliente->alias;
$serieModel = model('App\Models\Configuracion\SeriesFacturasModel');
$serie = $serieModel->find($factura->serie_id);
$factura->serie_nombre = $serie->nombre;
$factura->fecha_factura_at_text = $factura->fecha_factura_at ? date('d/m/Y', strtotime($factura->fecha_factura_at)) : '';
}
} }

View File

@ -0,0 +1,192 @@
<?php
namespace App\Controllers\Facturacion;
use App\Models\Facturas\FacturaLineaModel;
use App\Models\Collection;
use DataTables\Editor;
use DataTables\Editor\Field;
use DataTables\Editor\Validate;
class FacturasLineas extends \App\Controllers\BaseResourceController
{
protected $modelName = FacturaLineaModel::class;
protected $format = 'json';
protected static $controllerSlug = 'factura-lineas';
public function datatable($factura_id = null){
if ($this->request->isAJAX() && $factura_id != null) {
$reqData = $this->request->getPost();
if (!isset($reqData['draw']) || !isset($reqData['columns']) ) {
$errstr = 'No data available in response to this specific request.';
$response = $this->respond(Collection::datatable( [], 0, 0, $errstr ), 400, $errstr);
return $response;
}
$start = $reqData['start'] ?? 0;
$length = $reqData['length'] ?? 5;
$search = $reqData['search']['value'];
$requestedOrder = $reqData['order']['0']['column'] ?? 0;
//$order = FacturaModel::SORTABLE[$requestedOrder >= 0 ? $requestedOrder : 0];
$dir = $reqData['order']['0']['dir'] ?? 'asc';
$resourceData = $this->model->getResource($factura_id)->orderBy(1, $dir)->limit($length, $start)->get()->getResultObject();
return $this->respond(Collection::datatable(
$resourceData,
$this->model->getResource($factura_id)->countAllResults(),
$this->model->getResource($factura_id)->countAllResults()
));
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function deleteLinea($factura_linea_id = 0){
if (!empty(static::$pluralObjectNameCc) && !empty(static::$singularObjectNameCc)) {
$objName = mb_strtolower(lang(ucfirst(static::$pluralObjectNameCc).'.'.static::$singularObjectNameCc));
} else {
$objName = lang('Basic.global.record');
}
if($factura_linea_id == 0){
return $this->failNotFound(lang('Basic.global.deleteError', [$objName]));
}
$facturaLinea = $this->model->find($factura_linea_id);
if($facturaLinea == null){
return $this->failNotFound(lang('Basic.global.deleteError', [$objName]));
}
if($facturaLinea->pedido_linea_impresion_id != null){
$this->model->deleteFacturasLineasPedido($facturaLinea->factura_id, $facturaLinea->pedido_linea_impresion_id, $facturaLinea->cantidad);
}
if($facturaLinea->pedido_maquetacion_id != null){
//$this->model->deleteFacturasLineasPedido($facturaLinea->factura_id, $facturaLinea->pedido_maquetacion_id, $facturaLinea->cantidad);
}
$facturaLinea = $this->model->delete($factura_linea_id);
$message = lang('Basic.global.deleteSuccess', [lang('Basic.global.record')]);
$response = $this->respondDeleted(['id' => $factura_linea_id, 'msg' => $message]);
return $response;
}
public function datatable_editor() {
if ($this->request->isAJAX()) {
include(APPPATH . "ThirdParty/DatatablesEditor/DataTables.php");
// Build our Editor instance and process the data coming from _POST
$response = Editor::inst( $db, 'cliente_plantilla_precios_lineas' )
->fields(
Field::inst( 'plantilla_id' ),
Field::inst( 'tipo' ),
Field::inst( 'tipo_maquina' ),
Field::inst( 'tipo_impresion' ),
Field::inst( 'user_updated_id' ),
Field::inst( 'updated_at' ),
Field::inst( 'tiempo_min' )
->getFormatter( 'Format::toDecimalChar')->setFormatter( 'Format::fromDecimalChar')
->validator( 'Validate::notEmpty',array(
'message' => lang('ClientePrecios.validation.required'))
)
->validator('Validate::numeric', array(
"decimal" => ',',
'message' => lang('ClientePrecios.validation.decimal'))
),
Field::inst( 'tiempo_max' )
->getFormatter( 'Format::toDecimalChar')->setFormatter( 'Format::fromDecimalChar')
->validator( 'Validate::notEmpty',array(
'message' => lang('ClientePrecios.validation.required'))
)
->validator('Validate::numeric', array(
"decimal" => ',',
'message' => lang('ClientePrecios.validation.decimal'))
),
Field::inst( 'precio_hora' )
->getFormatter( 'Format::toDecimalChar')->setFormatter( 'Format::fromDecimalChar')
->validator( 'Validate::notEmpty',array(
'message' => lang('ClientePrecios.validation.required'))
)
->validator('Validate::numeric', array(
"decimal" => ',',
'message' => lang('ClientePrecios.validation.decimal'))
),
Field::inst( 'margen' )
->getFormatter( 'Format::toDecimalChar')->setFormatter( 'Format::fromDecimalChar')
->validator( 'Validate::notEmpty',array(
'message' => lang('ClientePrecios.validation.required'))
)
->validator('Validate::numeric', array(
"decimal" => ',',
'message' => lang('ClientePrecios.validation.decimal'))
),
)
->validator(function ($editor, $action, $data) {
if ($action === Editor::ACTION_CREATE || $action === Editor::ACTION_EDIT) {
foreach ($data['data'] as $pkey => $values) {
// Si no se quiere borrar...
if ($data['data'][$pkey]['is_deleted'] != 1) {
$process_data['tiempo_min'] = $data['data'][$pkey]['tiempo_min'];
$process_data['tiempo_max'] = $data['data'][$pkey]['tiempo_max'];
$process_data['tipo'] = $data['data'][$pkey]['tipo'];
$process_data['tipo_maquina'] = $data['data'][$pkey]['tipo_maquina'];
$process_data['tipo_impresion'] = $data['data'][$pkey]['tipo_impresion'];
$response = $this->model->checkIntervals($process_data, $pkey, $data['data'][$pkey]['plantilla_id']);
// No se pueden duplicar valores al crear o al editar
if (!empty($response)) {
return $response;
}
}
}
}
})
->on('preCreate', function ($editor, &$values) {
$session = session();
$datetime = (new \CodeIgniter\I18n\Time("now"));
$editor
->field('user_updated_id')
->setValue($session->id_user);
$editor
->field('updated_at')
->setValue($datetime->format('Y-m-d H:i:s'));
})
->on('preEdit', function ($editor, &$values) {
$session = session();
$datetime = (new \CodeIgniter\I18n\Time("now"));
$editor
->field('user_updated_id')
->setValue($session->id_user);
$editor
->field('updated_at')
->setValue($datetime->format('Y-m-d H:i:s'));
})
->debug(true)
->process($_POST)
->data();
$newTokenHash = csrf_hash();
$csrfTokenName = csrf_token();
$response[$csrfTokenName] = $newTokenHash;
echo json_encode($response);
} else {
return $this->failUnauthorized('Invalid request', 403);
}
}
}

View File

@ -258,6 +258,17 @@ class Pedido extends \App\Controllers\BaseResourceController
} }
} }
public function obtenerPedidosForFacturas(){
if ($this->request->isAJAX()) {
$reqData = $this->request->getPost();
$start = $reqData['start'] ?? 0;
}
else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function getlineas(){ public function getlineas(){
if ($this->request->isAJAX()) { if ($this->request->isAJAX()) {

View File

@ -192,7 +192,7 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
$this->viewData['presupuestoEntity'] = $presupuestoEntity; $this->viewData['presupuestoEntity'] = $presupuestoEntity;
$this->viewData['datosPresupuesto'] = $datosPresupuesto; $this->viewData['datosPresupuesto'] = $datosPresupuesto;
$this->viewData['clienteId'] = $clienteId; $this->viewData['clienteId'] = $presupuestoEntity->cliente_id; // En el caso del edit, se mantiene el clienteId del presupuesto
// Si se ha llamado a esta funcion porque se ha duplicado el presupuesto // Si se ha llamado a esta funcion porque se ha duplicado el presupuesto
// se actualiza la bbdd para que sólo ejecute algunas funciones una vez // se actualiza la bbdd para que sólo ejecute algunas funciones una vez
@ -1449,9 +1449,18 @@ class Presupuestocliente extends \App\Controllers\BaseResourceController
} }
// Servicios // Servicios
if ($datos_guardas > 0) { // se comprueba si $datos guardas es un array
array_push($servicios, 62); // Plegado de guardas if(is_array($datos_guardas)){
if(count($datos_guardas) > 0){
array_push($servicios, 62); // Plegado de guardas
}
} }
else{
if ($datos_guardas > 0) {
array_push($servicios, 62); // Plegado de guardas
}
}
/* /*
'retractilado' => 3, 'retractilado' => 3,
'retractilado5' => 5, 'retractilado5' => 5,

View File

@ -20,11 +20,18 @@ class Test extends BaseController
public function index() public function index()
{ {
$model = new PresupuestoModel(); /*
$data = $model->generarLineaPedido(123); $model = model("\App\Models\Pedidos\PedidoLineaModel");
echo '<pre>'; $data = $model->obtenerLineasPedidoSinFacturar(999);
*/
$model = model("\App\Models\Facturas\FacturaLineaModel");
$data = $model->getResource(9)->get()->getResultObject();
echo('<pre>');
var_dump($data); var_dump($data);
echo '</pre>'; echo('</pre>');
} }

View File

@ -43,8 +43,6 @@ class FacturaEntity extends \CodeIgniter\Entity\Entity
'factura_retificativa_id' => 'int', 'factura_retificativa_id' => 'int',
'cliente_id' => 'int', 'cliente_id' => 'int',
'serie_id' => 'int', 'serie_id' => 'int',
'estado' => 'int',
'estado_pago' => 'int',
'base' => 'float', 'base' => 'float',
'total' => 'float', 'total' => 'float',
'pendiente' => 'float', 'pendiente' => 'float',

View File

@ -8,7 +8,7 @@ class FacturaLineaEntity extends \CodeIgniter\Entity\Entity
protected $attributes = [ protected $attributes = [
'id' => null, 'id' => null,
'factura_id' => null, 'factura_id' => null,
'pedido_impresion_id' => null, 'pedido_linea_impresion_id' => null,
'pedido_maquetacion_id' => null, 'pedido_maquetacion_id' => null,
'descripcion' => null, 'descripcion' => null,
'cantidad' => null, 'cantidad' => null,
@ -19,14 +19,14 @@ class FacturaLineaEntity extends \CodeIgniter\Entity\Entity
'total' => null, 'total' => null,
'data' => null, 'data' => null,
'deleted_at' => null, 'deleted_at' => null,
'user_update_id' => null, 'user_updated_id' => null,
]; ];
protected $casts = [ protected $casts = [
'id' => 'int', 'id' => 'int',
'factura_id' => 'int', 'factura_id' => 'int',
'pedido_impresion_id' => 'int', 'pedido_linea_impresion_id' => 'int',
'pedido_maquetacion_id' => 'int', 'pedido_maquetacion_id' => 'int',
'cantidad' => 'float', 'cantidad' => 'float',
'precio_unidad' => 'float', 'precio_unidad' => 'float',

View File

@ -1,6 +1,7 @@
<?php <?php
return [ return [
'id' => 'ID',
'factura' => 'Invoice', 'factura' => 'Invoice',
'facturaList' => 'Invoice List', 'facturaList' => 'Invoice List',
'facturas' => 'Invoices', 'facturas' => 'Invoices',
@ -54,4 +55,14 @@ return [
'giroDocimiliado' => 'Direct Debit', 'giroDocimiliado' => 'Direct Debit',
'pagare' => 'Promissory Note', 'pagare' => 'Promissory Note',
'transferencia' => 'Transfer', 'transferencia' => 'Transfer',
'datosFactura' => 'Invoice Data',
'addPedidosImpresion' => 'Add Print Orders',
'addPedidosMaquetacion' => 'Add Layout Orders',
'peiddoImpresion' => 'Print Order',
'peiddoMaquetacion' => 'Layout Order',
'nuevaLinea' => 'New Line',
'errors' => [
'requiredFields' => 'Fields marked with * are required',
]
]; ];

View File

@ -52,7 +52,9 @@ return [
'dosCaras' => '2 sides', 'dosCaras' => '2 sides',
'lineasTemplates' =>[ 'lineasTemplates' =>[
'libro' => "[BUDGET %s] Printing of %s copies of %s pages.\nTitle: %s. Author: %s. ISBN: %s.Size: %smm.\n", 'presupuesto' => '[BUDGET %s] ',
'pedido' => '[ORDER %s] ',
'libro' => "Printing of %s copies of %s pages.\nTitle: %s. Author: %s. ISBN: %s.Size: %smm.\n",
'libro_linea_interior' => "%s black pages on %s paper of %s grams", 'libro_linea_interior' => "%s black pages on %s paper of %s grams",
'libro_linea_cubierta' => "\nCover printed on %s on %s paper of %s grams", 'libro_linea_cubierta' => "\nCover printed on %s on %s paper of %s grams",
'libro_linea_sobrecubierta' => "\nDust jacket on %s paper of %s grams", 'libro_linea_sobrecubierta' => "\nDust jacket on %s paper of %s grams",

View File

@ -89,6 +89,7 @@ return [
'ok' => 'Ok', 'ok' => 'Ok',
'wait' => 'Espere', 'wait' => 'Espere',
'yes' => 'Si', 'yes' => 'Si',
'no' => 'No',
], ],

View File

@ -1,6 +1,7 @@
<?php <?php
return [ return [
'id' => 'ID',
'factura' => 'Factura', 'factura' => 'Factura',
'facturaList' => 'Listado de Facturas', 'facturaList' => 'Listado de Facturas',
'facturas' => 'Facturas', 'facturas' => 'Facturas',
@ -54,4 +55,14 @@ return [
'giroDomiciliado' => 'Giro domiciliado', 'giroDomiciliado' => 'Giro domiciliado',
'pagare' => 'Pagaré', 'pagare' => 'Pagaré',
'transferencia' => 'Transferencia', 'transferencia' => 'Transferencia',
'datosFactura' => 'Datos Factura',
'addPedidosImpresion' => 'Añadir Pedidos Impresión',
'addPedidosMaquetacion' => 'Añadir Pedidos Maquetación',
'pedidoImpresion' => 'Pedido Impresión',
'pedidoMaquetacion' => 'Pedido Maquetación',
'nuevaLinea' => 'Nueva Línea',
'errors' => [
'requiredFields' => 'Los campos marcados con * son obligatorios',
]
]; ];

View File

@ -51,7 +51,9 @@ return [
'dosCaras' => '2 caras', 'dosCaras' => '2 caras',
'lineasTemplates' =>[ 'lineasTemplates' =>[
'libro' => "[PRESUPUESTO %s] Impresión de %s ejemplares de %s páginas.\nTítulo: %s. Autor: %s. ISBN: %s.Tamaño: %smm.\n", 'presupuesto' => '[PRESUPUESTO %s] ',
'pedido' => '[PEDIDO %s] ',
'libro' => "Impresión de %s ejemplares de %s páginas.\nTítulo: %s. Autor: %s. ISBN: %s.Tamaño: %smm.\n",
'libro_linea_interior' => "%s páginas en negro sobre papel %s de %s gramos", 'libro_linea_interior' => "%s páginas en negro sobre papel %s de %s gramos",
'libro_linea_cubierta' => "\nCubierta impresa a %s sobre papel %s de %s gramos", 'libro_linea_cubierta' => "\nCubierta impresa a %s sobre papel %s de %s gramos",
'libro_linea_sobrecubierta' => "\nSobrecubierta sobre papel %s de %s gramos", 'libro_linea_sobrecubierta' => "\nSobrecubierta sobre papel %s de %s gramos",

View File

@ -210,6 +210,8 @@ return [
'confirmar' => 'Confirmar presupuesto', 'confirmar' => 'Confirmar presupuesto',
'confirmado' => 'Presupuesto confirmado', 'confirmado' => 'Presupuesto confirmado',
'totalAceptado' => 'Total aceptado',
// Preview // Preview
'preview' => 'Previsualización de configuraciones', 'preview' => 'Previsualización de configuraciones',
'preview-conf-bn' => 'Configuración Blanco y Negro', 'preview-conf-bn' => 'Configuración Blanco y Negro',

View File

@ -315,4 +315,21 @@ class ClienteModel extends \App\Models\BaseModel
public function creditoDisponible($cliente_id){ public function creditoDisponible($cliente_id){
return true; return true;
} }
public function getClienteDataFacturas($cliente_id){
$builder = $this->db
->table($this->table . " t1")
->select(
"
t1.nombre AS cliente_nombre, t1.direccion AS cliente_address, t1.cif AS cliente_cif,
t2.nombre AS cliente_pais, t1.cp AS cliente_cp, t1.ciudad AS cliente_ciudad,
t3.nombre AS cliente_provincia, t1.credito_asegurado AS creditoAsegurado"
)
->where("t1.is_deleted", 0)
->where("t1.id", $cliente_id);
$builder->join("lg_paises t2", "t1.pais_id = t2.id", "left");
$builder->join("lg_provincias t3", "t1.provincia_id = t3.id", "left");
return $builder->get()->getResultArray();
}
} }

View File

@ -91,4 +91,21 @@ class SeriesFacturasModel extends \App\Models\BaseModel
->orLike("t1.grupo", $search) ->orLike("t1.grupo", $search)
->groupEnd(); ->groupEnd();
} }
public function getMenuItemsFacturas(){
$resultSorting = $this->getPrimaryKeyName();
$id = 'id AS id';
$text = 'nombre AS text';
$queryBuilder = $this->db->table($this->table);
$queryBuilder->select([$id, $text]);
$queryBuilder->where('tipo', 'facturacion');
$queryBuilder->where('grupo', '1');
$queryBuilder->orderBy($resultSorting);
$result = $queryBuilder->get()->getResult();
return $result;
}
} }

View File

@ -10,7 +10,7 @@ class FacturaLineaModel extends \App\Models\BaseModel {
// Lista de columnas basada en los campos de la tabla, para asignación masiva // Lista de columnas basada en los campos de la tabla, para asignación masiva
protected $allowedFields = [ protected $allowedFields = [
'factura_id', 'factura_id',
'pedido_impresion_id', 'pedido_linea_impresion_id',
'pedido_maquetacion_id', 'pedido_maquetacion_id',
'descripcion', 'descripcion',
'cantidad', 'cantidad',
@ -21,7 +21,7 @@ class FacturaLineaModel extends \App\Models\BaseModel {
'total', 'total',
'data', 'data',
'deleted_at', 'deleted_at',
'user_update_id' 'user_updated_id'
]; ];
protected $returnType = "App\Entities\Facturas\FacturaLineaEntity"; protected $returnType = "App\Entities\Facturas\FacturaLineaEntity";
@ -30,4 +30,43 @@ class FacturaLineaModel extends \App\Models\BaseModel {
protected $useSoftDeletes = true; protected $useSoftDeletes = true;
public static $labelField = "id"; public static $labelField = "id";
public function getResource($factura_id)
{
$builder = $this->db
->table($this->table . " t1")
->select(
"t1.id AS id, t1.factura_id AS factura_id,
t1.pedido_linea_impresion_id AS pedido_linea_impresion_id, t1.pedido_maquetacion_id AS pedido_maquetacion_id,
t1.descripcion AS concepto, t1.cantidad as unidades, t1.precio_unidad AS precio_unidad, t1.iva AS iva,
t1.base AS subtotal, t1.total_iva AS total_iva, t1.total AS total, t1.data AS data, t2.pedido_id AS pedido_id,
t3.total_aceptado AS total_aceptado"
)
->join("pedidos_linea t2", "t2.id = t1.pedido_linea_impresion_id", "left")
->join("presupuestos t3", "t3.id = t2.presupuesto_id", "left")
->where("t1.factura_id", $factura_id)
->where("t1.deleted_at", null);
return $builder;
}
public function addFacturaPedidoLinea($factura_id, $pedido_linea_id, $cantidad)
{
$data = [
"factura_id" => $factura_id,
"pedido_linea_id" => $pedido_linea_id,
"cantidad" => $cantidad
];
return $this->db->table("facturas_pedidos_lineas")->insert($data);
}
public function deleteFacturasLineasPedido($factura_id, $pedido_linea_id, $cantidad){
$this->db->table("facturas_pedidos_lineas")
->where("factura_id", $factura_id)
->where("pedido_linea_id", $pedido_linea_id)
->where("cantidad", $cantidad)
->delete();
}
} }

View File

@ -28,7 +28,7 @@ class FacturaModel extends \App\Models\BaseModel {
'pedido_id', 'pedido_id',
'factura_retificada_id', 'factura_retificada_id',
'factura_retificativa_id', 'factura_retificativa_id',
'customer_id', 'cliente_id',
'serie_id', 'serie_id',
'numero', 'numero',
'estado', 'estado',
@ -40,13 +40,13 @@ class FacturaModel extends \App\Models\BaseModel {
'pendiente', 'pendiente',
'total_pagos', 'total_pagos',
'creditoAsegurado', 'creditoAsegurado',
'customer_nombre', 'cliente_nombre',
'customer_address', 'cliente_address',
'customer_cif', 'cliente_cif',
'customer_pais', 'cliente_pais',
'customer_cp', 'cliente_cp',
'customer_ciudad', 'cliente_ciudad',
'customer_provincia', 'cliente_provincia',
'created_at', 'created_at',
'updated_at', 'updated_at',
'deleted_at', 'deleted_at',
@ -69,10 +69,10 @@ class FacturaModel extends \App\Models\BaseModel {
$builder = $this->db $builder = $this->db
->table($this->table . " t1") ->table($this->table . " t1")
->select( ->select(
"t1.id AS id, t1.numero AS numero, t1.fecha_factura_at AS fecha_factura_at, "t1.id AS id, t1.numero AS numero, DATE_FORMAT(t1.fecha_factura_at, '%d/%m/%Y') AS fecha_factura_at,
t2.nombre AS cliente, t1.base AS base, t1.total AS total, t1.pendiente AS pendiente, t2.nombre AS cliente, t1.base AS base, t1.total AS total, t1.pendiente AS pendiente,
t1.creditoAsegurado AS creditoAsegurado, t1.estado AS estado, t1.estado_pago AS estado_pago, t1.creditoAsegurado AS creditoAsegurado, t1.estado AS estado, t1.estado_pago AS estado_pago,
t4.nombre AS forma_pago, t3.fecha_vencimiento_at AS venciemento" t4.nombre AS forma_pago, DATE_FORMAT(t3.fecha_vencimiento_at, '%d/%m/%Y') AS vencimiento"
); );
$builder->join("clientes t2", "t2.id = t1.cliente_id", "left"); $builder->join("clientes t2", "t2.id = t1.cliente_id", "left");
@ -88,4 +88,15 @@ class FacturaModel extends \App\Models\BaseModel {
->orLike("t1.id", $search) ->orLike("t1.id", $search)
->groupEnd(); ->groupEnd();
} }
public function getCantidadLineaPedidoFacturada($linea_pedido_id)
{
$builder = $this->db
->table("facturas_pedidos_lineas t1")
->select("SUM(t1.cantidad) AS cantidad")
->where("t1.pedido_linea_id", $linea_pedido_id);
return $builder->get()->getRow()->cantidad;
}
} }

View File

@ -76,4 +76,40 @@ class PedidoLineaModel extends \App\Models\BaseModel
->orLike("t1.id", $search) ->orLike("t1.id", $search)
->groupEnd(); ->groupEnd();
} }
public function obtenerLineasPedidoSinFacturar($cliente_id){
$resultaArray = [];
$builder = $this->db
->table($this->table . " t1")
->select("t1.id AS id, t1.pedido_id AS pedido_id, t3.titulo AS titulo, t4.codigo AS tipo_impresion");
$builder->join("pedidos t2", "t2.id = t1.pedido_id", "left");
$builder->join("presupuestos t3", "t3.id = t1.presupuesto_id", "left");
$builder->join("tipos_presupuestos t4", "t4.id = t3.tipo_impresion_id", "left");
$builder->join("facturas_pedidos_lineas fpl", "fpl.pedido_linea_id = t1.id", "left");
$builder->where("t3.cliente_id", $cliente_id);
$builder->where("t2.estado", "finalizado");
$builder->where("(`t3`.`tirada` > `fpl`.`cantidad` OR fpl.pedido_linea_id IS NULL)");
// Ejecutar la consulta y devolver resultados
$query = $builder->get();
$data = $query->getResult();
foreach($data as $register){
$item = (object)[
'id' => $register->id,
'text' => '['. lang('Pedidos.pedido') . ' ' . $register->pedido_id . '] ' . $register->titulo . ' - ' . lang('Presupuestos.' . $register->tipo_impresion),
];
array_push($resultaArray, $item);
}
return $resultaArray;
}
} }

View File

@ -142,7 +142,7 @@ class PresupuestoModel extends \App\Models\BaseModel
], ],
"titulo" => [ "titulo" => [
"label" => "Presupuestos.titulo", "label" => "Presupuestos.titulo",
"rules" => "trim|required|max_length[30]", "rules" => "trim|required|max_length[300]",
], ],
"inc_rei" => [ "inc_rei" => [
"label" => "Presupuestos.incRei", "label" => "Presupuestos.incRei",
@ -538,7 +538,7 @@ class PresupuestoModel extends \App\Models\BaseModel
return $json; return $json;
} }
public function generarLineaPedido($presupuesto_id) public function generarLineaPedido($presupuesto_id, $forFactura = false, $pedido_id = 0)
{ {
$builder = $this->db $builder = $this->db
->table($this->table . " t1") ->table($this->table . " t1")
@ -565,13 +565,18 @@ class PresupuestoModel extends \App\Models\BaseModel
$presupuesto = $presupuesto[0]; $presupuesto = $presupuesto[0];
// Libro // Libro
if($presupuesto->tipo < 10){ if($presupuesto->tipo < 10 || $presupuesto->tipo==20 || $presupuesto->tipo==21){
if($presupuesto->papel_formato_personalizado == 1){ if($presupuesto->papel_formato_personalizado == 1){
$presupuesto->tamanio= $presupuesto->papel_formato_ancho . "x" . $presupuesto->papel_formato_alto; $presupuesto->tamanio= $presupuesto->papel_formato_ancho . "x" . $presupuesto->papel_formato_alto;
} }
$presupuesto->concepto = sprintf(lang('Pedidos.lineasTemplates.libro'), if($forFactura){
$presupuesto->numero, $presupuesto->concepto = sprintf(lang('Pedidos.lineasTemplates.pedido'), $pedido_id);
}
else{
$presupuesto->concepto = sprintf(lang('Pedidos.lineasTemplates.presupuesto'), $presupuesto->numero);
}
$presupuesto->concepto .= sprintf(lang('Pedidos.lineasTemplates.libro'),
$presupuesto->unidades, $presupuesto->unidades,
$presupuesto->paginas, $presupuesto->paginas,
$presupuesto->titulo, $presupuesto->titulo,

View File

@ -26,20 +26,34 @@
function asyncConfirmDialog(title, msg, yesCallbackFn, noCallbackFn) { function asyncConfirmDialog(title, msg, yesCallbackFn, noCallbackFn) {
var $confirmDialog = $("#modalConfirmYesNo"); var $confirmDialog = $("#modalConfirmYesNo");
$confirmDialog.modal('show'); $confirmDialog.modal('show');
$("#labelTitleConfirmDialog").html(title); $("#labelTitleConfirmDialog").html(title);
$("#labelMsgConfirmDialog").html(msg); $("#labelMsgConfirmDialog").html(msg);
$("#btnYesConfirmDialog").off('click').click(function () { $("#btnYesConfirmDialog").off('click').click(function () {
yesCallbackFn(); yesCallbackFn();
$confirmDialog.modal("hide"); $confirmDialog.modal("hide");
}); });
$("#btnNoConfirmDialog").off('click').click(function () { $("#btnNoConfirmDialog").off('click').click(function () {
noCallbackFn(); noCallbackFn();
$confirmDialog.modal("hide"); $confirmDialog.modal("hide");
}); });
} }
function asyncConfirmDialogWithParams(title, msg, yesCallbackFn, noCallbackFn, params) {
var $confirmDialog = $("#modalConfirmYesNo");
$confirmDialog.modal('show');
$("#labelTitleConfirmDialog").html(title);
$("#labelMsgConfirmDialog").html(msg);
$("#btnYesConfirmDialog").off('click').click(function () {
yesCallbackFn(params);
$confirmDialog.modal("hide");
});
$("#btnNoConfirmDialog").off('click').click(function () {
noCallbackFn(params);
$confirmDialog.modal("hide");
});
}
<?= $this->endSection() ?> <?= $this->endSection() ?>

View File

@ -0,0 +1,139 @@
<div class="row px-0">
<div style="padding-left: 0px;" class="col-md-12 col-lg-6 accordion accordion accordion-bordered mt-3 accordion-without-arrow" id="addPedidosImpresion">
<div class="card accordion-item active mt-3 mx-2">
<h3 class="accordion-header" id="headingAddPedidosImpresion">
<button type="button" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#accordionIcon-1" aria-controls="accordionIcon-1">
<h4><?= lang('Facturas.addPedidosImpresion') ?> </h4>
</button>
</h3>
<div id="accordionAddPedidosImpresionTip" class="accordion show" data-bs-parent="#accordioAddPedidosImpresion">
<div class="accordion-body">
<div class="row">
<div class="col-md-12 col-lg-10">
<select name="pedidoImpresion" id="pedidoImpresion" class="form-select">
</select>
</div>
<div class="col-md-12 col-lg-2">
<button
type="button"
class="btn btn-label-primary float-start me-sm-3 me-1"
name="addNewPedidoImpresion"
id="addNewPedidoImpresion" >
<?= lang("Basic.global.addNew") ?>
</button>
</div>
</div> <!--//row -->
</div> <!--//accordion-body -->
</div> <!--//accordionFechasTip-->
</div> <!--//card-->
</div>
<div style="padding-right: 0px;" class="col-md-12 col-lg-6 accordion accordion accordion-bordered mt-3 accordion-without-arrow" id="addPedidosMaquetacion">
<div class="card accordion-item active mt-3 mx-2">
<h3 class="accordion-header" id="headingAddPedidosMaquetacion">
<button type="button" class="accordion-button collapsed" data-bs-toggle="collapse" data-bs-target="#accordionIcon-1" aria-controls="accordionIcon-1">
<h4><?= lang('Facturas.addPedidosMaquetacion') ?> </h4>
</button>
</h3>
<div id="accordionAddPedidosMaquetacionTip" class="accordion show" data-bs-parent="#accordioAddPedidosMaquetacion">
<div class="accordion-body">
<div class="row">
<div class="col-md-12 col-lg-10">
<select name="pedidoMaquetacion" id="pedidoMaquetacion" class="form-select">
</select>
</div>
<div class="col-md-12 col-lg-2">
<button
type="button"
class="btn btn-label-primary float-start me-sm-3 me-1"
name="addNewPedidoMaquetacion"
id="addNewPedidoMaquetacion" >
<?= lang("Basic.global.addNew") ?>
</button>
</div>
</div> <!--//row -->
</div> <!--//accordion-body -->
</div> <!--//accordionFechasTip-->
</div> <!--//card-->
</div>
</div> <!--//row -->
<?=$this->section('additionalInlineJs') ?>
$('#pedidoImpresion').select2({
placeholder: "<?= lang('Facturas.pedidoImpresion') ?>",
allowClear: true,
ajax: {
url: '<?= route_to("menuPedidosPendientesImpresion", $facturaEntity->cliente_id) ?>',
type: 'post',
dataType: 'json',
data: function (params) {
return {
id: 'id',
text: 'nombre',
searchTerm: params.term,
<?= csrf_token() ?? "token" ?> : <?= csrf_token() ?>v
};
},
delay: 60,
processResults: function (response) {
yeniden(response.<?= csrf_token() ?>);
return {
results: response.menu
};
},
cache: true
}
});
$('#addNewPedidoImpresion').on('click', function(){
var lineaPedido = $('#pedidoImpresion').val();
if(lineaPedido == null) {
return;
}
$.ajax({
url: '<?= route_to("addLineaPedidoImpresion2Factura", $facturaEntity->id) ?>',
type: 'post',
data: {
lineaPedido: lineaPedido,
<?= csrf_token() ?? "token" ?> : <?= csrf_token() ?>v
},
success: function(response) {
yeniden(response.<?= csrf_token() ?>);
// Se actualiza la tabla de lineas de factura
$('#tableOfLineasFactura').DataTable().clearPipeline();
$('#tableOfLineasFactura').DataTable().ajax.reload();
// se ajustan el ancho de las columnas
$('#tableOfLineasFactura').DataTable().columns.adjust().draw();
$('#pedidoImpresion').val(null).trigger('change');
}
});
});
$('#pedidoMaquetacion').select2({
placeholder: "<?= lang('Facturas.pedidoMaquetacion') ?>",
allowClear: true,
width: '100%'
});
<?=$this->endSection() ?>

View File

@ -0,0 +1,307 @@
<div class="accordion accordion-bordered mt-3" id="cabeceraFactura">
<div class="card accordion-item active">
<h2 class="accordion-header" id="headingFacturas">
<button type="button" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#accordionFacturaTip" aria-expanded="false" aria-controls="accordionFacturaTip">
<h3><?= lang("Facturas.datosFactura") ?></h3>
</button>
</h2>
<div id="accordionFacturaTip" class="accordion-collapse collapse show" data-bs-parent="#accordioFactura">
<div class="accordion-body">
<div class="row">
<h4><?= lang('Facturas.factura') . ': '?> <span style="color:red;"> <?= lang('Facturas.' . $facturaEntity->estado)?> </span></h4>
</div>
<div class="row mb-2">
<div class="col-md-12 col-lg-2 px-4">
<?php if ($facturaEntity->estado === 'borrador') : ?>
<div class="mb-1">
<label for="id" class="form-label">
<?= lang('Facturas.id') ?>
</label>
<input disabled id="id" name="id" tabindex="1" maxLength="11" class="form-control" value="<?= old('id', $facturaEntity->id) ?>" >
</div>
<?php else : ?>
<div class="mb-1">
<label for="id" class="form-label">
<?= lang('Facturas.numeroFactura') ?>
</label>
<input disabled id="numero" name="numero" tabindex="1" maxLength="11" class="form-control" value="<?= old('numero', $facturaEntity->numero) ?>" >
</div>
<?php endif; ?>
</div>
<div class="col-md-12 col-lg-2 px-4">
<div class="mb-1">
<label for="serie_id" class="form-label">
<?= lang('Facturas.serieFacturacion') ?>
</label>
<select id="serie_id" tabindex="2" name="serie_id" class="form-control select2bs2" style="width: 100%;">
<option value="<?= old('serie_id', $facturaEntity->serie_id) ?>" selected><?= old('serie_nombre', $facturaEntity->serie_nombre) ?></option>
</select>
</div>
</div><!--//.mb-3 -->
<div class="col-md-12 col-lg-2 px-4">
<div class="mb-1">
<label for="creditoAsegurado" class="form-label">
<?= lang('Facturas.creditoAsegurado') ?>
</label>
<select id="creditoAsegurado" tabindex="3" name="creditoAsegurado" class="form-control select2bs2" style="width: 100%;">
<option value="0" <?= ($facturaEntity->creditoAsegurado == 0)?'selected':'' ?>> <?= lang('Basic.global.no') ?> </option>
<option value="1" <?= ($facturaEntity->creditoAsegurado == 1)?'selected':'' ?>> <?= lang('Basic.global.yes') ?> </option>
</select>
</div>
</div><!--//.mb-3 -->
<div class="col-md-12 col-lg-2 px-4">
<div class="mb-1">
<label for="fecha_factura_at" class="form-label">
<?= lang('Facturas.fechaFactura') ?>
</label>
<input type="text" value="" tabindex="4" id="fecha_factura_at" name="fecha_factura_at" tabindex="1" maxLength="11" class="form-control" value="<?= old('fecha_factura_at', $facturaEntity->fecha_factura_at) ?>" >
</div>
</div>
<div class="col-md-12 col-lg-4 px-4">
<div class="mb-1">
<label for="cliente_id" class="form-label">
<?= lang('Facturas.cliente') ?>
<div class="btn-group btn-group-sm">
<a href="<?= route_to('editarCliente', $facturaEntity->cliente_id); ?>" target="_blank" ><i class="ti ti-file-search ti-sm btn-edit mx-2" data-id="${data.id}"></i></a>
</div>
</label>
<select id="cliente_id" tabindex="5" name="tabindex="5"" class="form-control select2bs2" style="width: 100%;">
<option value="<?= old('cliente_id', $facturaEntity->cliente_id) ?>" selected><?= old('cliente_alias', $facturaEntity->cliente_alias) ?></option>
</select>
</div>
</div><!--//.mb-3 -->
</div><!--//.row -->
<div class="row mb-2">
<div class="col-md-12 col-lg-6 px-4">
<div class="mb-1">
<label for="cliente_nombre" class="form-label">
<?= lang('Facturas.razonSocial') ?>
</label>
<input id="cliente_nombre" name="cliente_nombre" tabindex="6" class="form-control"" value="<?= old('cliente_nombre', $facturaEntity->cliente_nombre) ?>"></input>
</div>
</div>
<div class="col-md-12 col-lg-3 px-4">
<div class="mb-1">
<label for="cliente_cif" class="form-label">
<?= lang('Facturas.cif') ?>
</label>
<input id="cliente_cif" name="cliente_cif" tabindex="7" class="form-control" value="<?= old('cliente_cif', $facturaEntity->cliente_cif) ?>"></input>
</div>
</div>
<div class="col-md-12 col-lg-3 px-4">
<div class="mb-1">
<label for="cliente_pais" class="form-label">
<?= lang('Facturas.pais') ?>
</label>
<input id="cliente_pais" name="cliente_pais" tabindex="8" class="form-control"" value="<?= old('cliente_pais', $facturaEntity->cliente_pais) ?>"></input>
</div>
</div>
</div><!--//.row -->
<div class="row mb-3">
<div class="col-md-12 col-lg-4 px-4">
<div class="mb-1">
<label for="cliente_direccion" class="form-label">
<?= lang('Facturas.direccion') ?>
</label>
<input id="cliente_direccion" name="cliente_direccion" tabindex="6" class="form-control"" value="<?= old('cliente_address', $facturaEntity->cliente_address) ?>"></input>
</div>
</div>
<div class="col-md-12 col-lg-2 px-4">
<div class="mb-1">
<label for="cliente_cp" class="form-label">
<?= lang('Facturas.cp') ?>
</label>
<input id="cliente_cp" name="cliente_cp" tabindex="7" class="form-control" value="<?= old('cliente_cp', $facturaEntity->cliente_cp) ?>"></input>
</div>
</div>
<div class="col-md-12 col-lg-3 px-4">
<div class="mb-1">
<label for="cliente_ciudad" class="form-label">
<?= lang('Facturas.localidad') ?>
</label>
<input id="cliente_ciudad" name="cliente_ciudad" tabindex="8" class="form-control"" value="<?= old('cliente_ciudad', $facturaEntity->cliente_ciudad) ?>"></input>
</div>
</div>
<div class="col-md-12 col-lg-3 px-4">
<div class="mb-1">
<label for="cliente_provincia" class="form-label">
<?= lang('Facturas.provincia') ?>
</label>
<input id="cliente_provincia" name="cliente_provincia" tabindex="8" class="form-control"" value="<?= old('cliente_provincia', $facturaEntity->cliente_provincia) ?>"></input>
</div>
</div>
</div><!--//.row -->
<div class="row">
<div class="col-md-12 col-lg-12 px-4">
<div class="pt-4">
<?php if ($facturaEntity->estado === 'validada' && (auth()->user()->inGroup('beta') || auth()->user()->inGroup('admin'))) : ?>
<button
type="button"
class="btn btn-label-primary float-start me-sm-3 me-1"
name="pasarBorrador"
id="pasarBorrador" >
<span class="ti-xs ti ti-save me-1"></span>
<?= lang("Facturas.pasarBorrador") ?>
</button>
<?php endif; ?>
<button
type="button"
class="btn btn-label-primary float-start me-sm-3 me-1"
name="exportar_lineas"
id="exportar_lineas" >
<span class="ti-xs ti ti-file-spreadsheet me-1"></span>
<?= lang("Facturas.exportarLineas") ?>
</button>
<button
type="button"
class="btn btn-label-primary float-start me-sm-3 me-1"
name="duplicar"
id="duplicar" >
<span class="ti-xs ti ti-copy me-1"></span>
<?= lang("Facturas.duplicar") ?>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<?=$this->section('additionalInlineJs') ?>
$("#fecha_factura_at").flatpickr({
defaultDate: <?= $facturaEntity->fecha_factura_at_text ? "'".$facturaEntity->fecha_factura_at_text."'" : 'null' ?>,
dateFormat: "d/m/Y",
locale: {
firstDayOfWeek: 1,
weekdays: {
shorthand: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa'],
longhand: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
},
months: {
shorthand: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Оct', 'Nov', 'Dic'],
longhand: ['Enero', 'Febreo', 'Мarzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
},
},
onChange: function(selectedDates, dateStr, instance) {
<?php if ($facturaEntity->estado == 'borrador'): ?>
updateDate('fecha_entrega_at', dateStr);
<?php endif; ?>
}
});
function updateDate(elementId, dateStr) {
var id = <?=$facturaEntity->id ?>;
data = {
<?= csrf_token() ?? "token" ?>: <?= csrf_token() ?>v,
};
var parts = dateStr.split('/');
var newFormat = parts[2] + '-' + parts[1] + '-' + parts[0]; // Asume dateStr en formato d/m/Y.
data[elementId] = newFormat;
var url = '<?= route_to('actualizarFactura', ':id') ?>';
url = url.replace(':id', id );
$.ajax({
url: url,
type: 'POST',
data: data,
success: function(response){
if('error' in response){
}
}
});
}
$('#serie_id').select2({
allowClear: false,
minimumResultsForSearch: -1,
ajax: {
url: '<?= route_to("menuItemsOfSeriesFacturas") ?>',
type: 'post',
dataType: 'json',
data: function(params) {
return {
id: 'id',
text: 'nombre',
searchTerm: params.term,
<?= csrf_token() ?? "token" ?> : <?= csrf_token() ?>v
};
},
delay: 60,
processResults: function(response) {
yeniden(response.<?= csrf_token() ?>);
return {
results: response.menu
};
},
cache: true
}
});
$('#cliente_id').select2({
allowClear: false,
ajax: {
url: '<?= route_to("menuItemsOfClientes") ?>',
type: 'post',
dataType: 'json',
data: function(params) {
return {
id: 'id',
text: 'alias',
searchTerm: params.term,
<?= csrf_token() ?? "token" ?> : <?= csrf_token() ?>v
};
},
delay: 60,
processResults: function(response) {
yeniden(response.<?= csrf_token() ?>);
return {
results: response.menu
};
},
cache: true
}
});
<?=$this->endSection() ?>

View File

@ -0,0 +1,327 @@
<div class="accordion accordion-bordered mt-3" id="lineasFactura">
<div class="card accordion-item active">
<h2 class="accordion-header" id="headingLineasFacturas">
<button type="button" class="accordion-button" data-bs-toggle="collapse" data-bs-target="#accordionLineasFacturaTip" aria-expanded="false" aria-controls="accordionLineasFacturaTip">
<h3><?= lang("Facturas.lineas") ?></h3>
</button>
</h2>
<div id="accordionLineasFacturaTip" class="accordion-collapse collapse show" data-bs-parent="#accordioLineasFactura">
<div class="accordion-body">
<table id="tableOfLineasFactura" class="table table-striped table-hover" style="width: 100%;grid-template-columns: 1fr 1fr 6fr 1fr 1fr 1fr;">
<thead>
<tr>
<th></th>
<th>id</th>
<th></th>
<th></th>
<th></th>
<th><?= lang('Facturas.unidades') ?></th>
<th><?= lang('Facturas.concepto') ?></th>
<th><?= lang('Facturas.precioUnidad') ?></th>
<th><?= lang('Facturas.iva') ?></th>
<th><?= lang('Facturas.subtotal') ?></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td colspan="8" style="text-align:right">Subtotal:</td>
<td id="subtotal-sum"></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="8" style="text-align:right">I.V.A.:</td>
<td id="total-iva-sum"></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="8" style="text-align:right">Total:</td>
<td id="total-sum"></td>
<td></td>
<td></td>
</tr>
<tr>
<td colspan="8" style="text-align:right">Pendiente de pago:</td>
<td id="pendiente-pago"></td>
<td></td>
<td></td>
</tr>
</tfoot>
</table>
<?php if($facturaEntity->estado =='borrador') : ?>
<div class="row">
<div class="col-md-12 col-lg-2">
<button
type="button"
class="btn btn-label-primary float-start me-sm-3 me-1"
name="addLineaFactura"
id="addLineaFactura" >
<?= lang("Facturas.nuevaLinea") ?>
</button>
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?=$this->section('additionalInlineJs') ?>
const actionBtns = function(data) {
// se comprueba si data es null
if (data.pedido_id === null) {
return `
<td class="text-right py-0 align-middle">
<div class="row mb-2">
<div class="btn-group btn-group-sm"><span class="edit"><a href="javascript:void(0);"><i class="ti ti-pencil ti-sm btn-edit mx-2" data-id="${data.id}"></i></a></span>
<a href="javascript:void(0);"><i class="ti ti-trash ti-sm btn-delete mx-2" data-id="${data.id}"></i></a>
<span class="edit"><a href="javascript:void(0);"><i class="ti ti-pencil ti-sm btn-edit mx-2" data-id="${data.id}"></i></a></span>
</div>
</div>
</td>`;
}
else{
return `
<td class="text-right py-0 align-middle">
<div class="row mb-2">
<div class="btn-group btn-group-sm">
<a href="javascript:void(0);"><i class="ti ti-trash ti-sm btn-delete mx-2" data-id="${data.id}"></i></a>
<span class="edit"><a href="javascript:void(0);"><i class="ti ti-pencil ti-sm btn-edit mx-2" data-id="${data.id}"></i></a></span>
</div>
</div>
<div class="row">
<button type="button" class="btn btn-sm btn-primary btn-view_pedido" data-id="${data.pedido_id}">Ver pedido</button>
</div>
</td>`;
}
};
var editor_lineas = new $.fn.dataTable.Editor( {
ajax: {
url: "<?= route_to('editorOfLineasFacturas') ?>",
headers: {
<?= csrf_token() ?? "token" ?> : <?= csrf_token() ?>v,
},
},
table : "#tableOfLineasFactura",
idSrc: 'id',
fields: [
{
name: "unidades",
}, {
name: "concepto"
}, {
name: "precio_unidad",
}
]
} );
editor_lineas.on( 'preSubmit', function ( e, d, type ) {
if ( type === 'create'){
d.data[0]['factura_id'] = <?= $facturaEntity->id ?>;
}
else if(type === 'edit' ) {
for (v in d.data){
d.data[v]['factura_id'] = <?= $facturaEntity->id ?>;
}
}
});
editor_lineas.on( 'postSubmit', function ( e, json, data, action ) {
yeniden(json.<?= csrf_token() ?>);
});
editor_lineas.on( 'submitSuccess', function ( e, json, data, action ) {
tableLineas.clearPipeline();
tableLineas.draw();
});
// Activate an inline edit on click of a table cell
$('#tableOfLineasFactura').on( 'click', 'tbody span.edit', function (e) {
editor_lineas.inline(
tableLineas.cells(this.parentNode.parentNode, '*').nodes(),
{
cancelHtml: '<a href="javascript:void(0);"><i class="ti ti-x"></i></a>',
cancelTrigger: 'span.cancel',
submitHtml: '<a href="javascript:void(0);"><i class="ti ti-device-floppy"></i></a>',
submitTrigger: 'span.edit',
submit: 'allIfChanged'
}
);
} );
var tableLineas = $('#tableOfLineasFactura').DataTable({
processing: true,
serverSide: true,
autoWidth: true,
responsive: true,
scrollX: true,
columns: [
{data: null, render: actionBtns},
{data: "id"},
{data: "pedido_linea_impresion_id"},
{data: "pedido_maquetacion_id"},
{data: "pedido_id"},
{data: "unidades"},
{
data: "concepto",
render: function (data, type, row, meta) {
// se convierten a float data.total_aceptado y subtotal
var total_aceptado = parseFloat(row.total_aceptado);
var subtotal = parseFloat(row.subtotal);
var error_text = '';
if(total_aceptado != subtotal){
error_text = 'El total del pedido ('+ total_aceptado + '€) no coincide con la línea ('+ subtotal + '€)';
}
return `
<div>
${data}
</div>
<div class="mt-5">
<span style="color: red;" id="error-${meta.row}">${error_text}</span>
</div>
<div class="mt-2">
<label for="input-${meta.row}">Total aceptado</label>
<input readonly type="text" id="input-${meta.row}" value="${row.total_aceptado}">
</div>
`;
}
},
{data: "precio_unidad"},
{data: "iva"},
{data: "subtotal"},
{data: "total_iva"},
{data: "total"},
],
order: [[1, "asc"]],
dom: 't',
language: {
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
},
ajax : $.fn.dataTable.pipeline( {
url: '<?= route_to('dataTableOfLineasFacturas', $facturaEntity->id) ?>',
method: 'POST',
headers: {'X-Requested-With': 'XMLHttpRequest'},
async: true,
}),
columnDefs: [
{
orderable: false,
searchable: false,
targets: [0]
},
{
visible: false,
targets: [1, 2, 3, 4, 10, 11]
}
],
footerCallback: function (row, data, start, end, display) {
var api = this.api();
// Remove the formatting to get integer data for summation
var intVal = function (i) {
return typeof i === 'string' ?
i.replace(/[\$,]/g, '')*1 :
typeof i === 'number' ?
i : 0;
};
// Total over all pages
var totalSubtotal = api
.column(8)
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
}, 0);
var totalIVA = api
.column(9)
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
}, 0);
var totalTotal = api
.column(10)
.data()
.reduce(function (a, b) {
return intVal(a) + intVal(b);
}, 0);
// Update footer
$('#subtotal-sum').html(totalSubtotal.toFixed(2));
$('#total-iva-sum').html(totalIVA.toFixed(2));
$('#total-sum').html(totalTotal.toFixed(2));
// Assuming pendiente de pago is totalTotal - totalIVA for this example
var pendientePago = totalTotal ;//- totalIVA;
$('#pendiente-pago').html(pendientePago.toFixed(2));
}
});
// Delete row
$(document).on('click', '.btn-delete', function(e) {
//$(".btn-remove").attr('data-id', $(this).attr('data-id'));
const dataId = $(this).attr('data-id');
const row = $(this).closest('tr');
if ($.isNumeric(dataId)) {
asyncConfirmDialogWithParams(
"Borrar Linea de Factura",
"¿Está seguro de borrar la línea? Esta acción no se puede deshacer.",
deleteConfirmed, null, [dataId, row])
}
});
function deleteConfirmed(params){
var factura_linea_id = params[0];
var row = params[1];
var url = '<?= route_to('deleteLineaFactura', ':id') ?>';
url = url.replace(':id', factura_linea_id );
$.ajax({
url: url,
method: 'GET',
}).done((data, textStatus, jqXHR) => {
$('#tableOfLineasFactura').DataTable().clearPipeline();
$('#tableOfLineasFactura').DataTable().row($(row)).invalidate().draw();
}).fail((jqXHR, textStatus, errorThrown) => {
popErrorAlert(jqXHR.responseJSON.messages.error)
})
}
$(document).on('click', '.btn-view_pedido', function(e) {
var pedido_id = $(this).data('id');
var url = '<?= route_to('editarPedido', ':id') ?>';
url = url.replace(':id', pedido_id );
window.open(url, '_blank');
});
<?=$this->endSection() ?>

View File

@ -0,0 +1,118 @@
<?= $this->include('themes/_commonPartialsBs/datatables') ?>
<?= $this->include("themes/_commonPartialsBs/select2bs5") ?>
<?= $this->include("themes/_commonPartialsBs/sweetalert") ?>
<?= $this->include('themes/_commonPartialsBs/_confirm2delete') ?>
<?=$this->extend('themes/vuexy/main/defaultlayout') ?>
<?= $this->section("content") ?>
<div class="row">
<div class="col-12">
<div class="card card-info">
<div class="card-header">
<h3 class="card-title"><?= $boxTitle ?? $pageTitle ?></h3>
</div><!--//.card-header -->
<form id="addFacturaForm" class="card-body" method="post" action="<?= $formAction ?>">
<?= csrf_field() ?>
<?= view("themes/_commonPartialsBs/_alertBoxes") ?>
<?= !empty($validation->getErrors()) ? $validation->listErrors("bootstrap_style") : "" ?>
<div class="row">
<div class="col-md-12 col-lg-6 px-4">
<div class="mb-3">
<label for="cliente_id" class="form-label">
<?= lang('Presupuestos.clienteId') ?>*
</label>
<select id="cliente_id" name="cliente_id" class="form-control select2bs2" style="width: 100%;"></select>
</div><!--//.mb-3 -->
</div><!--//.col -->
</div><!--//.row -->
<div class="row">
<div class="col-md-12 col-lg-6 px-4">
<div class="mb-3">
<label for="serie_id" class="form-label">
<?= lang('Facturas.serieFacturacion') ?>*
</label>
<select id="serie_id" name="serie_id" class="form-control select2bs2" style="width: 100%;"></select>
</div><!--//.mb-3 -->
</div><!--//.col -->
</div><!--//.row -->
<div class="pt-4">
<input type="submit"
class="btn btn-primary float-start me-sm-3 me-1"
name="save"
value="<?= lang("Basic.global.Save") ?>"
/>
<?= anchor(route_to("tarifaAcabadoList"), lang("Basic.global.Cancel"), ["class" => "btn btn-secondary float-start"]) ?>
</div><!-- /.card-footer -->
</form>
</div><!-- //.card -->
</div><!--//.col -->
</div><!--//.row -->
<?= $this->endSection() ?>
<?= $this->section("additionalInlineJs") ?>
$('#cliente_id').select2({
allowClear: false,
ajax: {
url: '<?= route_to("menuItemsOfClientes") ?>',
type: 'post',
dataType: 'json',
data: function(params) {
return {
id: 'id',
text: 'nombre',
searchTerm: params.term,
<?= csrf_token() ?? "token" ?> : <?= csrf_token() ?>v
};
},
delay: 60,
processResults: function(response) {
yeniden(response.<?= csrf_token() ?>);
return {
results: response.menu
};
},
cache: true
}
});
$('#serie_id').select2({
allowClear: false,
minimumResultsForSearch: -1,
ajax: {
url: '<?= route_to("menuItemsOfSeriesFacturas") ?>',
type: 'post',
dataType: 'json',
data: function(params) {
return {
id: 'id',
text: 'nombre',
searchTerm: params.term,
<?= csrf_token() ?? "token" ?> : <?= csrf_token() ?>v
};
},
delay: 60,
processResults: function(response) {
yeniden(response.<?= csrf_token() ?>);
return {
results: response.menu
};
},
cache: true
}
});
<?= $this->endSection() ?>

View File

@ -0,0 +1,69 @@
<?= $this->include('themes/_commonPartialsBs/datatables') ?>
<?= $this->include("themes/_commonPartialsBs/select2bs5") ?>
<?= $this->include("themes/_commonPartialsBs/sweetalert") ?>
<?= $this->include('themes/_commonPartialsBs/_confirm2delete') ?>
<?=$this->extend('themes/vuexy/main/defaultlayout') ?>
<?= $this->section("content") ?>
<div class="row">
<div class="col-12">
<div class="card card-info">
<div class="card-header">
<h3 class="card-title"><?= $boxTitle ?? $pageTitle ?></h3>
</div><!--//.card-header -->
<form id="addFacturaForm" class="card-body" method="post" action="<?= $formAction ?>">
<?= csrf_field() ?>
<?= view("themes/_commonPartialsBs/_alertBoxes") ?>
<?= !empty($validation->getErrors()) ? $validation->listErrors("bootstrap_style") : "" ?>
<?= view("themes/vuexy/form/facturas/_facturaCabeceraItems") ?>
<?php if($facturaEntity->estado =='borrador') : ?>
<?= view("themes/vuexy/form/facturas/_addPedidosItems") ?>
<?php endif; ?>
<?= view("themes/vuexy/form/facturas/_facturaLineasItems") ?>
<div class="pt-4">
<input type="submit"
class="btn btn-primary float-start me-sm-3 me-1"
name="save"
value="<?= lang("Basic.global.Save") ?>"
/>
<?= anchor(route_to("tarifaAcabadoList"), lang("Basic.global.Cancel"), ["class" => "btn btn-secondary float-start"]) ?>
</div><!-- /.card-footer -->
</form>
</div><!-- //.card -->
</div><!--//.col -->
<?= view("themes/_commonPartialsBs/_modalConfirmDialog") ?>
</div><!--//.row -->
<?= $this->endSection() ?>
<?= $this->section("additionalInlineJs") ?>
<?= $this->endSection() ?>
<?=$this->section('css') ?>
<link rel="stylesheet" href="<?= site_url("/themes/vuexy/vendor/libs/flatpickr/flatpickr.css") ?>">
<link rel="stylesheet" href="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/buttons.bootstrap5.min.css") ?>">
<link rel="stylesheet" href="<?= site_url('themes/vuexy/css/sk-datatables.css') ?>">
<link rel="stylesheet" href="<?= site_url('themes/vuexy/css/datatables-editor/editor.dataTables.min.css') ?>">
<?=$this->endSection() ?>
<?= $this->section('additionalExternalJs') ?>
<script src="<?= site_url("/themes/vuexy/vendor/libs/flatpickr/flatpickr.js") ?>"></script>
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/dataTables.buttons.min.js") ?>"></script>
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/buttons.bootstrap5.min.js") ?>"></script>
<script src="<?= site_url("themes/vuexy/vendor/libs/datatables-sk/plugins/select/dataTables.select.min.js") ?>"></script>
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/buttons.html5.min.js") ?>"></script>
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/buttons/buttons.print.min.js") ?>"></script>
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/jszip/jszip.min.js") ?>"></script>
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/pdfmake/pdfmake.min.js") ?>" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="<?= site_url("/themes/vuexy/vendor/libs/datatables-sk/plugins/pdfmake/vfs_fonts.js") ?>"></script>
<script src="<?= site_url('themes/vuexy/js/datatables-editor/dataTables.editor.min.js') ?>"></script>
<?=$this->endSection() ?>

View File

@ -49,12 +49,22 @@
const lastColNr = $('#tableOfFacturas').find("tr:first th").length - 1; const lastColNr = $('#tableOfFacturas').find("tr:first th").length - 1;
const actionBtns = function(data) { const actionBtns = function(data) {
return ` if(data.estado == 'borrador'){
return `
<td class="text-right py-0 align-middle">
<div class="btn-group btn-group-sm">
<a href="javascript:void(0);"><i class="ti ti-pencil ti-sm btn-edit mx-2" data-id="${data.id}"></i></a>
</div>
</td>`;
}
else{
return `
<td class="text-right py-0 align-middle"> <td class="text-right py-0 align-middle">
<div class="btn-group btn-group-sm"> <div class="btn-group btn-group-sm">
<a href="javascript:void(0);"><i class="ti ti-eye ti-sm btn-edit mx-2" data-id="${data.id}"></i></a> <a href="javascript:void(0);"><i class="ti ti-eye ti-sm btn-edit mx-2" data-id="${data.id}"></i></a>
</div> </div>
</td>`; </td>`;
}
}; };
theTable = $('#tableOfFacturas').DataTable({ theTable = $('#tableOfFacturas').DataTable({
@ -141,8 +151,7 @@
} }
} }
}, },
{ 'data': 'total_presupuesto' }, { 'data': 'forma_pago',
{ 'data': forma_pago,
render: function(data, type, row, meta) { render: function(data, type, row, meta) {
switch(data){ switch(data){
case "cheque": case "cheque":
@ -176,14 +185,14 @@
} }
} }
}, },
{ 'data': vencimiento }, { 'data': 'vencimiento' },
{ 'data': actionBtns } { 'data': actionBtns }
] ]
}); });
$(document).on('click', '.btn-edit', function(e) { $(document).on('click', '.btn-edit', function(e) {
var url = '<?= route_to('editarPedido', ':id') ?>'; var url = '<?= route_to('editarFactura', ':id') ?>';
url = url.replace(':id', `${$(this).attr('data-id')}` ); url = url.replace(':id', `${$(this).attr('data-id')}` );
window.location.href = url; window.location.href = url;
}); });

View File

@ -130,7 +130,6 @@ $(document).on('click', '.btn-view', function(e) {
var url = '<?= route_to('editarPresupuestoCliente2', ':id') ?>'; var url = '<?= route_to('editarPresupuestoCliente2', ':id') ?>';
<?php endif; ?> <?php endif; ?>
url = url.replace(':id', `${$(this).attr('data-id')}` ); url = url.replace(':id', `${$(this).attr('data-id')}` );
console.log(url);
window.open( window.open(
url, url,
'_blank' // <- This is what makes it open in a new window. '_blank' // <- This is what makes it open in a new window.

View File

@ -16,7 +16,7 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-6 mb-3" <?= $clienteId != 0 ?' style="display:none;"':''?>> <div class="col-sm-6 mb-3" <?= $clienteId != 0 && !(auth()->user()->inGroup('admin') || auth()->user()->inGroup('beta')) ?' style="display:none;"':''?>>
<label for="clienteId" class="form-label"> <label for="clienteId" class="form-label">
<?= lang('Presupuestos.clienteId') ?>* <?= lang('Presupuestos.clienteId') ?>*
</label> </label>

View File

@ -97,7 +97,7 @@
$total = $presupuestoEntity->total_aceptado; $total = $presupuestoEntity->total_aceptado;
$iva = $presupuestoEntity->iva_reducido?1.04:1.21; $iva = $presupuestoEntity->iva_reducido?1.04:1.21;
$total *= $iva; $total *= $iva;
$total_unidad = $total / $presupuestoEntity->tirada; $total_unidad = $presupuestoEntity->total_precio_unidad * $iva;;
echo '<h4 id="resumenTotalIVA" class="mb-1">Total: ' . round($total, 2) . '€</h4>'; echo '<h4 id="resumenTotalIVA" class="mb-1">Total: ' . round($total, 2) . '€</h4>';
echo '<h6 id="resumenPrecioU" class="mb-0">' . round($total_unidad, 4) . '€/ud</h6>' echo '<h6 id="resumenPrecioU" class="mb-0">' . round($total_unidad, 4) . '€/ud</h6>'
?> ?>

View File

@ -606,7 +606,7 @@ async function calcularPresupuesto() {
if($('#colorColorDiv').hasClass('checked') || $('#colorColorHqDiv').hasClass('checked')) if($('#colorColorDiv').hasClass('checked') || $('#colorColorHqDiv').hasClass('checked'))
isColor = true; isColor = true;
let isHq = false; let isHq = false;
if($('#colorNegroDiv').hasClass('checked') || $('#colorColorHqDiv').hasClass('checked')) if($('#colorNegroHqDiv').hasClass('checked') || $('#colorColorHqDiv').hasClass('checked'))
isHq = true; isHq = true;
if(!comprobarTiradasPOD()){ if(!comprobarTiradasPOD()){

View File

@ -76,6 +76,16 @@
</div> </div>
</div> </div>
<?php if ($presupuestoEntity->estado_id == 2): ?>
<div class="row mt-5">
<div class="mb-1">
<label for="paginas" class="form-label">
<?= lang('Presupuestos.totalAceptado') ?>
</label>
<input disabled type="text" id="totalAceptado" name="totalAceptado" class="form-control" value="<?= old('paginas', $presupuestoEntity->total_aceptado) ?>" <?php echo ($tipo_impresion_id == 21)?' max=80':'' ?>>
</div><!--//.mb-3 -->
</div>
<?php endif; ?>
</div> <!-- //.accordion-body --> </div> <!-- //.accordion-body -->
</div> <!-- //.accordion-collapse --> </div> <!-- //.accordion-collapse -->

View File

@ -177,8 +177,8 @@ function updateTotales(updateLP=true, updateServicios=true, updateEnvio=true){
margenEnvios = parseFloat($('#margenEnvios').attr('val')) margenEnvios = parseFloat($('#margenEnvios').attr('val'))
} }
var totalCostes = totalPapel + totalImpresion + totalServicios + totalEnvios var totalCostes = parseFloat(totalPapel.toFixed(2)) + parseFloat(totalImpresion.toFixed(2)) + parseFloat(totalServicios.toFixed(2)) + parseFloat(totalEnvios.toFixed(2))
var totalMargenes = margenPapel + margenImpresion + margenServicios + margenEnvios var totalMargenes = parseFloat(margenPapel.toFixed(2)) + parseFloat(margenImpresion.toFixed(2)) + parseFloat(margenServicios.toFixed(2)) + parseFloat(margenEnvios.toFixed(2))
$('#totalCostes').text((addSeparatorsNF(totalCostes.toFixed(2), ".", ",", ".")) + "€") $('#totalCostes').text((addSeparatorsNF(totalCostes.toFixed(2), ".", ",", ".")) + "€")
$('#totalMargenes').text((addSeparatorsNF(totalMargenes.toFixed(2), ".", ",", ".")) + "€") $('#totalMargenes').text((addSeparatorsNF(totalMargenes.toFixed(2), ".", ",", ".")) + "€")
$('#totalCostes').attr('val',(totalCostes).toFixed(2) + '€') $('#totalCostes').attr('val',(totalCostes).toFixed(2) + '€')
@ -251,11 +251,13 @@ function getValuesResumenForm(){
formResumen += '&total_presupuesto=' + $('#totalDespuesDecuento').attr('val'); formResumen += '&total_presupuesto=' + $('#totalDespuesDecuento').attr('val');
formResumen += '&total_precio_unidad=' + $('#precioUnidadPresupuesto').attr('val'); formResumen += '&total_precio_unidad=' + $('#precioUnidadPresupuesto').attr('val');
formResumen += '&total_factor=' + $('#total_factor').text(); // replace , for . in the values
formResumen += '&total_factor_ponderado=' + $('#total_factor_ponderado').text(); formResumen += '&total_factor=' + $('#factor').text().replace(/,/g, '.');
formResumen += '&total_factor_ponderado=' + $('#factor_ponderado').text().replace(/,/g, '.');
if($('#confirmar_presupuesto').prop('checked')){ if($('#confirmar_presupuesto').prop('checked')){
formResumen += '&confirmar=1'; formResumen += '&confirmar=1';
formResumen += '&total_aceptado=' + $('#totalDespuesDecuento').attr('val');
} }
return formResumen return formResumen

View File

@ -12,7 +12,7 @@ if (auth()->user()->inGroup('beta')) {
</a> </a>
<ul class="menu-sub"> <ul class="menu-sub">
<li class="menu-item"> <li class="menu-item">
<a href="<?= route_to('facturasList') ?>" class="menu-link"> <a href="<?= route_to('newFactura') ?>" class="menu-link">
<?= lang("App.menu_facturas_nueva") ?> <?= lang("App.menu_facturas_nueva") ?>
</a> </a>
</li> </li>