Integración WMS

Integración WMS

Web services para la integración bidireccional de inventario entre DrivErp y el WMS de Systech: notificaciones de llegada y salida de mercancía, transferencias y conversiones creadas directamente desde el WMS, edición de lotes, consulta de existencias y ajustes de inventario.

Requests

Todas las peticiones se realizan contra la misma URL base de la instancia del ERP (producción o pruebas), bajo el prefijo /integration/wms:

https://<instancia>/integration/wms/...

El cuerpo de las peticiones es siempre JSON plano (no el envoltorio JSON-RPC) con header Content-Type: application/json. La mayoría de los endpoints son POST; únicamente la consulta de existencias (/stock/stocklist/return) es GET. Enviar un método distinto al esperado responde la novedad C01.

curl -X POST 'https://<instancia>/integration/wms/stock/lots/edit' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "product_ref": "201",
    "lot_name": "20260701-A1",
    "expiration_date": "2027-06-30"
  }'

Documentos soportados

Las notificaciones de transferencia (/stock/incoming/notification y /stock/outgoing/notification) buscan el documento por nombre entre stock.picking, stock.inventory y product.converter creados en los últimos 6 meses, y validan que se encuentre en el estado esperado y habilitado para gestión WMS (systech_dvp_management) antes de procesarlo.

Vea la guía Autenticación para las credenciales requeridas en cada petición, Estructura de las respuestas para el formato de la respuesta y los códigos status_code, y Control de reintentos para el comportamiento de bloqueo temporal ante peticiones fallidas repetidas.

Autenticación

Esta integración no usa token de sesión: las credenciales se envían en el cuerpo de cada petición, en los campos user y passwd.

  • user: usuario de integración configurado por compañía.
  • passwd: hash SHA-256 (hexadecimal) de la contraseña de integración — nunca la contraseña en texto plano.

Ambos se validan contra los campos Usuario API y Contraseña API configurados en Ajustes > WMS Systech (res.company.systech_dvp_api_user / systech_dvp_api_pass). Son credenciales únicas por compañía: todas las peticiones de la integración usan el mismo par usuario/contraseña, independientemente del endpoint.

Si el usuario o la compañía no tienen configuradas estas credenciales, o si user/passwd no coinciden, la petición se rechaza sin construir la respuesta con status_code/novelty: esta validación corre antes de armar esa respuesta, por lo que result llega directamente como el texto de la excepción HTTP ("401 Unauthorized: ...") — el estado HTTP de la petición sigue siendo 200, el error queda descrito solo dentro de result.

{
  "jsonrpc": "2.0",
  "id": null,
  "result": "401 Unauthorized: The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser doesn't understand how to supply the credentials required."
}
curl -X POST 'https://<instancia>/integration/wms/stock/stocklist/return' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "location_code": "BOD01"
  }'

Solicite a su consultor funcional o técnico de DrivErp el usuario y la contraseña de integración habilitados para su instancia.

Estructura de las respuestas

Toda petición devuelve un objeto con la estructura JSON-RPC propia del framework: la versión jsonrpc, un id y el result. El estado HTTP de la respuesta es siempre 200; el resultado del procesamiento se distingue por el contenido de result, no por el código HTTP.

Las validaciones básicas de la petición (credenciales, campos vacíos o con palabras no permitidas, listas mal formadas — ver guía Autenticación) ocurren antes de construir la respuesta {status_code, novelty}: en esos casos result no es un objeto sino directamente el texto de la excepción (por ejemplo "400 Bad Request: Not valid string None" o "401 Unauthorized: ..."). El resto de la lógica de negocio de cada endpoint sí usa el formato {status_code, novelty, ...} descrito abajo.

Petición exitosa

El result contiene status_code igual a "00" y novelty vacío ({}), acompañados del detalle propio del endpoint — normalmente bajo la llave request_details (nombre del documento procesado y cantidad de líneas). La consulta de existencias (/stock/stocklist/return) es la excepción: su detalle llega bajo la llave result en lugar de request_details.

{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "request_details": {
      "processed_lines": 2,
      "document_name": "WH/IN/00123"
    }
  }
}

Petición con novedad no bloqueante

Algunos casos se resuelven pero informan una novedad — por ejemplo, un lote inexistente que se crea automáticamente. El status_code es "26" y el detalle del endpoint se entrega igual que en una petición exitosa, junto con la novedad en novelty.

{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "26",
    "novelty": {
      "L01": "Lote no encontrado, se ha creado uno nuevo. - 20260701-A1"
    },
    "request_details": {
      "processed_lines": 1,
      "document_name": "WH/IN/00123"
    }
  }
}

Petición rechazada

Si la petición no puede procesarse, el status_code es "99" y el detalle del endpoint (request_details/result) no se incluye. novelty es un objeto {código: descripción}; puede tener más de una entrada si varias validaciones fallan antes de detener el proceso.

{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "99",
    "novelty": {
      "D01": "Document no encontrado- WH/IN/00123"
    }
  }
}

Códigos de novedad

Cada código llega dentro del objeto novelty, normalmente junto con detalle adicional (id, nombre o referencia involucrada) separado por -. La siguiente tabla agrupa los códigos vigentes por categoría (fuente: controllers/utils.py, NOVELTY_CODES).

