BC Blueprint - Data Exchange Definition

BC Blueprint - Data Exchange Definition

BC Blueprint - Data Exchange Definition

Un análisis funcional y técnico en profundidad sobre el framework de intercambio de datos que Business Central esconde detrás de una página de configuración: cómo separa formato, ejecución y mapeo; qué tablas, codeunits y XMLports participan; cómo procesa CSV, fixed-width, XML y estructuras personalizadas; qué ocurre durante una importación o exportación; y dónde esperan las trampas detrás de la aparentemente inocente página Data Exchange Definition.

Nota de versión: los nombres e identificadores de objetos, campos, procedimientos públicos y eventos de este artículo se contrastaron originalmente con Microsoft Base Application 27.5.46862.47988 y se han revisado contra la documentación pública actual de Microsoft disponible el 31 de agosto de 2026. Los textos funcionales están en español, pero los objetos, campos, valores de configuración y referencias de AL conservan su nombre original en inglés. Comprueba siempre los símbolos de la versión exacta contra la que compila tu extensión: una definición puede ser configuración, pero los objetos Integer que contiene siguen teniendo una relación muy física con el runtime.

La funcionalidad que todo el mundo ha visto y casi nadie quiere tocar

Business Central tiene la costumbre de esconder maquinaria industrial detrás de páginas que parecen tan amenazantes como una hoja de Excel ligeramente enfadada.

Data Exchange Definitions es un ejemplo perfecto.

A primera vista, parece una página de configuración en la que alguien selecciona CSV, elige un separador, mapea unas cuantas columnas y vuelve a casa antes de que el edificio empiece a arder. Sin embargo, debajo de esa página existe un pipeline de integración completo capaz de:

  • Obtener archivos o streams desde diferentes orígenes.
  • Interpretar texto delimitado, texto de ancho fijo, XML y formatos personalizados.
  • Persistir los valores interpretados en un buffer de ejecución normalizado.
  • Representar relaciones padre-hijo en documentos jerárquicos.
  • Transformar valores antes de mapearlos.
  • Mapear valores externos mediante RecordRef y FieldRef.
  • Utilizar registros intermedios en lugar de atacar directamente las tablas de producción.
  • Exportar documentos delimitados, de ancho fijo y XML.
  • Inyectar lógica personalizada antes, durante y después del mapeo.

Microsoft utiliza este framework en escenarios como extractos bancarios, exportaciones de pagos, documentos electrónicos, tipos de cambio, nóminas, Intrastat y otras integraciones localizadas. La documentación oficial lo presenta como una capa configurable para intercambiar documentos empresariales y archivos de datos cuyos formatos varían según el proveedor, la autoridad o el país. Esa es la descripción educada. La descripción menos educada es que se trata de un pequeño motor ETL configurable que vive dentro del ERP y finge que no lo es. Consulta About the Data Exchange Framework y Set up data exchange definitions.

Dentro de la serie BC Blueprint, este módulo ocupa un lugar distinto a Posting Groups y Dimensions: aquellos explican cómo Business Central decide y clasifica el registro; Data Exchange Definition explica cómo un dato externo consigue cruzar la frontera del ERP sin que cada proveedor obligue a escribir un importador completamente nuevo. Después de cruzarla, posting groups, dimensions, validaciones y reglas empresariales siguen esperando al otro lado. El framework traduce; no concede ciudadanía automática.

Este artículo explica qué hace realmente el framework, qué objetos AL participan y dónde guardan sus papeles los dragones.

Primero, el modelo mental

Una Data Exchange Definition no es una sola cosa. Son tres contratos que trabajan juntos:

  1. El contrato de formato describe el archivo externo: tipo, codificación, líneas, columnas, longitudes, rutas, separadores y culturas.
  2. El contrato de mapeo conecta esos elementos externos con tablas y campos de Business Central.
  3. El contrato de ejecución selecciona los codeunits y XMLports que obtienen, leen, validan, mapean, escriben y entregan los datos.

Durante la ejecución se crea una entrada Data Exch. independiente para cada intercambio. La definición es la receta; Data Exch. es la desafortunada cena de esta noche.

Pipeline de importación del Data Exchange Framework Un archivo entra en Data Exch., un lector genera Data Exch. Field, las transformaciones normalizan valores y el mapeo elige una ruta directa o intermedia antes del procesamiento empresarial. De bytes externos a datos empresariales La frontera observable es Data Exch. Field: antes hay parsing; después hay transformación y negocio. Adquisición File · Stream · API Data Exch. + File BLOB Ext. Data Handling Codeunit Lectura Codeunit o XMLport CSV · Fixed · XML Parsing según la definición Capa normalizada Data Exch. Field Line · Column · Node Valor original y jerarquía Transformación Transformation Rule Formato · cultura · limpieza Pipelines reutilizables Mapeo y proceso Direct staging o Intermediate Data Import Validación empresarial posterior Acquire → Parse → Inspect → Transform → Stage → Validate → Process → Clean up
Una importación es una cadena de contratos. La definición decide los componentes; la entrada Data Exch. conserva la ejecución.

La idea arquitectónica más importante es la frontera entre Data Exch. Field y la tabla final. Cuando entiendes esa frontera, todo el framework deja de parecer magia negra y empieza a parecer magia negra organizada.

Mapa de objetos

Todos los objetos principales se encuentran en el namespace System.IO en Base Application 27.5.

Tablas de configuración y ejecución

ID Objeto AL Propósito
1222 table "Data Exch. Def" Cabecera de la definición reutilizable de formato y ejecución.
1227 table "Data Exch. Line Def" Describe tipos de línea lógicos o nodos jerárquicos.
1223 table "Data Exch. Column Def" Describe columnas, elementos XML, atributos, constantes, formatos, longitudes y rutas.
1224 table "Data Exch. Mapping" Conecta una definición de línea con una tabla y con codeunits de premapeo, mapeo y posmapeo.
1225 table "Data Exch. Field Mapping" Conecta una columna con un campo y almacena transformación, prioridad, sobrescritura, valor predeterminado, opcionalidad y multiplicador.
1265 table "Data Exch. Field Mapping Buf." Buffer utilizado por la configuración del mapeo genérico y las sugerencias de campos.
1238 table "Data Exch. Field Grouping" Define los campos de agrupación utilizados por el mapeo genérico de exportación.
1233 table "Data Exch. Table Filter" Almacena vistas adicionales de tablas de origen utilizadas en exportaciones con varias partes.
1239 table "Data Exch. FlowField Gr. Buff." Soporte temporal para agregar FlowFields en exportaciones agrupadas.
1220 table "Data Exch." Una ejecución del intercambio, incluyendo nombre y BLOB del archivo, código de definición, filtros, documento entrante y registro relacionado.
1221 table "Data Exch. Field" Valores normalizados interpretados o generados, identificados por intercambio, línea, columna y nodo.
1214 table "Intermediate Data Import" Estructura genérica de staging que almacena tabla destino, campo destino, relación entre registros y valor.
1237 table "Transformation Rule" Transformaciones reutilizables y encadenables.

La documentación pública de objetos confirma las tablas centrales de configuración y sus campos actuales: Data Exch. Def, Data Exch. Mapping, Data Exch. Field Mapping y Data Exch..

Objetos de procesamiento que merece la pena conocer por su nombre

