Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dinogamer089/SiCom/llms.txt

Use this file to discover all available pages before exploring further.

SiCom uses a three-layer approach to inventory management. The articulo.unidades column records the total physical units in the warehouse. The stock_diario table snapshots daily opening and closing counts. The stock_reservado_diario table accumulates how many units are already committed to approved rentals on any given calendar date. The combination of these three tables lets the system answer the question “how many units of article X can still be rented on day D?” without scanning individual rental records at query time.

Tables and Entities at a Glance

LayerTableEntityPurpose
Physical inventoryarticuloArticuloMaster unit count (unidades)
Daily snapshotstock_diarioStockDiarioOpening / closing counts per article per day
Reservation logstock_reservado_diarioStockReservadoDiarioReserved units per article per date, driven by state transitions
Movement auditmovimiento_almacenMovimientoAlmacenImmutable record of every warehouse entry or exit

Available Stock Formula

To determine how many units of an article can still be rented on a specific date:
availableOnDay(idarticulo, date) =
    articulo.unidades
    − SUM(stock_reservado_diario.cantidad_reservada
          WHERE idarticulo = ? AND fecha = ?)
Because articulo.unidades is the ground-truth total, and stock_reservado_diario accumulates all approved-but-not-yet-finalised reservations, their difference gives the units still available for new quotations on that date.

StockDiario Entity

StockDiario stores a daily inventory snapshot for each article. It is generated (or updated) by the DelegateTarjetaAlmacen layer whenever the warehouse card (TarjetaAlmacen) is queried or a new day’s snapshot needs initialising.
FieldJava TypeColumnDescription
idIntegerid (PK)Auto-generated identity
articuloArticuloidarticulo (FK)The article this snapshot belongs to
fechaLocalDatefechaThe calendar date
inventarioInicialIntegerinventario_inicialUnits on hand at the start of the day
existenciaFinalIntegerexistencia_finalUnits on hand at the end of the day
A unique constraint on (idarticulo, fecha) ensures at most one snapshot row per article per day. When no row exists for a requested date, DelegateTarjetaAlmacen.obtenerOCrearStockDiario() creates a zero-initialised row on demand:
// DelegateTarjetaAlmacen.java
public StockDiario obtenerOCrearStockDiario(Integer idArticulo, LocalDate fecha) {
    var stockDAO = ServiceLocator.getInstanceStockDiarioDAO();
    return stockDAO.obtenerPorArticuloYFecha(idArticulo, fecha)
        .orElseGet(() -> {
            StockDiario nuevo = new StockDiario();
            nuevo.setArticulo(
                ServiceLocator.getInstanceArticuloDAO().find(idArticulo).orElse(null));
            nuevo.setFecha(fecha);
            nuevo.setInventarioInicial(0);
            nuevo.setExistenciaFinal(0);
            stockDAO.save(nuevo);
            return nuevo;
        });
}

StockReservadoDiario Entity

StockReservadoDiario is the reservation ledger. Each row represents the cumulative number of units of a single article reserved across all active rentals for a specific calendar date.
FieldJava TypeColumnDescription
idLongid_stock_reservado (PK)Auto-generated identity
idarticuloArticuloidarticulo (FK)Reserved article; ON DELETE CASCADE
fechaLocalDatefechaThe date units are reserved for
cantidadReservadaIntegercantidad_reservadaINT UNSIGNED; total reserved units for this article on this date

How rows are written

Rows are never written directly by JPA code. They are exclusively managed by the cambiar_estado_renta stored procedure using an upsert pattern:
-- Reserve: triggered when Solicitada → Aprobada or Confirmado
INSERT INTO stock_reservado_diario (idarticulo, fecha, cantidad_reservada)
VALUES (v_idarticulo, v_dia_actual, v_cantidad)
ON DUPLICATE KEY UPDATE
    cantidad_reservada = cantidad_reservada + v_cantidad;
The procedure iterates through each Detallerenta row and each day in the rental period [fechaInicio, fecha], creating or incrementing one row per (idarticulo, fecha) combination. This means a five-day rental of 10 chairs produces five separate reservation rows for that chair article.

How rows are released

When a rental moves to Finalizada or Cancelada (from an active state), the procedure decrements each row and removes zero-quantity rows:
-- Release: triggered when active state → Cancelada or Finalizada
UPDATE stock_reservado_diario
SET cantidad_reservada = GREATEST(cantidad_reservada - v_cantidad, 0)
WHERE idarticulo = v_idarticulo AND fecha = v_dia_actual;

