Saltar para o conteúdo principal
Nosso aplicativo precisa de dois objetos personalizados: modelos de documentos (o que escrever) e documentos (o resultado gerado). Vamos defini-los. Crie cada arquivo de entidade com o CLI — gera uma pasta UUID válida e correta para você:
yarn twenty dev:add object
Abaixo nós mostramos os arquivos concluídos.
Todo *_UNIVERSAL_IDENTIFIER constante vive em src/constants/universal-identifiers.ts e é importado onde usado. Os trechos abaixo omitem essas importações por brevidade — mantenha-as em seus próprios arquivos.

O objeto modelo

Um template tem um nome, um body com {{placeholders}}, e um alvo que diz se é escrito para uma pessoa ou para uma empresa. O body é um campo RICH_TEXT, então Vinte dá um editor completo de texto rico.
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 opção valores deve ser UPPER_CASE (PERSON, não person), e o defaultValue está entre aspas extras: `'PERSON'`. A etiqueta é o que usuários veem.

O objeto do documento

O documento gerado armazena o conteúdo renderizado e um estado. Defina da mesma forma, com uma seleção status de DRAFT / GENERATED. Arquivo completo: document.object.ts.

Vinculando eles com uma relação

Cada documento deve apontar para o modelo de onde veio. Relações são bidirecionais — você define ambos os lados, cada um em seu próprio arquivo 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',
  },
});
O outro lado (template-documents-relation.field.ts) é um campo RelationType.ONE_TO_MANY chamado documentos que aponta para o lado oposto. Ver Relations para o padrão completo.

Veja em Vinte

Com yarn 20 dev executando, abra Settings → Data model. Ambos os objetos aparecem, marcados com seu aplicativo.
Configurações do modelo de dados mostrando documentos e modelos de documento
Crie um modelo para testar com — nomeie-a proposta de vendas, defina destino para Personagem, e cole um corpo com alguns espaços reservados:
Dear {{name.firstName}} {{name.lastName}},

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

Best,
The Team
Um registro de modelo de proposta de vendas com corpo de placeholder
Após essa etapa: você tem objetos documentTemplate e documento, ligados por a relação e um modelo para gerar. Em seguida, a lógica que a preenche.

Próximo: gerando documentos →

Escreva a função lógica que preenche o template.