Saltar al contenido principal
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:
yarn twenty dev:add object
A continuación mostramos los archivos terminados.
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.

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.
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 },
      ] },
  ],
});
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.

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.

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.
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 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.
Configuración del modelo de datos mostrando plantillas de documentos y documentos
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:
Dear {{name.firstName}} {{name.lastName}},

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

Best,
The Team
Un registro de plantilla de propuesta de ventas con el cuerpo del marcador de posición
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.

Siguiente: generando documentos →

Escriba la función lógica que llena la plantilla.