DELETE FROM stock_reservado_diario
WHERE idarticulo = v_idarticulo
  AND fecha = v_dia_actual
  AND cantidad_reservada <= 0;
The GREATEST(cantidad_reservada - v_cantidad, 0) guard ensures that cantidad_reservada can never go negative, even if data inconsistencies exist (for example, if a reservation row was manually modified). Any row that reaches zero is immediately deleted to keep the table compact.

MovimientoAlmacen Entity

MovimientoAlmacen is an immutable audit log of every physical stock movement — rental dispatches, returns, purchases, and write-offs. It is used by the TarjetaAlmacen (warehouse card) feature to reconstruct article history.
FieldJava TypeColumnDescription
idIntegerid (PK)Auto-generated identity
articuloArticuloidarticulo (FK)Affected article
rentaRentaidrenta (FK, nullable)Associated rental, if any
fechaLocalDatefechaCalendar date of the movement
fechaHoraRegistroLocalDateTimefecha_hora_registroPrecise timestamp of registration
tipoMovimientoTipoMovimientotipo_movimientoENTRADA or SALIDA (stored as VARCHAR(10))
cantidadIntegercantidadUnits moved
precioUnitarioBigDecimalprecio_unitarioDECIMAL(10,2) — unit price at movement time
conceptoStringconceptoMax 200 chars; free-text description

TipoMovimiento enum

ValueMeaning
ENTRADAUnits arriving — new stock purchases or rental returns
SALIDAUnits leaving — dispatched to rental events or written off

TarjetaAlmacen — Querying Warehouse Movements

The TarjetaAlmacen page lets administrators view the complete movement history for any article, either for a single day or a date range. All queries are routed through FacadeTarjetaAlmacen.

FacadeTarjetaAlmacen methods

// Query movements for a single day
List<MovimientoAlmacen> consultarMovimientosPorFecha(Integer idArticulo, LocalDate fecha);

// Query movements across a date range
List<MovimientoAlmacen> consultarMovimientosPorRango(
    Integer idArticulo, LocalDate fechaInicio, LocalDate fechaFin);

// Retrieve the opening inventory for a given day from stock_diario
int obtenerInventarioInicial(Integer idArticulo, LocalDate fecha);

// Compute daily ENTRADA and SALIDA totals; returns int[]{entradas, salidas}
int[] calcularTotalesDiarios(Integer idArticulo, LocalDate fecha);

// Persist a new movement record
void registrarMovimiento(MovimientoAlmacen movimiento);
calcularTotalesDiarios returns a two-element int[] where index 0 is the sum of all ENTRADA movements and index 1 is the sum of all SALIDA movements for the given article on the given date.

idx_renta_fecha_inicio Index

The migration script migration_fecha_inicio.sql adds a B-tree index on renta.fecha_inicio to accelerate the date-range window queries executed by the stored procedure and by the TarjetaAlmacen’s range lookups:
-- Created idempotently in migration_fecha_inicio.sql
CREATE INDEX idx_renta_fecha_inicio ON renta(fecha_inicio);
Without this index, every call to cambiar_estado_renta would perform a full table scan on renta when the procedure reads fecha_inicio and fecha for the rental, and range-based MovimientoAlmacen queries would similarly degrade as the table grows. The migration script checks INFORMATION_SCHEMA.STATISTICS before creating the index so it can be run safely on a database that already has it.

End-to-End Stock Flow Example

The following sequence illustrates how stock moves through the system for a three-day rental of 5 chairs (article ID 7, rental ID 99, dates 2025-08-01 to 2025-08-03):
  1. Client submits quotationestado = Solicitada. No reservation rows written.
  2. Admin approvesCALL cambiar_estado_renta(99, 'Aprobada'). The procedure inserts or increments three rows in stock_reservado_diario:
    (idarticulo=7, fecha=2025-08-01, cantidad_reservada=5)
    (idarticulo=7, fecha=2025-08-02, cantidad_reservada=5)
    (idarticulo=7, fecha=2025-08-03, cantidad_reservada=5)
    
  3. Rental progresses through Pendiente a reparto → En reparto → Entregado → Pendiente a recoleccion → En recoleccion. No stock table changes during these transitions.
  4. Rental finalisedCALL cambiar_estado_renta(99, 'Finalizada'). The procedure decrements all three rows by 5; rows at zero are deleted.
  5. Movements logged by the application when articles leave and return to the warehouse as MovimientoAlmacen records of type SALIDA (dispatch) and ENTRADA (return).

Build docs developers (and LLMs) love