Datos de Test – Connector SAGE 200c (FACTSYNC)

Este documento especifica el conjunto mínimo de datos que es necesario crear en el endpoint SAGE para validar que todas las importaciones (y exportaciones) del conector funcionan correctamente, cubriendo casos normales, casos límite y caminos de código críticos.

Índice

  1. Divisas
  2. Empleados / Comisionistas
  3. Familias y Grupos de productos
  4. Artículos (productos)
  5. Imágenes de artículos
  6. Clientes
  7. Direcciones
  8. Líneas de descuento / Tarifas
  9. Precios estándar por tarifa
  10. Precios especiales por cliente
  11. Condiciones especiales
  12. Almacenes
  13. Stocks
  14. Pedidos
  15. Albaranes
  16. Facturas
  17. Matriz de escenarios transversales

1. Divisas GET /api/divisas

Necesitamos EUR como moneda por defecto (código vacío en los clientes debe resolver a EUR) y al menos una moneda extranjera para probar la conversión de factor en pedidos.

CodigoDivisa Divisa SimboloDivisa Decimales FactorCambioEuro Motivo del test
EUR Euro 2 1.0 Moneda base / fallback por defecto
USD Dólar EEUU $ 2 1.08 Factor > 1; prueba resolución _get_id_divisa y factor_conversio en pedidos
GBP Libra esterlina £ 2 0.85 Factor < 1; cubre la tercera moneda para clientes

2. Empleados / Comisionistas GET /api/comisionistas

Los clientes pueden tener hasta 4 comisionistas (CodigoComisionistaCodigoComisionista4_). Es necesario crear 4 para probar el mapeo completo del campo __treballadors[].

CodigoComisionista Comisionista CifDni Telefono Telefono2 EMail1 Domicilio Motivo del test
COM001 Anna García 12345678A 93 111 2233 600 111 222 anna@test.com Carrer Major, 1 Registro completo; comisionista 1 del cliente CLI001
COM002 Jordi López 87654321B 93 444 5566 jordi@test.com Sin teléfono2 ni dirección; comisionista 2
COM003 Marta Vidal 11223344C Registro mínimo; comisionista 3
COM004 Pere Mas 44332211D Registro mínimo; comisionista 4

3. Familias y Grupos de productos GET /api/familias

El conector separa familias (CodigoSubfamilia = '**********') de grupos (CodigoSubfamilia <> '**********') en dos pasadas. Es necesario tener ambos niveles para probar la resolución de jerarquía.

Familias (CodigoSubfamilia = **********)

CodigoFamilia CodigoSubfamilia Descripcion Motivo del test
FAM001 ********** Electrónica Familia con múltiples grupos hijos
FAM002 ********** Alimentación Familia con un solo grupo; IVA superreducido en los artículos

Grupos (CodigoSubfamilia <> **********)

CodigoFamilia CodigoSubfamilia Descripcion Motivo del test
FAM001 SUB001 Telefonía Grupo con múltiples artículos
FAM001 SUB002 Audio Grupo con un solo artículo; prueba resolución _get_id_familia
FAM002 SUB003 Conservas Grupo de alimentación; artículos con IVA reducido

4. Artículos (productos) GET /api/articulos

Es necesario cubrir: artículo normal, artículo obsoleto, artículo sin subfamilia, variación de IVA y precios de oferta activos.

CodigoArticulo DescripcionArticulo CodigoFamilia CodigoSubfamilia PrecioVenta PrecioCompra PrecioVentasinIVA1 PrecioVentasinIVA2 PrecioVentasinIVA3 PrecioOfertasinIVA GrupoIva ObsoletoLc CodigoContable FechaAlta Motivo del test
ART001 Teléfono Estándar FAM001 SUB001 299.00 150.00 280.00 260.00 240.00 S1 0 700001 2024-01-01T00:00:00 Artículo completo; genera precios LINIA_DESC_1/2/3
ART002 Auriculares Pro FAM001 SUB002 89.99 40.00 75.00 S2 0 700002 2024-01-01T00:00:00 Precio de oferta activo → TARIFA_BASE_OFERTA
ART003 Teléfono Descatalogado FAM001 SUB001 199.00 90.00 S1 1 700003 2023-01-01T00:00:00 ObsoletoLc=1arxivat='Y', web='N'
ART004 Conserva Test FAM002 SUB003 3.50 1.50 S3 0 700004 2024-06-01T00:00:00 IVA superreducido; usado en condiciones especiales por cadena
ART005 Artículo Sin Subfamilia FAM001 50.00 20.00 S1 0 700005 2024-01-01T00:00:00 CodigoSubfamilia vacío → prueba resolución nula de grupo
Nota (ART002 – oferta): Para activar TARIFA_BASE_OFERTA, el campo PrecioOfertasinIVA debe ser > 0 y la fecha actual debe caer entre FechaInicioOferta y FechaFinalOferta. Usar fechas amplias: 2024-01-012030-12-31.