Código Descripción
Documentos
D01 Documento no encontrado
D02 El documento no se puede procesar. Por favor contacte a soporte
D03 La importación no se encuentra lista para ser procesada
S01 Error al procesar el documento. Por favor contactar a soporte
S02 No se encontró un tipo de Operación válido para este documento
S03 El tipo de Operación no es válido para este documento
S04 No se puede procesar menos cantidad de la esperada
S05 El documento no puede ser procesado por la integración WMS
S06 Picking con menos movimientos de los esperados
S07 Error al crear el documento. Por favor contactar a soporte
S08 Límite máximo de intentos superado para esta solicitud
S09 Solicitud baneada por control de ERP (ver Control de reintentos)
S10 Credenciales insuficientes
S11 Parámetros insuficientes
S12 Estructura de parámetro inválida: se espera una lista (array) de objetos JSON
Tipos de operación / transacción
T01 Tipo de Operación no encontrado
T02 El tipo de Operación para lotes debe ser 'adjustment'
T03 No se ha parametrizado el campo WMS en el Tipo de Operación
T04 El tipo de Operación no permite cantidades negativas
T05 Error en el 'qty_type' indicado
T06 No se ha parametrizado la analítica en las políticas de compañía
T07 El tipo de ajuste no permite cantidades positivas
T08 Tipo de ajuste indicado no coincide con el parametrizado en DrivErp
Productos
P01 Producto no encontrado
P02 Productos con trazabilidad por serial deben ser únicos en el listado
P03 Pares (product_id, lot_name) duplicados; deben ser únicos
P04 El producto tiene trazabilidad serial y las cantidades deben ser unitarias
P05 Los productos de tipo Servicio no se pueden transferir
P06 Hay más de un picking con los mismos parámetros
P07 El producto no cuenta con trazabilidad por lotes
B01 Error al intentar actualizar el código de barras
Lotes
L01 Lote no encontrado, se ha creado uno nuevo
L02 Ubicación de origen no encontrada
L03 Ubicación de destino no encontrada
L04 Lote no encontrado. Si desea crearlo indique la fecha de vencimiento
L05 Fecha de vencimiento no requerida (el lote debe existir o el producto no controla vencimiento)
L06 Lote no encontrado
L07 No se puede actualizar la información del lote
L08 El lote indicado no coincide con el lote asignado
L09 No se cuenta con la disponibilidad del producto
L10 Transferencia interna con ubicaciones de diferente almacén
L11 Inconsistencia en ubicaciones (iguales, o ambas de tránsito)
L12 Pendiente referencia/placa de lote
L13 Ubicación no integrada al WMS
L14 Fecha de vencimiento requerida
L15 / L16 Localización de origen / destino obligatoria
G01 Grupo de lote no encontrado, se ha creado uno nuevo
E01 Por política de compañía no se pueden procesar lotes vencidos
E02 Documento con uno o más lotes vencidos (novedad informativa)
Movimientos
M01 Stock move no encontrado
M02 product_id no está relacionado a la línea indicada
M03 El id del stock.move.line no está relacionado al documento
M04 La línea indicada no está relacionada a ningún stock move (nota: en la salida controlada por WMS, el mensaje real que acompaña esta clave es el texto de O03 por una particularidad del código, no el de M04)
M05 El id del stock.move no está relacionado al documento
M06 No se detalló el id de movimiento de inventario
O01 Los avisos de salida no pueden procesar más cantidad de la reservada
O02 Los avisos de salida de una conversión no pueden procesar menos cantidad
O03 La transferencia no debe tener líneas de detalle asignado (su texto se usa actualmente bajo la clave M04, ver nota arriba; O03 nunca aparece como clave real en novelty)
O04 No se encontraron líneas detalladas de inventario a crear
Inventario y ajustes
I01 No se encuentra la línea de Ajuste de Inventario
I02 Cantidad a transferir no coincide con la reportada en el Ajuste
I03 Faltan líneas del Ajuste de Inventario
I04 Error al procesar el Ajuste de Inventario
I05 Mensaje de error del proceso (detalle dinámico)
I06 Las cantidades deben ser todas positivas o negativas, no mezcladas (código reservado: la validación que lo produciría está comentada en el código, actualmente no puede recibirse)
I07 Hay más de un producto para el mismo lote en la línea de Ajuste (código reservado: la función que lo produce está comentada en el código, actualmente no puede recibirse)
I08 No está permitido indicar líneas duplicadas
I09 Ajustes lot_edit requieren exactamente 2 líneas de producto
I10 Ajustes lot_edit requieren una línea qty_type positiva y una negativa
I11 Los product_ref de ambas líneas lot_edit deben coincidir
I12 El lote no cuenta con disponibilidad para este ajuste
I13 La ubicación del ajuste no corresponde a una ubicación de recepción
Q01 No hay disponibilidad en la ubicación para esta transferencia
Q02 No se encuentra el ajuste/existencias solicitadas
Q03 Balance de cantidades debe ser 0 o positivo
Q04 Balance de cantidades debe dar 0
Q05 Disponibilidad parcial de inventario
Q06 Cantidad incorrecta
Conversiones
C01 El tipo de solicitud HTTP no es el correcto
C02 Línea de conversión no encontrada
C03 Las referencias de producto no coinciden para la conversión
C04 Cantidad a transferir no coincide con la cantidad de la conversión
C05 Cantidad incorrecta en conversión
C06 Lotes a generar pendientes
C07 Lotes a generar no necesarios
C08 Cantidad total en conversión no acorde a detalle
C09 Componente faltante en detalle
C10 Error procesando conversión existente
C11 Total detallado en línea de componente de conversión no coincide
Otros
R01 Debe indicarse product_ref y/o location_code
R02 El código de ubicación es obligatorio

