Pesquisar K
Appearance
Appearance
Um Inventário representa o estoque disponível de uma variante de produto no sistema. Pode operar em 3 estratégias diferentes: ilimitado (não-rastreado), manualmente controlado (rastreado) ou dinamicamente sincronizado com um grupo (rastreado por referência).
{
"_id": "698b8a805eaf8de7c5af1cb9",
"community": "test",
"itemId": "698b8a805eaf8de7c5af1cba",
"variantId": "SKU-001",
"alias": null,
"strategy": "tracked",
"isVirtual": false,
"trackedQuantity": 100,
"invalidatedAt": null,
"indexedAt": "2026-02-12T20:45:01.549Z",
"referencedTrackingAllowed": false,
"variantReference": null,
"level": {
"quantity": 100,
"alocated": 100,
"tracked": true,
"reserves": 2,
"reserved": 5,
"available": 95,
"reservedUntil": "2026-02-13T20:45:01.549Z",
"availableUntil": "2026-02-12T21:45:01.549Z",
"validUntil": "2026-02-12T21:10:01.549Z",
"processDuration": 245
},
"createdAt": "2026-02-10T19:44:01.198Z",
"updatedAt": "2026-02-12T20:45:01.697Z"
}| Campo | Tipo | Descrição |
|---|---|---|
_id | string | ID único do inventário no formato ObjectId |
community | string | Comunidade (tenant) |
itemId | string | null | ID do produto. Obrigatório para inventários não-virtuais. Caso virtual, null |
variantId | string | null | SKU/Identificador da variante. Obrigatório para não-virtuais. Caso virtual, null |
alias | string | null | Alias único do inventário. Obrigatório para virtuais (integrados). Caso não-virtual, null |
strategy | string | Estratégia de rastreamento. Valores possíveis: untracked, tracked, tracked:reference |
isVirtual | boolean | Indica se é um inventário virtual (integrado/não-associado a item específico) |
trackedQuantity | integer | Quantidade atual em estoque. Aplicável apenas para strategies tracked e tracked:reference |
invalidatedAt | string (ISO 8601) | null | Data e hora da última invalidação do cache. Caso não invalidado, null |
indexedAt | string (ISO 8601) | null | Data e hora do último cálculo do nível de estoque |
referencedTrackingAllowed | boolean | Indicador virtual: Se rastreamento por referência está permitido (readonly, derivado de variantReference.dynamicInventory) |
variantReference | object | null | Referência dinâmica para um grupo (layers:group). Caso não vinculado, null |
level | object | null | Nível de estoque calculado com disponibilidade. Caso não indexado/cacheado, null |
createdAt | string (ISO 8601) | Data e hora de criação do inventário |
updatedAt | string (ISO 8601) | Data e hora da última atualização |
O inventário suporta 3 estratégias que definem como a quantidade é gerenciada:
| Estratégia | Comportamento | Quantidade | Rastreamento | Caso de Uso |
|---|---|---|---|---|
untracked | Estoque ilimitado (padrão) | Infinito/Ignorado | Não | Produtos digitais, serviços ilimitados |
tracked | Estoque manualmente controlado | trackedQuantity | Sim, manual | Produtos físicos com estoque definido |
tracked:reference | Estoque dinamicamente sincronizado com um grupo | Vinculado a grupo | Sim, automático | Combos/kits com sincronização dinâmica |
untracked (Padrão)
trackedQuantity é ignoradotracked (Rastreamento Manual)
trackedQuantitytracked:reference (Rastreamento Dinâmico)
variantReference com dynamicInventory = trueO sistema automaticamente muda a estratégia em certas condições:
tracked → tracked:reference: Quando variantReference.dynamicInventory é definido como truetracked:reference → tracked: Quando variantReference é removido ou dynamicInventory muda para falselevel - Nível de Estoque (InventoryLevel) Representa a disponibilidade calculada do inventário, incluindo quantidade, reservas e cache.
{
"quantity": 100,
"alocated": 100,
"tracked": true,
"reserves": 2,
"reserved": 5,
"available": 95,
"reservedUntil": "2026-02-13T20:45:01.549Z",
"availableUntil": "2026-02-12T21:45:01.549Z",
"validUntil": "2026-02-12T21:10:01.549Z",
"processDuration": 245
}| Campo | Tipo | Descrição |
|---|---|---|
quantity | integer | Quantidade total em estoque (quantidade física/rastreada) |
alocated | integer | null | Total de "assentos" alocados para este produto. Caso não aplicável, null |
tracked | boolean | Indica se o produto é rastreado (true) ou ilimitado (false) |
reserves | integer | null | Número de reservas ativas. Caso não aplicável, null |
reserved | integer | null | Quantidade total reservada (soma de todas as reservas). Caso não aplicável, null |
available | integer | Quantidade disponível para venda: quantity - reserved |
reservedUntil | string (ISO 8601) | Data e hora de expiração das reservas |
availableUntil | string (ISO 8601) | Data e hora de validade do cálculo de disponibilidade |
validUntil | string (ISO 8601) | Data e hora até quando este nível é válido (TTL do cache) |
processDuration | integer | Tempo em milissegundos para calcular este nível |
A disponibilidade é calculada como:
available = quantity - reservedOnde:
quantity = quantidade atual em estoque (ou ilimitado se não-rastreado)reserved = somatório de todas as reservas pendentesSe tracked = false (estoque ilimitado), então available é sempre considerado suficiente.
O level é cacheado para performance e expira de acordo com validUntil:
getLevel() e cache expirouadjust() é chamado ou invalidateInventories() é executadovariantReference - Referência Dinâmica (ItemSkuReference) Representa uma referência dinâmica a um grupo de produtos, permitindo sincronização automática de estoque e formulário.
{
"resourceKind": "layers:group",
"resourceId": "grupo-camisa-azul-123",
"dynamicInventory": true,
"dynamicForm": true
}| Campo | Tipo | Descrição |
|---|---|---|
resourceKind | string | Tipo de recurso referenciado. Valor: layers:group |
resourceId | string | ID único do grupo referenciado |
dynamicInventory | boolean | Se inventário deve ser sincronizado dinamicamente com o grupo. Quando true, muda strategy para tracked:reference |
dynamicForm | boolean | Se formulário deve ser sincronizado dinamicamente com o grupo |
strategy = untracked por padrãovariantReference com dynamicInventory = true, automaticamente muda para tracked:referenceitemId E variantIdalias obrigatoriamentelevel é calculado quando necessário (getter getLevel())levelindexedAt marca quando foi último cálculovalidUntil indica quando cache expirainvalidatedAt marca quando foi invalido (força recalcular)adjust({ quantity }) apenas afetam estratégias tracked e tracked:referencetrackedQuantityInventoryEvent com sequence incrementallevel = null)✓ itemId é obrigatório
✓ variantId é obrigatório
✗ Erro se ambos não estiverem presentes: "Inventory must have an item"✓ alias é obrigatório
✗ Erro se não tiver: "Virtual Inventory must have an alias"
✗ itemId/variantId devem estar vazios✓ trackedQuantity deve ser número inteiro
✗ Decimais não são permitidos
✓ Padrão: 0✓ Deve ser único por comunidade
✓ Sparse index (permite null para não-virtuais)
✗ Colisão de alias resulta em erro de índice✓ Enum: 'untracked', 'tracked', 'tracked:reference'
✓ Padrão: 'untracked'
✓ Transições automáticas aplicadas na validaçãoCada movimentação de estoque cria um evento rastreável para auditoria e histórico.
{
"_id": "698b8a805eaf8de7c5af1cc0",
"community": "test",
"inventoryId": "698b8a805eaf8de7c5af1cb9",
"kind": "manual",
"delta": 10,
"sequence": 5,
"balance": 110,
"lineItemId": "698b8a805eaf8de7c5af1cc1",
"refs": [],
"createdAt": "2026-02-12T20:45:01.549Z",
"updatedAt": "2026-02-12T20:45:01.549Z"
}| Campo | Tipo | Descrição |
|---|---|---|
_id | string | ID único do evento |
community | string | Comunidade (tenant) |
inventoryId | string | ID do inventário ajustado |
kind | string | Tipo do evento. Valores: manual, system |
delta | integer | Mudança na quantidade (pode ser negativo ou positivo) |
sequence | integer | Número sequencial do evento (índice histórico) |
balance | integer | Saldo de trackedQuantity após o ajuste |
lineItemId | string | null | ID do item de linha da venda (se aplicável) |
refs | array | Referências a objetos relacionados |
createdAt | string (ISO 8601) | Data e hora de criação |
updatedAt | string (ISO 8601) | Data e hora de atualização |
sequence começa em 0 e incrementa com cada evento(inventoryId, sequence)itemId referencia o Item relacionadonull se não indexadoadjust() chamadostrategy = tracked:reference{
"itemId": "produto-123",
"variantId": "camiseta-azul-p",
"strategy": "tracked",
"isVirtual": false,
"trackedQuantity": 50,
"level": {
"quantity": 50,
"available": 48,
"tracked": true
}
}Comportamento:
trackedQuantity{
"itemId": "curso-123",
"variantId": "modulo-basico",
"strategy": "untracked",
"isVirtual": false,
"trackedQuantity": 0,
"level": {
"available": 999999,
"tracked": false
}
}Comportamento:
trackedQuantity ignorado{
"itemId": "combo-123",
"variantId": "kit-completo",
"strategy": "tracked:reference",
"isVirtual": false,
"variantReference": {
"resourceKind": "layers:group",
"resourceId": "grupo-camiseta-azul",
"dynamicInventory": true
},
"level": {
"available": 25,
"tracked": true
}
}Comportamento:
{
"alias": "produto-externo-sku-789",
"strategy": "tracked",
"isVirtual": true,
"itemId": null,
"variantId": null,
"trackedQuantity": 100,
"level": {
"available": 100,
"tracked": true
}
}Comportamento:
itemId/variantId (virtual)alias únicoPOST /inventories
{
"community": "test",
"itemId": "camiseta-123",
"variantId": "azul-p",
"strategy": "tracked",
"trackedQuantity": 100
}Resultado: Inventário criado com strategy = tracked, level = null (não indexado ainda)
GET /inventories/{id}/levelResultado:
{
"quantity": 100,
"available": 100,
"tracked": true,
"validUntil": "2026-02-12T21:10:01.549Z"
}POST /sales
{
"items": [{ "inventoryId": "...", "quantity": 5 }]
}Resultado: 5 unidades reservadas, available = 95
POST /inventories/{id}/adjust
{
"quantity": 50
}Resultado:
trackedQuantity = 150InventoryEvent com delta = 50, balance = 150, sequence = 1level = null)GET /inventories/{id}/levelResultado:
{
"quantity": 150,
"available": 145,
"tracked": true,
"validUntil": "2026-02-12T21:15:01.549Z"
}| Aspecto | untracked | tracked | tracked:reference |
|---|---|---|---|
| Estoque | Ilimitado | Limitado | Dinâmico (grupo) |
Campo trackedQuantity | Ignorado | Usado | Usado |
| Reservas | Ignoradas | Rastreadas | Rastreadas |
| Eventos | Nenhum | Sim | Sim |
| Caso de Uso | Digital/Serviço | Físico | Combo/Kit |
Cache (level) | Sempre válido | Expira | Expira |
O level fornece várias métricas úteis:
| Métrica | Cálculo | Exemplo |
|---|---|---|
| Disponível | quantity - reserved | 100 - 5 = 95 |
| Taxa de Ocupação | reserved / quantity | 5 / 100 = 5% |
| Utilizável | available / quantity | 95 / 100 = 95% |
| Dias até Expiração | (validUntil - now()) / 86400000 | Cache expira em ~4 minutos |