5. Imágenes de artículos GET /api/imagenes_articulos + GET /api/imagen/{ImagenExt}

El conector identifica las imágenes por UUID (ImagenExt). Cuando el UUID cambia, elimina la anterior y guarda la nueva. Es necesario ejecutar la sincronización dos veces para probar esta rotación.

CodigoArticulo ImagenExt (1a sync) ImagenExt (2a sync) sysDescripcionBinario Motivo del test
ART001 img-uuid-001a img-uuid-001b Imagen principal teléfono Rotación de UUID: la 2a sync debe eliminar 001a y guardar 001b
ART001 img-uuid-002 img-uuid-002 Imagen secundaria UUID estable entre syncs → no se vuelve a descargar
ART002 img-uuid-003 img-uuid-003 Imagen auriculares Artículo con una sola imagen
Nota: El endpoint /api/imagen/{ImagenExt} debe devolver la imagen codificada en Base64. Usar un PNG pequeño válido (< 10 KB) para agilizar el test.

6. Clientes GET /api/clientes

Se necesitan seis clientes para cubrir todos los casos: completo, cabeza de una cadena, hijo de cadena, inactivo, moneda extranjera y cliente con tipo (para condiciones especiales).

CLI001 — Cliente completo (todas las relaciones)

Campo SAGEValorMotivo del test
CodigoClienteCLI001Clave primaria
RazonSocialACME Corporation, SLempresa
NombreJoan Puignom
Email1joan@acme.comemail
Telefono93 100 0001telefon
Telefono293 100 0002telefon2
Telefono3600 100 001telefon_movil
Fax93 100 0099fax
CifDniB12345678nif / num_doc
FechaAlta2020-01-15T00:00:00data_alta (conversión timestamp)
CodigoContable430001subcuenta
CodigoDivisaEURid_divisa
FormadePagoREC30id_forma_pago
TarifaPrecioTAR001id_linea_descompte
CodigoRuta_RUTA01id_ruta
CodigoComisionistaCOM001Comisionista 1 → id_treballador
CodigoComisionista2_COM002Comisionista 2 → __treballadors[]
CodigoComisionista3_COM003Comisionista 3
CodigoComisionista4_COM004Comisionista 4 (prueba máximo de 4)
ObservacionesClienteCliente VIP. Trato preferente.observacions
IBANES91 2100 0418 4502 0005 1332CC_iban
SiglaNacionESCC_pais
RiesgoMaximo5000.00credit
ClaveIVAS1clau_iva
%Descuento5.0descompte1
BajaEmpresaLc0arxivat='N' (activo)
CodigoCadena_CLI001Igual al propio código → no es hijo de cadena
CodigoTipoClienteLcTIPOAUsado en condiciones especiales por tipo
FechaNacimiento1980-05-20T00:00:00data_naixement

CLICHAIN — Cabeza de cadena

Campo SAGEValorMotivo del test
CodigoClienteCLICHAINClave primaria
RazonSocialCadena Supermercats, SA
CodigoCadena_CLICHAINIgual al propio código → cabeza de cadena, no hijo
BajaEmpresaLc0Activo
CodigoDivisaEUR

CLISUB01 — Hijo de cadena caso crítico

Campo SAGEValorMotivo del test
CodigoClienteCLISUB01Clave primaria
RazonSocialCadena - Sucursal Barcelona
CodigoCadena_CLICHAINDiferente del propio código → hijo; debe asignar id_parent a CLICHAIN, enllacar_factures='N', enllacar_condicions='Y'
BajaEmpresaLc0Activo
CodigoDivisaEUR

CLIBAJA — Cliente inactivo

Campo SAGEValorMotivo del test
CodigoClienteCLIBAJA
RazonSocialCliente Inactivo, SL
BajaEmpresaLc1arxivat='Y'
FechaBajaLc2025-12-01T00:00:00data_baixa
CodigoDivisaEUR
Nota CLIBAJA: Crear una factura para este cliente en la sección 17 para verificar que los documentos históricos se importan correctamente aunque el cliente esté archivado.