Control de reintentos

Para evitar tormentas de reintentos sobre un mismo documento, cada petición fallida (status_code distinto de "00") queda registrada por compañía + nombre de documento + ruta de origen (systech.dvp.banned.doc). Mientras el documento esté bloqueado, cualquier nuevo intento sobre esa misma combinación responde de inmediato con la novedad S09, sin volver a ejecutar la lógica de negocio.

Importante — el contador no se reinicia al tener éxito. Una vez que una combinación compañía+documento+ruta tuvo una sola falla en el pasado, cualquier petición posterior sobre esa misma combinación —incluso si es exitosa, e incluso si ya pasó mucho tiempo desde el bloqueo anterior— vuelve a incrementar el contador de intentos internamente. Esto es relevante sobre todo para claves que se reutilizan a propósito (por ejemplo, el adjustment_name de un ajuste de inventario al que se le van agregando líneas en varias llamadas): con el tiempo, el simple reúso repetido de la misma clave puede acercarla al límite de 20 intentos y requerir desbloqueo manual, sin que haya habido 20 fallas reales.

El tiempo de bloqueo escala con el número de intentos fallidos consecutivos:

Intentos fallidos Tiempo de bloqueo
1 5 minutos
2 10 minutos
3 15 minutos
4 25 minutos
5 30 minutos
6 a 20 60 minutos
Más de 20 Desbloqueo manual (contactar a soporte)
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "99",
    "novelty": {
      "S09": "Solicitud baneada por control de ERP. Espere los siguientes minutos para intentar nuevamente 15"
    }
  }
}

El "nombre de documento" que identifica el bloqueo varía por endpoint (por ejemplo, document_name en las notificaciones de transferencia, o la concatenación de origin_doc + ubicaciones en la creación de transferencias internas) — se detalla en la sección de parámetros de cada endpoint. Ante un S09, la integración debe esperar el tiempo indicado antes de reintentar la misma petición; reintentar de inmediato solo reinicia el contador y extiende el bloqueo.

Transferencias

Crear transferencia interna

GETPOST /integration/wms/picking/internal/create
Sin autenticación

Crea (o reutiliza, si existe una previamente cancelada con esas ubicaciones — ver origin_doc) una transferencia interna de inventario entre dos ubicaciones, con sus líneas de producto, y la procesa de forma completa: confirma, verifica disponibilidad y la marca como realizada en la misma llamada. El picking y sus movimientos se crean desde cero a partir de product_lines — no se referencia ningún move_id existente. Si se omite origin_doc, cualquier movimiento previo del picking reutilizado se elimina antes de crear los nuevos (siempre aplica aquí, ya que el tipo de operación de este endpoint es siempre internal).

Ambas ubicaciones deben existir (L02/L03) y no pueden ser la misma (L11). Si ambas están gestionadas por WMS, deben pertenecer al mismo almacén (L10) — para mover entre almacenes distintos debe usarse una ubicación de tránsito intermedia; tampoco se permite transferir entre dos ubicaciones de tránsito (L11). El tipo de operación internal con esas ubicaciones por defecto debe existir parametrizado en DrivErp (S02). Si no hay disponibilidad suficiente del producto/lote en origen, la transferencia se cancela automáticamente y responde L09; alcanzar el límite de reintentos fallidos para el mismo origen responde S08.

Parámetros

ParámetroTipoDescripción
user requerido string Usuario de integración de la compañía. Ver guía Autenticación.
passwd requerido string SHA-256 de la contraseña de integración. Ver guía Autenticación.
location_code requerido string Código de la ubicación de origen (stock.location, campo code). L02 si no existe.
location_dest_code requerido string Código de la ubicación de destino. L03 si no existe. No puede ser igual a location_code (L11); si ambas ubicaciones son gestionadas por WMS deben pertenecer al mismo almacén (L10); no se permite transferir entre dos ubicaciones de tránsito (L11).
origin_doc string Referencia del documento origen. Si existe una transferencia cancelada con el mismo tipo de operación y ubicaciones, se reutiliza (si se envía origin_doc, además debe coincidir exactamente; si se omite, se reutiliza cualquier cancelada con esas ubicaciones sin filtrar por origen). Si además coincide con el nombre de una recepción de proveedor ya existente y no cancelada, la transferencia interna queda enlazada a esa recepción como transferencia en dos pasos. Junto con location_code/location_dest_code es también la clave del control de reintentos (S09).
product_lines requerido array Líneas de producto a transferir (se crean como nuevos movimientos, no se referencia un move_id existente).
product_ref requerido string Id del producto en DrivErp (product.product). Aunque es un identificador numérico, debe enviarse como texto (la validación de la petición exige string, no número JSON). P01 si no existe; P05 si es de tipo Servicio; P02 si aparece repetido y el producto no tiene trazabilidad por lote.
qty requerido number Cantidad a transferir (mayor a cero; formato inválido responde I05).
lot_name string Nombre del lote. Si el producto tiene trazabilidad y el lote no existe, se crea automáticamente siempre que no se requiera expiration_date (o que sí se haya enviado); si se requiere y no se envió, no se crea el lote y en su lugar se exige que ya exista (L06 si no existe).
lot_ref string Referencia/placa del lote, exigida al crear un lote nuevo si el producto lo requiere (L12).
expiration_date date Fecha de vencimiento del lote a crear (YYYY-MM-DD). Enviarla cuando el producto no controla vencimiento responde L05.
lot_group string Nombre del grupo de lotes; se crea automáticamente si no existe.
Request
curl -X POST 'https://<instancia>/integration/wms/picking/internal/create' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "origin_doc": "WMS-MOV-000451",
    "location_code": "354",
    "location_dest_code": "356",
    "product_lines": [
      {
        "product_ref": "201",
        "qty": 3,
        "lot_name": "20260701-A1"
      }
    ]
  }'