ID Objeto AL Función
1201 codeunit "Process Data Exch." Mapeador genérico de campos de importación y conversor de tipos.
1203 codeunit "Import XML File to Data Exch." Interpreta rutas XML y nodos padre-hijo configurados en Data Exch. Field.
1214 codeunit "Map DataExch To Intermediate" Convierte campos normalizados en Intermediate Data Import.
1241 codeunit "Fixed File Import" Divide líneas de ancho fijo según las longitudes configuradas en las columnas.
1413 codeunit "Read Data Exch. from Stream" Obtiene el contenido del archivo mediante un suscriptor de eventos.
1240 codeunit "Read Data Exch. from File" Utiliza el selector de archivos del cliente y coloca el archivo seleccionado en el BLOB del intercambio.
1220 xmlport "Data Exch. Import - CSV" Lee texto delimitado y escribe valores en Data Exch. Field.
1268 codeunit "Export Launcher" Inicia una exportación genérica desde un registro de origen o RecordRef.
1269 codeunit "Export Mapping" Lee registros de origen y genera líneas de Data Exch. Field para exportación.
1283 codeunit "Export Generic XML" Construye XML a partir de rutas de columnas y campos de intercambio generados.
1230 xmlport "Export Generic CSV" Escribe campos secuenciales del intercambio como texto delimitado.
1231 xmlport "Export Generic Fixed Width" Escribe campos secuenciales del intercambio sin delimitadores.
1225 xmlport "Imp / Exp Data Exch Def & Map" Mueve definiciones y mapeos entre entornos.

Las páginas que más suelen encontrar los desarrolladores son Data Exch Def List (1211), Data Exch Def Card (1210), Data Exch Line Def Card (1212) y Data Exch Mapping Card (1214).

La lista parece grande porque el framework separa deliberadamente lo que se configura de lo que ocurre en cada ejecución. Esa separación es el motivo por el que una definición puede reutilizarse miles de veces sin convertirse ella misma en un log de archivos importados.

Capas de configuración y ejecución del Data Exchange Framework La definición describe formato, líneas, columnas y mapeos. Cada ejecución crea Data Exch., Data Exch. Field y, opcionalmente, Intermediate Data Import. La receta no es la ejecución Configuración reutilizable Define contratos; no contiene el archivo de esta noche. Data Exch. Def (1222) Line Def + Column Def Mapping + Field Mapping Transformation Rule · codeunit IDs Ejecución trazable Una instancia por intercambio y sus valores. Data Exch. (1220) Data Exch. Field (1221) Intermediate Data Import Opcional · staging genérico y jerárquico instancia Los objetos de configuración describen el proceso; los buffers de ejecución cuentan qué ocurrió.
La separación entre receta y ejecución permite reutilización, diagnóstico y distintos procesadores sobre la misma capa normalizada.

Data Exch. Def: la cabecera y el armario de conexiones

table 1222 "Data Exch. Def" contiene los campos generales del formato:

  • Code y Name identifican la definición reutilizable.
  • Type utiliza el enum extensible Data Exchange Definition Type.
  • File Type admite Xml, Variable Text, Fixed Text y Json.
  • File Encoding admite codificaciones MS-DOS, UTF-8, UTF-16 y Windows.
  • Column Separator, Custom Column Separator y Line Separator controlan la interpretación del texto.
  • Header Lines, Header Tag y Footer Tag controlan qué líneas no deben convertirse en datos.

Los tipos estándar de definición son Bank Statement Import, Payment Export, Payroll Import, Generic Import, Positive Pay Export y Generic Export. El enum es extensible, aunque añadir un valor nuevo solamente pone nombre al escenario. No invoca un procesador desde el vacío. Aún tienes que conectar el pipeline. Consulta Data Exchange Definition Type.

La definición también contiene campos Integer que apuntan a cinco codeunits, además de un XMLport de lectura y escritura:

Campo Responsabilidad práctica
Ext. Data Handling Codeunit Introduce datos en el BLOB del intercambio durante una importación, o los entrega externamente durante una exportación.
Reading/Writing Codeunit Interpreta contenido importado o escribe contenido generado. Durante la importación tiene prioridad sobre el XMLport cuando su valor no es cero.
Reading/Writing XMLport Lector o escritor estándar cuando lo invoca el pipeline correspondiente.
Validation Codeunit Hook de validación utilizado por los lanzadores estándar de exportación. No se invoca automáticamente mediante Data Exch. Def.ProcessDataExchange() durante una importación genérica.
Data Handling Codeunit Preparación específica del escenario. Durante ProcessDataExchange() se ejecuta antes del bucle de mapeo.
User Feedback Codeunit Limpieza final o información al usuario cuando la ruta de exportación lo invoca.

Aquí existe un detalle peligroso pero importante: estos campos son simples identificadores Integer de objetos. La tabla puede confirmar que el objeto seleccionado es un codeunit, pero no puede imponer el contrato TableNo del codeunit.

Un launcher puede ejecutar un hook con un registro Data Exch., otro puede hacerlo con Data Exch. Mapping y una exportación especializada de pagos puede pasar una línea de diario. Una combinación incorrecta compila estupendamente porque la configuración son datos, y después falla en ejecución con toda la elegancia de un piano cayendo por unas escaleras.

Trata el codeunit seleccionado y el registro que recibe como un único contrato inseparable.

Data Exch. Line Def: una línea a veces es una línea y a veces un subárbol XML

Para archivos delimitados y de ancho fijo, una definición de línea suele describir la línea de detalle repetitiva. Sus campos principales son:

  • Column Count, relevante sobre todo para texto delimitado y para preparar columnas durante la exportación.
  • Line Type: Detail, Header o Footer.
  • Data Line Tag, utilizado para reconocer una línea de texto fijo o seleccionar un nodo XML.
  • Namespace, utilizado para validar el namespace XML en los lectores compatibles.
  • Parent Code, que crea una jerarquía entre definiciones de línea.

Para un CSV sencillo, una sola línea DETAIL suele ser suficiente.

En XML, la definición de línea se parece más al límite de un registro. Una definición padre puede representar una factura y una definición hija sus líneas. El Data Line Tag configurado identifica el nodo repetitivo, mientras que Parent Code indica al framework qué registros lógicos pertenecen debajo de otro registro.

No confundas Header Lines de Data Exch. Def con una definición de línea cuyo Line Type sea Header. El primero indica a un lector de texto cuántas filas físicas debe omitir. El segundo describe un tipo lógico de registro que puede participar en código especializado de importación o exportación. La misma palabra, dos criaturas distintas, porque la paz nunca fue una opción.

Data Exch. Column Def: describir datos externos antes de que tengan hogar

table 1223 "Data Exch. Column Def" describe un elemento externo. Para CSV, normalmente significa una columna posicional. Para XML, significa un elemento o atributo seleccionado mediante una ruta.

Los campos principales son:

  • Column No.: identificador estable utilizado por los mapeos de campos.
  • Data Type: Text, Date, Decimal, DateTime o Boolean.
  • Data Format y Data Formatting Culture: instrucciones de lectura o salida.
  • Length: obligatorio para texto de ancho fijo y útil para validar exportaciones.
  • Path: información de ruta XML o JSON.
  • Constant: valor configurado, especialmente útil durante la exportación.
  • Negative-Sign Identifier: identifica un valor de signo independiente, por ejemplo D para débito.
  • Text Padding Required, Pad Character y Justification: control de salida de ancho fijo.
  • Use Node Name as Value: almacena el nombre del elemento en lugar de su texto interno en los lectores compatibles.
  • Blank Zero: exporta el cero como vacío.
  • Export If Not Blank: evita generar un elemento XML vacío.

