Catàleg de productes
Modela productes i serveis amb unitats UNECE, presentacions, variants, ofertes de proveïdor i snapshots documentals immutables.
El catàleg modela què vens i, per separat, com es presenta, identifica,
emmagatzema i compra. Comença amb una clau fact_test_ i concedeix només
products:read i/o products:write segons necessitis.
Producte o servei
Cada ítem declara un item_kind explícit:
productpot gestionar estoc decimal i tenir variants amb estoc propi.servicesempre témanage_stock: false, estoc0.0000i llindar d'estoc baix nul. Un servei no admet variants amb estoc propi.
La unitat base pertany al catàleg UNECE tancat: C62, KGM, GRM, LTR,
MLT, MTR, MTK, HUR o DAY. Quantitats i estoc admeten quatre decimals;
els factors de conversió, sis. La unitat base no es pot canviar quan
reinterpretaria estoc, presentacions, variants, ofertes o historial existent.
{
"name": "Oli d'oliva verge extra",
"sku": "OOVE-GRANEL",
"price": "8.75",
"item_kind": "product",
"base_unit": "LTR",
"manage_stock": true,
"stock": "125.5000",
"low_stock_threshold": "20.0000",
"specifications": { "origen": "Jaén", "collita": 2026 }
}Semàntica de creació i actualització
POST /v1/products exigeix name i price. Si external_id ja identifica un
producte de la mateixa empresa, la creació actua com un upsert idempotent en
comptes de duplicar-lo. sku també és únic per empresa, però una col·lisió amb
un altre producte és un error, no un upsert.
PUT /v1/products/{product} té semàntica parcial: cada camp omès conserva
el valor actual. Dos camps apliquen substitució explícita:
specificationssubstitueix l'objecte clau-valor complet;nullel buida. Les llistes JSON no buides es rebutgen, mentre que{}i[]continuen sent representacions buides compatibles.stockés una quantitat absoluta, no un delta.nullel posa a zero. Una diferència real registra un moviment manual; enviar el valor actual no registra res. Utilitza l'endpoint dedicat d'estoc ambincreaseodecreaseper a deltes explícits.
stock i low_stock_threshold admeten fins a quatre decimals. metadata de
Producte conserva la frontera retrocompatible: fins a 50 claus, els valors
escalars es converteixen a strings i les llistes JSON s'accepten i es
persisteixen amb claus numèriques. Això és deliberadament diferent de
specifications.
Presentacions
Una presentació és una forma comercial de vendre el producte; mai té estoc propi.
| Mode | Significat |
|---|---|
fixed | quantitat base = quantitat comercial × conversion_factor. Una caixa de 12 usa 12.000000. |
variable_measure | La mesura nominal és informativa. Cada línia ha de confirmar la quantitat base real. |
POST /v1/products/{product}/presentations{
"name": "Caixa de 12",
"mode": "fixed",
"unit": "C62",
"conversion_factor": "12.000000",
"active": true
}Usa GET/POST sobre la col·lecció i PUT/DELETE sobre cada ítem. Una
presentació inactiva no es pot seleccionar en línies noves, però els documents
antics continuen renderitzant des del seu snapshot.
Variants de producte
Una variant conserva identitat comercial pròpia: nom, SKU/codi de barres opcionals, overrides de preu i cost i, opcionalment, estoc propi.
{
"name": "Blau / M",
"sku": "SAM-BLA-M",
"price_override": "24.5000",
"manage_stock": true,
"stock": "8.5000",
"active": true
}Amb manage_stock: true, els moviments afecten només la variant; altrament
deleguen en el producte base sense perdre la identitat de variant a la línia ni
al ledger. Una presentació es pot combinar amb una variant: la variant tria el
destí d'estoc i la presentació converteix la quantitat.
Opcions configurables i combinacions vendibles
Els grups d'opcions modelen eleccions del comprador —acabat, sabor o nivell de
servei—, no specifications informatives. Cada grup conté valors de selecció
única; un valor pot afegir un price_adjustment per unitat comercial. Els
grups i valors inactius continuen sent llegibles per conservar snapshots
històrics, però no es poden triar en una línia nova.
Les configuracions comercials combinen una variant opcional, una presentació
opcional i un conjunt canònic de valors d'opció. Cada configuració té una
signature estable, pot declarar un preu final per unitat comercial i pot
estar activa o inactiva.
catalog_availability_mode controla què es pot vendre:
| Mode | Disponibilitat |
|---|---|
open | El producte cartesià dels eixos actius és vendible. Una configuració només restringeix la disponibilitat amb restricts_availability: true: limita la variant que anomena i tracta la presentació/opcions omeses com a comodins. |
closed | Les configuracions actives són la llista exacta permesa. Sense cap configuració activa, no es pot vendre res. |
La creació fa servir open per defecte; ometre el camp en actualitzar conserva
el mode actual. Una fila amb restricts_availability: false encara pot aportar
identitat o un preu exacte sense restringir un catàleg obert.
Fes servir GET /v1/products/{product}/options i
GET /v1/products/{product}/configurations per inspeccionar el catàleg. Tots
dos fan servir products:read i paginació per cursor. El detall del producte
els pot incloure amb include=configurable_catalog.
POST /v1/products/{product}/resolve-selection també és una lectura malgrat
ser POST: accepta una selecció parcial niada i retorna resolved, incomplete,
ambiguous o incompatible, a més dels eixos compatibles i grups pendents.
Dos valors del mateix grup formen una petició invàlida.
Abans d'una escriptura que redueixi la disponibilitat, crida
POST /v1/products/{product}/configurations/impact-preview amb
products:write. No persisteix res i retorna les combinacions afectades, els
preus negociats que es retirarien i un impact_token que identifica aquell
estat exacte del catàleg. Retorna el token a l'actualització destructiva; si el
catàleg o els preus afectats canvien, demana una altra previsualització.
Ledger de stock
GET /v1/products/{product}/stock-movements exposa el llibre major immutable
d'estoc del més recent al més antic. Cada fila porta el delta signat en unitats
base, el saldo stock_after calculat sobre el llibre complet, el motiu, el
document origen, l'usuari i la variant gestora. La paginació fa servir limit
i starting_after; direction=in|out filtra les files visibles sense canviar
els valors històrics de stock_after.
Ofertes de proveïdor
Una oferta representa condicions de compra sense canviar el preu de venda. Apunta al producte o a una variant i registra proveïdor, unitat de compra, factor, disponibilitat, cost i termini.
{
"supplier_id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a10",
"variant_id": null,
"supplier_sku": "PROV-OOVE-20L",
"purchase_unit": "LTR",
"conversion_factor": "1.000000",
"unit_cost": "5.1250",
"availability": "available",
"minimum_quantity": "20.0000",
"lead_time_days": 3,
"preferred": true,
"active": true
}available exigeix unit_cost no negatiu. unavailable, unknown, seasonal
i store_dependent exigeixen unit_cost: null. Només hi pot haver una oferta
activa preferida per destí; l'acció preferred la canvia atòmicament.
Quan una línia de factura de compra compra contra una oferta,
purchase_measurement registra els embalums rebuts i la unitat en què
s'expressa el cost (offer_unit, base_unit o presentation_unit); el
servidor deriva la quantitat facturada i congela el cost unitari. unit_price
omès en una línia de catàleg significa «cost no confirmat»: l'API aplica el cost
de l'oferta o rebutja la línia si el proveïdor no té cap oferta activa. Consulta
Línies de compra mesurades.
Els documents guarden snapshots
Les línies de catàleg retornen product_id, variant_id, presentation_id,
configuració/signatura comercial i valors d'opció, item_kind, unitat
comercial i base, factor, quantitat base, origen i semàntica del preu, ajustos
d'opció, identitat de tarifa i unitat de preu. Són snapshots: canviar o retirar
el catàleg viu no reescriu documents emesos ni històrics.
Per a una presentació variable_measure, envia confirmed_base_quantity en
crear la línia. Deixa que l'API derivi totals i quantitats de moviment.
Permisos, eliminació i MCP
- Les lectures usen
products:read; altes, edicions i eliminacions dels nous subrecursos usenproducts:write. El producte base s'elimina ambproducts:delete. - Les eliminacions de presentació, variant i oferta porten
x-irreversible: truea OpenAPI. - Un producte referenciat per un ítem de tarifa o oferta vigent no es pot eliminar físicament. Retira abans la referència; l'històric queda en snapshots.
- El domini Product de MCP té ara 38 tools. A més de les 13 tools de presentacions, variants i ofertes, quatre lectures noves exposen opcions, configuracions, moviments de stock i resolució de seleccions.
Consulta Tarifes, Scopes i irreversibilitat i els esquemes exactes a la Referència de l'API.
Descripcions i consultes de documents
Les línies admeten additional_description nullable de fins a 5000 caràcters al costat de description. Està disponible en factures de venda i rectificatives, pressupostos, proformes, albarans, factures de compra i plantilles recurrents. Mantén aquest detall separat de quantitats, preus, camps fiscals i identificadors del catàleg; afegir descripció no canvia el càlcul de l’import. Consulta GET /v1/products/low-stock-report per a la col·lecció i total_count, i GET /v1/products/{product}/sales-analytics per a les mètriques de vendes; aquestes respostes no són recursos de producte individuals. Els exemples complets són a la referència de l’API.