Definición de entidad basada en modelo
Id del esquema: model-driven-entity@1
Esquema legible por máquina: model-driven-entity.schema.json
La representación canónica, en texto plano, de una entidad de las aplicaciones basadas en modelo. Es la fuente de verdad con la que se valida una entidad: la misma definición que produce el diseñador, que envía una llamada a la API, que genera un asistente de IA y que transporta una importación de solución. La validación se aplica de forma idéntica sea cual sea el origen, así que un archivo escrito a mano o generado que cumpla este esquema puede importarse con seguridad.
Forma
Una definición es un objeto JSON con estos miembros:
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
logicalName | string | sí | Con el prefijo del editor, en snake_case en minúsculas (p. ej., par_invoice). |
displayName | string | sí | Etiqueta en singular (p. ej., Invoice). |
displayCollectionName | string | sí | Etiqueta en plural (p. ej., Invoices). |
icon | string | no | Clave de icono del conjunto de iconos seleccionado de la plataforma, que se muestra junto a la tabla en la navegación de una aplicación (§4.4). Omítala para usar el glifo predeterminado. |
publisherPrefix | string | sí | Prefijo corto en minúsculas (p. ej., par). |
primaryField | string | sí | Nombre lógico del campo principal (nombre); debe aparecer en fields. |
primaryImage | string | no | Nombre lógico de la imagen del registro (§6.16): la imagen que se muestra junto a un registro en cuadrículas y búsquedas. Debe nombrar un campo de tipo Image en fields. Omítalo en una tabla sin imagen. |
secondaryField | string | null | no | Nombre lógico del campo que se muestra como texto secundario del registro: la segunda línea, más pequeña, bajo su nombre allí donde los registros se listan sin cuadrícula, como en un panel de búsqueda (§6.13.5). Debe nombrar un campo de fields que no sea el campo principal ni una columna File/Image. |
hierarchyParentField | string | null | no | Nombre lógico de la búsqueda que convierte esta tabla en una jerarquía: el campo que contiene el padre de cada registro y que apunta de vuelta a esta misma tabla (la categoría padre de una categoría, la unidad padre de una unidad). Debe nombrar un campo de fields de tipo Lookup cuyo targetEntity sea esta tabla. No concede nada ni impone nada: la tabla se sigue mostrando como una cuadrícula hasta que una vista anida sus registros. Sirve para que ser una jerarquía sea una propiedad de los datos y no de una vista concreta: el nivel superior de una vista de árbol usa este campo como vínculo hijo predeterminado. |
personField | string | null | no |
constraints | array | no | Reglas que aplica la base de datos, no la aplicación (vea más abajo): una columna única, o un periodo que no puede solaparse con otro del mismo ámbito. |
fields | array | sí | Una o varias definiciones de campo (vea más abajo). |
relationships | array | no | Relaciones de uno a varios respaldadas por campos de búsqueda. |
isAuditEnabled | boolean | no | Habilita la auditoría de cambios para la entidad (sección 6.5). El valor predeterminado es false. |
states | array | no | Los estados en los que puede estar un registro de esta tabla (§6.14): su ciclo de vida. Vea más abajo. Ausente en un documento escrito antes de que existieran los estados, que es como un importador lo distingue de una tabla sin ninguno. |
reasons | array | no | Los motivos, cada uno de los cuales pertenece exactamente a un estado. Vea más abajo. |
statusValueBase | integer | no | El límite inferior del rango desde el que se numeran las opciones de estado y motivo añadidas de esta tabla: la base de valores de opción del editor propietario (§6.14). Los valores Active/Inactive creados de serie quedan fuera de él, en 0 y 1: todas las tablas los tienen y significan lo mismo en todas partes, así que no necesitan espacio de nombres. |
nextStatusValue | integer | no | La marca máxima de estado de la tabla: el siguiente valor que asignará. Se almacena en lugar de derivarse de las opciones, por el mismo motivo que en un conjunto de opciones: el número de una opción eliminada queda retirado, y volver a derivarlo se lo daría a la siguiente opción nueva mientras algunos registros aún podrían contenerlo. |
Campo
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
logicalName | string | sí | En snake_case en minúsculas. |
displayName | string | sí | |
dataType | string | sí | Uno de Text, MultilineText, Integer, Decimal, Boolean, DateTime, Lookup, PolymorphicLookup, File, Image, OptionSet, State, Reason. |
isRequired | boolean | no | |
isPrimary | boolean | no | Verdadero para el único campo principal. |
maxLength | integer | no | Para Text (1–4000). |
precision, scale | integer | no | Para Decimal (scale ≤ precision ≤ 38). |
targetEntity | string | condicional | Obligatorio cuando dataType es Lookup; el nombre lógico de la entidad a la que se hace referencia. |
targetEntities | string[] | condicional | Obligatorio cuando dataType es PolymorphicLookup; las tablas a las que puede apuntar un valor, en el orden del selector. Al menos dos, sin repeticiones. |
isAuditExcluded | boolean | no | Excluye el campo de la auditoría de cambios cuando la entidad se audita (sección 6.5). El valor predeterminado es false. |
Los campos
PolymorphicLookupse aprovisionan como dos columnas: la propia columnauuiddel campo, que contiene el id del registro, y una columna hermana<column>_typede tipotext, que contiene el nombre lógico de la tabla de destino. Ninguna de las dos tiene clave externa —una sola columna no puede hacer referencia a varias tablas—, así que la integridad depende de la ruta de escritura: comprueba que el destino existe, y un destino eliminado después se lee como una referencia sin resolver.En la transmisión, las dos mitades viajan como un único escalar,
<table>:<id>, de modo que losvaluesde un registro siguen siendo un mapa plano de nombre lógico de campo a escalar y la columna discriminadora nunca aparece como campo. Es la convención ya existente en la plataforma para una referencia autodescriptiva (recordfile:<id>,webresource:par_/app.js).Se almacena el nombre lógico de la tabla y no un número, porque un discriminador numérico sería un índice en
targetEntities, de modo que reordenar los destinos en el diseñador haría apuntar en silencio cada fila almacenada a otra tabla. Las columnas de propietario de un registro usan en cambio una enumeración numérica, lo cual es coherente y no contradictorio: sus cinco valores son conceptos de la plataforma fijados en el código, no una lista que edite un creador.Cada entrada de
targetEntitiestiene su propia relación de respaldo, que es lo que hace que el formulario de la tabla referenciada ofrezca una pestaña Relacionado para estos registros.
Los campos
File/Imagese aprovisionan como una columna de texto que contiene una referencia con esquema:recordfile:<id>para un archivo guardado en el propio esquema del entorno, uobjectstore:<key>para uno lo bastante grande como para haberse desbordado al almacenamiento de objetos. Los bytes se cargan en el propio endpoint de archivos del campo, en lugar de escribirse a través de la API de registros, y se sirven con la autorización del propio registro. Cuál de los dos almacenes contiene un archivo lo decide su tamaño y nada que configure un creador.
Relación
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
logicalName | string | sí | En snake_case en minúsculas. |
type | string | sí | OneToMany. |
referencedEntity | string | sí | El lado «uno». |
referencingEntity | string | sí | El lado «varios» (contiene la búsqueda). |
lookupField | string | sí | El campo de búsqueda de la entidad que hace referencia y que respalda la relación. |
Estado y motivo
Un estado indica en qué punto de su ciclo de vida está un registro; un motivo indica qué variante de ese estado tiene. Viajan con la tabla porque forman parte de lo que diseñó el creador.
🔴 No son un conjunto de opciones. Active en una factura y Active en un contacto no son la
misma opción, y modelarlos como una lista compartida haría que cambiar el nombre de uno cambiara
el del otro.
Estado:
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
value | integer | sí | El valor almacenado, que se conserva en una importación: los registros del entorno de origen ya lo contienen, así que Desarrollo y Pruebas deben coincidir en lo que significa. |
displayName | string | sí | La etiqueta. |
color | string | no | El color con el que se dibuja su distintivo. |
icon | string | no | El glifo de su distintivo. |
defaultReason | integer | no | Cuál de los motivos de este estado recibe un registro al entrar en él. Si falta, es el primero, lo que hace que este ajuste sea opcional. |
Motivo:
| Campo | Tipo | Obligatorio | Notas |
|---|---|---|---|
state | integer | sí | El value del estado al que pertenece este motivo. Se identifica por valor y no por id de fila, porque el valor es lo que almacena un registro y lo que sobrevive a una exportación. |
value | integer | sí | El valor almacenado. |
displayName | string | sí | La etiqueta. |
color · icon | string | no | Igual que en un estado. |
Lo esencial es la pertenencia: Won y Lost son ambos motivos por los que una oportunidad
está inactiva, y ofrecerlos mientras está activa no tendría sentido.
Ejemplo
{
"logicalName": "par_invoice",
"displayName": "Invoice",
"displayCollectionName": "Invoices",
"publisherPrefix": "par",
"primaryField": "par_name",
"fields": [
{ "logicalName": "par_name", "displayName": "Name", "dataType": "Text", "isPrimary": true, "isRequired": true, "maxLength": 200 },
{ "logicalName": "par_total", "displayName": "Total", "dataType": "Decimal", "precision": 18, "scale": 2 },
{ "logicalName": "par_account", "displayName": "Account", "dataType": "Lookup", "targetEntity": "par_account" }
],
"relationships": [
{ "logicalName": "par_account_invoices", "type": "OneToMany", "referencedEntity": "par_account", "referencingEntity": "par_invoice", "lookupField": "par_account" }
]
}
Control de versiones
Las versiones anteriores del esquema se conservan junto a las nuevas para que las soluciones ya
implementadas sigan validándose después de que el esquema evolucione. Cuando se necesita un cambio
incompatible, se publica una versión nueva (model-driven-entity@2) en lugar de editar esta.