The Terminar Jornada (End of Day) feature allows administrators to close out the working day by generating a consolidated PDF sales report for a selected client. The report is produced entirely in the browser using jsPDF and jspdf-autotable — no server-side rendering is involved. The resulting file,Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Edwin950821/BodegaX/llms.txt
Use this file to discover all available pages before exploring further.
Jornada.pdf, is downloaded directly to the user’s machine the moment the admin clicks Confirmar.
The
TerminarJornada component imports jsPDF as import { jsPDF } from "jspdf" and import autoTable from 'jspdf-autotable'. Confirm both packages are present in your package.json before deploying.Where Terminar Jornada Is Available
The Terminar Jornada button appears on multiple pages, but its functional status differs between them:Home Page
The orange Terminar Jornada button on
/home is rendered only when user.role === 'admin'. Clicking it calls terminar(), which opens TerminarJornada passing this.clientes and title: ''. This is the fully wired implementation.History Page
On
/history, the button is conditionally rendered with *ngIf="user2.role === 'admin'" and calls terminar(), which attempts this.dialog.open(TerminarJornada, ...) with this.client. However, MatDialog is not injected in HistoryComponent’s constructor — dialog is typed any — so this call fails at runtime.Management Page
The Terminar Jornada button is present in the
/management template, but the terminar() handler is an empty stub (terminar() { }). No dialog is opened and no PDF is generated from this page.Orders Page
The button is rendered in the
/orders template, but terminar() throws Error('Method not implemented.'). The end-of-day feature is not functional on the Orders page.PDF Generation Workflow
Dialog Opens — Four Data Fetches
When
TerminarJornada is constructed, it immediately chains four HTTP GET requests in its constructor:GET /admin/all→this.client(all users, used to resolve client names)GET /ventas/all→this.history(all sales, each enriched with aclientename)GET /productos/all→this.productos(all products, used to resolve product names)GET /producto-ventas/all→this.productoventas(all line items, enriched withprodutoname and grouped intoventa.detalle)
Admin Selects a Client
The dialog presents a dropdown populated from
this.clientes (passed as dialog data from the parent component). The admin selects the client whose report they want to generate. The selection is bound to clienteSelected (the client’s uuid).Validate Client Selection
When the admin clicks Confirmar, the
confirmar() method first checks whether clienteSelected is empty. If it is, a browser alert fires — “Debe escoger cliente” — and the function returns early. No PDF is created until a client is chosen.Initialise the PDF Document
A new
jsPDF instance is created with default portrait A4 settings. The page width is read via doc.internal.pageSize.width || doc.internal.pageSize.getWidth() to support both older and newer jsPDF API versions.Write Admin and Client Headers
The admin’s details — sourced from Client information is then written left-aligned:
this.myUser (parsed from sessionStorage key bodegax) — are centred at the top of the page:Filter Sales for the Selected Client
Sales are filtered to the selected client’s UUID:If
ventas.length === 0, the dialog writes “No hay ventas registradas para este cliente.” at position (20, 60) and immediately calls doc.save('Jornada.pdf') before returning. The PDF is still downloaded even when there are no sales.Consolidate Products with a Map
To avoid duplicating product rows when the same beer appears across multiple sales, a After the loop, the Map is converted into the
Map keyed by product name consolidates all quantities and totals:rows array expected by autoTable:PDF Structure Reference
| Section | Content | Position |
|---|---|---|
| Admin name | user.nombre — centred | y = 10 |
| Admin ID | user.id — centred | y = 20 |
| Admin address | user.direccion — centred | y = 30 |
| Client name | cliente: {client.nombre} — left | y = 40 |
| Client UUID | ID Cliente: {client.uuid} — left | y = 50 |
| Product table | autoTable with Produto / cantidad / total columns | top margin = 50 |
Empty Sales Behaviour
Cancelling the Dialog
Clicking Cancelar inside theTerminarJornada dialog calls this.mydialog.close(false). No PDF is generated, no data is mutated, and the parent component receives false from its afterClosed() subscription.