El formato y la cultura no son decorativos

Si una fecha externa es 20260822, configura su formato como yyyyMMdd. Si un decimal es 1.234,56, utiliza una cultura que entienda esa notación. No dependas del idioma del service tier, del usuario actual, de la fase lunar o del formato que funcionó por casualidad en la máquina del desarrollador.

Durante el mapeo directo de una importación, Process Data Exch. utiliza Type Helper.Evaluate para campos Date y Decimal, pasando Data Format y Data Formatting Culture de la columna. Un valor incorrecto produce un error que identifica el archivo, la definición, la línea, la columna, el tipo esperado y el valor real. Es bastante mejor que importar silenciosamente 1,234 como uno coma doscientos treinta y cuatro o como mil doscientos treinta y cuatro y dejar que Finanzas descubra después la sorpresa.

La capa de ejecución: Data Exch. y Data Exch. Field

Cada ejecución comienza con table 1220 "Data Exch.".

Almacena:

  • El número de entrada.
  • El nombre del archivo y el BLOB con su contenido.
  • Los códigos de la definición y de la definición de línea actual.
  • Los filtros serializados de la tabla de origen para exportación.
  • Un vínculo con el documento entrante.
  • Un valor genérico Related Record.

Cuando se elimina el registro, también se eliminan sus líneas relacionadas de Data Exch. Field. Ambas tablas tienen ReplicateData = false, lo cual tiene sentido porque los buffers de ejecución de una integración no necesitan irse de vacaciones a todas las réplicas de la empresa.

table 1221 "Data Exch. Field" es el almacén normalizado de valores. Su clave agrupada es:

Data Exch. No., Line No., Column No., Node ID

Cada registro contiene el valor sin procesar, además de:

  • Data Exch. Line Def Code.
  • Node ID y Parent Node ID para la jerarquía.
  • Value BLOB para valores que superan los 250 caracteres del campo Value.

Esta tabla es la superficie de depuración más útil del framework. Si un resultado mapeado es incorrecto, hazte tres preguntas en este orden:

  1. ¿Llegó el archivo de origen a Data Exch."File Content"?
  2. ¿Creó el lector las líneas esperadas de Data Exch. Field?
  3. ¿Convirtieron correctamente esas líneas la transformación y el mapeo?

No depures el Sales Header final durante tres horas cuando la columna 5 nunca salió del lector CSV. He visto esa película. El final contiene sobre todo palabrotas.

El pipeline de importación, órgano por órgano

1. Crear u obtener la entrada Data Exch.

Puedes introducir un InStream existente en la entrada de ejecución mediante Data Exch.InsertRec(). Si el BLOB sigue vacío, Data Exch.ImportFileContent() ejecuta el Ext. Data Handling Codeunit configurado, que debe rellenar el nombre y el BLOB del archivo.

Read Data Exch. from File (1240) es un origen interactivo estándar. Read Data Exch. from Stream (1413) publica un evento que un suscriptor puede gestionar para devolver un Temp Blob, algo útil cuando el origen es una API, un servicio documental u otra extensión.

2. Leer el archivo en Data Exch. Field

Data Exch.ImportToDataExch(DataExchDef) abre el BLOB del archivo como InStream.

Su regla de selección es sencilla y extremadamente importante:

if DataExchDef."Reading/Writing Codeunit" > 0 then
    Codeunit.Run(DataExchDef."Reading/Writing Codeunit", DataExch)
else
    XmlPort.Import(DataExchDef."Reading/Writing XMLport", Source, DataExch);

Si hay un codeunit de lectura configurado, el XMLport no se ejecuta. Configurar ambos no crea un equipo de lucha libre. Crea un lector activo y un identificador de objeto decorativo.

Los lectores estándar incluyen:

El XMLport CSV aplica dinámicamente el separador de campos, la codificación y el separador de líneas de la definición. Omite las cabeceras y pies configurados, numera solamente las filas de datos importadas e inserta un registro Data Exch. Field por cada valor no vacío.

Esa última frase importa: una celda CSV vacía no crea una línea de campo. Durante el mapeo directo, un mapeo obligatorio falla entonces con un error de valor ausente, mientras que uno opcional puede continuar.

3. Ejecutar el tratamiento de datos de la definición

Data Exch. Def.ProcessDataExchange() ejecuta primero Data Handling Codeunit, si está configurado.

Este hook suele confundirse con el codeunit final de registro. En realidad, no es necesariamente el final de nada. Se ejecuta antes del bucle de mapeo de la definición. Un uso estándar es Map DataExch To Intermediate (1214), que convierte los campos normalizados del intercambio en la tabla intermedia genérica.

4. Ejecutar los codeunits de mapeo

Para cada definición de línea de nivel superior, la definición localiza sus registros Data Exch. Mapping y ejecuta:

  1. Pre-Mapping Codeunit.
  2. Mapping Codeunit.
  3. Post-Mapping Codeunit.

ProcessDataExchange() solamente enumera directamente las definiciones de línea de nivel superior. Un codeunit de mapeo jerárquico debe gestionar por sí mismo las definiciones hijas. Map DataExch To Intermediate lo hace de forma recursiva.

Este orden permite que cada escenario prepare el contexto, realice un mapeo genérico o personalizado y finalice el procesamiento empresarial. También nos proporciona cuerda suficiente para tejer una integración preciosa o ahorcar todo el pipeline de documentos de compra. La documentación sigue siendo importante.

Mapeo directo con Process Data Exch.

codeunit 1201 "Process Data Exch." contiene el mapeador estándar de importación directa.

Su procedimiento ProcessColumnMapping() recibe:

  • El registro de ejecución Data Exch..
  • Un Data Exch. Line Def.
  • Un RecordRef que sirve como plantilla de la tabla destino.

Para cada línea importada, duplica la plantilla, asigna los identificadores del intercambio y de la línea cuando están configurados, mapea los campos, los valida e inserta un registro.

Lo que realmente admite SetField()

El switch estándar gestiona estos tipos de campos destino:

  • Text.
  • Code.
  • Date.
  • Decimal.
  • Option.
  • BLOB.

Otros tipos de destino alcanzan el error de tipo de datos no compatible, salvo que un suscriptor de eventos gestione la conversión. Conviene fijarse en esto porque Data Exch. Column Def."Data Type" también ofrece DateTime y Boolean. El tipo de la columna externa y los tipos de campo admitidos como destino directo no comparten exactamente la misma lista de capacidades.

Para tipos de destino más amplios, validaciones complejas o creación de documentos, utiliza un modelo de staging o intermedio y controla explícitamente la conversión final.

Comportamiento de la validación y la inserción

Después de asignar cada FieldRef destino, el mapeador llama a FieldRef.Validate(). Por tanto, se ejecutan los triggers de validación del campo.

El registro final se inserta con RecRef.Insert() sin solicitar la ejecución de los triggers de tabla. En el comportamiento estándar de AL, esto significa que el trigger OnInsert de la tabla no se ejecuta. La distinción es crítica:

  • Se ejecuta la lógica OnValidate de los campos.
  • La lógica OnInsert de la tabla no se ejecuta de forma predeterminada.

