Almacenamiento
El sistema de almacenamiento permite gestionar contenedores jerárquicos (salas, estantes, bóvedas), items de producto con trazabilidad completa, y un log de todos los movimientos.
La API de Almacenamiento es actualmente una implementación mocked. Todas las operaciones funcionan correctamente pero no persisten datos en un backend real.
Modelo de Contenedor
Los contenedores pueden ser jerárquicos (una sala contiene estantes, un estante contiene contenedores).
Propiedades
- Name
id- Type
- string
- Description
Identificador único del contenedor.
- Name
name- Type
- string
- Description
Nombre descriptivo del contenedor.
- Name
type- Type
- StorageContainerType
- Description
Tipo de contenedor:
room,shelf,container,vault.
- Name
capacity- Type
- object
- Description
Capacidad máxima del contenedor.
- Name
maxWeight- Type
- number
- Description
Peso máximo en gramos.
- Name
maxVolume- Type
- number
- Description
Volumen máximo en cm³.
- Name
maxUnits- Type
- number
- Description
Cantidad máxima de unidades.
- Name
currentOccupancy- Type
- object
- Description
Ocupación actual del contenedor.
- Name
weight- Type
- number
- Description
Peso actual en gramos.
- Name
volume- Type
- number
- Description
Volumen actual en cm³.
- Name
units- Type
- number
- Description
Cantidad actual de unidades.
- Name
environmentalControls- Type
- object
- Description
Controles ambientales disponibles.
- Name
hasTemperatureControl- Type
- boolean
- Description
Control de temperatura.
- Name
hasHumidityControl- Type
- boolean
- Description
Control de humedad.
- Name
hasCO2Control- Type
- boolean
- Description
Control de CO2.
- Name
parentContainerId- Type
- string
- Description
ID del contenedor padre (para jerarquía).
- Name
location- Type
- string
- Description
Ubicación física del contenedor.
- Name
items- Type
- StorageItem[]
- Description
Items almacenados en el contenedor.
- Name
createdAt- Type
- timestamp
- Description
Fecha de creación.
- Name
updatedAt- Type
- timestamp
- Description
Última actualización.
Ejemplo de Contenedor
{
"id": "container-1",
"name": "Bóveda Principal",
"type": "vault",
"capacity": {
"maxWeight": 10000,
"maxUnits": 100
},
"currentOccupancy": {
"weight": 750,
"volume": 0,
"units": 2
},
"environmentalControls": {
"hasTemperatureControl": true,
"hasHumidityControl": true,
"hasCO2Control": false
},
"items": [],
"location": "Sala de Almacenamiento A",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
Modelo de Item
Los items representan productos almacenados con trazabilidad completa.
Propiedades
- Name
id- Type
- string
- Description
Identificador único del item.
- Name
name- Type
- string
- Description
Nombre descriptivo del item.
- Name
strain- Type
- object
- Description
Cepa/variedad del producto.
- Name
id- Type
- string
- Description
- ID de la cepa.
- Name
name- Type
- string
- Description
- Nombre de la cepa.
- Name
type- Type
- string
- Description
- Tipo: sativa, indica, hybrid.
- Name
quantity- Type
- number
- Description
Cantidad almacenada.
- Name
unit- Type
- StorageUnit
- Description
Unidad de medida:
grams,units,milliliters,ounces.
- Name
containerId- Type
- string
- Description
ID del contenedor donde está almacenado.
- Name
batchId- Type
- string
- Description
Número de lote para trazabilidad.
- Name
harvestDate- Type
- timestamp
- Description
Fecha de cosecha.
- Name
expirationDate- Type
- timestamp
- Description
Fecha de vencimiento.
- Name
thcContent- Type
- number
- Description
Contenido de THC en porcentaje.
- Name
cbdContent- Type
- number
- Description
Contenido de CBD en porcentaje.
- Name
testResults- Type
- array
- Description
Resultados de análisis de laboratorio.
Ejemplo de Item
{
"id": "item-1",
"name": "Amnesia Haze - Lote 2024-01",
"strain": {
"id": "strain-1",
"name": "Amnesia Haze",
"type": "sativa"
},
"quantity": 500,
"unit": "grams",
"containerId": "container-1",
"batchId": "BATCH-2024-01",
"harvestDate": "2024-01-15T00:00:00Z",
"expirationDate": "2025-01-15T00:00:00Z",
"weight": 500,
"thcContent": 22.5,
"cbdContent": 0.3,
"createdAt": "2024-01-20T00:00:00Z",
"updatedAt": "2024-01-20T00:00:00Z"
}
Modelo de Log
Registro de todos los movimientos y operaciones sobre items.
Propiedades
- Name
id- Type
- string
- Description
Identificador único del log.
- Name
itemId- Type
- string
- Description
ID del item afectado.
- Name
itemName- Type
- string
- Description
Nombre del item para referencia rápida.
- Name
action- Type
- StorageLogAction
- Description
Acción realizada:
add,remove,transfer,test,consume,adjust.
- Name
quantity- Type
- number
- Description
Cantidad involucrada en la operación.
- Name
unit- Type
- StorageUnit
- Description
Unidad de medida.
- Name
fromContainerId- Type
- string
- Description
Contenedor origen (para transferencias).
- Name
toContainerId- Type
- string
- Description
Contenedor destino (para transferencias y adiciones).
- Name
performedBy- Type
- object
- Description
Usuario que realizó la operación.
- Name
timestamp- Type
- timestamp
- Description
Fecha y hora de la operación.
Ejemplo de Log
{
"id": "log-1",
"itemId": "item-1",
"itemName": "Amnesia Haze - Lote 2024-01",
"action": "transfer",
"quantity": 100,
"unit": "grams",
"fromContainerId": "container-1",
"fromContainerName": "Bóveda Principal",
"toContainerId": "container-2",
"toContainerName": "Estante A1",
"notes": "Transferencia para distribución",
"performedBy": {
"id": "user-1",
"name": "Admin User"
},
"timestamp": "2024-02-10T09:15:00Z"
}
Endpoints de Contenedores
Listar contenedores
Obtiene la lista de contenedores con filtros opcionales.
Parámetros de consulta
- Name
type- Type
- string
- Description
Filtrar por tipo de contenedor.
- Name
parentContainerId- Type
- string
- Description
Filtrar por contenedor padre.
- Name
hasItems- Type
- boolean
- Description
Filtrar contenedores con/sin items.
- Name
search- Type
- string
- Description
Búsqueda por nombre o ubicación.
- Name
page- Type
- number
- Description
Número de página (default: 1).
- Name
limit- Type
- number
- Description
Items por página (default: 20).
Request
curl -X GET "https://api.cannahub.com/api/storages/containers?type=vault" \
-H "Authorization: Bearer {token}"
Response
{
"containers": [
{
"id": "container-1",
"name": "Bóveda Principal",
"type": "vault",
...
}
],
"count": 1,
"filters": { "type": "vault" }
}
Crear contenedor
Crea un nuevo contenedor de almacenamiento.
Campos requeridos
- Name
name- Type
- string
- Description
Nombre del contenedor.
- Name
type- Type
- StorageContainerType
- Description
Tipo de contenedor.
Campos opcionales
- Name
capacity- Type
- object
- Description
Capacidad máxima.
- Name
environmentalControls- Type
- object
- Description
Controles ambientales.
- Name
parentContainerId- Type
- string
- Description
ID del contenedor padre.
- Name
location- Type
- string
- Description
Ubicación física.
Request
curl -X POST "https://api.cannahub.com/api/storages/containers" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Estante B1",
"type": "shelf",
"parentContainerId": "container-1",
"capacity": { "maxWeight": 2000 }
}'
Response
{
"container": {
"id": "container-new",
"name": "Estante B1",
"type": "shelf",
"parentContainerId": "container-1",
...
}
}
Obtener contenedor
Obtiene los detalles de un contenedor específico, incluyendo sus items almacenados.
Parámetros de ruta
- Name
id- Type
- string
- Description
ID del contenedor.
Request
curl -X GET "https://api.cannahub.com/api/storages/containers/container-1" \
-H "Authorization: Bearer {token}"
Response
{
"container": {
"id": "container-1",
"name": "Bóveda Principal",
"type": "vault",
"capacity": {
"maxWeight": 10000,
"maxUnits": 100
},
"currentOccupancy": {
"weight": 750,
"volume": 0,
"units": 2
},
"items": [
{
"id": "item-1",
"name": "Amnesia Haze - Lote 2024-01",
"quantity": 500,
"unit": "grams"
}
],
"location": "Sala de Almacenamiento A",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z"
}
}
Actualizar contenedor
Actualiza los datos de un contenedor existente. Solo se modifican los campos enviados.
Parámetros de ruta
- Name
id- Type
- string
- Description
ID del contenedor a actualizar.
Campos actualizables
- Name
name- Type
- string
- Description
Nuevo nombre del contenedor.
- Name
type- Type
- StorageContainerType
- Description
Nuevo tipo de contenedor.
- Name
capacity- Type
- object
- Description
Nueva capacidad máxima.
- Name
environmentalControls- Type
- object
- Description
Nuevos controles ambientales.
- Name
location- Type
- string
- Description
Nueva ubicación física.
- Name
parentContainerId- Type
- string
- Description
Nuevo contenedor padre.
Request
curl -X PATCH "https://api.cannahub.com/api/storages/containers/container-1" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "Bóveda Principal - Actualizada",
"capacity": { "maxWeight": 15000, "maxUnits": 150 }
}'
Response
{
"container": {
"id": "container-1",
"name": "Bóveda Principal - Actualizada",
"type": "vault",
"capacity": {
"maxWeight": 15000,
"maxUnits": 150
},
"updatedAt": "2024-03-01T12:00:00Z",
...
}
}
Eliminar contenedor
Elimina un contenedor del sistema. La operación falla si el contenedor aún contiene items; primero deben transferirse o eliminarse.
Parámetros de ruta
- Name
id- Type
- string
- Description
ID del contenedor a eliminar.
No se puede eliminar un contenedor que tenga items almacenados. Primero transfiera o elimine todos los items.
Request
curl -X DELETE "https://api.cannahub.com/api/storages/containers/container-3" \
-H "Authorization: Bearer {token}"
Response (éxito)
{
"success": true,
"message": "Contenedor eliminado correctamente"
}
Response (error: items existentes)
{
"error": "No se puede eliminar el contenedor porque aún contiene items",
"itemCount": 3
}
Endpoints de Items
Listar items
Obtiene la lista de items con filtros opcionales.
Parámetros de consulta
- Name
containerId- Type
- string
- Description
Filtrar por contenedor.
- Name
strainId- Type
- string
- Description
Filtrar por cepa.
- Name
unit- Type
- string
- Description
Filtrar por unidad de medida:
grams,units,milliliters,ounces.
- Name
quantity- Type
- string
- Description
Filtrar por rango de cantidad (ej.
0-100).
- Name
search- Type
- string
- Description
Búsqueda por nombre, cepa o lote.
- Name
expiringBefore- Type
- string
- Description
Items que vencen antes de esta fecha (ISO 8601).
Request
curl -X GET "https://api.cannahub.com/api/storages/items?containerId=container-1" \
-H "Authorization: Bearer {token}"
Response
{
"items": [
{
"id": "item-1",
"name": "Amnesia Haze - Lote 2024-01",
"strain": {
"id": "strain-1",
"name": "Amnesia Haze",
"type": "sativa"
},
"quantity": 500,
"unit": "grams",
"containerId": "container-1",
"batchId": "BATCH-2024-01",
"thcContent": 22.5,
"cbdContent": 0.3,
"createdAt": "2024-01-20T00:00:00Z",
"updatedAt": "2024-01-20T00:00:00Z"
}
],
"count": 1,
"filters": { "containerId": "container-1" }
}
Crear item
Agrega un nuevo item al almacenamiento.
Campos requeridos
- Name
name- Type
- string
- Description
- Nombre del item.
- Name
strainId- Type
- string
- Description
- ID de la cepa.
- Name
containerId- Type
- string
- Description
- ID del contenedor.
- Name
quantity- Type
- number
- Description
- Cantidad inicial.
- Name
unit- Type
- StorageUnit
- Description
- Unidad de medida.
Request
curl -X POST "https://api.cannahub.com/api/storages/items" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"name": "OG Kush - Lote 2024-03",
"strainId": "strain-2",
"containerId": "container-1",
"quantity": 300,
"unit": "grams",
"batchId": "BATCH-2024-03",
"thcContent": 24.5
}'
Response
{
"item": {
"id": "item-new",
"name": "OG Kush - Lote 2024-03",
"strain": {
"id": "strain-2",
"name": "OG Kush",
"type": "hybrid"
},
"quantity": 300,
"unit": "grams",
"containerId": "container-1",
"batchId": "BATCH-2024-03",
"thcContent": 24.5,
"createdAt": "2024-03-01T10:00:00Z",
"updatedAt": "2024-03-01T10:00:00Z"
}
}
Obtener item
Obtiene los detalles completos de un item específico, incluyendo información de cepa, resultados de tests y contenedor asociado.
Parámetros de ruta
- Name
id- Type
- string
- Description
ID del item.
Request
curl -X GET "https://api.cannahub.com/api/storages/items/item-1" \
-H "Authorization: Bearer {token}"
Response
{
"item": {
"id": "item-1",
"name": "Amnesia Haze - Lote 2024-01",
"strain": {
"id": "strain-1",
"name": "Amnesia Haze",
"type": "sativa"
},
"quantity": 500,
"unit": "grams",
"containerId": "container-1",
"batchId": "BATCH-2024-01",
"harvestDate": "2024-01-15T00:00:00Z",
"expirationDate": "2025-01-15T00:00:00Z",
"thcContent": 22.5,
"cbdContent": 0.3,
"testResults": [],
"createdAt": "2024-01-20T00:00:00Z",
"updatedAt": "2024-01-20T00:00:00Z"
}
}
Actualizar item
Actualiza los datos de un item existente. Solo se modifican los campos enviados.
Parámetros de ruta
- Name
id- Type
- string
- Description
ID del item a actualizar.
Campos actualizables
- Name
name- Type
- string
- Description
Nuevo nombre del item.
- Name
quantity- Type
- number
- Description
Nueva cantidad.
- Name
unit- Type
- StorageUnit
- Description
Nueva unidad de medida.
- Name
batchId- Type
- string
- Description
Nuevo número de lote.
- Name
harvestDate- Type
- timestamp
- Description
Nueva fecha de cosecha.
- Name
expirationDate- Type
- timestamp
- Description
Nueva fecha de vencimiento.
- Name
thcContent- Type
- number
- Description
Nuevo contenido de THC.
- Name
cbdContent- Type
- number
- Description
Nuevo contenido de CBD.
Request
curl -X PATCH "https://api.cannahub.com/api/storages/items/item-1" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"quantity": 450,
"thcContent": 23.0
}'
Response
{
"item": {
"id": "item-1",
"name": "Amnesia Haze - Lote 2024-01",
"quantity": 450,
"unit": "grams",
"thcContent": 23.0,
"updatedAt": "2024-03-05T14:30:00Z",
...
}
}
Eliminar item
Elimina un item del almacenamiento. Se genera un log de tipo remove automáticamente.
Parámetros de ruta
- Name
id- Type
- string
- Description
ID del item a eliminar.
Request
curl -X DELETE "https://api.cannahub.com/api/storages/items/item-3" \
-H "Authorization: Bearer {token}"
Response
{
"success": true,
"message": "Item eliminado correctamente"
}
Transferir item
Transfiere un item (total o parcial) a otro contenedor.
Campos requeridos
- Name
toContainerId- Type
- string
- Description
ID del contenedor destino.
Campos opcionales
- Name
quantity- Type
- number
- Description
Cantidad a transferir (si es parcial).
- Name
notes- Type
- string
- Description
Notas sobre la transferencia.
Request
curl -X POST "https://api.cannahub.com/api/storages/items/item-1/transfer" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"toContainerId": "container-2",
"quantity": 50,
"notes": "Transferencia parcial para distribución"
}'
Response
{
"success": true,
"item": {
"id": "item-1",
"name": "Amnesia Haze - Lote 2024-01",
"quantity": 450,
"unit": "grams",
"containerId": "container-1"
},
"log": {
"id": "log-new",
"action": "transfer",
"quantity": 50,
"unit": "grams",
"fromContainerId": "container-1",
"toContainerId": "container-2",
"notes": "Transferencia parcial para distribución",
"timestamp": "2024-03-10T16:00:00Z"
}
}
Endpoints de Logs
Listar logs
Obtiene el historial de movimientos y operaciones realizadas sobre items de almacenamiento.
Parámetros de consulta
- Name
itemId- Type
- string
- Description
Filtrar por item específico.
- Name
containerId- Type
- string
- Description
Filtrar por contenedor (origen o destino).
- Name
action- Type
- string
- Description
Filtrar por tipo de acción:
add,remove,transfer,test,consume,adjust.
- Name
performer- Type
- string
- Description
Filtrar por ID del usuario que realizó la acción.
- Name
fromDate- Type
- string
- Description
Desde fecha (ISO 8601).
- Name
toDate- Type
- string
- Description
Hasta fecha (ISO 8601).
Request
curl -X GET "https://api.cannahub.com/api/storages/logs?action=transfer&fromDate=2024-01-01T00:00:00Z" \
-H "Authorization: Bearer {token}"
Response
{
"logs": [
{
"id": "log-1",
"itemId": "item-1",
"itemName": "Amnesia Haze - Lote 2024-01",
"action": "transfer",
"quantity": 100,
"unit": "grams",
"fromContainerId": "container-1",
"fromContainerName": "Bóveda Principal",
"toContainerId": "container-2",
"toContainerName": "Estante A1",
"notes": "Transferencia para distribución",
"performedBy": {
"id": "user-1",
"name": "Admin User"
},
"timestamp": "2024-02-10T09:15:00Z"
}
],
"count": 1,
"filters": { "action": "transfer" }
}
Estadísticas
Obtiene estadísticas agregadas del sistema de almacenamiento, incluyendo totales, desglose por tipo/unidad, items próximos a vencer (30 días) y items con bajo stock (menos de 50 unidades).
Respuesta
- Name
totalItems- Type
- number
- Description
- Total de items almacenados.
- Name
totalContainers- Type
- number
- Description
- Total de contenedores registrados.
- Name
totalWeight- Type
- number
- Description
- Peso total en gramos.
- Name
byContainerType- Type
- object
- Description
- Desglose de contenedores por tipo (
room,shelf,container,vault).
- Name
byUnit- Type
- object
- Description
- Desglose de items por unidad de medida (
grams,units,milliliters,ounces).
- Name
expiringIn30Days- Type
- number
- Description
- Cantidad de items que vencen dentro de los próximos 30 días.
- Name
lowStockItems- Type
- number
- Description
- Cantidad de items con stock por debajo de 50 unidades.
Request
curl -X GET "https://api.cannahub.com/api/storages/stats" \
-H "Authorization: Bearer {token}"
Response
{
"totalItems": 15,
"totalContainers": 8,
"totalWeight": 2500,
"byContainerType": {
"room": 2,
"shelf": 4,
"container": 1,
"vault": 1
},
"byUnit": {
"grams": 12,
"units": 2,
"milliliters": 1,
"ounces": 0
},
"expiringIn30Days": 3,
"lowStockItems": 2
}
React Query Hooks
// Query keys
export const storageKeys = {
allItems: ['storage-items'],
itemLists: () => [...storageKeys.allItems, 'list'],
itemList: (filters) => [...storageKeys.itemLists(), filters],
itemDetail: (id) => [...storageKeys.allItems, 'detail', id],
allContainers: ['storage-containers'],
containerLists: () => [...storageKeys.allContainers, 'list'],
containerList: (filters) => [...storageKeys.containerLists(), filters],
containerDetail: (id) => [...storageKeys.allContainers, 'detail', id],
allLogs: ['storage-logs'],
logList: (filters) => [...storageKeys.allLogs, 'list', filters],
stats: ['storage-stats'],
}
// Available hooks
import {
useStorageItemsQuery,
useStorageItemQuery,
useStorageContainersQuery,
useStorageContainerQuery,
useStorageLogsQuery,
useStorageStatsQuery,
useCreateStorageItemMutation,
useUpdateStorageItemMutation,
useDeleteStorageItemMutation,
useTransferStorageItemMutation,
useCreateStorageContainerMutation,
useUpdateStorageContainerMutation,
useDeleteStorageContainerMutation,
} from '@/features/Club/Storages'