Response
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "request_details": {
      "processed_lines": 1,
      "document_name": "WH/INT/00087"
    }
  }
}

Notificación de llegada de mercancía

GETPOST /integration/wms/stock/incoming/notification
Sin autenticación

Confirma la llegada de mercancía notificada por el WMS: busca el documento por document_name entre stock.picking (avisos de llegada, transferencias internas y devoluciones de salida), stock.inventory y product.converter, valida su estado y que esté habilitado para gestión WMS, crea/actualiza las líneas detalladas de movimiento (stock.move.line) a partir de product_lines, confirma, reserva y completa el documento.

Cada línea se relaciona con un movimiento existente mediante move_id (obligatorio en este endpoint). Si el producto tiene trazabilidad por lote, el lote se busca por lot_name; si no existe, se crea automáticamente (salvo que el producto exija expiration_date y no se haya enviado, en cuyo caso responde L04). Si el producto está integrado al WMS (has_wms), se registra además la localización física destino (localization_dest_code).

Errores expuestos por el propio documento (no por línea): D01 si el documento no existe o no está en el estado esperado; D02 si su estado no corresponde; S05 si no está habilitado para gestión WMS; S03 si el tipo de recepción del picking no corresponde a un flujo de llegada (incoming, return_outgoing, internal); S08 si supera el máximo de intentos fallidos para el mismo documento.

Parámetros

ParámetroTipoDescripción
user requerido string Usuario de integración de la compañía. Ver guía Autenticación.
passwd requerido string SHA-256 de la contraseña de integración. Ver guía Autenticación.
document_name requerido string Nombre del documento a confirmar (stock.picking, stock.inventory o product.converter, búsqueda entre los últimos 6 meses). D01 si no se encuentra o no está en el estado esperado (confirmado/asignado según tipo) y gestionado por WMS (D02). También es la clave del control de reintentos (S09) para esta ruta.
product_lines requerido array Líneas del documento a confirmar. Cada línea corresponde a un movimiento de inventario (stock.move) existente.
move_id requerido integer Id del stock.move de la transferencia al que corresponde esta línea. M06 si se omite, M01 si no existe o no pertenece al documento, M02 si el producto no coincide con el del movimiento.
product_ref requerido integer Id del producto en DrivErp (product.product). P01 si no existe. No puede ser de tipo Servicio (P05). Con trazabilidad por serial, cada product_ref debe ser único en la lista (P02).
qty requerido number Cantidad recibida para la línea (mayor a cero).
lot_name string Nombre del lote. Obligatorio si el producto tiene trazabilidad por lote (L04 si no existe y no puede crearse porque falta expiration_date). Se crea automáticamente si no existe y el producto lo permite (novedad informativa L01).
lot_ref string Referencia/placa del lote. Obligatoria para crear un lote nuevo cuando el producto exige referencia de lote (product_restrict_ref); L12 si falta.
expiration_date date Fecha de vencimiento del lote (YYYY-MM-DD). Requerida para crear un lote nuevo de productos con control de vencimiento (product_restrict_date).
lot_group string Nombre del grupo de lotes (stock.production.lot.group). Se crea automáticamente si no existe.
localization_dest_code string Código de la ubicación física destino (stock.location.wms) dentro de la bodega. Solo aplica si el producto está integrado al WMS (has_wms). Si se omite se usa la ubicación WMS por defecto configurada en la ubicación destino (L16 si tampoco existe); si se envía y no existe, responde L16.
Request
curl -X POST 'https://<instancia>/integration/wms/stock/incoming/notification' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "document_name": "WH/IN/00123",
    "product_lines": [
      {
        "move_id": 4521,
        "product_ref": 201,
        "qty": 10,
        "lot_name": "20260701-A1",
        "expiration_date": "2027-06-30",
        "localization_dest_code": "354/P0/0/C00/."
      }
    ]
  }'
Response
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "request_details": {
      "processed_lines": 1,
      "document_name": "WH/IN/00123"
    }
  }
}

Notificación de salida de mercancía

GETPOST /integration/wms/stock/outgoing/notification
Sin autenticación

Confirma la salida de mercancía notificada por el WMS: mismo mecanismo de búsqueda y validación de documento que /stock/incoming/notification, pero para flujos de salida (outgoing, return_incoming, internal) — S03 si el tipo de picking no corresponde a uno de estos flujos.