Por eso, mapear directamente a una tabla empresarial compleja es arriesgado incluso antes de hablar de numeración, dimensiones, grupos contables, relaciones entre documentos o la colonia salvaje de suposiciones que vive dentro de los triggers de tabla estándar.

Mapea a una tabla de staging diseñada para ese propósito salvo que tengas una razón excelente para no hacerlo.

Suposiciones sobre la clave primaria

El mapeador genérico examina la clave primaria de la tabla destino y espera que su último campo sea Integer. Utiliza ese campo para generar valores basados en el número de línea importado y en el desplazamiento existente de la clave.

En tablas personalizadas, diseña la clave del staging de acuerdo con esta condición. Configura también los dos campos ocultos de Data Exch. Mapping:

  • Data Exch. No. Field ID.
  • Data Exch. Line Field ID.

El fallback cuando falta el campo de línea está programado específicamente para Bank Acc. Reconciliation Line y Gen. Journal Line. Tu tabla de staging personalizada no es secretamente una de ellas, por mucho que se identifique como un diario.

Varios mapeos, sobrescritura y prioridad

Varias columnas externas pueden mapearse al mismo campo Text o Code de destino.

  • Con Overwrite Value = false, los valores se combinan con un espacio hasta llenar el campo destino.
  • Con Overwrite Value = true, el mapeo procesado más tarde sustituye el valor actual.

Si algún mapeo tiene un valor Priority distinto de cero, los mapeos se procesan por Priority descendente. Utilízalo cuando un valor mapeado dependa de que otro campo ya haya sido validado o cuando importe el orden de sobrescritura.

Multiplicador decimal y campos de signo independientes

Multiplier se aplica después de interpretar un decimal. Resulta útil para invertir el signo, porcentajes, unidades monetarias menores o proveedores que han inventado una nueva y emocionante manera de representar el dinero.

Negative-Sign Identifier admite formatos en los que el importe y el indicador de débito o crédito se encuentran en columnas distintas. Mapea la columna de signo al mismo campo Decimal destino y configura el identificador, por ejemplo D. El mapeador recuerda el campo destino y cambia su signo después de ejecutar todos los mapeos de la línea.

La ruta intermedia: más segura, flexible y con un poco más de papeleo

Map DataExch To Intermediate (1214) escribe en table 1214 "Intermediate Data Import".

En lugar de crear inmediatamente registros destino, almacena una línea por cada campo de destino:

  • Data Exch. No..
  • Table ID de destino.
  • Record No. lógico.
  • Field ID de destino.
  • Valor Text o BLOB.
  • Parent Record No..
  • Validate Only.

Esta estructura puede representar un Purchase Header con varias Purchase Lines sin crear ninguna de las dos tablas durante la lectura. Después, un procesador específico del escenario agrupa las líneas, construye registros reales, los valida, gestiona los valores predeterminados y decide qué hacer cuando las reglas de negocio se rebelan.

El flujo estándar de documentos entrantes utiliza este patrón. El código de mapeo genérico conserva las relaciones padre-hijo del XML mediante Record No. y Parent Record No., y después el código especializado crea el documento de compra.

El campo Optional cambia de significado

En un mapeo directo de campos, Optional significa que la ausencia de un valor interpretado no provoca un error.

Cuando Use as Intermediate Table está habilitado, la página presenta ese mismo campo físico como Validate Only. El mapeador intermedio lo copia en Intermediate Data Import."Validate Only" y el procesador posterior decide no asignar ese valor como un campo destino normal.

El mismo Boolean. Un disfraz semántico diferente. No lo configures por memoria muscular.

La limpieza es responsabilidad tuya

Eliminar un registro Data Exch. elimina sus líneas Data Exch. Field. No elimina automáticamente todas las líneas Intermediate Data Import pertenecientes al intercambio.

Los procesadores de escenarios estándar eliminan explícitamente sus registros intermedios. Los procesadores personalizados deberían hacer lo mismo después de completar correctamente el proceso, o conservarlos deliberadamente mediante una estrategia de retención documentada. De lo contrario, tu tabla de integración temporal se convierte lentamente en un yacimiento arqueológico.

Elección entre mapeo directo, staging e Intermediate Data Import La complejidad empresarial y la jerarquía del archivo determinan si conviene mapear directamente a staging o utilizar Intermediate Data Import antes de construir los registros finales. ¿Dónde debe aterrizar el dato interpretado? Data Exch. Field Valores ya interpretados y trazables Ruta directa a staging • Estructura plana • Conversión simple y controlada • Clave compatible con el mapper Process Data Exch. → custom staging Ruta intermedia • Header + Lines / jerarquía XML • Validación empresarial compleja • Creación transaccional posterior Intermediate Data Import → processor plano y predecible jerárquico o complejo La tabla empresarial final no debería ser el lugar donde descubres que el proveedor cambió el formato.
El mapeo directo no significa “insertar inmediatamente en Sales Header”. Una tabla de staging propia sigue siendo la opción prudente para estructuras planas.

XML: donde las definiciones de línea se convierten en un árbol

El lector XML Import XML File to Data Exch. comienza con las definiciones de línea cuyo Parent Code está vacío. Selecciona nodos mediante el Data Line Tag de cada definición y después procesa recursivamente las definiciones hijas.

Para cada registro XML lógico escribe una línea especial Data Exch. Field con Column No. = -1. Esta línea ancla la definición incluso cuando no se ha extraído ninguna columna normal. Los nodos interpretados reciben valores Node ID generados y los registros hijos almacenan un Parent Node ID.

Esa relación permite posteriormente que el mapeador intermedio conecte un registro de cabecera con sus hijos.

Rutas y namespaces

Los valores Path de las columnas seleccionan elementos o atributos relativos al Data Line Tag de la línea.

El lector utiliza un administrador de namespaces XML. Si un segmento XPath no tiene prefijo, el helper estándar puede reescribirlo para buscar por nombre local. Esto facilita el consumo de archivos imperfectos de proveedores, pero también puede ocultar ambigüedades cuando dos vocabularios usan el mismo nombre local de elemento.

En integraciones controladas por un esquema formal:

  • Mantén explícitos los prefijos de namespace cuando tengan significado.
  • Configura Namespace cuando sea necesario validar el namespace raíz.
  • Prueba documentos con nodos opcionales, nodos repetidos, atributos y varios prefijos de namespace.
  • No asumas que el XML de ejemplo del proveedor representa todo el caos disponible en producción.

La acción Get File Structure puede sugerir definiciones de columna para XML y JSON, y los esquemas XML también pueden ayudar a inicializar una definición. Trata las rutas generadas como un punto de partida, no como tablas sagradas descubiertas en una montaña.

Una nota sobre JSON

La tabla de definición incluye Json y la aplicación contiene objetos para descubrir estructuras JSON. Eso no significa que todas las versiones y escenarios dispongan de un lector JSON de ejecución completo y listo para usar, equivalente a los lectores estándar de CSV o XML.

Comprueba el Reading/Writing Codeunit configurado en tu versión destino. Para importaciones JSON personalizadas, un lector dedicado que interprete JsonObject y escriba registros Data Exch. Field suele ser el enfoque más limpio. El framework ejecutará encantado las etapas posteriores de transformación y mapeo cuando existan las líneas normalizadas.

