COSTINV.GEN

Amazon Vendor · EDI Generator

Cambiar contraseña

Debes cambiar la contraseña por defecto antes de continuar.

COSTINV.GEN

Amazon Vendor · EDI EDIFACT INVRPT Generator

INVRPT:D:96A:UN:EAN008
⚡ Generar EDI
🏢 Clientes
📋 Historial
📡 Log SFTP
{ } API
👥 Usuarios
1
Cargar costes
2
Parámetros EDI
3
Generar & Enviar
Archivo de costes (XLSX / CSV) EAN · QTY_ON_HAND · COST_PRICE
Procesando archivo...
📊
Arrastra el archivo o haz clic
XLSX / CSV (costes con EAN)
0 líneas detectadas
#EAN/GTINQTY On HandCost Price (€)
⚠
Parámetros EDI Manual · Desde EDI anterior · Desde cliente guardado
📄 Arrastra un .txt EDI

Generar & Enviar
Vista previa EDI generado
⚠
✓
Clientes / Configuraciones EDI
Nuevo cliente
📄 Importar EDI anterior para autorellenar campos

Configuración SFTP (opcional)
🔑 Subir .ppk o .pem
ClienteGLNAlmacénMonedaSFTP HostAcciones
Cargando...
Historial de ficheros generados
FechaFicheroClienteMsg RefLíneasÚltimo SFTPAcciones
Cargando...
Log de envíos SFTP
FechaFicheroClienteHostRutaEstadoError
Cargando...
Autenticación

Todas las peticiones (excepto /api/auth/login y /api/health) requieren un token JWT en la cabecera:

Authorization: Bearer <token>

Obtener token

# Login
curl -s -X POST https://vendor.cliptack.com/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"tu_usuario","password":"tu_password"}'

# Respuesta
{
  "token": "eyJhbGciOi...",
  "user": { "id": 1, "username": "admin", "role": "admin" }
}
El token expira en 24 horas. Se puede configurar el secreto con la variable de entorno JWT_SECRET.
Automatización — Flujo completo

Para automatizar la generación y envío de EDI desde un script bash/cron:

  1. Login — Obtener token JWT
  2. Subir XLSX o CSV — Parsear el fichero de costes para obtener las líneas de producto
  3. Obtener config — Leer los datos del cliente y sus contadores auto-incrementales
  4. Generar EDI — Construir el EDIFACT INVRPT y guardarlo en BD
  5. Enviar por SFTP — Enviar el fichero generado al servidor de Amazon

Script completo (bash + curl + jq)

#!/bin/bash
# COSTINV — Script de automatización
# Requiere: curl, jq
# Uso: ./send_edi.sh <client_id> <fichero.xlsx|csv>

BASE="https://vendor.cliptack.com/api"
USER="tu_usuario"
PASS="tu_password"
CLIENT_ID="$1"
COST_FILE="$2"

# 1. Login
TOKEN=$(curl -s -X POST "$BASE/auth/login" \
  -H 'Content-Type: application/json' \
  -d "{\"username\":\"$USER\",\"password\":\"$PASS\"}" \
  | jq -r .token)

echo "Token obtenido: ${TOKEN:0:20}..."

# 2. Parsear fichero de costes (XLSX o CSV)
if [[ "$COST_FILE" == *.csv ]]; then
  PARSE=$(curl -s -X POST "$BASE/edi/parse-csv" \
    -H "Authorization: Bearer $TOKEN" \
    -F "csv=@$COST_FILE")
else
  PARSE=$(curl -s -X POST "$BASE/edi/parse-xlsx" \
    -H "Authorization: Bearer $TOKEN" \
    -F "xlsx=@$COST_FILE")
fi
LINES=$(echo "$PARSE" | jq .lines)
COUNT=$(echo "$PARSE" | jq .count)
echo "Líneas parseadas: $COUNT"

# 3. Obtener config del cliente y contadores
CLIENT=$(curl -s "$BASE/clients/$CLIENT_ID" \
  -H "Authorization: Bearer $TOKEN")
COUNTER=$(curl -s "$BASE/clients/$CLIENT_ID/counters" \
  -H "Authorization: Bearer $TOKEN")

GLN=$(echo "$CLIENT" | jq -r .gln_su)
GLN_Q=$(echo "$CLIENT" | jq -r .gln_qualifier)
WH=$(echo "$CLIENT" | jq -r .wh_code)
WH_Q=$(echo "$CLIENT" | jq -r .wh_qualifier)
CUR=$(echo "$CLIENT" | jq -r .currency)
IREF=$(echo "$COUNTER" | jq -r .interchange_ref)
PREFIX=$(echo "$COUNTER" | jq -r .last_msg_prefix)
SEQ=$(echo "$COUNTER" | jq -r .msg_seq)
TODAY=$(date +%Y-%m-%d)
TIME=$(date +%H%M)
MREF="${PREFIX}$(date +%Y%m)$(printf '%05d' $SEQ)"