En salida el lote debe existir previamente (no se crea automáticamente). El comportamiento depende de la estrategia de salida configurada en la ubicación origen (systech_dvp_out_strategy):

  • Controlada por el ERP (valor distinto de external, el caso más común): move_id referencia directamente el stock.move.line ya reservado por el ERP al asignar la transferencia. La cantidad de cada línea se valida contra lo ya reservado: reportar más cantidad responde O01, y en salidas originadas por una conversión de producto reportar menos cantidad responde O02.
  • Controlada por el WMS (external): move_id referencia el stock.move (no debe haber líneas detalladas creadas aún, O03) y puede indicarse la localización física de origen (localization_code); no hay validación de cantidad por línea — se confía en lo reportado por el WMS y la disponibilidad se valida de forma agregada al confirmar (S01, Q01/Q05).

Tras procesar las líneas, la transferencia se confirma y reserva; si la disponibilidad de inventario no es suficiente para completarla responde Q01 (o Q05 en transferencias de un solo movimiento).

Parámetros

ParámetroTipoDescripción
user requerido string Usuario de integración de la compañía. Ver guía Autenticación.
passwd requerido string SHA-256 de la contraseña de integración. Ver guía Autenticación.
document_name requerido string Nombre del documento a confirmar (stock.picking, stock.inventory o product.converter, búsqueda entre los últimos 6 meses). D01 si no se encuentra o no está en el estado esperado, D02 si su estado no corresponde. También es la clave del control de reintentos (S09) para esta ruta.
product_lines requerido array Líneas del documento a confirmar. No se permiten pares (product_ref, lot_name) duplicados en salidas (P03).
move_id requerido integer Id de la línea a procesar: id de stock.move si la estrategia de salida de la ubicación origen es 'external' (controlada por el WMS), o id de stock.move.line en caso contrario. M06 si se omite, M01 si no existe, M02/M03/M05 si no corresponde al producto o al documento.
product_ref requerido integer Id del producto en DrivErp (product.product). P01 si no existe. No puede ser de tipo Servicio (P05).
qty requerido number Cantidad despachada para la línea. Cuando la estrategia de salida es controlada por el ERP (no 'external'), se valida contra la cantidad ya reservada en el stock.move.line: reportar más cantidad responde O01, y en salidas originadas por una conversión reportar menos cantidad responde O02. Cuando la estrategia es controlada por el WMS ('external') no hay esta comparación por línea; la disponibilidad se valida de forma agregada al confirmar la transferencia (S01/Q01/Q05).
lot_name string Nombre del lote. En salidas el lote debe existir previamente (no se crea): L06 si no existe. Debe coincidir con el lote ya asignado al movimiento (L08 en caso contrario). Lotes vencidos responden E01 si la política de compañía lo restringe, o quedan como novedad informativa E02 si está permitido.
localization_code string Código de la ubicación física de origen (stock.location.wms). Solo aplica cuando la estrategia de salida es controlada por el WMS ('external') y el producto está integrado (has_wms); si se omite se calcula por disponibilidad, si se envía y no existe responde L15.
localization_dest_code string Código de la ubicación física destino. Solo aplica si la ubicación destino del documento es interna y el producto está integrado al WMS; si se omite se usa la ubicación WMS por defecto (L16 si tampoco existe).
Request
curl -X POST 'https://<instancia>/integration/wms/stock/outgoing/notification' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "document_name": "WH/OUT/00451",
    "product_lines": [
      {
        "move_id": 8931,
        "product_ref": 201,
        "qty": 5,
        "lot_name": "20260701-A1",
        "localization_code": "354/P0/0/C00/."
      }
    ]
  }'
Response
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "request_details": {
      "processed_lines": 1,
      "document_name": "WH/OUT/00451"
    }
  }
}

Conversión

Crear conversión de producto

GETPOST /integration/wms/converter/internal/create
Sin autenticación

Crea (o reabre, si existe una previamente cancelada con el mismo product_ref, origin y ubicaciones) una conversión de producto (product.converter): consume los product_components indicados desde location_code y produce incoming_quantity de product_ref en location_dest_code, dejando la conversión completada (3_done) en la misma llamada.

Ambas ubicaciones deben estar gestionadas por WMS (L13). Si el producto a producir tiene trazabilidad por lote, debe enviarse el detalle en incoming_lots (C06 si falta, C07 si se envía sin necesitarlo) y la suma de sus cantidades debe coincidir exactamente con incoming_quantity (C08). Cada componente de product_components se valida por separado: producto existente (P01), lote requerido si aplica (L06), cantidad positiva (Q06) y consistencia entre el total consumido por componente y su detalle por lote (C11).

Parámetros