Transformation Rules: blanqueo de datos civilizado

table 1237 "Transformation Rule" almacena transformaciones de texto reutilizables. Un mapeo selecciona una regla mediante Data Exch. Field Mapping."Transformation Rule".

Base Application 27.5 proporciona, entre otros, los siguientes tipos de transformación:

  • Uppercase, Lowercase, Title Case y Trim.
  • Substring.
  • Sustitución de texto y sustitución mediante expresiones regulares.
  • Remove non-alphanumeric characters.
  • Formato de Date, DateTime y decimales.
  • Coincidencia mediante expresiones regulares.
  • Field Lookup.
  • Round.
  • Extract From Date.
  • Unix timestamp.
  • Custom.

La superficie completa del registro y sus métodos públicos de creación están documentados en Transformation Rule.

Las reglas pueden encadenarse

Next Transformation Rule apunta a otra regla. TransformText() aplica la regla actual y envía recursivamente el resultado a la siguiente.

Esto permite crear pipelines como:

Trim -> Remove non-alphanumeric -> Uppercase

Mantén las cadenas cortas y sin ciclos. La llamada recursiva estándar no proporciona un detector de ciclos amable. RULE-A -> RULE-B -> RULE-A no es arquitectura de integración. Es un diminuto uróboros devorando el service tier.

Extender el enum de transformación cuando la configuración deja de ser suficiente

enum 1237 "Transformation Rule Type" es extensible e implementa interface "Transformation Rule". Por tanto, un tipo personalizado puede conectarse a la página estándar de transformaciones y al pipeline de mapeo.

using System.IO;

enumextension 50100 "Generic Transform. Type" extends "Transformation Rule Type"
{
    value(50100; "Normalize External Ref.")
    {
        Caption = 'Normalize External Reference';
        Implementation = "Transformation Rule" = "External Ref. Normalizer";
    }
}

codeunit 50100 "External Ref. Normalizer" implements "Transformation Rule"
{
    procedure TransformText(
        TransformationRule: Record "Transformation Rule";
        OldValue: Text;
        var NewValue: Text)
    begin
        NewValue := DelChr(UpperCase(OldValue), '=', ' ');
    end;

    procedure IsDataFormatUpdateAllowed(): Boolean
    begin
        exit(false);
    end;

    procedure CheckMandatoryFieldsInTransformationRule(
        TransformationRule: Record "Transformation Rule")
    begin
    end;

    procedure ValidateTransformationRuleField(
        FieldNo: Integer;
        var TransformationRule: Record "Transformation Rule";
        var xTransformationRule: Record "Transformation Rule"): Boolean
    begin
        exit(false);
    end;

    procedure GetVisibleGroups(
        TransformationRule: Record "Transformation Rule";
        var VisibleGroups: List of [Enum "Transformation Rule Group"])
    begin
    end;
}

Utiliza una transformación personalizada para una normalización pura de valor a valor. Si la lógica necesita varios registros, contexto de configuración, llamadas externas o el estado de un documento empresarial, pertenece a un codeunit de mapeo o procesamiento.

Ejemplo práctico en AL: importar líneas de venta externas

Imagina que una tienda web, un punto de venta o una aplicación comercial externa entrega este archivo UTF-8 separado por punto y coma:

ExternalDocumentNo;PostingDate;CustomerNo;ItemNo;Quantity;UnitPrice;Currency
WEB-10001;2026-08-20;10000;1896-S;2;245.50;EUR
WEB-10002;2026-08-21;20000;1900-S;1;199.95;eur

El objetivo es interpretar y normalizar el archivo en una tabla de staging. Más adelante, un procesador independiente agrupará líneas por documento externo y creará Sales Header y Sales Line mediante la lógica empresarial apropiada. El lector no debería crear directamente una Sales Invoice: todavía faltan customers, items, unidades, prices, dimensions, posting groups, duplicados y todas las formas creativas en que una venta puede negarse a existir.

1. Crear una tabla de staging diseñada para el mapeador genérico

using System.IO;

table 50110 "External Sales Staging"
{
    Caption = 'External Sales Staging';
    DataClassification = CustomerContent;

    fields
    {
        field(1; "Entry No."; Integer)
        {
            Caption = 'Entry No.';
        }
        field(2; "Data Exch. Entry No."; Integer)
        {
            Caption = 'Data Exch. Entry No.';
            TableRelation = "Data Exch."."Entry No.";
        }
        field(3; "Data Exch. Line No."; Integer)
        {
            Caption = 'Data Exch. Line No.';
        }
        field(10; "External Document No."; Code[50])
        {
            Caption = 'External Document No.';
        }
        field(20; "Posting Date"; Date)
        {
            Caption = 'Posting Date';
        }
        field(30; "Customer No."; Code[20])
        {
            Caption = 'Customer No.';
        }
        field(40; "Item No."; Code[20])
        {
            Caption = 'Item No.';
        }
        field(50; Quantity; Decimal)
        {
            Caption = 'Quantity';
        }
        field(60; "Unit Price"; Decimal)
        {
            Caption = 'Unit Price';
        }
        field(70; "Currency Code"; Code[10])
        {
            Caption = 'Currency Code';
        }
        field(80; Processed; Boolean)
        {
            Caption = 'Processed';
        }
        field(90; "Error Message"; Text[2048])
        {
            Caption = 'Error Message';
        }
    }

    keys
    {
        key(PK; "Entry No.")
        {
            Clustered = true;
        }
        key(ExchangeLine; "Data Exch. Entry No.", "Data Exch. Line No.")
        {
        }
    }
}

El último campo de la clave primaria es Integer, lo que satisface la suposición del mapeador genérico sobre la clave. La tabla también almacena el intercambio de ejecución y la línea de origen, haciendo trazable cada línea del staging.

2. Crear el codeunit de mapeo

using System.IO;

codeunit 50111 "External Sales Exch. Mapper"
{
    TableNo = "Data Exch.";

    trigger OnRun()
    var
        DataExchLineDef: Record "Data Exch. Line Def";
        ExternalSalesStaging: Record "External Sales Staging";
        ProcessDataExch: Codeunit "Process Data Exch.";
        StagingRecordRef: RecordRef;
    begin
        DataExchLineDef.Get(
            Rec."Data Exch. Def Code",
            Rec."Data Exch. Line Def Code");

        StagingRecordRef.GetTable(ExternalSalesStaging);
        ProcessDataExch.ProcessColumnMapping(
            Rec,
            DataExchLineDef,
            StagingRecordRef);
    end;
}

Este codeunit no interpreta el CSV. Comienza después de que el lector haya rellenado Data Exch. Field. Su trabajo consiste en seleccionar la tabla destino y permitir que el mapeador estándar aplique los mapeos de campos configurados.

3. Configurar la definición

Los valores relevantes de la definición son:

Configuración Valor
Code GEN-SALES
Type Generic Import
File Type Variable Text
File Encoding UTF-8
Column Separator Semicolon
Header Lines 1
Reading/Writing XMLport Data Exch. Import - CSV (1220)
Line Definition DETAIL, type Detail, column count 7

Crea estas definiciones de columna:

Columna Nombre Tipo de datos Formato Cultura
1 External Document No. Text
2 Posting Date Date yyyy-MM-dd en-US
3 Customer No. Text
4 Item No. Text
5 Quantity Decimal en-US
6 Unit Price Decimal en-US
7 Currency Text