7. Direcciones GET /api/domicilios

El conector ignora NumeroDomicilio = 0 (dirección principal, ya incluida en el cliente). TipoDomicilio = 'F'defecte='Y'.

IdDomicilio CodigoCliente NumeroDomicilio RazonSocial TipoDomicilio Domicilio Domicilio2 Numero1 Piso Escalera Puerta CodigoPostal Municipio Provincia CodigoNacion Telefono Motivo del test
DOM000 CLI001 0 ACME – Principal F Carrer Principal, 1 1 08001 Barcelona Barcelona ES SKIP NumeroDomicilio=0 → debe ser ignorado
DOM001 CLI001 1 ACME – Fiscal F Av. Diagonal Edifici A 123 3 B 2a 08010 Barcelona Barcelona ES 93 200 0001 TipoDomicilio=F → defecte='Y'; todos los campos de dirección
DOM002 CLI001 2 ACME – Entrega E Polígon Industrial 5 08820 El Prat de Llobregat Barcelona ES TipoDomicilio=E → defecte='N'
DOM003 CLIUSD 1 International Corp – Office E 123 Main St 10001 New York NY US CodigoNacion=US → prueba resolución de país no-ES

8. Líneas de descuento / Tarifas GET /api/tarifas

Se necesita un registro por cada valor de IndicadorTarifa (0, 1, 2) para cubrir los tres caminos de cálculo de precio en los precios estándar.

Tarifa DescripcionTarifa IndicadorTarifa Tipo de cálculo Motivo del test
TAR001 Tarifa Estándar Directa 0 Precio directo Camino principal; usada por CLI001 vía TarifaPrecio
TAR002 Tarifa Porcentaje Incremento 1 Precio base × (1 + %/100) Prueba cálculo de markup porcentual
TAR003 Tarifa Valor Fijo 2 Precio base + valor fijo Prueba cálculo de incremento de valor fijo

9. Precios estándar por tarifa GET /api/tarifa_precio

El conector genera N+1 filas por registro (N tramos + 1 fila base final). Es necesario probar múltiples tramos, precios expirados y los tres tipos de IndicadorTarifa.

TP001 — TAR001 / ART001 — 3 tramos de volumen (genera 4 filas) caso crítico

CampoValor
IdTarifaPrecioTP001
TarifaTAR001
CodigoArticuloART001
IndicadorTarifa0 (precio directo)
FechaInicio2024-01-01T00:00:00
FechaFinal2026-12-31T00:00:00
HastaUnidades110
Precio1299.00
HastaUnidades250
Precio2275.00
HastaUnidades3100
Precio3250.00
HastaUnidades410(vacíos)
StatusActivo-1 (activo)
Resultado esperado: 4 filas en Softbase: TP001-1 (≤10 u. → 299.00), TP001-2 (≤50 u. → 275.00), TP001-3 (≤100 u. → 250.00) y TP001 (fila base final sin límite de volumen).

TP002 — TAR002 / ART002 — % incremento, expirado caso límite

CampoValor
IdTarifaPrecioTP002
TarifaTAR002
CodigoArticuloART002
IndicadorTarifa1 (% markup)
FechaInicio2024-01-01T00:00:00
FechaFinal2025-01-01T00:00:00
HastaUnidades19999
Precio15.0 (% a añadir al precio base)
StatusActivo0 (inactivo)
Resultado esperado: El registro debe crearse pero con eliminat = timestamp (StatusActivo ≠ -1).

TP003 — TAR003 / ART004 — valor fijo, un solo tramo

CampoValor
IdTarifaPrecioTP003
TarifaTAR003
CodigoArticuloART004
IndicadorTarifa2 (valor fijo)
FechaInicio2025-01-01T00:00:00
FechaFinal
HastaUnidades19999
Precio10.50 (euros a sumar al precio base)
StatusActivo-1

10. Precios especiales por cliente GET /api/articulos_clientes

Es necesario cubrir: precio directo, descuentos en cascada, registro sin precio ni descuento (debe ser ignorado) y un precio asignado a un cliente de cadena.

CodigoCliente CodigoArticulo PrecioOferta %Descuento %Descuento2 %Descuento3 Resultado esperado
CLI001 ART001 250.00 0 0 0 tipus_condicio='preu', valor=250.00
CLI001 ART002 0 10.0 5.0 0 tipus_condicio='desc'; cascada: (1-0.10)×(1-0.05) → 14.5% efectivo
CLICHAIN ART004 3.00 0 0 0 tipus_condicio='preu', precio para la cabeza de cadena
CLISUB01 ART001 0 0 0 0 SKIP Ni precio ni descuento → __import=false, registro ignorado