ParámetroTipoDescripción
user requerido string Usuario de integración de la compañía. Ver guía Autenticación.
passwd requerido string SHA-256 de la contraseña de integración. Ver guía Autenticación.
product_ref requerido string Id del producto a producir (product.product). Aunque es un identificador numérico, debe enviarse como texto (la validación de la petición exige string, no número JSON). P01 si no existe.
incoming_quantity requerido number Cantidad total a producir del producto indicado.
location_code requerido string Código de la ubicación donde se consumen los componentes. L02 si no existe. Debe estar gestionada por WMS junto con location_dest_code (L13).
location_dest_code requerido string Código de la ubicación donde queda disponible el producto producido. L03 si no existe. Debe estar gestionada por WMS junto con location_code (L13).
origin string Referencia del documento origen. Junto con product_ref y las ubicaciones, es la clave del control de reintentos (S09) y permite reutilizar una conversión previamente cancelada.
incoming_lots array Lotes a producir del producto indicado. Obligatorio si el producto tiene trazabilidad por lote (C06); no debe enviarse si no la tiene (C07). La suma de qty debe ser igual a incoming_quantity (C08).
lot_name requerido string Nombre del lote a producir. Se crea si no existe (L06 si el producto tiene trazabilidad y no se indica).
qty requerido number Cantidad a producir en este lote. Debe ser mayor a cero (Q06).
lot_group_name string Nombre del grupo de lotes; se crea automáticamente si no existe.
expiration_date date Fecha de vencimiento del lote (YYYY-MM-DD). Obligatoria si el producto controla vencimiento (L14).
localization_code string Código de la ubicación física destino del lote producido, si el producto está integrado al WMS (L15 si se envía y no existe). **Excepción**: si location_dest_code es '354', '356', '357' o '375', el valor enviado se ignora y se sobrescribe internamente con un código fijo por ubicación (parametrización específica de un cliente, no configurable).
product_components requerido array Componentes a consumir de location_code para producir el producto indicado.
product_ref requerido string Id del producto componente (product.product), enviado como texto (mismo requisito que el product_ref de nivel superior). C09 si se omite, P01 si no existe.
qty requerido number Cantidad del componente a consumir. Debe ser mayor a cero (Q06). La suma de cantidades por lote de un mismo componente debe coincidir con el total consumido (C11).
lot_name string Nombre del lote a consumir. Obligatorio si el componente tiene trazabilidad por lote (L06 si no existe).
localization_code string Código de la ubicación física de origen del componente, si está integrado al WMS (L15 si se envía y no existe). **Excepción**: si location_code es '354', '356', '357' o '375', el valor enviado se ignora y se sobrescribe internamente con un código fijo por ubicación.
Request
curl -X POST 'https://<instancia>/integration/wms/converter/internal/create' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "origin": "CONV-000012",
    "product_ref": "305",
    "incoming_quantity": 10,
    "location_code": "354",
    "location_dest_code": "354",
    "incoming_lots": [
      {"lot_name": "20260701-B1", "qty": 10, "expiration_date": "2027-01-01"}
    ],
    "product_components": [
      {"product_ref": "201", "qty": 20, "lot_name": "20260701-A1"}
    ]
  }'
Response
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "request_details": {
      "processed_lines": 1,
      "document_name": "CONV/00012"
    }
  }
}

Lotes

Editar lote

GETPOST /integration/wms/stock/lots/edit
Sin autenticación

Actualiza la fecha de vencimiento (life_date) de un lote de producción ya existente, y lo marca como no_edit para evitar sobrescrituras posteriores desde el ERP. Si el lote no existe para el producto indicado responde L06. Un error al escribir el cambio (por ejemplo, restricciones de integridad) responde L07.

Si el producto indicado no maneja trazabilidad por lotes se marca la novedad P07, pero el proceso no se detiene ahí: sigue intentando ubicar el lote de todas formas. Si el lote existe, la respuesta final mezcla de forma inconsistente status_code "99" con novelty.P07 y, al mismo tiempo, un request_details de éxito; si no existe, la respuesta termina siendo L06 (el P07 previo queda sobrescrito). En la práctica, P07 no debe interpretarse como una respuesta final confiable de este endpoint.

Parámetros

ParámetroTipoDescripción
user requerido string Usuario de integración de la compañía. Ver guía Autenticación.
passwd requerido string SHA-256 de la contraseña de integración. Ver guía Autenticación.
product_ref requerido string Id del producto en DrivErp (product.product). Aunque es un identificador numérico, debe enviarse como texto (la validación de la petición exige string, no número JSON). P01 si no existe.
lot_name requerido string Nombre del lote a editar (stock.production.lot). Debe existir para el producto indicado (L06 si no). También es la clave del control de reintentos (S09) para esta ruta.
expiration_date date Nueva fecha de vencimiento del lote (YYYY-MM-DD). No es realmente obligatoria a nivel de código: si se omite, no se produce ningún error y el lote queda con su fecha de vencimiento en blanco (se sobrescribe con el valor vacío enviado).
lot_group string Nombre del grupo de lotes; se incluye únicamente en la validación de la petición, no modifica la relación del lote existente.
Request
curl -X POST 'https://<instancia>/integration/wms/stock/lots/edit' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "product_ref": "201",
    "lot_name": "20260701-A1",
    "expiration_date": "2027-06-30"
  }'
Response
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "request_details": {
      "product_name": "Producto de ejemplo",
      "lot_name": "20260701-A1"
    }
  }
}

Inventario

Crear ajuste de inventario

GETPOST /integration/wms/stock/inventory/adjustment
Sin autenticación

Crea (o reutiliza, si existe exactamente un ajuste en borrador/cancelado con la misma referencia, tipo de transacción y ubicación — se crea uno nuevo si hay más de una coincidencia) un ajuste de inventario (stock.inventory) y lo procesa completamente. Requiere que la compañía tenga configurados el contrato y la cuenta analítica de ajustes WMS (systech_contract_id/systech_analytic_id; T06 si faltan), y que la ubicación esté gestionada por WMS (L13).