Crea un Data Exch. Mapping para la tabla External Sales Staging:

  • Mapping Codeunit = External Sales Exch. Mapper.
  • Data Exch. No. Field ID = External Sales Staging."Data Exch. Entry No.".
  • Data Exch. Line Field ID = External Sales Staging."Data Exch. Line No.".

Después, mapea las siete columnas con los siete campos de staging. Aplica TRIM donde corresponda, una regla de mayúsculas a Currency Code y Normalize External Ref. solo si eliminar espacios forma parte realmente del contrato externo. No normalices un dato solo porque una vez te miró de manera extraña.

Las definiciones pueden crearse manualmente, importarse con XMLport 1225 o instalarse desde AL. El siguiente fragmento muestra las referencias de objetos utilizadas al inicializar la cabecera y el mapeo:

using System.IO;

local procedure CreateExternalSalesDefinition()
var
    DataExchDef: Record "Data Exch. Def";
begin
    if DataExchDef.Get('GEN-SALES') then
        exit;

    DataExchDef.Init();
    DataExchDef.Code := 'GEN-SALES';
    DataExchDef.Name := 'Generic External Sales Import';
    DataExchDef.Type := DataExchDef.Type::"Generic Import";
    DataExchDef."File Type" := DataExchDef."File Type"::"Variable Text";
    DataExchDef."File Encoding" := DataExchDef."File Encoding"::"UTF-8";
    DataExchDef."Column Separator" := DataExchDef."Column Separator"::Semicolon;
    DataExchDef."Header Lines" := 1;
    DataExchDef."Reading/Writing XMLport" := XmlPort::"Data Exch. Import - CSV";
    DataExchDef.Insert(true);
end;

local procedure CreateExternalSalesMapping()
var
    DataExchMapping: Record "Data Exch. Mapping";
    ExternalSalesStaging: Record "External Sales Staging";
begin
    DataExchMapping.Init();
    DataExchMapping."Data Exch. Def Code" := 'GEN-SALES';
    DataExchMapping."Data Exch. Line Def Code" := 'DETAIL';
    DataExchMapping."Table ID" := Database::"External Sales Staging";
    DataExchMapping.Name := 'External sales to staging';
    DataExchMapping."Mapping Codeunit" := Codeunit::"External Sales Exch. Mapper";
    DataExchMapping."Data Exch. No. Field ID" :=
        ExternalSalesStaging.FieldNo("Data Exch. Entry No.");
    DataExchMapping."Data Exch. Line Field ID" :=
        ExternalSalesStaging.FieldNo("Data Exch. Line No.");
    DataExchMapping.Insert(true);
end;

En código de configuración para producción, haz que toda la operación sea idempotente, inserta las definiciones de líneas y columnas, crea todos los mapeos de campos, actualiza las versiones modificadas y nunca elimines una definición que el cliente haya personalizado sin una estrategia explícita de actualización.

La definición exportada contiene identificadores de tablas, campos y objetos de procesamiento. Al moverla a otro tenant o versión, instala primero las extensiones necesarias y valida todos los objetos referenciados después de la importación. Basado en configuración no significa libre de dependencias. Solo significa que las dependencias llevan bigotes falsos.

4. Crear un importador basado en streams

using System.IO;

codeunit 50112 "External Sales Import"
{
    procedure Import(FileName: Text[250]; var Source: InStream): Integer
    var
        DataExch: Record "Data Exch.";
        DataExchDef: Record "Data Exch. Def";
        ImportFailedErr: Label 'The external sales file could not be imported.';
    begin
        DataExchDef.Get('GEN-SALES');

        DataExch.InsertRec(FileName, Source, DataExchDef.Code);

        if not DataExch.ImportToDataExch(DataExchDef) then
            Error(ImportFailedErr);

        DataExchDef.ProcessDataExchange(DataExch);

        exit(DataExch."Entry No.");
    end;
}

La secuencia de llamadas es la esencia de una importación personalizada:

InsertRec -> ImportToDataExch -> ProcessDataExchange

No es necesario ningún diálogo de selección de archivos. El llamador puede proporcionar un stream procedente de una carga, una respuesta de API, un adjunto, un adaptador de Azure Storage o una integración programada.

5. Mantener separado el procesamiento empresarial

Después de importar, procesa los registros External Sales Staging por Data Exch. Entry No. y External Document No.. Valida allí duplicados, customers, items, currencies, posting dates, quantities, prices, dimensions y posting groups antes de crear el sales document.

Esta separación proporciona:

  • Interpretación técnica repetible.
  • Datos originales y de staging trazables.
  • Errores empresariales vinculados a una línea de origen específica.
  • Reintentos controlados.
  • Un lugar donde revisar los datos antes de crear registros operativos.

También evita que un CSV malformado se convierta en una Sales Invoice creada a medias y con una crisis existencial.

Pipeline de exportación: las flechas apuntan al otro lado, pero los buffers permanecen

La ruta genérica de exportación comienza con Export Launcher (1268). El llamador proporciona un Record, RecordId o RecordRef. El launcher almacena la vista del origen en Data Exch."Table Filters", ejecuta la preparación y validación configuradas y después llama a Data Exch.ExportFromDataExch().

Export Mapping (1269) abre la tabla de origen, aplica la vista almacenada, selecciona opcionalmente el Key Index configurado y escribe los valores de salida formateados en Data Exch. Field.

El código estándar de gestión de exportación de pagos realiza gran parte de la conversión a nivel de campo:

  • Calcula FlowFields cuando es necesario.
  • Aplica las comprobaciones de campos obligatorios.
  • Convierte al tipo de destino de la columna.
  • Aplica el multiplicador.
  • Formatea valores.
  • Ejecuta reglas de transformación.
  • Rellena valores de ancho fijo.
  • Comprueba las longitudes configuradas.

Después, el escritor serializa esos campos.

Los campos secuenciales son obligatorios para los escritores genéricos de texto

Export Generic CSV y Export Generic Fixed Width esperan que los números de línea y columna sean secuenciales. Una columna ausente produce un error en lugar de desplazar silenciosamente todo hacia la izquierda y crear un archivo que parece válido hasta que el banco lo rechaza un viernes a las 16:59.

La agrupación es una operación de exportación

Export Mapping consume Data Exch. Field Grouping. Cuando existen campos de agrupación, el mapeador construye un conjunto temporal agrupado del origen. Los campos numéricos mapeados que no forman parte de la clave se acumulan, incluidos los valores FlowField compatibles mediante un buffer temporal de agrupación.

Utiliza la agrupación cuando la autoridad externa necesite una línea resumida por combinación de campos en lugar de una línea por cada registro de Business Central.

Exportación XML

Export Generic XML crea elementos a partir de las rutas configuradas, admite namespaces y determinados patrones de atributos, y puede omitir elementos vacíos mediante Export If Not Blank.

Su compatibilidad con XPath es deliberadamente más limitada que un lenguaje general de transformación XML. Cuando un documento exige estructuras condicionales complejas, varios namespaces no relacionados, firmas u ordenación específica del esquema, un escritor XML dedicado puede resultar más claro que obligar a la configuración genérica a bailar danza interpretativa.

Qué queda guardado y qué significa para la trazabilidad

El framework distribuye la evidencia entre varias capas:

