Skip to main content

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.

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, 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

1

Dialog Opens — Four Data Fetches

When TerminarJornada is constructed, it immediately chains four HTTP GET requests in its constructor:
  1. GET /admin/allthis.client (all users, used to resolve client names)
  2. GET /ventas/allthis.history (all sales, each enriched with a cliente name)
  3. GET /productos/allthis.productos (all products, used to resolve product names)
  4. GET /producto-ventas/allthis.productoventas (all line items, enriched with produto name and grouped into venta.detalle)
2

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).
3

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.
4

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.
5

Write Admin and Client Headers

The admin’s details — sourced from this.myUser (parsed from sessionStorage key bodegax) — are centred at the top of the page:
doc.text(user.nombre,    w / 2, 10, { align: 'center' });
doc.text(user.id,        w / 2, 20, { align: 'center' });
doc.text(user.direccion, w / 2, 30, { align: 'center' });
Client information is then written left-aligned:
doc.text(`cliente: ${client.nombre}`, 20, 40);
doc.text(`ID Cliente: ${client.uuid}`,  20, 50);
6

Filter Sales for the Selected Client

Sales are filtered to the selected client’s UUID:
const ventas = this.history.filter(
  v => v.uuid_cliente === this.clienteSelected
);
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.
7

Consolidate Products with a Map

To avoid duplicating product rows when the same beer appears across multiple sales, a Map keyed by product name consolidates all quantities and totals:
let myMap = new Map();

ventas.forEach(v => {
  v.detalle.forEach((d: any) => {
    if (myMap.has(d.produto)) {
      const found = myMap.get(d.produto);
      found.cantidad += d.cantidad;
      found.total    += d.total_parcial;
    } else {
      myMap.set(d.produto, {
        cantidad: d.cantidad,
        total:    d.total_parcial
      });
    }
  });
});
After the loop, the Map is converted into the rows array expected by autoTable:
const rows: any[] = [];
myMap.forEach((value, key) => {
  rows.push([key, value.cantidad, value.total]);
});
8

Render the AutoTable and Save

autoTable renders the consolidated product table with a 50 px top margin (to clear the header text) and a three-column header row:
autoTable(doc, {
  head: [['Produto', 'cantidad', 'total']],
  body: rows,
  margin: { top: 50 },
});

doc.save('Jornada.pdf');
The browser immediately triggers a file download named Jornada.pdf.

PDF Structure Reference

SectionContentPosition
Admin nameuser.nombre — centredy = 10
Admin IDuser.id — centredy = 20
Admin addressuser.direccion — centredy = 30
Client namecliente: {client.nombre} — lefty = 40
Client UUIDID Cliente: {client.uuid} — lefty = 50
Product tableautoTable with Produto / cantidad / total columnstop margin = 50

Empty Sales Behaviour

If no sales exist in this.history for the selected client (ventas.length === 0), the PDF will contain the admin and client header information followed by the message “No hay ventas registradas para este cliente.” The file is still saved as Jornada.pdf and downloaded immediately. Always verify data is present for the target client before generating the report to avoid confusion.

Cancelling the Dialog

Clicking Cancelar inside the TerminarJornada dialog calls this.mydialog.close(false). No PDF is generated, no data is mutated, and the parent component receives false from its afterClosed() subscription.

Build docs developers (and LLMs) love