El comportamiento de product_lines depende de adjustment_type:

  • adjustment: cada línea suma o resta qty según qty_type (pos/neg), sujeto a que el tipo de transacción permita ese signo (T07/T04).
  • final_count: qty es el conteo físico total reportado por el WMS para el lote; se registra como recuento pendiente de aprobación (stock.inventory.count.wms), sin afectar inventario hasta su aprobación en el ERP.
  • lot_edit: mueve cantidad de un lote a otro del mismo producto. Exige exactamente 2 líneas (I09) con qty_type opuesto (I10), mismo product_ref (I11) y balance neto igual a 0 (Q04); requiere que el tipo de transacción tenga habilitado el cambio de lote.

El ajuste debe poder confirmarse (action_start()) o responde I04, independientemente de si la aprobación es manual o automática. Salvo que el tipo de transacción tenga configurada aprobación manual (wms_adjustment_action = 'manual'), además se aprueba y completa automáticamente en la misma llamada (I04 también si la aprobación o el cierre fallan en ese paso).

Parámetros

ParámetroTipoDescripción
user requerido string Usuario de integración de la compañía. Ver guía Autenticación.
passwd requerido string SHA-256 de la contraseña de integración. Ver guía Autenticación.
adjustment_name requerido string Referencia del ajuste (stock.inventory, campo ref). Si existe exactamente un ajuste con la misma referencia, tipo de transacción y ubicación en estado 'borrador' o 'cancelado', se reutiliza; si hay más de una coincidencia, se crea uno nuevo. También es la clave del control de reintentos (S09).
location_code requerido string Código de la ubicación del ajuste (stock.location). L02 si no existe; debe estar gestionada por WMS (L13).
transaction_code requerido string Código del tipo de transacción de ajuste (inventory.transactions.types, campo code). T01 si no existe. Debe estar configurado para ajustes WMS ('adjustment' o 'final_count'; T03 en caso contrario), y su tipo debe coincidir con adjustment_type (T08).
adjustment_type requerido string 'adjustment': qty representa la cantidad a sumar/restar. 'final_count': qty es el conteo físico total del lote (recuento). 'lot_edit': mueve cantidad entre dos lotes del mismo producto (exige exactamente 2 líneas de signo opuesto; requiere que el tipo de transacción tenga habilitado el cambio de lote, T08/T02 en caso contrario).
Valores: adjustment final_count lot_edit
product_lines requerido array Líneas del ajuste. Para adjustment_type 'lot_edit' deben ser exactamente 2 (I09), con qty_type opuesto entre ambas (I10) y el mismo product_ref (I11); el balance de cantidades debe dar 0 (Q04).
product_ref requerido integer Id del producto (product.product). P01 si no existe.
qty requerido number Cantidad de la línea. Su interpretación depende de adjustment_type: cantidad a ajustar ('adjustment'), conteo físico ('final_count') o cantidad a mover entre lotes ('lot_edit'). Solo en 'adjustment' se valida que el resultado no deje el saldo en negativo (Q03); en 'lot_edit' el chequeo equivalente responde I12; 'final_count' no valida saldo negativo en este paso (queda pendiente de la aprobación del recuento en el ERP).
qty_type string Obligatorio cuando el tipo de transacción está configurado como 'adjustment' (T05 si es inválido) — esto incluye tanto adjustment_type 'adjustment' como 'lot_edit', ya que 'lot_edit' exige un tipo de transacción con wms_adjustment_type='adjustment'. 'pos' exige que el tipo de transacción permita ajustes positivos (T07) y permite crear el lote si no existe; 'neg' exige que permita negativos (T04) y nunca crea lote (debe existir, L06).
Valores: pos neg
lot_name string Nombre del lote. Se crea automáticamente si el producto tiene trazabilidad y la línea tiene qty_type 'pos' (o no aplica qty_type, en 'final_count'); las líneas con qty_type 'neg' exigen que el lote ya exista.
lot_ref string Referencia/placa del lote, exigida al crear un lote nuevo si el producto lo requiere (L12).
expiration_date date Fecha de vencimiento del lote a crear (YYYY-MM-DD), si el producto controla vencimiento. No hay un código de novedad específico si falta: simplemente el lote queda sin fecha de vencimiento.
lot_group string Nombre del grupo de lotes; se crea automáticamente si no existe.
localization_code string Código de la ubicación física del lote, si el producto está integrado al WMS (L15 si se envía y no existe). **Excepción**: si location_code es '354', '356', '357' o '375', el valor enviado se ignora y se sobrescribe internamente con un código fijo por ubicación (parametrización específica de un cliente, no configurable).
wms_doc_id string Identificador de la línea en el sistema WMS. Se guarda como reference en el registro de auditoría del movimiento (stock.move.line.wms), no en la línea de stock.inventory.line. En adjustment_type 'final_count' no se persiste en ningún lado.
documento1 string Referencia libre adicional de la línea. En el módulo base no tiene ningún efecto observable: se pasa a un hook de extensión (action_wms_process_oncreate) que por defecto no hace nada, y se descarta antes de guardar el movimiento WMS. Solo es útil si un módulo de extensión instalado sobrescribe ese hook.
Request
curl -X POST 'https://<instancia>/integration/wms/stock/inventory/adjustment' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "adjustment_name": "Ajuste vencidos julio",
    "location_code": "354",
    "transaction_code": "AJVE",
    "adjustment_type": "adjustment",
    "product_lines": [
      {
        "product_ref": 201,
        "lot_name": "20260701-A1",
        "qty": 5,
        "qty_type": "neg",
        "wms_doc_id": "AJ-000123"
      }
    ]
  }'