Capa Objeto principal Qué conserva Pregunta que responde
Configuración Data Exch. Def y tablas hijas Formato, componentes y mapeos ¿Cómo debía interpretarse?
Ejecución Data Exch. Archivo, nombre, definición y contexto relacionado ¿Qué intercambio se ejecutó?
Parsing Data Exch. Field Valores por línea, columna y nodo ¿Qué entendió el lector?
Staging Tabla propia o Intermediate Data Import Datos convertidos hacia una estructura destino ¿Qué preparó el mapper?
Negocio Documento o ledger creado Resultado validado por el proceso ¿Qué aceptó finalmente Business Central?

La configuración puede cambiar después de una importación. Eso significa que conservar únicamente el código de la definición no demuestra por sí solo qué versión exacta del mapeo produjo un documento histórico. Para integraciones reguladas o auditables, añade una estrategia de versionado: versión funcional en la definición o en tu setup, hash del archivo, fecha, estado, usuario o job, y relación con los registros creados.

Data Exch. y Data Exch. Field no sustituyen a un log funcional. Son buffers de ejecución y diagnóstico. Decide cuánto tiempo se conservan, quién puede ver el contenido y si contienen datos personales, bancarios o confidenciales. ReplicateData = false evita su replicación estándar, pero no convierte un BLOB lleno de datos bancarios en decoración inocua.

La transacción y el reintento

El framework no define por sí solo una semántica universal de reintentos. Si una línea de negocio falla después de crear otras, el resultado depende de los límites de transacción del procesador que hayas escrito. Una integración robusta decide explícitamente entre:

  • Todo o nada: un error revierte el lote completo.
  • Por registro: cada registro lógico se confirma o rechaza de forma independiente.
  • Staging primero: la importación técnica termina; el procesamiento empresarial marca estados y permite reintentar solo lo pendiente.

La tercera opción suele ser la más operable para lotes de terceros. También requiere idempotencia: un External ID o una clave equivalente debe impedir que pulsar “reprocesar” cree el mismo documento dos veces. El botón no debería funcionar como una fotocopiadora contable.

Impacto funcional: mucho más que importar un CSV

El Data Exchange Framework influye en varias áreas de Business Central porque actúa como frontera entre un contrato externo y objetos empresariales internos.

Banca y conciliación

Los bank statement imports convierten líneas bancarias en estructuras que después participan en reconciliation y matching. Un separador decimal incorrecto no es solo un error de formato: altera importes, signos y capacidad de conciliación. Un Negative-Sign Identifier mal configurado puede transformar cobros en pagos con una serenidad escalofriante.

Payment exports

Las exportaciones de pagos deben cumplir formato, longitud, orden, agrupación y campos obligatorios exigidos por el banco. Aquí el framework no solo serializa: prepara datos, valida y entrega el fichero. El resultado puede ser técnicamente XML y aun así ser rechazado por el banco por una regla que vive tres capas por encima del XML.

Incoming Documents y documentos electrónicos

La ruta intermedia permite representar header y lines antes de construir purchase documents o general journal lines. Es el lugar donde se reconcilian códigos externos con vendors, items, units of measure, VAT setup, dimensions y posting groups. El framework transporta valores; el procesador empresarial debe crear documentos mediante las validaciones correctas.

Currency exchange rates

La configuración puede importar valores de servicios externos y mapearlos al proceso de actualización. La cultura, el formato de fecha y la unidad —por uno, por cien, directa o inversa— son parte del contrato. Un decimal perfectamente parseado puede seguir siendo económicamente incorrecto si representa la escala equivocada.

Localizaciones e Intrastat

Las localizaciones utilizan el framework para formatos que dependen de país, autoridad y versión. Esto demuestra su mayor virtud: mover parte del cambio desde código a configuración. También demuestra su coste: una actualización puede modificar definiciones, objetos y expectativas de formato. La configuración local no debe tratarse como una reliquia que nadie compara después de una actualización.

En todos estos escenarios, Data Exchange Definition es modular porque separa adquisición, parsing, transformación, mapeo, validación y entrega. El impacto de un error depende del módulo en el que se introduce. Por eso la depuración debe recorrer el pipeline en orden y no empezar por la tabla final como quien busca unas llaves debajo de la farola porque allí hay más luz.

Puntos de extensibilidad que son realmente útiles

El framework expone integration events en la mayoría de sus fronteras importantes.

En Process Data Exch.

Entre los eventos útiles se incluyen:

  • OnBeforeFormatFieldValue para gestionar un tipo de destino no compatible o una conversión personalizada.
  • OnSetFieldOnBeforeGetTransformedValue para modificar el contexto del origen o del mapeo.
  • OnSetFieldOnBeforeFieldRefValidate para sustituir el comportamiento estándar de validación.
  • OnProcessColumnMappingOnBeforeRecRefInsert para controlar la inserción final.
  • OnBeforeProcessAllLinesColumnMapping para sustituir el mapeo de un escenario.
  • OnAfterProcessColumnMapping para posprocesamiento.

En los lectores

  • La importación CSV permite que los suscriptores sustituyan mensajes de error relacionados con la cabecera.
  • La importación de archivos fijos expone la línea antes del bucle estándar de longitudes.
  • La importación XML expone el XML interno y externo antes de insertar una columna.
  • La adquisición mediante stream publica un evento que devuelve el contenido del archivo mediante Temp Blob.

En las reglas de transformación

El enum extensible junto con la interfaz Transformation Rule es la ruta recomendada para crear un tipo personalizado de transformación reutilizable.

Elige el punto de extensión más pequeño que resuelva el problema. Sustituir un mapeo completo porque un proveedor envía Y y N para un Boolean es técnicamente posible, pero también lo es demoler una cocina porque hay una cuchara sucia.

Modos de fallo y sus causas

“The value is missing”

El lector no creó una línea Data Exch. Field para ese intercambio, línea y columna. Las causas habituales son una celda CSV vacía, un separador incorrecto, una configuración errónea de la cabecera, un código de definición de línea equivocado o un archivo con menos columnas de las esperadas.

Inspecciona Data Exch. Field antes de tocar la tabla destino.

“Incorrect format or type”

El valor llegó al mapeador, pero Type Helper.Evaluate no pudo convertirlo utilizando el formato y la cultura de la columna. Comprueba el valor original real, incluidos espacios, separadores decimales y texto de zona horaria.

“Data type not supported”

El mapeador directo alcanzó un campo de destino fuera de su conjunto estándar compatible. Utiliza OnBeforeFormatFieldValue, un codeunit de mapeo personalizado o la ruta intermedia.

El codeunit de mapeo falla inmediatamente

Comprueba su TableNo frente al registro que pasa el pipeline que lo invoca. Los identificadores de objeto almacenados en configuración no son contratos de ejecución fuertemente tipados.

Los valores XML aparecen debajo del padre incorrecto

Comprueba Parent Code, Data Line Tag, las rutas relativas de las columnas, el Node ID generado y Parent Node ID. Los errores padre-hijo normalmente se crean durante la lectura, no durante la creación final del documento.

La importación creó registros pero omitió la lógica de inicialización

Recuerda que el mapeador directo estándar valida los campos, pero inserta el RecordRef destino sin ejecutar el trigger OnInsert de la tabla.

La misma definición funciona manualmente pero falla en una job queue

