> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 1. Modelo de datos

> Modelo de documentos y plantillas con objetos, campos y una relación.

Nuestra aplicación necesita dos objetos personalizados: **plantillas de documentos** (qué escribir) y
**documentos** (el resultado generado). Vamos a definirlos.

Escaffold cada archivo de entidad con la CLI — genera un UUID válido y la carpeta
correcta para ti:

```bash filename="Terminal" theme={null}
yarn twenty dev:add object
```

A continuación mostramos los archivos terminados.

<Note>
  Cada `*_UNIVERSAL_IDENTIFIER` vida constante en
  `src/constants/universal-identifiers.ts` y es importado donde se utiliza. Los fragmentos
  a continuación omiten las importaciones por brevedad — manténgalos en tus propios archivos.
</Note>

## El objeto de plantilla

Una plantilla tiene un `nombre`, un `cuerpo` con `{{placeholders}}`, y un `target` que
dice si está escrito para una persona o una empresa. El `body` es un campo
`RICH_TEXT`, así que Veinte le da un editor completo de texto.

```ts filename="src/objects/document-template.object.ts" theme={null}
import { defineObject, FieldType } from 'twenty-sdk/define';

export default defineObject({
  universalIdentifier: DOCUMENT_TEMPLATE_OBJECT_UNIVERSAL_IDENTIFIER,
  nameSingular: 'documentTemplate',
  namePlural: 'documentTemplates',
  labelSingular: 'Document template',
  labelPlural: 'Document templates',
  icon: 'IconFileText',
  labelIdentifierFieldMetadataUniversalIdentifier:
    TEMPLATE_NAME_FIELD_UNIVERSAL_IDENTIFIER,
  fields: [
    { universalIdentifier: TEMPLATE_NAME_FIELD_UNIVERSAL_IDENTIFIER,
      type: FieldType.TEXT, name: 'name', label: 'Name', icon: 'IconAbc' },
    { universalIdentifier: TEMPLATE_BODY_FIELD_UNIVERSAL_IDENTIFIER,
      type: FieldType.RICH_TEXT, name: 'body', label: 'Body', icon: 'IconFileText',
      description: 'Use {{placeholders}} like {{name.firstName}} or {{jobTitle}}.' },
    { universalIdentifier: TEMPLATE_TARGET_FIELD_UNIVERSAL_IDENTIFIER,
      type: FieldType.SELECT, name: 'target', label: 'Target', icon: 'IconTarget',
      defaultValue: `'PERSON'`,
      options: [
        { id: TEMPLATE_TARGET_OPTION_PERSON_UNIVERSAL_IDENTIFIER,
          value: 'PERSON', label: 'Person', color: 'blue', position: 0 },
        { id: TEMPLATE_TARGET_OPTION_COMPANY_UNIVERSAL_IDENTIFIER,
          value: 'COMPANY', label: 'Company', color: 'green', position: 1 },
      ] },
  ],
});
```

<Warning>
  `SELECT` option **values** debe ser `UPPER_CASE` (`PERSON`, no `person`), y el
  `defaultValue` está envuelto en comillas adicionales: `` `'PERSON'` ``. La `label` es lo que
  los usuarios ven.
</Warning>

## El objeto del documento

El documento generado almacena el `contenido` renderizado y un `status`. Definirlo
de la misma manera, con un `status` seleccionado de `DRAFT` / `GENERATED`. Archivo completo:
[`document.object.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/examples/document-generator/src/objects/document.object.ts).

## Vinculándolas con una relación

Cada documento debe apuntar de nuevo a la plantilla de la que proviene. Las relaciones son
**bidireccionales** — defines ambos lados, cada uno en su propio archivo de campo.

```ts filename="src/fields/document-template-relation.field.ts" theme={null}
import { defineField, FieldType, OnDeleteAction, RelationType } from 'twenty-sdk/define';

// The "many" side: each document belongs to one template.
export default defineField({
  universalIdentifier: DOCUMENT_TEMPLATE_FIELD_UNIVERSAL_IDENTIFIER,
  objectUniversalIdentifier: DOCUMENT_OBJECT_UNIVERSAL_IDENTIFIER,
  type: FieldType.RELATION,
  name: 'template',
  label: 'Template',
  relationTargetObjectMetadataUniversalIdentifier:
    DOCUMENT_TEMPLATE_OBJECT_UNIVERSAL_IDENTIFIER,
  relationTargetFieldMetadataUniversalIdentifier:
    TEMPLATE_DOCUMENTS_FIELD_UNIVERSAL_IDENTIFIER,
  universalSettings: {
    relationType: RelationType.MANY_TO_ONE,
    onDelete: OnDeleteAction.SET_NULL,
    joinColumnName: 'templateId',
  },
});
```

El otro lado (`template-documents-relation.field.ts`) es un campo
`RelationType.ONE_TO_MANY` llamado `documents` que apunta a la manera opuesta.
Ver [Relations](/l/es/developers/extend/apps/data/relations) para ver el patrón completo.

## Ver en Veinte

Con `yarn veinte dev` en ejecución, abre **Ajustes → Modelo de datos**. Ambos objetos
aparecen, etiquetados con tu aplicación.

<Frame caption="Ambos objetos personalizados, propiedad del generador de documentos.">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/twenty/images/docs/desarrolladores/extends/apps/document-generator/01-data-model.png" alt="Configuración del modelo de datos mostrando plantillas de documentos y documentos" />
</Frame>

Crea una plantilla para probar con — nombra la *propuesta de ventas*, establece el **objetivo** a
*Persona*, y pega un cuerpo con unos pocos marcadores de posición:

```text theme={null}
Dear {{name.firstName}} {{name.lastName}},

As {{jobTitle}} at {{company.name}}, we think you'll love our product.

Best,
The Team
```

<Frame caption="Un registro de plantilla. El cuerpo mantiene sus marcadores de posición hasta que se genere un documento.">
  <img src="https://mintlify.s3.us-west-1.amazonaws.com/twenty/images/docs/desarrolladores/extends/apps/document-generator/03-template-record.png" alt="Un registro de plantilla de propuesta de ventas con el cuerpo del marcador de posición" />
</Frame>

**Después de este paso:** tienes los objetos `documentTemplate` y `document`, enlazados por
una relación, y una plantilla para generar. Después, la lógica que lo llena.

<Card title="Siguiente: generando documentos →" icon="bolt" href="/developopers/extend/apps/tutorials/document-generator/generating-documents">
  Escriba la función lógica que llena la plantilla.
</Card>