Response
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "request_details": {
      "processed_lines": 1,
      "document_name": "Ajuste vencidos julio"
    }
  }
}

Consultar existencias

GETPOST /integration/wms/stock/stocklist/return
Sin autenticación

Consulta las existencias actuales por lote. Es una petición de solo lectura (método GET), pero igualmente sujeta al control de reintentos (clave: location_code + product_ref) y a las credenciales de autenticación. Debe enviarse al menos uno de product_ref o location_code; enviar ambos vacíos marca la novedad R01 (sin detener el proceso: la respuesta igual incluye result: [], ya que ninguna de las tres combinaciones descritas abajo aplica). Sin existencias encontradas para el criterio indicado responde Q02excepto en la combinación product_ref + location_code, donde un error de programación en esa rama (referencia a un atributo inexistente del producto) hace que, en vez de Q02, la petición termine en un error interno no controlado cuando no hay existencias para ese producto en esa ubicación.

La forma de la respuesta (bajo la llave result, no request_details) varía según la combinación enviada — incluyendo el nombre de la llave que contiene el detalle por lote de cada producto:

  • product_ref + location_code: un único objeto con las existencias del producto en esa ubicación, desglosadas por lote bajo la llave stocklist.
  • Solo product_ref: un objeto por cada ubicación gestionada por WMS donde el producto tiene existencias, cada uno con el detalle por lote también bajo stocklist.
  • Solo location_code: un único objeto con todos los productos que tienen existencias en la ubicación, cada uno con su detalle por lote bajo la llave stock_list (con guion bajo — nombre distinto al de las otras dos combinaciones), calculado directamente por consulta SQL e incluyendo lotes con cantidad 0. En esta combinación, si el producto no tiene ningún lote asociado, available_qty llega como el string "-" en vez de un número.

Parámetros

ParámetroTipoDescripción
user requerido string Usuario de integración de la compañía. Ver guía Autenticación.
passwd requerido string SHA-256 de la contraseña de integración. Ver guía Autenticación.
product_ref string Id del producto a consultar (product.product, no puede ser de tipo Servicio), enviado como texto (la validación de la petición exige string, no número JSON). Debe enviarse product_ref y/o location_code (R01 si se omiten ambos). P01 si no existe.
location_code string Código de la ubicación a consultar (stock.location, gestionada por WMS). Debe enviarse product_ref y/o location_code (R01 si se omiten ambos). L02 si no existe o no está gestionada por WMS.
Request
curl -X GET 'https://<instancia>/integration/wms/stock/stocklist/return' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "product_ref": "201",
    "location_code": "354"
  }'
Response
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "result": [
      {
        "location_code": "354",
        "location_name": "Bodega Principal",
        "products": {
          "product_name": "Producto de ejemplo",
          "product_ref": 201,
          "stocklist": [
            {
              "lot": "20260701-A1",
              "total_qty": 100.0,
              "reserved_qty": 20.0,
              "available_qty": 80.0,
              "exp_date": "2027-06-30 00:00:00"
            }
          ]
        }
      }
    ]
  }
}

Productos

Editar código de barras

GETPOST /integration/wms/product/barcode/edit
Sin autenticación

Actualiza el código de barras (barcode) de un producto existente. Es el único endpoint de la integración fuera del grupo Inventario/Transferencias: se usa para mantener sincronizado el maestro de códigos de barras cuando el WMS gestiona su propia numeración o etiquetado. Un error al guardar el cambio (por ejemplo, un código de barras duplicado) responde B01.

Parámetros

ParámetroTipoDescripción
user requerido string Usuario de integración de la compañía. Ver guía Autenticación.
passwd requerido string SHA-256 de la contraseña de integración. Ver guía Autenticación.
product_ref requerido integer Id del producto en DrivErp (product.product). No pasa por la validación genérica de credenciales/campos (no se incluye en la verificación de usuario/contraseña): D01 si no puede convertirse a entero; P01 si no existe. Si se omite, la petición falla con un error interno no controlado (no D01), ya que el código no contempla el caso de valor ausente. También es parte de la clave del control de reintentos (S09), junto con barcode.
barcode requerido string Nuevo código de barras del producto. Se normaliza según la política de nomenclatura de lotes/códigos de la compañía antes de guardarse.
Request
curl -X POST 'https://<instancia>/integration/wms/product/barcode/edit' \
  -H 'Content-Type: application/json' \
  -d '{
    "user": "Us31#WM",
    "passwd": "9ccd3cdccdffdc88197c4c5c8d2e3b015be22fa76da6bf057bba5ef4e8eb45c4",
    "product_ref": 201,
    "barcode": "7701234567890"
  }'
Response
{
  "jsonrpc": "2.0",
  "id": null,
  "result": {
    "status_code": "00",
    "novelty": {},
    "request_details": {
      "product_name": "Producto de ejemplo",
      "barcode": "7701234567890"
    }
  }
}