mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-12 16:38:48 +00:00
trabajando en la vista de pedidos
This commit is contained in:
@ -0,0 +1,128 @@
|
|||||||
|
package com.imprimelibros.erp.pedidos;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
import java.security.Principal;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.common.Utils;
|
||||||
|
import com.imprimelibros.erp.datatables.DataTable;
|
||||||
|
import com.imprimelibros.erp.datatables.DataTablesParser;
|
||||||
|
import com.imprimelibros.erp.datatables.DataTablesRequest;
|
||||||
|
import com.imprimelibros.erp.datatables.DataTablesResponse;
|
||||||
|
import com.imprimelibros.erp.payments.model.Payment;
|
||||||
|
import com.imprimelibros.erp.payments.model.PaymentTransaction;
|
||||||
|
import com.imprimelibros.erp.payments.model.PaymentTransactionStatus;
|
||||||
|
import com.imprimelibros.erp.payments.model.PaymentTransactionType;
|
||||||
|
import com.imprimelibros.erp.users.User;
|
||||||
|
import com.imprimelibros.erp.users.UserDao;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/pedidos")
|
||||||
|
public class PedidosController {
|
||||||
|
|
||||||
|
private final PedidoRepository repoPedido;
|
||||||
|
private final UserDao repoUser;
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
public PedidosController(PedidoRepository repoPedido, UserDao repoUser, MessageSource messageSource) {
|
||||||
|
this.repoPedido = repoPedido;
|
||||||
|
this.repoUser = repoUser;
|
||||||
|
this.messageSource = messageSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String listarPedidos() {
|
||||||
|
if (Utils.isCurrentUserAdmin()) {
|
||||||
|
return "imprimelibros/pedidos/pedidos-list";
|
||||||
|
}
|
||||||
|
return "imprimelibros/pedidos/pedidos-list-cliente";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "datatable", produces = "application/json")
|
||||||
|
@ResponseBody
|
||||||
|
public DataTablesResponse<Map<String, Object>> getDatatable(
|
||||||
|
HttpServletRequest request,
|
||||||
|
Principal principal,
|
||||||
|
Locale locale) {
|
||||||
|
|
||||||
|
DataTablesRequest dt = DataTablesParser.from(request);
|
||||||
|
|
||||||
|
Boolean isAdmin = Utils.isCurrentUserAdmin();
|
||||||
|
Long currentUserId = Utils.currentUserId(principal);
|
||||||
|
|
||||||
|
List<String> searchable = List.of(
|
||||||
|
"id",
|
||||||
|
"estado"
|
||||||
|
// "client" no, porque lo calculas a posteriori
|
||||||
|
);
|
||||||
|
|
||||||
|
// Campos ordenables
|
||||||
|
List<String> orderable = List.of(
|
||||||
|
"id",
|
||||||
|
"client",
|
||||||
|
"created_at",
|
||||||
|
"total",
|
||||||
|
"estado");
|
||||||
|
|
||||||
|
Specification<Pedido> base = (root, query, cb) -> cb.conjunction();
|
||||||
|
if (!isAdmin) {
|
||||||
|
base = base.and((root, query, cb) -> cb.equal(root.get("userId"), currentUserId));
|
||||||
|
}
|
||||||
|
String clientSearch = dt.getColumnSearch("cliente");
|
||||||
|
|
||||||
|
// 2) Si hay filtro, traducirlo a userIds y añadirlo al Specification
|
||||||
|
if (clientSearch != null) {
|
||||||
|
List<Long> userIds = repoUser.findIdsByFullNameLike(clientSearch.trim());
|
||||||
|
|
||||||
|
if (userIds.isEmpty()) {
|
||||||
|
// Ningún usuario coincide → forzamos 0 resultados
|
||||||
|
base = base.and((root, query, cb) -> cb.disjunction());
|
||||||
|
} else {
|
||||||
|
base = base.and((root, query, cb) -> root.get("created_by").in(userIds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Long total = repoPedido.count(base);
|
||||||
|
|
||||||
|
return DataTable
|
||||||
|
.of(repoPedido, Pedido.class, dt, searchable)
|
||||||
|
.orderable(orderable)
|
||||||
|
.add("id", Pedido::getId)
|
||||||
|
.add("created_at", pedido -> Utils.formatDateTime(pedido.getCreatedAt(), locale))
|
||||||
|
.add("client", pedido -> {
|
||||||
|
if (pedido.getCreatedBy() != null) {
|
||||||
|
Optional<User> user = repoUser.findById(pedido.getCreatedBy());
|
||||||
|
return user.map(User::getFullName).orElse("");
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
})
|
||||||
|
.add("total", pedido -> {
|
||||||
|
if (pedido.getTotal() != null) {
|
||||||
|
return Utils.formatCurrency(pedido.getTotal(), locale);
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.add("actions", pedido -> {
|
||||||
|
return "<span class=\'badge bg-success btn-view \' data-id=\'" + pedido.getId() + "\' style=\'cursor: pointer;\'>"
|
||||||
|
+ messageSource.getMessage("app.view", null, locale) + "</span>";
|
||||||
|
})
|
||||||
|
.where(base)
|
||||||
|
.toJson(total);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
54
src/main/resources/static/assets/js/pages/pedidos/pedidos.js
Normal file
54
src/main/resources/static/assets/js/pages/pedidos/pedidos.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
$(() => {
|
||||||
|
|
||||||
|
const csrfToken = document.querySelector('meta[name="_csrf"]')?.getAttribute('content');
|
||||||
|
const csrfHeader = document.querySelector('meta[name="_csrf_header"]')?.getAttribute('content');
|
||||||
|
if (window.$ && csrfToken && csrfHeader) {
|
||||||
|
$.ajaxSetup({
|
||||||
|
beforeSend: function (xhr) {
|
||||||
|
xhr.setRequestHeader(csrfHeader, csrfToken);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const language = document.documentElement.lang || 'es-ES';
|
||||||
|
|
||||||
|
const tablePedidos = $('#table-pedidos').DataTable({
|
||||||
|
processing: true,
|
||||||
|
serverSide: true,
|
||||||
|
orderCellsTop: true,
|
||||||
|
pageLength: 50,
|
||||||
|
lengthMenu: [10, 25, 50, 100, 500],
|
||||||
|
order: [[5, 'desc']], // Ordena por fecha por defecto
|
||||||
|
language: { url: '/assets/libs/datatables/i18n/' + language + '.json' },
|
||||||
|
responsive: true,
|
||||||
|
dom: 'lBrtip',
|
||||||
|
buttons: {
|
||||||
|
dom: {
|
||||||
|
button: {
|
||||||
|
className: 'btn btn-sm btn-outline-primary me-1'
|
||||||
|
},
|
||||||
|
buttons: [
|
||||||
|
{ extend: 'copy' },
|
||||||
|
{ extend: 'csv' },
|
||||||
|
{ extend: 'excel' },
|
||||||
|
{ extend: 'pdf' },
|
||||||
|
{ extend: 'print' },
|
||||||
|
{ extend: 'colvis' }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ajax: {
|
||||||
|
url: '/pedidos/datatable',
|
||||||
|
method: 'GET',
|
||||||
|
},
|
||||||
|
order: [[0, 'desc']],
|
||||||
|
columns: [
|
||||||
|
{ data: 'id', name: 'id', orderable: true },
|
||||||
|
{ data: 'cliente', name: 'cliente', orderable: true },
|
||||||
|
{ data: 'created_at', name: 'created_at', orderable: true },
|
||||||
|
{ data: 'total', name: 'total', orderable: true },
|
||||||
|
{ data: 'actions', name: 'actions', orderable: false, searchable: false }
|
||||||
|
|
||||||
|
],
|
||||||
|
});
|
||||||
|
})
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{imprimelibros/layout}">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<th:block layout:fragment="pagetitle" />
|
||||||
|
<th:block th:replace="~{imprimelibros/partials/head-css :: head-css}" />
|
||||||
|
<th:block layout:fragment="pagecss">
|
||||||
|
<link th:href="@{/assets/libs/datatables/dataTables.bootstrap5.min.css}" rel="stylesheet" />
|
||||||
|
</th:block>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div th:replace="~{imprimelibros/partials/topbar :: topbar}" />
|
||||||
|
<div th:replace="~{imprimelibros/partials/sidebar :: sidebar}"
|
||||||
|
sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')">
|
||||||
|
|
||||||
|
<th:block layout:fragment="content">
|
||||||
|
<div th:if="${#authorization.expression('isAuthenticated()')}">
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item"><a href="/"><i class="ri-home-5-fill"></i></a></li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page" th:text="#{pedido.module-title}">
|
||||||
|
Pedidos</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<table id="pagos-redsys-datatable" class="table table-striped table-nowrap responsive w-100">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col" th:text="#{pedido.table.id}">Num. Pedido</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.cliente}">Cliente</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.fecha}">Fecha</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.importe}">Importe</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.estado}">Estado</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.acciones}">Acciones</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th><input type="text" class="form-control form-control-sm input-filter" /></th>
|
||||||
|
<th><input type="text" class="form-control form-control-sm input-filter" /></th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
<th>
|
||||||
|
<select class="form-control form-control-sm select-filter">
|
||||||
|
<option value="" ></option>
|
||||||
|
<option value="aprobado" th:text="#{pedido.estado.aprobado}">Aprobado</option>
|
||||||
|
<option value="maquetacion" th:text="#{pedido.estado.maquetacion}">Maquetación</option>
|
||||||
|
<option value="haciendo_ferro" th:text="#{pedido.estado.haciendo_ferro}">Haciendo ferro</option>
|
||||||
|
<option value="produccion" th:text="#{pedido.estado.produccion}">Producción</option>
|
||||||
|
<option value="terminado" th:text="#{pedido.estado.terminado}">Terminado</option>
|
||||||
|
<option value="cancelado" th:text="#{pedido.estado.cancelado}">Cancelado</option>
|
||||||
|
</select>
|
||||||
|
</th>
|
||||||
|
<th></th> <!-- Acciones (sin filtro) -->
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</th:block>
|
||||||
|
|
||||||
|
<th:block th:replace="~{theme/partials/vendor-scripts :: scripts}" />
|
||||||
|
<th:block layout:fragment="pagejs">
|
||||||
|
<script th:inline="javascript">
|
||||||
|
window.languageBundle = /*[[${languageBundle}]]*/ {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script th:src="@{/assets/libs/datatables/datatables.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/datatables/dataTables.bootstrap5.min.js}"></script>
|
||||||
|
|
||||||
|
<!-- JS de Buttons y dependencias -->
|
||||||
|
<script th:src="@{/assets/libs/datatables/dataTables.buttons.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/jszip/jszip.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/pdfmake/pdfmake.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/pdfmake/vfs_fonts.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/datatables/buttons.html5.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/datatables/buttons.print.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/datatables/buttons.colVis.min.js}"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="module" th:src="@{/assets/js/pages/imprimelibros/pedidos/pedidos.js}"></script>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@ -0,0 +1,83 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{imprimelibros/layout}">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<th:block layout:fragment="pagetitle" />
|
||||||
|
<th:block th:replace="~{imprimelibros/partials/head-css :: head-css}" />
|
||||||
|
<th:block layout:fragment="pagecss">
|
||||||
|
<link th:href="@{/assets/libs/datatables/dataTables.bootstrap5.min.css}" rel="stylesheet" />
|
||||||
|
</th:block>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div th:replace="~{imprimelibros/partials/topbar :: topbar}" />
|
||||||
|
<div th:replace="~{imprimelibros/partials/sidebar :: sidebar}"
|
||||||
|
sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')">
|
||||||
|
|
||||||
|
<th:block layout:fragment="content">
|
||||||
|
<div th:if="${#authorization.expression('isAuthenticated()')}">
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<nav aria-label="breadcrumb">
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item"><a href="/"><i class="ri-home-5-fill"></i></a></li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page" th:text="#{pedido.module-title}">
|
||||||
|
Pedidos</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<table id="pagos-redsys-datatable" class="table table-striped table-nowrap responsive w-100">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col" th:text="#{pedido.table.id}">Num. Pedido</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.cliente}">Cliente</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.fecha}">Fecha</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.importe}">Importe</th>
|
||||||
|
<th scope="col" th:text="#{pedido.table.acciones}">Acciones</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th><input type="text" class="form-control form-control-sm input-filter" /></th>
|
||||||
|
<th><input type="text" class="form-control form-control-sm input-filter" /></th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
<th></th> <!-- Acciones (sin filtro) -->
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</th:block>
|
||||||
|
|
||||||
|
<th:block th:replace="~{theme/partials/vendor-scripts :: scripts}" />
|
||||||
|
<th:block layout:fragment="pagejs">
|
||||||
|
<script th:inline="javascript">
|
||||||
|
window.languageBundle = /*[[${languageBundle}]]*/ {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script th:src="@{/assets/libs/datatables/datatables.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/datatables/dataTables.bootstrap5.min.js}"></script>
|
||||||
|
|
||||||
|
<!-- JS de Buttons y dependencias -->
|
||||||
|
<script th:src="@{/assets/libs/datatables/dataTables.buttons.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/jszip/jszip.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/pdfmake/pdfmake.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/pdfmake/vfs_fonts.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/datatables/buttons.html5.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/datatables/buttons.print.min.js}"></script>
|
||||||
|
<script th:src="@{/assets/libs/datatables/buttons.colVis.min.js}"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="module" th:src="@{/assets/js/pages/imprimelibros/pedidos/pedidos.js}"></script>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user