echo "Generando EDI: GLN=$GLN WH=$WH Intercambio=$IREF Msg=$MREF"

# 4. Generar EDI
GEN=$(curl -s -X POST "$BASE/edi/generate" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d "{
    \"client_id\": $CLIENT_ID,
    \"lines\": $LINES,
    \"config\": {
      \"gln_su\": \"$GLN\", \"gln_qualifier\": \"$GLN_Q\",
      \"wh_code\": \"$WH\", \"wh_qualifier\": \"$WH_Q\",
      \"currency\": \"$CUR\", \"msg_date\": \"$TODAY\",
      \"interchange_ref\": \"$IREF\", \"msg_ref\": \"$MREF\",
      \"time\": \"$TIME\"
    }
  }")

FILE_ID=$(echo "$GEN" | jq -r .id)
FNAME=$(echo "$GEN" | jq -r .filename)
echo "Fichero generado: $FNAME (ID: $FILE_ID)"

# 5. Enviar por SFTP
SFTP=$(curl -s -X POST "$BASE/sftp/send/$FILE_ID" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{}')

echo "SFTP: $(echo $SFTP | jq -r .remotePath // .error)"
echo "Completado."
Guarda las credenciales en variables de entorno o un fichero .env, nunca directamente en el script.
Auth — /api/auth
POST /api/auth/login Iniciar sesión (público)

Request body

{ "username": "admin", "password": "admin123" }

Response 200

{
  "token": "eyJhbG...",
  "user": { "id": 1, "username": "admin", "role": "admin", "must_change_pw": 0 }
}
GET /api/auth/me Datos del usuario autenticado

Response 200

{ "id": 1, "username": "admin", "role": "admin", "must_change_pw": 0 }
PUT /api/auth/password Cambiar contraseña propia

Request body

{ "current_password": "vieja", "new_password": "nueva" }

Response 200

{ "ok": true, "token": "eyJhbG..." }
Clientes — /api/clients
GET /api/clients Listar todos los clientes

Response 200

[
  {
    "id": 1, "name": "Amazon ES",
    "gln_su": "5450534000000", "gln_qualifier": "14",
    "wh_code": "MKCX4", "wh_qualifier": "92",
    "currency": "EUR",
    "sftp_host": "edi.amazon.com", "sftp_auth_type": "password", ...
  }
]
GET /api/clients/:id Obtener un cliente por ID

Response 200

{ "id": 1, "name": "Amazon ES", "gln_su": "5450534000000", ... }
GET /api/clients/:id/counters Contadores auto-incrementales del cliente

Response 200

{
  "client_id": 1,
  "interchange_ref": 100000005,
  "msg_seq": 5,
  "last_msg_prefix": "IVR"
}
Los contadores se incrementan automáticamente cada vez que se genera un EDI con client_id.
POST /api/clients Crear un cliente

Request body

{
  "name": "Amazon ES",
  "gln_su": "5450534000000",
  "gln_qualifier": "14",
  "wh_code": "MKCX4",
  "wh_qualifier": "92",
  "currency": "EUR",
  "sftp_host": "edi.amazon.com",
  "sftp_port": 22,
  "sftp_user": "vendor",
  "sftp_password": "secret",
  "sftp_path": "/inbox/INVRPT/",
  "sftp_auth_type": "password",
  // Para inicializar contadores desde un EDI previo (opcional):
  "initial_interchange_ref": "100000005",
  "initial_msg_ref": "IVR20260300005"
}

Response 201

{ "id": 1 }
PUT /api/clients/:id Actualizar un cliente

Request body

// Mismos campos que POST. Incluir initial_interchange_ref / initial_msg_ref para actualizar contadores.

Response 200

{ "ok": true }
DELETE /api/clients/:id Eliminar un cliente (cascada)

Elimina el cliente, sus contadores y desvincula sus ficheros e historial SFTP.

Response 200

{ "ok": true }
EDI — /api/edi
POST /api/edi/parse-xlsx Parsear XLSX de costes

Request (multipart/form-data)

# Campo: xlsx (fichero)
curl -X POST /api/edi/parse-xlsx \
  -H "Authorization: Bearer $TOKEN" \
  -F "xlsx=@NUevo_Cost_10-03-2026.xlsx"

El XLSX debe tener columnas: EAN (o GTIN), QTY_ON_HAND (o QTY), COST_PRICE (o COST/PRICE). La detección es flexible por nombre parcial.

Response 200

{
  "count": 150,
  "lines": [
    { "seq": 1, "ean": "8424385000000", "qty": 50, "price": 12.50 },
    ...
  ]
}
POST /api/edi/parse-csv Parsear CSV de costes (formato CABECERA/LINEA)

Request (multipart/form-data)

# Campo: csv (fichero)
curl -X POST /api/edi/parse-csv \
  -H "Authorization: Bearer $TOKEN" \
  -F "csv=@costes_20260311.csv"

El CSV usa ; como separador. Filas CABECERA (GLN, almacén, fecha) y LINEA (nº, EAN, stock, precio, stock_pedido, fecha_prevista).

Response 200

{
  "count": 4,
  "lines": [
    { "seq": 1, "ean": "3165140001939", "qty": 999, "price": 8.93 },
    ...
  ],
  "header": { "gln": "1323336000001", "warehouse": "SYVOW", "date": "20260311" }
}
POST /api/edi/parse-edi Extraer parámetros de un EDI existente

Request (multipart/form-data)

curl -X POST /api/edi/parse-edi \
  -H "Authorization: Bearer $TOKEN" \
  -F "edi=@fichero_anterior.txt"

Response 200

{
  "gln_su": "5450534000000", "gln_qualifier": "14",
  "wh_code": "MKCX4", "wh_qualifier": "92",
  "currency": "EUR",
  "interchange_ref": "100000006",
  "interchange_prev": "100000005",
  "msg_ref": "IVR20260300006",
  "msg_ref_prev": "IVR20260300005",
  "msg_date": "2026-03-10",
  "segments_count": 465
}
Los campos interchange_ref y msg_ref ya están incrementados respecto al fichero parseado.
POST /api/edi/generate Generar fichero EDIFACT INVRPT

Request body

{
  "client_id": 1,
  "lines": [
    { "seq": 1, "ean": "8424385000000", "qty": 50, "price": 12.50 }
  ],
  "config": {
    "gln_su": "5450534000000",
    "gln_qualifier": "14",
    "wh_code": "MKCX4",
    "wh_qualifier": "92",
    "currency": "EUR",
    "msg_date": "2026-03-10",
    "interchange_ref": "100000005",
    "msg_ref": "IVR20260300005",
    "time": "1430"
  }
}
Si se incluye client_id, los contadores del cliente se incrementan automáticamente tras generar.

Response 200

{
  "id": 42,
  "filename": "edi_fact_5450534000000_20260310_100000005.txt",
  "edi_content": "UNB+UNOC:2+...",
  "lines_count": 150
}
GET /api/edi/files Historial de ficheros generados

Response 200

[
  {
    "id": 42, "filename": "edi_fact_...", "client_name": "Amazon ES",
    "msg_ref": "IVR20260300005", "lines_count": 150,
    "last_sftp_status": "success", "created_at": "2026-03-10 14:30:00"
  }
]
GET /api/edi/files/:id/download Descargar fichero EDI generado (.txt)
curl -OJ /api/edi/files/42/download \
  -H "Authorization: Bearer $TOKEN"

Devuelve text/plain con Content-Disposition: attachment.

SFTP — /api/sftp
POST /api/sftp/send/:fileId Enviar fichero por SFTP

Usa la config SFTP del cliente asociado al fichero. Se puede sobreescribir pasando la config en el body.

Request body (opcional, para override)

{
  "host": "edi.amazon.com",
  "port": 22,
  "username": "vendor",
  "password": "secret",
  "remotePath": "/inbox/INVRPT/"
}

Response 200

{ "ok": true, "remotePath": "/inbox/INVRPT/edi_fact_....txt" }

Response 502 (error)

{ "error": "Connection refused" }
POST /api/sftp/test Probar conexión SFTP

Request body

// Por password:
{ "host": "edi.amazon.com", "port": 22, "username": "vendor", "password": "secret" }

// Por clave privada:
{ "host": "...", "username": "...", "authType": "key", "privateKey": "-----BEGIN RSA..." }

Response 200

{ "success": true }
// o
{ "success": false, "error": "Authentication failed" }
GET /api/sftp/logs Historial de envíos SFTP

Response 200

[
  {
    "id": 1, "filename": "edi_fact_...", "client_name": "Amazon ES",
    "sftp_host": "edi.amazon.com", "status": "success",
    "error_msg": null, "sent_at": "2026-03-10 14:31:00"
  }
]
Usuarios — /api/users (solo admin)
GET /api/users Listar usuarios

Response 200

[{ "id": 1, "username": "admin", "role": "admin", "created_at": "..." }]
POST /api/users Crear usuario

Request body

{ "username": "nuevo", "password": "1234", "role": "user" }

Response 201

{ "id": 2, "username": "nuevo", "role": "user" }
PUT /api/users/:id Editar usuario

Request body

{ "username": "editado", "role": "admin", "password": "nueva_pw" }
// password es opcional: si no se incluye, no se cambia

Response 200

{ "ok": true }
DELETE /api/users/:id Eliminar usuario

No puedes eliminarte a ti mismo.

Response 200

{ "ok": true }
Health — /api/health (público)
curl https://vendor.cliptack.com/api/health
# → { "ok": true, "ts": "2026-03-10T14:30:00.000Z" }
Gestión de usuarios
Nuevo usuario
UsuarioRolCreadoAcciones
Cargando...
Desarrollado por Cliptack SL © 2026