Los codeunits interactivos de origen pueden abrir un diálogo de archivos o una ventana de progreso. El procesamiento programado necesita una adquisición basada en streams y código que respete GuiAllowed.

Estrategia de pruebas

Una Data Exchange Definition debe probarse como configuración más código. Probar únicamente el mapeador personalizado no es suficiente, porque un separador o cultura incorrectos pueden destruir los datos antes de que el mapeador se despierte.

Como mínimo, cubre:

  1. Un archivo válido con varias líneas.
  2. Valores opcionales y obligatorios vacíos.
  3. Demasiadas o muy pocas columnas.
  4. Formatos de fecha y decimal no válidos.
  5. Separadores decimales específicos de una cultura.
  6. Variaciones en cabeceras y pies.
  7. Texto más largo que el campo destino.
  8. Cadenas de transformaciones.
  9. Identificadores de origen duplicados.
  10. Rollback cuando falla una línea.
  11. XML sin nodos opcionales.
  12. XML con hijos repetidos y prefijos de namespace.

Utiliza Temp Blob para crear streams en memoria durante las pruebas. Llama al mismo importador que utiliza el código de producción y valida después ambas capas:

  • Líneas Data Exch. Field interpretadas.
  • Registros finales de staging o intermedios.

Esto permite saber si el fallo pertenece a la adquisición, lectura, transformación, mapeo o procesamiento empresarial. Cinco capas, cinco sospechosos, una sala de interrogatorios.

Guía de diseño y operación

Utiliza Data Exchange Definitions cuando

  • El formato de archivo de un partner se presta a la configuración.
  • Los administradores pueden necesitar ajustar mapeos sin publicar una extensión.
  • Necesitas valores interpretados y trazables.
  • Varios formatos similares de proveedores comparten una arquitectura de procesamiento.
  • Trabajas con CSV, ancho fijo o XML de complejidad moderada.
  • Los formatos de exportación necesitan ordenación, formato, agrupación o constantes configurables.

Prefiere una lectura dedicada en AL cuando

  • El payload es un contrato JSON profundamente condicional.
  • La integración es API-first y el esquema JSON ya está modelado limpiamente en AL.
  • El documento necesita firmas, cifrado, streaming a gran escala o una validación de esquema compleja.
  • Todos los campos están controlados por código y la configuración no aporta valor empresarial real.
  • El framework genérico necesitaría más eventos personalizados para sustituir comportamiento que comportamiento estándar.

La elección no es configuración buena, código malo. La cuestión es si convertir el contrato de formato en datos aporta una ventaja. Si la página de configuración se convierte en la representación críptica de un programa, escribe el programa.

Migración, despliegue y gobierno

Una definición completa contiene referencias a tablas, fields, codeunits, XMLports y transformation rules. Exportarla con Imp / Exp Data Exch Def & Map (XMLport 1225) mueve la configuración, pero no instala los objetos que esa configuración espera encontrar.

Orden de despliegue

  1. Publica primero las extensiones con tablas, enums, interfaces y codeunits requeridos.
  2. Ejecuta los datos de setup mediante install/upgrade codeunits o importa la definición.
  3. Verifica que los object IDs y field IDs existen en el entorno destino.
  4. Revisa separadores, encoding, formatos y culturas.
  5. Ejecuta un fichero de prueba conocido.
  6. Compara Data Exch. Field, staging y resultado empresarial.
  7. Activa job queues o endpoints solamente después de esa reconciliación.

No uses una renumeración de fields alegremente en una tabla de staging que ya participa en field mappings. La configuración guarda Field ID, no el nombre ni el sentimiento que te produce. Cambiar el ID rompe el contrato aunque el caption siga pareciendo correcto.

Setup como código, pero sin borrar al cliente

Crear definiciones desde AL hace el despliegue repetible. El install codeunit puede insertar una versión inicial y el upgrade codeunit aplicar cambios conocidos. El reto es distinguir configuración gestionada por la extensión de ajustes que el cliente tiene derecho a modificar.

Un patrón razonable conserva:

  • Setup Version en una tabla propia.
  • Procedimientos idempotentes de creación y actualización.
  • Cambios por versión, no un DeleteAll() seguido de optimismo.
  • Validación de dependencias antes de modificar.
  • Un export de respaldo antes de cambios grandes.
  • Documentación de qué campos son personalizables.

Si cada actualización reconstruye toda la definición, el sistema es repetible para el desarrollador y sorprendente para el cliente. La automatización también puede destruir configuración con una eficiencia admirable.

Seguridad y privacidad

Los archivos pueden contener IBAN, importes, nombres, direcciones, documentos fiscales o información de empleados. Aplica permisos mínimos sobre las páginas de configuración, Data Exch., staging y acciones de reintento. No escribas payloads completos en telemetry o error messages. Para diagnóstico, registra identificadores, tamaños, tiempos, definición, etapa y resultado; enmascara los valores sensibles.

Observabilidad

Para procesos programados, mide al menos:

  • definición y versión;
  • origen y nombre lógico del archivo;
  • bytes y líneas/nodos leídos;
  • filas de Data Exch. Field creadas;
  • registros de staging válidos, rechazados y procesados;
  • duración por etapa;
  • mensaje y etapa de error;
  • relación con documentos creados.

Esto convierte “la importación no funciona” en “el lector terminó, produjo 4.812 fields, 37 registros llegaron a staging y el registro 19 falló por Currency Code”. Una frase permite trabajar. La otra convoca una sesión de espiritismo con el debugger.

Checklist antes de producción

Contrato externo

Configuración

Arquitectura

Operación

Reflexiones finales

Data Exchange Definitions es una de las piezas más capaces y menos celebradas de Business Central. Separa el conocimiento del formato externo del procesamiento empresarial, proporciona una capa persistente de normalización y expone hooks suficientes para soportar integraciones serias.

También tiene edad suficiente para contener patrones de varias generaciones de arquitectura de Business Central: campos Option junto a enums extensibles, identificadores de objetos almacenados como Integer, XMLports al lado de codeunits de lectura, lógica XML basada en DotNet junto a tipos XML modernos de AL y campos de configuración cuyo significado cambia según la ruta seleccionada.

Eso no es una razón para evitar el framework. Es una razón para entenderlo antes de introducir identificadores de objetos al azar en la configuración y esperar que el ERP respete nuestra confianza.

El patrón seguro es sencillo:

Acquire -> Parse -> Inspect -> Transform -> Stage -> Validate -> Process -> Clean up

Utiliza Data Exch. Field como frontera observable. Prefiere staging o Intermediate Data Import para registros empresariales complejos. Mantén documentados los contratos de los codeunits. Prueba explícitamente formatos y culturas. Exporta la definición junto con sus mapeos. Y nunca construyas una cadena circular de transformaciones salvo que el objetivo sea enseñar recursividad a un servidor mediante el sufrimiento.

La regla que conecta todo el módulo es esta:

Una Data Exchange Definition no importa ni exporta por sí sola. Define contratos. Data Exch. instancia el intercambio, el reader convierte bytes en Data Exch. Field, las transformaciones normalizan, el mapping proyecta y un procesador empresarial decide qué merece entrar realmente en Business Central.

Este es el Data Exchange Framework: configurable, potente, ligeramente embrujado y algo que merece absolutamente la pena conocer.

Ese es el blueprint.

Referencias oficiales

Post a Comment

Previous Post Next Post