11. Condiciones especiales GET /api/condiciones_especiales (Automatico=0)

Se necesita un registro por cada ámbito posible: cliente concreto, cadena, tipo de cliente, familia y grupo.

Ámbito CodigoCliente CodigoCadena_ CodigoTipoClienteLc CodigoFamilia CodigoSubfamilia Precio %Descuento Automatico Motivo del test
Por cliente CLI001 FAM001 0 15.0 0 taula='cli_ficha', tipus_element='art_families'
Por cadena CLICHAIN FAM001 SUB001 270.00 0 0 Resolución de cadena → cliente cabeza; tipus_element='art_articles'
Por familia FAM001 0 5.0 0 Condición global de familia sin cliente concreto
Por grupo FAM001 SUB002 80.00 0 0 Condición global de grupo; tipus_condicio='preu'
Automática (ignorada) CLI001 FAM001 0 3.0 1 SKIP Automatico=1 → filtrada por el endpoint, no debe importarse

12. Almacenes GET /api/almacenes

CodigoAlmacen Almacen Domicilio Municipio CodigoPostal Provincia Motivo del test
ALM001 Almacén Central Polígon Industrial, 12 Molins de Rei 08750 Barcelona Almacén principal; usado en pedidos y stocks
ALM002 Almacén Secundario Madrid 28001 Madrid Dirección parcial (Domicilio vacío); ART001 tiene stock aquí

13. Stocks GET /api/stock

Es necesario cubrir el mismo artículo en dos almacenes, un artículo obsoleto con stock residual, y una referencia a un artículo inexistente para probar el skip silencioso.

IdAcumuladoStock CodigoArticulo CodigoAlmacen UnidadSaldo PrecioMedio Motivo del test
STK001 ART001 ALM001 150 145.00 Artículo activo en almacén principal
STK002 ART001 ALM002 30 148.00 Mismo artículo, segundo almacén → dos registros en mag_estocs
STK003 ART002 ALM001 200 39.50 Artículo con oferta activa
STK004 ART003 ALM001 5 88.00 Artículo obsoleto → el stock debe importarse igualmente
STK005 ART004 ALM001 1000 1.45 Artículo de alimentación; stock grande

14. Pedidos GET /api/pedidos + GET /api/pedido/{any}-{serie}-{num}

Es necesario cubrir los tres estados posibles, moneda extranjera y un pedido sin líneas.

PED-2026-A-1 — PENDIENTE, múltiples líneas, descuento en cascada

{ "IdPedidoCli": "PED-2026-A-1", "CodigoCliente": "CLI001", "EjercicioPedido": 2026, "SeriePedido": "A", "NumeroPedido": 1, "FechaPedido": "2026-03-01T00:00:00", "CodigoDivisa": "EUR", "FactorCambio": 1.0, "ImporteBruto": 369.79, "ImporteLiquido": 433.95, "Estado": "PENDIENTE", "Lineas": [ { "CodigoArticulo": "ART001", "DescripcionArticulo": "Telèfon Estàndard", "UnidadesPedidas": 1, "Precio": 299.00, "ImporteBruto": 299.00, "BaseImponible": 284.05, "ImporteNeto": 284.05, "GrupoIva": "S1" }, { "CodigoArticulo": "ART002", "DescripcionArticulo": "Auriculars Pro", "UnidadesPedidas": 1, "Precio": 89.99, "ImporteBruto": 89.99, "BaseImponible": 80.99, "ImporteNeto": 80.99, "GrupoIva": "S2" } ] }
Comprobación de descuento: (ImporteBruto - BaseImponible) / ImporteBruto × 100 debe coincidir con el campo descompte guardado en Softbase. Usar valores que den un % no entero para probar el redondeo.

PED-2026-A-2 — BLOQUEADO, sin líneas caso límite

{ "IdPedidoCli": "PED-2026-A-2", "CodigoCliente": "CLI001", "EjercicioPedido": 2026, "SeriePedido": "A", "NumeroPedido": 2, "FechaPedido": "2026-03-10T00:00:00", "CodigoDivisa": "EUR", "FactorCambio": 1.0, "ImporteBruto": 0.00, "ImporteLiquido": 0.00, "Estado": "BLOQUEADO", "Lineas": [] }
Resultado esperado: La cabecera se importa correctamente. La ausencia de líneas no debe provocar ningún error.

15. Albaranes GET /api/albaranes + GET /api/albaran/{any}-{serie}-{num}

Es necesario cubrir: abierto, facturado y nota de crédito (abono).

IdAlbaranCli CodigoCliente Año Serie Numero FechaAlbaran StatusFacturado StatusAbono ImporteBruto ImporteLiquido estado esperado subestado esperado
ALB-2026-A-1 CLI001 2026 A 1 2026-03-10T00:00:00 0 0 358.80 433.95 OBERT
ALB-2026-A-2 CLI001 2026 A 2 2026-03-15T00:00:00 1 0 100.00 121.00 FACTURAT
ALB-2026-A-3 CLI001 2026 A 3 2026-03-20T00:00:00 0 1 -50.00 -60.50 OBERT ABONO

16. Facturas GET /api/facturas + GET /api/factura/{any}-{serie}-{num}

Es necesario cubrir: pendiente de contabilizar, contabilizada, nota de crédito y documento de un cliente inactivo.

IdAlbaranCli CodigoCliente Año Serie Numero FechaFactura StatusContabilizado StatusAbono ImporteBruto ImporteLiquido estado esperado subestado esperado
FAC-2026-A-1 CLI001 2026 A 1 2026-03-20T00:00:00 0 0 100.00 121.00 PENDENT
FAC-2026-A-2 CLI001 2026 A 2 2026-03-25T00:00:00 1 0 200.00 242.00 COMPTABILITZAT
FAC-2026-A-3 CLI001 2026 A 3 2026-04-01T00:00:00 1 1 -100.00 -121.00 COMPTABILITZAT ABONO
FAC-2026-B-1 CLIBAJA 2026 B 1 2026-02-01T00:00:00 1 0 500.00 605.00 COMPTABILITZAT
FAC-2026-B-1 (cliente inactivo): CLIBAJA tiene BajaEmpresaLc=1. La factura debe importarse correctamente, verificando que el archivado del cliente no bloquea la importación de documentos históricos.

17. Matriz de escenarios transversales

Comprobación rápida de que todos los caminos de código críticos quedan cubiertos por el conjunto de datos anterior.

Escenario Cómo se dispara Resultado esperado
Resolución de cadena (hijo) CLISUB01.CodigoCadena_ = CLICHAIN ≠ CLISUB01 id_parent apunta a CLICHAIN; enllacar_factures='N'; enllacar_condicions='Y'
4 comisionistas CLI001 con CodigoComisionista{1..4} todos rellenados __treballadors[] contiene los 4 IDs resueltos
Descuentos en cascada CLI001/ART002 con %Descuento=10 + %Descuento2=5 Valor final = precio × 0.90 × 0.95 = 14.5% efectivo
N+1 tramos de precio TP001 con 3 HastaUnidades rellenados 4 filas en Softbase: IDs TP001-1, TP001-2, TP001-3, TP001
Precio inactivo → eliminado TP002 con StatusActivo=0 Fila creada con eliminat = timestamp
Artículo obsoleto ART003.ObsoletoLc=1 arxivat='Y', web='N'
Artículo sin subfamilia ART005.CodigoSubfamilia vacío id_article=0 (resolución nula), sin error
NumeroDomicilio=0 ignorado DOM000 con NumeroDomicilio=0 No se crea ninguna dirección secundaria para este registro
Dirección fiscal → por defecto DOM001 con TipoDomicilio='F' defecte='Y'
Rotación de UUID de imagen ART001 imagen principal: cambiar ImagenExt entre la 1a y la 2a sync Imagen antigua eliminada; nueva UUID guardada en fsync_external_id
Pedido sin líneas PED-2026-A-2 con Lineas: [] Cabecera importada; ningún error por array vacío
Albarán nota de crédito ALB-2026-A-3 con StatusAbono=1 subestat='ABONO'
Factura de un cliente inactivo FAC-2026-B-1 → CLIBAJA (BajaEmpresaLc=1) Documento importado correctamente a pesar de cliente archivado
Precios LINIA_DESC 1/2/3 ART001 con PrecioVentasinIVA1/2/3 rellenados Tres entradas de precio adicionales creadas en Softbase
TARIFA_BASE_OFERTA ART002 con PrecioOfertasinIVA=75.00 y fechas activas Precio de oferta creado con __id_extern__ = TARIFA_BASE_OFERTA
Cliente sin CodigoCadena_ CLIUSD sin campo cadena id_parent=NULL; sin enllacar_* forzados