snapshot of https://github.com/twentyhq/twenty.git (main, 2026-09-17; blobs > 131072B omitted)
Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-17 23:28:13 +05:00
commit e7da97194a
32688 changed files with 4208681 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
---
title: Zpracování polí v akcích Code
description: Naučte se správně pracovat se vstupy typu pole v akcích Code v pracovních postupech.
---
Při práci s poli v akcích Code se můžete setkat se dvěma běžnými problémy:
1. **Pole předaná jako řetězce** — data z externích systémů nebo předchozích kroků dorazí jako řetězec místo skutečného pole
2. **Nelze vybírat jednotlivé položky** — můžete vybrat pouze celé pole, nikoli konkrétní pole objektů v něm
Obojí lze vyřešit pomocí uzlu Code.
## Parsování polí z řetězců
Pole se mezi kroky pracovního postupu často předávají jako řetězce nebo JSON, nikoli jako nativní pole. K tomu dochází, když:
* Příjem dat z externích API pomocí HTTP Request
* Zpracování dat webhooků
* Předávání dat mezi kroky pracovního postupu
**Řešení**: Přidejte tento vzor na začátek své akce Code:
```javascript
export const main = async (params: {
users: any;
}): Promise<object> => {
const { users } = params;
// Handle input that may come as a string or an array
const usersFormatted = typeof users === "string" ? JSON.parse(users) : users;
// Now you can safely work with usersFormatted as an array
return {
users: usersFormatted.map((user) => ({
...user,
activityStatus: String(user.activityStatus).toUpperCase(),
})),
};
};
```
Klíčový řádek `typeof users === "string" ? JSON.parse(users) : users` ověřuje, zda je vstup řetězec, v případě potřeby jej rozparsuje, nebo jej použije přímo, pokud už jde o pole.
## Extrahování jednotlivých atributů z polí
Webhook může vrátit pole jako `answers: [...]`, ale v následujících krocích pracovního postupu lze vybrat pouze celé pole — nikoli jednotlivé položky v něm.
**Řešení**: Přidejte uzel Code, který extrahuje konkrétní pole a vrátí je jako strukturovaný objekt:
```javascript
export const main = async (params: {
answers: any;
}): Promise<object> => {
const { answers } = params;
// Handle input that may come as a string or an array
const answersFormatted = typeof answers === "string"
? JSON.parse(answers)
: answers;
// Extract specific fields from the array
const firstname = answersFormatted[0]?.text || "";
const name = answersFormatted[1]?.text || "";
return {
answer: {
firstname,
name
}
};
};
```
Uzel Code vrátí místo pole strukturovaný objekt. V následujících krocích nyní můžete ve výběru proměnných vybrat jednotlivá pole, jako `answer.firstname` a `answer.name`.
<Tip>
**Chcete místo rozbalování polí iterovat přímo přes pole?** Když krok Code nebo Logic Function vrátí pole na nejvyšší úrovni, můžete ho předat přímo do [Iteratoru](/l/cs/user-guide/workflows/capabilities/use-iterator): jako vstup Iteratoru vyberte možnost kroku **Whole list** a uvnitř smyčky pak na každou položku odkazujte pomocí `{{iterator.currentItem}}`. V takovém případě nemusíte pole převádět na objekt.
</Tip>
<Tip>
Klikněte na čtvercovou ikonu vpravo nahoře v editoru kódu a zobrazte jej na celou obrazovku — hodí se to, protože výchozí šířka editoru je omezená.
</Tip>

View File

@@ -0,0 +1,182 @@
---
title: Přeneste produktová data do Twenty
description: Synchronizujte data produktového katalogu z datového skladu do svého CRM podle plánu.
---
Použijte tento vzor k udržení synchronizace Twenty s produktovými daty z vašeho datového skladu (např. Snowflake, BigQuery, PostgreSQL).
## Struktura pracovního postupu
1. **Spouštěč**: Podle plánu
2. **Code**: Spusťte dotaz na svůj datový sklad
3. **Code** (volitelné): Naformátujte data jako pole
4. **Iterator**: Procházejte jednotlivé produkty
5. **Upsert Record**: Vytvořte nebo aktualizujte záznam v Twenty
<img src="/images/user-guide/workflows/create_users_workflow.png" style={{width:'100%'}} />
## Krok 1: Naplánujte spouštěč
Nastavte pracovní postup tak, aby běžel s frekvencí odpovídající vašim požadavkům na aktuálnost dat:
* Každých 5 minut pro synchronizaci téměř v reálném čase
* Každou hodinu pro méně kritická data
* Denně pro dávkové aktualizace
## Krok 2: Proveďte dotaz na svůj datový sklad
Přidejte akci **Code** pro načtení nejnovějších dat:
```javascript
export const main = async () => {
const intervalMinutes = 10; // Match your schedule frequency
const cutoffTime = new Date(Date.now() - intervalMinutes * 60 * 1000).toISOString();
// Replace with your actual data warehouse connection
const response = await fetch("https://your-warehouse-api.com/query", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
query: `
SELECT id, name, sku, price, stock_quantity, updated_at
FROM products
WHERE updated_at >= '${cutoffTime}'
`
})
});
const data = await response.json();
return { products: data.results };
};
```
<Tip>
Filtrováním podle `updated_at >= last X minutes` získáte pouze nedávno změněné záznamy. Díky tomu zůstane synchronizace efektivní.
</Tip>
## Krok 3: Formátování dat (volitelné)
Pokud váš datový sklad vrací data ve formátu, který vyžaduje transformaci, přidejte další akci **Code**. Mezi běžné transformace patří převody typů, přejmenování polí a čištění dat.
### Příklad: Uživatelská data s logickými a stavovými poli
```javascript
export const main = async (params: {
users: any;
}): Promise<object> => {
const { users } = params;
const usersFormatted = typeof users === "string" ? JSON.parse(users) : users;
// Convert string "true"/"false" to actual booleans
const toBool = (v: any) => v === true || v === "true";
return {
users: usersFormatted.map((user) => ({
...user,
activityStatus: String(user.activityStatus).toUpperCase(),
isActiveLast30d: toBool(user.isActiveLast30d),
isActiveLast7d: toBool(user.isActiveLast7d),
isActiveLast24h: toBool(user.isActiveLast24h),
isTwenty: toBool(user.isTwenty),
})),
};
};
```
### Příklad: Produktová data s převody typů
```javascript
export const main = async (params: { products: any }) => {
const products = typeof params.products === "string"
? JSON.parse(params.products)
: params.products;
return {
products: products.map(product => ({
externalId: product.id,
name: product.name,
sku: product.sku,
price: parseFloat(product.price), // String → Number
stockQuantity: parseInt(product.stock_quantity),
isActive: product.status === "active" // String → Boolean
}))
};
};
```
### Příklad: Formátování dat a měn
```javascript
export const main = async (params: { deals: any }) => {
const deals = typeof params.deals === "string"
? JSON.parse(params.deals)
: params.deals;
return {
deals: deals.map(deal => ({
...deal,
// Convert Unix timestamp to ISO date
closedAt: deal.closed_timestamp
? new Date(deal.closed_timestamp * 1000).toISOString()
: null,
// Ensure amount is a number (remove currency symbols)
amount: parseFloat(String(deal.amount).replace(/[^0-9.-]/g, "")),
// Normalize stage names
stage: deal.stage?.toLowerCase().replace(/_/g, " ")
}))
};
};
```
### Běžné transformace
| Zdrojový formát | Cílový formát | Kód |
| -------------------- | -------------------- | ---------------------------------------- |
| `"true"` / `"false"` | `true` / `false` | `v === true \|\| v === "true"` |
| `"123.45"` | `123.45` | `parseFloat(value)` |
| `"active"` | `"ACTIVE"` | `value.toUpperCase()` |
| `1704067200` (Unix) | Datum ve formátu ISO | `new Date(v * 1000).toISOString()` |
| `"$1,234.56"` | `1234.56` | `parseFloat(v.replace(/[^0-9.-]/g, ""))` |
| `null` / `undefined` | `""` | `value \|\| ""` |
## Krok 4: Projděte produkty
Přidejte akci **Iterator**:
* Vstup: `{{code.products}}`
Tímto projdete každý produkt v poli.
## Krok 5: Proveďte upsert pro každý záznam
Uvnitř iterátoru přidejte akci **Upsert Record**:
| Nastavení | Hodnota |
| --------------- | --------------------------------------------- |
| **Objekt** | Váš vlastní objekt Product |
| **Shoda podle** | Externí ID nebo SKU (jedinečný identifikátor) |
| **Název** | `{{iterator.item.name}}` |
| **SKU** | `{{iterator.item.sku}}` |
| **Cena** | `{{iterator.item.price}}` |
<Tip>
Použijte **Upsert** (aktualizace nebo vytvoření) místo vytváření samostatných větví pro vytvoření vs. aktualizaci. Je to rychlejší na vytvoření a snazší na ladění.
</Tip>
## Příklady použití
| Zdroj | Data |
| ------------------------ | ------------------------------------------- |
| **ERP systém** | Katalog produktů, ceny, skladové zásoby |
| **E-commerce platforma** | Objednávky, zákazníci, aktualizace produktů |
| **Datový sklad** | Agregované metriky, obohacená data |
| **Skladový systém** | Stavy zásob, upozornění na doobjednání |
## Související
* [Spouštěče pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-triggers)
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Práce s poli v akcích Code](/l/cs/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,130 @@
---
title: Přeneste odeslané odpovědi z Typeformu do Twenty
description: Zpracujte payload webhooku Typeformu a vytvářejte leady z odeslaných formulářů.
---
Pro standardní nastavení webhooku viz [Nastavení spouštěče webhooku](/l/cs/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). Tento článek se věnuje specifickému zpracování požadovanému pro vlastní strukturu payloadu Typeformu.
### Krok 1: Vytvořte pracovní postup pro webhook
1. Přejděte na **Nastavení → Pracovní postupy**
2. Klikněte na **+ Nový pracovní postup**
3. Vyberte **Webhook** jako spouštěč
4. Zkopírujte URL webhooku
### Krok 2: Nakonfigurujte Typeform
1. V Typeformu otevřete svůj formulář
2. Přejděte na **Connect → Webhooks**
3. Vložte svou URL webhooku Twenty
4. Uložit
### Krok 3: Porozumějte payloadu Typeformu
Typeform posílá vnořenou strukturu JSON. Zde je zjednodušený příklad:
```json
{
"event_type": "form_response",
"form_response": {
"form_id": "abc123",
"submitted_at": "2025-01-15T10:30:00Z",
"answers": [
{
"text": "Jane",
"type": "text",
"field": { "id": "field1", "type": "short_text", "title": "First Name" }
},
{
"text": "Smith",
"type": "text",
"field": { "id": "field2", "type": "short_text", "title": "Last Name" }
},
{
"text": "Acme Corp",
"type": "text",
"field": { "id": "field3", "type": "short_text", "title": "Company" }
},
{
"email": "jane@acme.com",
"type": "email",
"field": { "id": "field4", "type": "email", "title": "Email" }
},
{
"type": "choice",
"field": { "id": "field5", "type": "dropdown", "title": "Team Size" },
"choice": { "label": "10-50" }
}
]
}
}
```
Důležité body:
* Data formuláře jsou vnořena pod `form_response`
* **Odpovědi jsou vráceny jako pole**, nikoli jako pojmenovaná pole
* Každá odpověď obsahuje pro referenci typ a název pole
### Krok 4: Extrahujte pole z pole odpovědí
Protože `answers` je pole, v následujících krocích můžete vybrat pouze celé pole — nikoli jednotlivá pole. Přidejte akci **Code** k extrakci potřebných polí:
```javascript
export const main = async (params: {
answers: any;
}): Promise<object> => {
const { answers } = params;
// Handle input that may come as a string or an array
const answersFormatted = typeof answers === "string"
? JSON.parse(answers)
: answers;
// Extract fields by position or by finding the field type
const firstName = answersFormatted[0]?.text || "";
const lastName = answersFormatted[1]?.text || "";
const company = answersFormatted[2]?.text || "";
const email = answersFormatted.find(a => a.type === "email")?.email || "";
const teamSize = answersFormatted.find(a => a.type === "choice")?.choice?.label || "";
return {
contact: {
firstName,
lastName,
company,
email,
teamSize
}
};
};
```
Nyní v následujících krocích můžete z výběru proměnných vybrat `contact.firstName`, `contact.email` apod.
<Tip>
Další podrobnosti o práci s poli v akcích Code viz [Práce s poli v akcích Code](/l/cs/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions).
</Tip>
### Krok 5: Vytvořte záznam
Přidejte akci **Vytvořit záznam**:
| Pole | Hodnota |
| -------------- | -------------------------------------------------------------- |
| **Objekt** | Osoby |
| **Jméno** | `{{code.contact.firstName}}` |
| **Příjmení** | `{{code.contact.lastName}}` |
| **Email** | `{{code.contact.email}}` |
| **Společnost** | Vyhledejte nebo vytvořte na základě `{{code.contact.company}}` |
### Krok 6: Otestujte a aktivujte
1. Odešlete testovou odpověď v Typeformu
2. Zkontrolujte běh pracovního postupu, abyste ověřili, že data byla zachycena
3. Aktivujte pracovní postup
## Související
* [Nastavení spouštěče webhooku](/l/cs/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger)
* [Práce s poli v akcích Code](/l/cs/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,263 @@
---
title: Vygenerovat PDF z Twenty
description: Vytvořte pracovní postup pro generování a připojení PDF (například nabídky) k záznamu.
---
Automaticky vygenerujte nebo získejte PDF a připojte ho k záznamu v Twenty. To se běžně používá k vytváření nabídek, faktur nebo reportů, které jsou propojené se společnostmi, příležitostmi nebo jinými objekty.
## Přehled
Tento pracovní postup používá **Ruční spouštěč**, takže uživatelé mohou na požádání vygenerovat PDF pro libovolný vybraný záznam. O zpracování se stará **logická funkce**:
1. Stažení PDF z adresy URL (ze služby pro generování PDF)
2. Nahrání souboru do Twenty
3. Vytvoření přílohy propojené se záznamem
## Předpoklady
Než nastavíte pracovní postup:
1. **Vytvořte klíč API**: Přejděte do **Nastavení → API** a vytvořte nový klíč API. Tento token budeš potřebovat pro logickou funkci.
2. **Nastavte službu pro generování PDF** (volitelné): Pokud chcete dynamicky generovat PDF (např. nabídky), použijte službu jako Carbone, PDFMonkey nebo DocuSeal k vytvoření PDF a získání adresy URL pro stažení.
## Nastavení krok za krokem
### Krok 1: Nakonfigurujte spouštěč
1. Přejděte na **Pracovní postupy** a vytvořte nový pracovní postup
2. Vyberte **Ruční spouštěč**
3. Zvolte objekt, ke kterému chcete připojovat PDF (např. **Společnost** nebo **Příležitost**)
<Tip>
s manuálním spouštěčem, uživatelé mohou spustit tento pracovní postup pomocí tlačítka, které se zobrazí vpravo nahoře, jakmile je vybrán záznam - toto běží pracovní postup pro generování a připojení PDF.
</Tip>
### Krok 2: Přidejte logickou funkci
1. Přidat akci **Code** (funkce Logike)
2. Vytvořte novou funkci pomocí kódu níže
3. Nakonfigurujte vstupní parametry
#### Vstupní parametry
| Parametr | Hodnota |
| ----------- | ----------------------- |
| `companyId` | `{{trigger.object.id}}` |
<Note>
Pokud připojujete k jinému objektu (Osoba, Příležitost apod.), přejmenujte parametr podle toho (např. `personId`, `opportunityId`) a aktualizujte logickou funkci.
</Note>
#### Kód logické funkce
```typescript
export const main = async (
params: { companyId: string },
) => {
const { companyId } = params;
// Replace with your Twenty GraphQL endpoints (/metadata for metadata and files or /graphql for your records)
// Cloud: https://api.twenty.com/graphql
// Self-hosted: https://your-domain.com/graphql
const metadataGraphqlEndpoint = 'https://api.twenty.com/metadata';
const dataGraphqlEndpoint = 'https://api.twenty.com/graphql';
// Replace with your API key from Settings → APIs
const authToken = 'YOUR_API_KEY';
// Replace with your PDF URL
// This could be from a PDF generation service or a static URL
const pdfUrl = 'https://your-pdf-service.com/generated-quote.pdf';
const filename = 'quote.pdf';
// Step 1: Download the PDF file
const pdfResponse = await fetch(pdfUrl);
if (!pdfResponse.ok) {
throw new Error(`Failed to download PDF: ${pdfResponse.status}`);
}
const pdfBlob = await pdfResponse.blob();
const pdfFile = new File([pdfBlob], filename, { type: 'application/pdf' });
const fieldMetadataIdQuery = `
query FindUploadFileFieldMetadataId {
objects {
edges {
node {
nameSingular
fieldsList {
id
name
}
}
}
}
}
`;
// Step 2: Find a fieldMetadataId of "Attachment file" field in Attachments object with GraphQL API
const response = await fetch(metadataGraphqlEndpoint, {
method: 'POST',
headers: {
Authorization: `Bearer ${authToken}`
},
body: {
query: fieldMetadataIdQuery,
}
});
const result = await response.json();
const uploadFileFieldMetadataId = result.data.objects.edges.find(object => object.node.nameSingular === 'attachment').node.fieldsList.find(field => field.name === 'file').id;
// Step 3: Upload the file via GraphQL multipart upload
const uploadMutation = `
mutation UploadFilesFieldFile($file: Upload!, $fieldMetadataId: String!) {
uploadFilesFieldFile(file: $file, fieldMetadataId: $fieldMetadataId) {
id
}
}
`;
const uploadForm = new FormData();
uploadForm.append('operations', JSON.stringify({
query: uploadMutation,
variables: { file: null, fieldMetadataId: uploadFileFieldMetadataId },
}));
uploadForm.append('map', JSON.stringify({ '0': ['variables.file'] }));
uploadForm.append('0', pdfFile);
const uploadResponse = await fetch(metadataGraphqlEndpoint, {
method: 'POST',
headers: { Authorization: `Bearer ${authToken}` },
body: uploadForm,
});
const uploadResult = await uploadResponse.json();
if (uploadResult.errors?.length) {
throw new Error(`Upload failed: ${uploadResult.errors[0].message}`);
}
const fileId = uploadResult.data?.uploadFilesFieldFile?.id;
if (!fileId) {
throw new Error('No file id returned from upload');
}
// Step 4: Create the attachment linked to the company
const attachmentMutation = `
mutation CreateOneAttachment($data: AttachmentCreateInput!) {
createAttachment(data: $data) {
id
name
}
}
`;
const attachmentResponse = await fetch(dataGraphqlEndpoint, {
method: 'POST',
headers: {
Authorization: `Bearer ${authToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: attachmentMutation,
variables: {
data: {
name: filename,
targetCompanyId: companyId,
file: [
{
fileId: fileId,
label: filename
}
]
},
},
}),
});
const attachmentResult = await attachmentResponse.json();
if (attachmentResult.errors?.length) {
throw new Error(`Attachment creation failed: ${attachmentResult.errors[0].message}`);
}
return attachmentResult.data?.createAttachment;
};
```
### Krok 3: Přizpůsobte pro svůj případ použití
#### Chcete-li připojit k jinému objektu
Nahraďte `targetCompanyId` příslušným polem:
| Objekt | Název pole |
| -------------- | -------------------------- |
| Společnost | `targetCompanyId` |
| Osoba | `targetPersonId` |
| Příležitost | `targetOpportunityId` |
| Vlastní objekt | `targetYourCustomObjectId` |
Aktualizujte jak parametr funkce, tak objekt `variables.data` v mutaci přílohy.
#### Chcete-li použít dynamickou adresu URL PDF
Pokud používáte službu pro generování PDF, můžete:
1. Nejprve proveďte akci HTTP Request pro vygenerování PDF
2. Předejte vrácenou adresu URL PDF logické funkci jako parametr
```typescript
export const main = async (
params: { companyId: string; pdfUrl: string; filename: string },
) => {
const { companyId, pdfUrl, filename } = params;
// ... rest of the function
};
```
### Krok 4: Otestujte a aktivujte
1. Uložte pracovní postup
2. Přejděte na záznam společnosti
3. Klikněte na nabídku **⋮** a vyberte svůj pracovní postup
4. Zkontrolujte v části **Přílohy** u záznamu, že bylo PDF připojeno
5. Aktivujte pracovní postup
## Kombinace se službami pro generování PDF
Pro vytváření dynamických nabídek nebo faktur:
### Příklad: Vygenerovat nabídku → Připojit PDF
| Krok | Akce | Účel |
| ---- | --------------------------- | ------------------------------------------------------ |
| 1 | Ruční spouštěč (Společnost) | Uživatel spustí na záznamu |
| 2 | Vyhledat záznam | Získat podrobnosti o příležitosti nebo řádkové položce |
| 3 | HTTP požadavek | Zavolat API pro generování PDF s daty záznamu |
| 4 | Logická funkce | Stáhnout a připojit vygenerované PDF |
### Oblíbené služby pro generování PDF
* **Carbone** - Generování dokumentů založené na šablonách
* **PDFMonkey** - Dynamické vytváření PDF ze šablon
* **DocuSeal** - Platforma pro automatizaci dokumentů
* **Documint** - Generování dokumentů primárně přes API
Každá služba poskytuje API, které vrátí PDF adresu URL, kterou můžete předat funkci Logika.
## Řešení potíží
| Problém | Řešení |
| -------------------------------- | --------------------------------------------------------------- |
| "Nepodařilo se stáhnout PDF" | Zkontrolujte, že adresa URL PDF je dostupná a vrací platné PDF |
| "Nepodařilo se nahrát" | Ověřte, že váš klíč API je platný a má oprávnění k zápisu |
| "Vytvoření přílohy se nezdařilo" | Ujistěte se, že název pole ID objektu odpovídá cílovému objektu |
## Související
* [Spouštěče pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-triggers)
* [Logické funkce](/l/cs/user-guide/workflows/capabilities/workflow-actions#code)
* [Vygenerujte nabídku nebo fakturu z Twenty](/l/cs/user-guide/workflows/how-tos/connect-to-other-tools/generate-quote-or-invoice-from-twenty)

View File

@@ -0,0 +1,144 @@
---
title: Vytvořte nabídku nebo fakturu z Twenty
description: Automaticky vytvářejte faktury v externích nástrojích, když se obchodní případy uzavřou.
---
Automaticky odesílejte data o obchodních případech do vašeho fakturačního systému (Stripe, QuickBooks, Xero atd.). když je příležitost vyhrána.
## Struktura pracovního postupu
1. **Spouštěč**: Záznam je aktualizován (Příležitost)
2. **Filtr**: Stav = Uzavřeno – vyhráno
3. **Vyhledat záznam**: Získat podrobnosti o společnosti
4. **Kód** (volitelné): Formátovat payload
5. **Požadavek HTTP**: Odeslat do fakturačního systému
## Krok 1: Nastavení spouštěče
1. Vytvořte nový pracovní postup
2. Vyberte spouštěč **Záznam je aktualizován**
3. Vyberte jako objekt **Příležitost**
## Krok 2: Filtrování na Uzavřeno – vyhráno
Přidejte akci **Filtr**, aby se pokračovalo pouze tehdy, když je obchodní případ vyhraný:
| Nastavení | Hodnota |
| ------------ | -------------------------------------- |
| **Pole** | Fáze |
| **Podmínka** | Rovná se |
| **Hodnota** | `CLOSED_WON` (nebo název vašeho stavu) |
<Tip>
Spouštěč se vyvolá při jakékoli aktualizaci Příležitosti. Filtr zajistí, že pracovní postup bude pokračovat pouze tehdy, když se stav změní na Uzavřeno – vyhráno.
</Tip>
## Krok 3: Získat podrobnosti o společnosti
Záznam Příležitosti nemusí obsahovat všechna pole Společnosti, která potřebujete pro fakturu. Přidejte akci **Vyhledat záznam**:
| Nastavení | Hodnota |
| --------------- | ------------------------------------------ |
| **Objekt** | Společnost |
| **Shoda podle** | ID se rovná `{{trigger.object.companyId}}` |
Tímto získáte úplný záznam Společnosti s fakturační adresou, daňovým ID atd.
## Krok 4: Formátování payloadu (volitelné)
Pokud váš fakturační systém očekává specifický formát, přidejte akci **Kód**:
```javascript
export const main = async (params: {
opportunity: any;
company: any;
}): Promise<object> => {
const { opportunity, company } = params;
return {
invoice: {
// Customer info from Company
customer_name: company.name,
customer_email: company.email || "",
billing_address: {
line1: company.address?.street || "",
city: company.address?.city || "",
postal_code: company.address?.postalCode || "",
country: company.address?.country || ""
},
tax_id: company.taxId || null,
// Invoice details from Opportunity
amount: opportunity.amount,
currency: opportunity.currency || "USD",
description: `Invoice for ${opportunity.name}`,
due_days: 30,
// Reference back to Twenty
metadata: {
opportunity_id: opportunity.id,
company_id: company.id
}
}
};
};
```
## Krok 5: Odeslání do fakturačního systému
Přidejte akci **Požadavek HTTP**:
| Nastavení | Hodnota |
| ----------- | -------------------------------------------- |
| **Metoda** | POST |
| **URL** | Koncový bod API vašeho fakturačního systému |
| **Záhlaví** | `Authorization: Bearer YOUR_API_KEY` |
| **Tělo** | `{{code.invoice}}` nebo namapujte pole přímo |
### Příklad: Faktura ve Stripe
```
POST https://api.stripe.com/v1/invoices
Headers:
Authorization: Bearer sk_live_xxx
Content-Type: application/x-www-form-urlencoded
Body:
customer: {{company.stripeCustomerId}}
collection_method: send_invoice
days_until_due: 30
```
### Příklad: Faktura v QuickBooks
```
POST https://quickbooks.api.intuit.com/v3/company/{realmId}/invoice
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Body: {{code.invoice}}
```
## Shrnutí kompletního pracovního postupu
| Krok | Akce | Účel |
| ---- | ----------------------------- | ------------------------------------------------------ |
| 1 | Spouštěč: Záznam aktualizován | Spustí se při jakékoli změně Příležitosti |
| 2 | Filtr | Pokračujte pouze pokud Stav = Uzavřeno – vyhráno |
| 3 | Vyhledat záznam | Získejte úplné podrobnosti o Společnosti pro fakturaci |
| 4 | Kód | Naformátujte data pro fakturační API |
| 5 | HTTP požadavek | Vytvořte fakturu v externím systému |
## Tipy
* **Ukládejte externí ID**: Uložte ID faktury vrácené API zpět do Příležitosti pomocí akce **Aktualizovat záznam**
* **Zpracování chyb**: Přidejte větev pro odeslání upozornění, pokud požadavek HTTP selže
* **Nejprve testujte**: Použijte sandbox/test režim vašeho fakturačního systému před ostrým spuštěním
## Související
* [Vygenerovat PDF z Twenty](/l/cs/user-guide/workflows/how-tos/connect-to-other-tools/generate-pdf-from-twenty) — připojte vygenerované soubory PDF k záznamům
* [Spouštěče pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-triggers)
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Automatizace pro Uzavřeno – vyhráno](/l/cs/user-guide/workflows/how-tos/crm-automations/closed-won-automations)

View File

@@ -0,0 +1,170 @@
---
title: Nastavení spouštěče webhooku
description: Přijímejte data z externích služeb pro spouštění pracovních postupů.
---
Spouštěče webhooků umožňují externím službám spustit vaše pracovní postupy zasláním dat na jedinečnou adresu URL. Použijte je k propojení formulářů, aplikací třetích stran a vlastních integrací.
## Kdy použít webhooky
| Případ použití | Příklad |
| -------------------------- | -------------------------------------------- |
| **Webové formuláře** | Odeslání kontaktního formuláře vytváří leady |
| **Aplikace třetích stran** | Platba ve Stripe → vytvořit záznam zákazníka |
| **Vlastní integrace** | Vaše aplikace → automatizace v Twenty |
| **Nástroje bez kódu** | Připojení Zapier, Make, n8n |
## Nastavení krok za krokem
### Krok 1: Vytvořte pracovní postup
1. Přejděte na **Nastavení → Pracovní postupy**
2. Klikněte na **+ Nový pracovní postup**
3. Pojmenujte jej (např. "Odeslání webového formuláře")
### Krok 2: Nakonfigurujte spouštěč webhooku
1. Klikněte na blok spouštěče
2. Vyberte **Webhook**
3. Obdržíte jedinečnou adresu URL webhooku, například:
```
https://api.twenty.com/webhooks/workflow/abc123...
```
4. Zkopírujte tuto adresu URL — budete ji potřebovat pro svou externí službu
### Krok 3: Definujte očekávanou datovou strukturu
Pro požadavky **POST** definujte očekávanou strukturu těla:
1. Klikněte na **Definovat očekávané tělo**
2. Zadejte ukázkový JSON, který odpovídá tomu, co vaše služba pošle:
```json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"company": "Acme Inc",
"message": "Interested in your product"
}
```
3. Klikněte na **Uložit** — tím se vytvoří proměnné, které můžete použít v dalších krocích
### Krok 4: Přidejte akce
Nyní přidejte akce, které využívají data z webhooku:
**Příklad: Vytvořit záznam osoby**
1. Přidejte akci **Vytvořit záznam**
2. Vyberte objekt **People**
3. Namapujte pole:
| Pole | Hodnota |
| ---------- | -------------------------------------------------------------- |
| Jméno | `{{trigger.body.firstName}}` |
| Příjmení | `{{trigger.body.lastName}}` |
| Email | `{{trigger.body.email}}` |
| Společnost | Vyhledejte nebo vytvořte na základě `{{trigger.body.company}}` |
### Krok 5: Otestujte webhook
Před aktivací otestujte svůj webhook:
**Pomocí cURL**:
```bash
curl -X POST https://api.twenty.com/webhooks/workflow/abc123... \
-H "Content-Type: application/json" \
-d '{"firstName":"Test","lastName":"User","email":"test@example.com"}'
```
**Pomocí Postmanu nebo podobného nástroje**:
1. Vytvořte požadavek POST na adresu URL vašeho webhooku
2. Nastavte hlavičku Content-Type na `application/json`
3. Přidejte své testovací tělo JSON
4. Odešlete a zkontrolujte spuštění pracovního postupu
### Krok 6: Aktivujte
Po otestování klikněte na **Aktivovat**, aby byl pracovní postup aktivní.
## Zpracování různých datových struktur
### Vnořená data
Pokud váš webhook posílá vnořená data:
```json
{
"contact": {
"name": "John Doe",
"email": "john@example.com"
},
"source": "website"
}
```
Odkazujte pomocí: `{{trigger.body.contact.email}}`
### Pole
Pokud data obsahují pole:
```json
{
"items": [
{"name": "Product A", "qty": 2},
{"name": "Product B", "qty": 1}
]
}
```
Jak pole zpracujete, závisí na vašem případě použití:
**Neznámý počet položek → Použijte Iterator**
Pokud potřebujete zpracovat každou položku v poli (např. pro každou vytvořit záznam), přidejte akci **Code** pro rozparsování pole a poté použijte **Iterator**:
```javascript
export const main = async (params: { items: any }) => {
const items = typeof params.items === "string"
? JSON.parse(params.items)
: params.items;
return { items };
};
```
Poté použijte Iterator k procházení: `{{code.items}}`
**Známá/konkrétní pole → Extrahujte do pojmenovaných polí**
Pokud pole obsahuje konkrétní položky, ke kterým chcete přistupovat jednotlivě (např. odpovědi formuláře, kde pozice 0 je vždy "křestní jméno", pozice 1 je vždy "příjmení"), přidejte akci **Code** k jejich extrakci:
```javascript
export const main = async (params: { items: any }) => {
const items = typeof params.items === "string"
? JSON.parse(params.items)
: params.items;
return {
product: {
name: items[0]?.name || "",
qty: items[0]?.qty || 0
}
};
};
```
Nyní můžete v následujících krocích vybírat `product.name` a `product.qty` jednotlivě.
<Tip>
Další podrobnosti o práci s poli viz [Zpracování polí v akcích Code](/l/cs/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions).
</Tip>
## Související
* [Spouštěče pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-triggers)
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,121 @@
---
title: Automatická odpověď na příchozí e-maily
description: Vytvořte pracovní postup, který pomocí AI třídí příchozí e-maily a automaticky odesílá odpovědi ve vláknu.
---
Odpovídejte na příchozí e-maily během několika sekund — ne hodin. Tento pracovní postup používá AI agenta k odfiltrování šumu (newslettery, spam, automatické odpovědi) a k vypracování individualizované odpovědi na skutečné zprávy. Pak ji AI zašle jako odpověď v závitu v původní konverzaci.
## Jak funguje vláknování e-mailů
Každý e-mail obsahuje skrytou hlavičku `Message-ID` — jedinečný identifikátor přiřazený poštovním serverem odesílatele. Když odpovíte na e-mail, váš poštovní klient nastaví hlavičku `In-Reply-To`, která odkazuje na tento otisk. Takto Gmail, Outlook a další klienti seskupují zprávy do vláken.
V Twenty je tento otisk uložen jako `headerMessageId` na objektu Message. Váš pracovní postup jej vezme a předá do pole In-Reply-To akce Odeslat e-mail.
## Sestavení pracovního postupu
### Krok 1: Vytvořte nový pracovní postup
Přejděte do **Nastavení -> Pracovní postupy** a klikněte na **+ Nový pracovní postup**.
### Krok 2: Spouštění při příchozích zprávách
Vyberte **Když je vytvořen záznam** a zvolte **Zprávy**.
Pokaždé, když do Twenty dorazí e-mail, toto se spustí.
<img src="/images/user-guide/workflows/auto-reply/workflow-overview.png" style={{width:'100%'}} />
### Krok 3: Vyhledejte, kdo to poslal
Přidejte akci **Vyhledat záznamy**.
Adresa odesílatele není přímo v samotné zprávě — je v souvisejícím záznamu Message Participant.
| Pole | Hodnota |
| ---------- | ------------------------------ |
| **Objekt** | Účastníci zprávy |
| **Filtr** | Zpráva **je** `{{trigger.id}}` |
| **Filtr** | Role **je** From |
| **Limit** | 1 |
To vám poskytne e-mail odesílatele v `handle` a jeho jméno v `displayName`.
<img src="/images/user-guide/workflows/auto-reply/find-sender.png" style={{width:'100%'}} />
### Krok 4: Triage a návrh odpovědi s UI
Přidejte akci **AI Agent**. Tento jediný krok dělá dvě věci: rozhodne, zda si e-mail zaslouží odpověď, a pokud ano, napíše ji.
Použijte prompt například takto:
```
You are an email triage assistant for a sales team. Read the following
inbound email and decide if it deserves a reply.
Subject: {{trigger.subject}}
Body: {{trigger.text}}
From: {{Find Sender.first.displayName}} ({{Find Sender.first.handle}})
If this email is spam, a newsletter, an automated notification, or
otherwise does not need a human reply, respond with exactly: SKIP
Otherwise, write a short, professional reply (3-4 sentences max) that:
- Acknowledges their specific message
- Lets them know someone from the team will follow up shortly
- Is warm but not overly casual
Respond with only the reply text, no subject line or greeting prefix.
```
AI Agent vypíše svou odpověď do pole `response`, na které mohou navazující kroky odkazovat.
<img src="/images/user-guide/workflows/auto-reply/ai-triage.png" style={{width:'100%'}} />
### Krok 5: Rozvětvěte podle rozhodnutí AI
Přidejte akci **If/Else** k ověření, zda se AI rozhodla odpovědět, nebo přeskočit.
| Pole | Hodnota |
| ------------ | ----------------------------------------- |
| **Podmínka** | AI Agent `response` **neobsahuje** `SKIP` |
| **If true** | Pokračovat na Odeslat e-mail |
| **Else** | Nedělat nic (pracovní postup končí) |
Spam, newslettery a automaticky generované zprávy se zahodí. Vše ostatní přejde do dalšího kroku.
<img src="/images/user-guide/workflows/auto-reply/should-reply.png" style={{width:'100%'}} />
### Krok 6: Odeslat odpověď ve vlákně
Přidejte akci **Odeslat e-mail** ve větvi "if true". Klikněte na **Pokročilé možnosti** a poté na **Přidat In-Reply-To**.
| Pole | Hodnota |
| --------------- | -------------------------------------- |
| **Komu** | `{{Find Sender.first.handle}}` |
| **Předmět** | `Re: {{trigger.subject}}` |
| **Text zprávy** | `{{AI Triage & Draft Reply.response}}` |
| **In-Reply-To** | `{{trigger.headerMessageId}}` |
Pole In-Reply-To je to, co z toho dělá odpověď místo nové konverzace. Příjemce ji uvidí zařazenou pod původní e-mail ve službě Gmail, v Outlooku nebo v jiném klientovi.
<img src="/images/user-guide/workflows/auto-reply/send-email.png" style={{width:'100%'}} />
<Tip>
**In-Reply-To** očekává ze spouštěče `message.headerMessageId` — jde o jedinečný otisk e-mailu, nikoli adresu příjemce. Pokud jej necháte prázdné, e-mail se i tak odešle, jen jako samostatná zpráva.
</Tip>
<Warning>
Gmail používá předmět k seskupování zpráv do vláken. Předmět **musí** začínat `Re:` (včetně dvojtečky a mezery), aby Gmail zobrazil odpověď v rámci původního vlákna. Bez toho se odpověď zobrazí jako samostatná konverzace — i když je hlavička In-Reply-To nastavena správně.
</Warning>
### Krok 7: Otestujte a aktivujte
Klikněte na **Test**, poté zkontrolujte svého e-mailového klienta. Odpověď by se měla zobrazit vnořená pod původní zprávou.
Aktivujte, až s tím budete spokojeni.
## Nápady k rozšíření
* **Odpovídat pouze VIP** — přidejte větev, která zkontroluje doménu odesílatele nebo zda existuje jako Kontakt v Twenty
* **Směrovat podle záměru** — použijte samostatné prompty pro AI Agenta k odlišnému zpracování obchodních dotazů oproti požadavkům na podporu
* **Obohaťte před odpovědí** — přidejte krok Vyhledat záznamy, který do promptu AI načte společnost odesílatele nebo historii obchodů pro osobnější odpovědi

View File

@@ -0,0 +1,179 @@
---
title: Automatizace pro Uzavřeno - Vyhráno
description: Automatizujte činnosti po výhře, když se příležitosti uzavřou.
---
Když se obchod uzavře, je potřeba provést několik věcí: aktualizovat stav společnosti, upozornit členy týmu, vytvořit onboardingové úkoly. Automatizujte to vše jediným pracovním postupem.
## Problém
Když se příležitost přesune do stavu "Uzavřeno - Vyhráno":
* Typ společnosti je třeba změnit z "Zájemce" na "Zákazník"
* Je třeba vytvořit onboardingové úkoly
* Je třeba upozornit tým Customer Success
* Obchodní zástupce potřebuje potvrzení
Dělat to ručně je časově náročné a náchylné k chybám.
## Řešení
Vytvořte pracovní postup, který automaticky zajistí všechny činnosti po výhře.
## Kompletní nastavení pracovního postupu
### Krok 1: Vytvořte pracovní postup
1. Přejděte na **Nastavení → Pracovní postupy**
2. Klikněte na **+ Nový pracovní postup**
3. Pojmenujte jej "Vyhraný obchod - Automatizace po výhře"
### Krok 2: Nakonfigurujte spouštěč
1. Vyberte **Záznam je aktualizován**
2. Vyberte **Příležitosti**
3. V části "Pole ke sledování" vyberte **Stádium**
### Krok 3: Přidejte filtr podle stádia
1. Přidejte akci **Filtr**
2. Podmínka: `{{trigger.object.stage}}` se rovná "Uzavřeno - Vyhráno"
### Krok 4: Aktualizujte typ společnosti
1. Přidejte akci **Aktualizovat záznam**
2. Nakonfigurujte:
| Pole | Hodnota |
| ------------------------- | ------------------------------- |
| **Objekt** | Společnosti |
| **Záznam** | `{{trigger.object.company.id}}` |
| **Typ** | Zákazník |
| **Datum prvního obchodu** | `{{trigger.object.closedAt}}` |
| **Vlastník účtu** | `{{trigger.object.owner.id}}` |
### Krok 5: Vytvořte onboardingový úkol
1. Přidejte akci **Vytvořit záznam**
2. Nakonfigurujte:
| Pole | Hodnota |
| --------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **Objekt** | Úkoly |
| **Název** | `Onboarding: {{trigger.object.name}}` |
| **Přiřazený** | Člen týmu Customer Success |
| **Datum splatnosti** | Za 3 dny |
| **Priorita** | Vysoká |
| **Související společnost** | `{{trigger.object.company.id}}` |
| **Související příležitost** | `{{trigger.object.id}}` |
| **Popis** | `Onboarding nového zákazníka pro {{trigger.object.company.name}}. Hodnota obchodu: {{trigger.object.amount}}` |
### Krok 6: Upozorněte Customer Success
1. Přidejte akci **Odeslat e-mail**
2. Nakonfigurujte:
| Pole | Hodnota |
| --------------- | --------------------------------------------------- |
| **Komu** | customer-success@yourcompany.com |
| **Předmět** | `🎉 Nový zákazník: {{trigger.object.company.name}}` |
| **Text zprávy** | Viz příklad níže |
**Příklad textu e-mailu**:
```
Hi CS Team,
We have a new customer!
Company: {{trigger.object.company.name}}
Deal: {{trigger.object.name}}
Value: {{trigger.object.amount}}
Sales Rep: {{trigger.object.owner.name}}
Close Date: {{trigger.object.closedAt}}
An onboarding task has been created automatically.
Let's give them a great start!
```
### Krok 7: Potvrďte obchodnímu zástupci
1. Přidejte další akci **Odeslat e-mail**
2. Nakonfigurujte:
| Pole | Hodnota |
| --------------- | --------------------------------------------------------------------------------------------------- |
| **Komu** | `{{trigger.object.owner.email}}` |
| **Předmět** | `✅ Obchod uzavřen: {{trigger.object.name}}` |
| **Text zprávy** | Gratulujeme! Váš obchod byl zpracován. Tým Customer Success byl upozorněn a onboarding byl zahájen. |
### Krok 8: Otestujte a aktivujte
1. Otestujte přesunutím testovací příležitosti do stavu "Uzavřeno - Vyhráno"
2. Ověřit:
* Typ společnosti změněn na "Zákazník"
* Onboardingový úkol vytvořen
* Tým Customer Success obdržel e-mail
* Obchodní zástupce obdržel potvrzení
3. Až budete připraveni, aktivujte
## Zpracování Uzavřeno - Prohráno
Vytvořte podobný pracovní postup pro prohrané obchody:
### Spouštěč
* Záznam je aktualizován (Příležitosti, Stádium = "Uzavřeno - Prohráno")
### Akce
1. **Vytvořit záznam**: Úkol pro "Analýzu prohraného obchodu"
2. **Aktualizovat záznam**: Přidat důvod prohry do záznamu společnosti
3. **Odeslat e-mail**: Upozornit manažera na prohraný obchod
## Pokročilé: Vícefázový onboarding
Pro složitější onboarding vytvořte více úkolů:
```javascript
export const main = async (params) => {
const tasks = [
{ title: "Welcome call", daysFromNow: 1, assignee: "CS" },
{ title: "Send onboarding materials", daysFromNow: 2, assignee: "CS" },
{ title: "Technical setup", daysFromNow: 5, assignee: "Support" },
{ title: "30-day check-in", daysFromNow: 30, assignee: "CS" }
];
return { tasks };
};
```
Použijte **Iterator** k vytvoření každého úkolu z pole.
## Nápady na přizpůsobení
### Udržujte své další nástroje aktuální
* Vytvořte zákazníka ve fakturačním systému pomocí **HTTP Request**
### Podmíněná opatření
Použijte akce **Filtr** k:
* Odlišný onboarding pro enterprise vs SMB
* Různé přiřazené osoby podle regionu
* Přeskočit upozornění u malých obchodů
### Zahrnout detaily Deal
Použijte akci **Code** k formátování:
* Dokumenty se souhrnem obchodu
* Poznámky k předání pro tým Customer Success
* Vlastní onboardingové kontrolní seznamy
## Související
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Odesílání e-mailů z pracovních postupů](/l/cs/user-guide/workflows/capabilities/send-emails-from-workflows)

View File

@@ -0,0 +1,136 @@
---
title: Odhalte zastaralé příležitosti
description: Automaticky upozorňujte manažery, když příležitosti nebyly aktualizovány.
---
Udržujte svou obchodní pipeline zdravou tím, že budete upozorňovat manažery, když příležitosti zastarávají. Tento pracovní postup kontroluje příležitosti, které nebyly aktualizovány po zadaný počet dní.
## Problém
Příležitosti bez aktualizací vedou k:
* Obchody chladnou
* Nespolehlivé prognózy
* Ztracené tržby
## Řešení
Vytvořte plánovaný pracovní postup, který najde zastaralé příležitosti a odešle e-mail jejich manažerům.
## Nastavení krok za krokem
### Krok 1: Vytvořte pracovní postup
1. Přejděte na **Nastavení → Pracovní postupy**
2. Klikněte na **+ Nový pracovní postup**
3. Pojmenujte jej "Upozornění na zastaralé příležitosti"
### Krok 2: Nakonfigurujte spouštěč
1. Vyberte **Podle plánu**
2. Nastavte spouštění denně (např. každý den v 8:00)
### Krok 3: Vyhledejte zastaralé příležitosti
1. Přidejte akci **Vyhledat záznamy**
2. Nakonfigurujte:
| Pole | Hodnota |
| ---------- | --------------------------------------------- |
| **Objekt** | Příležitosti |
| **Filtr** | Datum aktualizace je dříve než (dnes - 7 dní) |
| **Filtr** | Fáze není "Closed Won" a není "Closed Lost" |
| **Limit** | 100 |
### Krok 4: Zkontrolujte, zda se něco našlo
1. Přidejte akci **Filtr**
2. Podmínka: `{{searchRecords.length}}` je větší než 0
3. Pokud nejsou žádné zastaralé příležitosti, pracovní postup se zde zastaví
### Krok 5: Naformátujte upozornění (akce Code)
Přidejte akci **Code** pro formátování e-mailu:
```javascript
export const main = async (params) => {
const opportunities = params.opportunities;
// Group opportunities by owner
const byOwner = {};
opportunities.forEach(opp => {
const ownerEmail = opp.owner?.email || 'unassigned';
if (!byOwner[ownerEmail]) {
byOwner[ownerEmail] = [];
}
byOwner[ownerEmail].push({
name: opp.name,
amount: opp.amount,
lastUpdated: opp.updatedAt,
stage: opp.stage
});
});
// Format summary for manager
let summary = "Stale Opportunities Report\n\n";
Object.entries(byOwner).forEach(([owner, opps]) => {
summary += `${owner}: ${opps.length} stale opportunities\n`;
opps.forEach(opp => {
summary += ` - ${opp.name} (${opp.stage})\n`;
});
summary += "\n";
});
return {
summary,
totalCount: opportunities.length
};
};
```
### Krok 6: Odešlete upozornění e-mailem
Přidejte akci **Odeslat e-mail**:
| Pole | Hodnota |
| --------------- | -------------------------------------------------------------------- |
| **Komu** | sales-manager@yourcompany.com |
| **Předmět** | `🚨 {{code.totalCount}} zastaralých příležitostí vyžaduje pozornost` |
| **Text zprávy** | `{{code.summary}}` |
### Krok 7: Otestujte a aktivujte
1. Klikněte na **Test** a spusťte pracovní postup
2. Zkontrolujte, že e-mail obsahuje správné údaje
3. Až budete připraveni, aktivujte
## Možnosti přizpůsobení
### Změňte hranici zastarání
Upravte filtr akce Vyhledat záznamy a změňte ze 7 dnů na vámi preferované období:
* 3 dny pro rychlé prodeje
* 14 dní pro podnikové obchody
* 30 dní pro dlouhé prodejní cykly
### Upozorněte jednotlivé obchodní zástupce
Místo jednoho e-mailu manažerovi použijte **Iterator** k odeslání personalizovaných e-mailů každému zástupci o jeho vlastních zastaralých obchodech.
### Přidejte eskalaci
Vytvořte více pracovních postupů se zvyšující se závažností:
1. Den 7: E-mail zástupci
2. Den 14: E-mail zástupci + manažerovi
3. Den 21: Vytvořte úkol pro manažera k zásahu
### Zahrňte do Slacku
Použijte **HTTP Request** k odeslání na webhook ve Slacku místo e-mailu nebo navíc k e-mailu.
## Související
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Odesílání e-mailů z pracovních postupů](/l/cs/user-guide/workflows/capabilities/send-emails-from-workflows)

View File

@@ -0,0 +1,69 @@
---
title: Zobrazení počtu přijatých e-mailů
description: Vytvořte pracovní postup, který automaticky spočítá a zobrazí počet e-mailů přijatých od každého kontaktu.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<img src="/images/user-guide/workflows/workflow-number-of-emails-received.png" style={{width:'100%'}} />
## Přehled
Tento pracovní postup se spustí pokaždé, když je přijat nový e-mail, a aktualizuje vlastní pole u záznamu osoby celkovým počtem e-mailů od tohoto odesílatele.
## Předpoklady
Než tento pracovní postup nastavíte, vytvořte v objektu **Lidé** vlastní pole:
1. Přejděte do **Nastavení → Datový model → Lidé**
2. Přidejte nové pole **Number**
3. Pojmenujte ho například "Počet e-mailů přijatých od této osoby"
## Nastavení krok za krokem
<VimeoEmbed videoId="1148700336" title="Ukázka videa" />
### Krok 1: Nakonfigurujte spouštěč
1. Přejděte na **Pracovní postupy** a vytvořte nový pracovní postup
2. Vyberte jako spouštěč **Záznam je vytvořen**
3. Zvolte **Účastníci zpráv** (k dispozici v části Pokročilé objekty)
<Note>
Účastník zprávy je kombinace ID zprávy a ID osoby, čímž vzniká jeden jedinečný záznam na zprávu. To je snazší sledovat než přímo Zprávy, protože můžeme přistupovat k poli `handle`, které obsahuje e-mailovou adresu odesílatele (nebo příjemce).
</Note>
### Krok 2: Filtrování podle role
1. Přidejte akci **Filtr**
2. Nastavte podmínku: **Role** se rovná **FROM**
Tím zajistíte, že budete počítat pouze zprávy odeslané touto osobou, nikoli zprávy jí zaslané.
### Krok 3: Vyhledejte všechny účastníky zpráv se stejnou hodnotou handle
1. Přidejte akci **Vyhledat záznamy**
2. Vyberte jako objekt **Účastníci zpráv**
3. Přidejte filtry: **Handle** se rovná hodnotě handle ze spouštěče (e-mailová adresa odesílatele) a **Role** se rovná **FROM**
4. Zvyšte **Limit** z 1 na **200** (maximum)
Tímto najdete všechny zprávy z této e-mailové adresy a získáte celkový počet.
<Note>
Akce Vyhledat záznamy je omezena na vrácení maximálně 200 záznamů. Protože však používáte pouze hodnotu `totalCount` (nikoli jednotlivé záznamy), tento krok vrátí celkový počet e-mailů odeslaných touto osobou.
</Note>
### Krok 4: Aktualizujte záznam osoby pomocí akce Vytvořit nebo aktualizovat záznam
1. Přidejte akci **Vytvořit nebo aktualizovat záznam**
2. Vyberte jako objekt **Lidé**
3. Najděte osobu podle shody jejího e-mailu s hodnotou `handle` z účastníka zprávy
4. Nastavte své vlastní pole "Počet přijatých e-mailů" na hodnotu `{{searchRecords.totalCount}}`
Hodnota `totalCount` z akce Vyhledat záznamy představuje celkový počet e-mailů přijatých od této osoby.
## Související
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Vytvořit vlastní pole](/l/cs/user-guide/data-model/how-tos/customize-your-data-model)
* [Akce Vyhledat záznamy](/l/cs/user-guide/workflows/capabilities/workflow-actions#search-records)

View File

@@ -0,0 +1,170 @@
---
title: Zobrazení dat souvisejících záznamů
description: Zobrazujte data ze souvisejících záznamů (např. informace o společnosti na příležitostech) pomocí pracovních postupů.
---
Zobrazujte data ze souvisejících záznamů přímo na svých záznamech — například zobrazte počet zaměstnanců ze společnosti na jejích příležitostech. Toto řešení pomocí pracovních postupů je užitečné do doby, než budou vnořená pole nativně dostupná.
## Běžné scénáře použití
| Zdroj | Cíl | Pole ke kopírování |
| ----------- | ----------- | ------------------------------------------------------------- |
| Společnost | Příležitost | Odvětví, velikost společnosti, ARR |
| Osoba | Příležitost | E-mail, telefon, pozice |
| Příležitost | Společnost | Částka posledního obchodu, datum posledního vyhraného obchodu |
## Základní kopírování polí
### Příklad: Zkopírovat e-mail kontaktu do příležitosti
**Cíl**: Při nastavení kontaktní osoby u příležitosti zkopírujte její e-mail do příležitosti pro snadný přístup.
### Předpoklad
Vytvořte cílová pole v **Nastavení → Datový model → Příležitosti** před vytvořením pracovního postupu:
* E-mail kontaktu (typ: E-mail)
* Telefon kontaktu (typ: Telefon)
### Nastavení
1. **Spouštěč**: Záznam je aktualizován (Příležitosti, pole Kontaktní osoba)
2. **Filtr**: Zkontrolujte, že pole Kontaktní osoba není prázdné
3. **Vyhledat záznamy**: Najděte propojenou osobu
* Objekt: Lidé
* Filtr: ID se rovná `{{trigger.object.pointOfContact.id}}`
4. **Aktualizovat záznam**:
* Objekt: Příležitosti
* Záznam: `{{trigger.object.id}}`
* E-mail kontaktu: `{{searchRecords[0].email}}`
* Telefon kontaktu: `{{searchRecords[0].phone}}`
## Kopírování více polí
### Příklad: Synchronizace informací o společnosti do všech souvisejících příležitostí
**Cíl**: Když se změní údaje společnosti, aktualizujte všechny související příležitosti.
### Nastavení
1. **Spouštěč**: Záznam je aktualizován (Společnosti)
* Pole: Odvětví, velikost společnosti, roční tržby
2. **Vyhledat záznamy**: Najděte všechny příležitosti pro tuto společnost
* Objekt: Příležitosti
* Filtr: ID společnosti se rovná `{{trigger.object.id}}`
3. **Iterátor**: Procházejte každou příležitost
4. **Aktualizovat záznam** (uvnitř iterátoru):
* Objekt: Příležitosti
* Záznam: `{{iterator.currentItem.id}}`
* Odvětví společnosti: `{{trigger.object.industry}}`
* Velikost společnosti: `{{trigger.object.companySize}}`
* ARR společnosti: `{{trigger.object.annualRevenue}}`
## Kopírování při vytvoření záznamu
### Příklad: Předvyplnit příležitost údaji společnosti
**Cíl**: Při vytváření příležitosti propojené se společností automaticky zkopírujte klíčové informace o společnosti.
### Předpoklad
Vytvořte cílová pole v **Nastavení → Datový model → Příležitosti**:
* Odvětví společnosti (typ: Text)
* Velikost společnosti (typ: Číslo)
### Nastavení
1. **Spouštěč**: Záznam je vytvořen (Příležitosti)
* Filtr: Společnost není prázdná
2. **Vyhledat záznamy**: Získejte podrobnosti propojené společnosti
* Objekt: Společnosti
* Filtr: ID se rovná `{{trigger.object.company.id}}`
3. **Aktualizovat záznam**:
* Objekt: Příležitosti
* Záznam: `{{trigger.object.id}}`
* Odvětví společnosti: `{{searchRecords[0].industry}}`
* Velikost společnosti: `{{searchRecords[0].employees}}`
<Note>
**Omezení pro Úkoly a Poznámky**: Relace u Úkolů a Poznámek jsou napevno nastaveny jako mnoho k mnoha a zatím nejsou k dispozici ve spouštěčích ani akcích pracovních postupů. Pro přístup k těmto relacím použijte místo toho [API](/l/cs/developers/extend/api).
</Note>
## Oboustranná synchronizace
### Příklad: Udržujte primární kontakt v synchronizaci
**Cíl**: Když se změní primární kontakt společnosti, aktualizujte kontakt. Když se osoba stane primárním kontaktem, aktualizujte společnost.
### Pracovní postup 1: Společnost → Osoba
1. **Spouštěč**: Záznam je aktualizován (Společnosti, pole Primární kontakt)
2. **Aktualizovat záznam**: Nastavte u osoby "Is Primary Contact" na hodnotu true
3. **Vyhledat záznamy**: Najděte předchozí primární kontakt
4. **Aktualizovat záznam**: Nastavte u předchozího kontaktu "Is Primary Contact" na hodnotu false
### Pracovní postup 2: Osoba → Společnost
1. **Spouštěč**: Záznam je aktualizován (Lidé, Is Primary Contact = true)
2. **Aktualizovat záznam**: Nastavte u společnosti Primární kontakt na tuto osobu
<Note>
Dávejte pozor u oboustranných synchronizací, abyste se vyhnuli nekonečným smyčkám. Před aktualizací použijte filtry ke kontrole, zda se hodnota skutečně změnila.
</Note>
## Použití kódu pro složité mapování
### Příklad: Transformace dat během kopírování
**Cíl**: Zkopírovat a naformátovat telefonní číslo z osoby do příležitosti.
```javascript
export const main = async (params) => {
const { phone } = params;
if (!phone) return { formattedPhone: null };
// Remove non-numeric characters
const digits = phone.replace(/\D/g, '');
// Format as (XXX) XXX-XXXX
const formatted = digits.length === 10
? `(${digits.slice(0,3)}) ${digits.slice(3,6)}-${digits.slice(6)}`
: phone;
return { formattedPhone: formatted };
};
```
## Osvědčené postupy
### Vyhněte se smyčkám
* Nevytvářejte pracovní postupy, které se navzájem spouštějí donekonečna
* Používejte konkrétní podmínky polí
* Přidejte kontroly, zda se hodnota skutečně změnila
### Zpracování chybějících dat
* Před kopírováním vždy zkontrolujte, zda zdrojový záznam existuje
* Poskytněte výchozí hodnoty pro volitelná pole
* Použijte filtry k vynechání, pokud je zdrojové pole prázdné
### Výkon
* Pro mnoho záznamů používejte dávkové aktualizace při kopírování
* Pro hromadné synchronizační operace použijte plánované pracovní postupy
* Zvažte použití iterátoru pro aktualizace více záznamů
## Související
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Spouštěče pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-triggers)

View File

@@ -0,0 +1,202 @@
---
title: Vzorcová pole
description: Vytvářejte vzorcová pole pomocí pracovních postupů, dokud nebude k dispozici nativní podpora.
---
Dvacet ještě nepodporuje pole s rodilými vzorci (přicházející v roce 2026), ale můžete dosáhnout stejného výsledku pomocí pracovních postupů. Toto dočasné řešení vám umožní automaticky počítat a vyplňovat hodnoty polí — od jednoduchých zřetězení až po složitou obchodní logiku.
## Běžné scénáře použití
| Případ použití | Příklad vzorce |
| ------------------------ | ------------------------------ |
| **Celé jméno** | Křestní jméno + " " + Příjmení |
| **Očekávaná částka** | Částka × Pravděpodobnost |
| **Počet dní do termínu** | Termín splnění - Dnes |
| **Počet dní ve fázi** | Dnes - Datum vstupu do fáze |
| **Skóre leadu** | Body podle více kritérií |
<Tip>
Kompletní příklad sledování času ve fázích kanálu najdete v článku [Jak dlouho zůstávají příležitosti v jednotlivých fázích](/l/cs/user-guide/views-pipelines/how-tos/track-time-in-stage).
</Tip>
## Základní vzorec: Zřetězení
### Příklad: Automatické vyplnění celého jména
**Cíl**: Automaticky spojit křestní jméno a příjmení do pole pro celé jméno.
### Nastavení
1. **Spouštěč**: Záznam je aktualizován nebo vytvořen (Lidé)
2. **Filtr**: Ověřte, že se změnilo křestní jméno nebo příjmení
3. **Akce kódu**:
```javascript
export const main = async (params) => {
const { firstName, lastName } = params;
const fullName = [firstName, lastName]
.filter(Boolean)
.join(' ');
return { fullName };
};
```
4. **Aktualizovat záznam**: Nastavte Celé jméno na `{{code.fullName}}`
## Číselný vzorec: Očekávaná částka
### Příklad: Výpočet očekávaných tržeb
**Cíl**: Vynásobit částku příležitosti pravděpodobností a získat očekávanou částku.
Viz [Jak zobrazit očekávanou částku v kanálu](/l/cs/user-guide/views-pipelines/how-tos/show-expected-amount-in-pipeline) pro kompletní pracovní postup.
### Nastavení
1. **Spouštěč**: Záznam je aktualizován (Příležitosti, pole Částka NEBO Pravděpodobnost)
2. **Akce kódu**:
```javascript
export const main = async (params) => {
const { amount, probability } = params;
const expectedAmount = (amount || 0) * (probability || 0) / 100;
return { expectedAmount };
};
```
3. **Aktualizovat záznam**: Nastavte Očekávanou částku na `{{code.expectedAmount}}`
## Datumový vzorec: Výpočet počtu dní
### Příklad: Počet dní do termínu úkolu
**Cíl**: Spočítat, kolik dní zbývá do termínu úkolu.
### Nastavení
1. **Spouštěč**: Záznam je aktualizován nebo vytvořen (Úkoly, pole Termín)
2. **Akce kódu**:
```javascript
export const main = async (params) => {
const { dueDate } = params;
if (!dueDate) {
return { daysUntilDue: null };
}
const due = new Date(dueDate);
const today = new Date();
const diffTime = due - today;
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
return { daysUntilDue: diffDays };
};
```
3. **Aktualizovat záznam**: Nastavte Počet dní do termínu na `{{code.daysUntilDue}}`
<Note>
Záporné hodnoty označují úkoly po termínu. Toto pole můžete použít k filtrování nebo řazení úkolů podle naléhavosti.
</Note>
## Podmíněný vzorec: Skóre leadu
### Příklad: Výpočet skóre leadu na základě kritérií
**Cíl**: Ohodnotit leady podle velikosti společnosti, odvětví a zapojení.
### Nastavení
1. **Spouštěč**: Záznam je aktualizován (Lidé nebo Společnosti)
2. **Akce kódu**:
```javascript
export const main = async (params) => {
const { companySize, industry, hasEmail, hasPhone, source } = params;
let score = 0;
// Company size scoring
if (companySize === 'Enterprise') score += 30;
else if (companySize === 'Mid-Market') score += 20;
else if (companySize === 'SMB') score += 10;
// Industry scoring
const targetIndustries = ['Technology', 'Finance', 'Healthcare'];
if (targetIndustries.includes(industry)) score += 25;
// Contact info scoring
if (hasEmail) score += 10;
if (hasPhone) score += 15;
// Source scoring
if (source === 'Referral') score += 20;
else if (source === 'Website') score += 10;
return { leadScore: score };
};
```
3. **Aktualizovat záznam**: Nastavte Skóre leadu na `{{code.leadScore}}`
## Textový vzorec: Extrakce domény
### Příklad: Získání domény z e-mailu
**Cíl**: Automaticky získat a uložit doménu e-mailu.
### Nastavení
1. **Spouštěč**: Záznam je aktualizován (Lidé, pole E-mail)
2. **Akce kódu**:
```javascript
export const main = async (params) => {
const { email } = params;
if (!email) return { domain: null };
const domain = email.split('@')[1]?.toLowerCase();
return { domain };
};
```
3. **Aktualizovat záznam**: Nastavte pole Doména na `{{code.domain}}`
## Osvědčené postupy
### Výkon
* Spouštějte pouze při relevantních změnách polí
* Pomocí filtrů přeskočte záznamy, které nevyžadují výpočet
* Vyhněte se složitým výpočtům v pracovních postupech s vysokým objemem
### Zpracování chyb
* Před výpočty kontrolujte hodnoty null/undefined
* Používejte výchozí hodnoty, když data chybí
* Vracejte jasné chybové zprávy, když výpočty selžou
### Testování
* Testujte okrajové případy (prázdná pole, nulové hodnoty)
* Před aktivací ručně ověřte výpočty
* Sledujte běhy pracovních postupů kvůli neočekávaným výsledkům
## Související
* [Jak zobrazit očekávanou částku v kanálu](/l/cs/user-guide/views-pipelines/how-tos/show-expected-amount-in-pipeline)
* [Jak sledovat čas ve fázi](/l/cs/user-guide/views-pipelines/how-tos/track-time-in-stage)
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,127 @@
---
title: Upozorněte kolegy na poznámku ke kontrole
description: Odesílejte automatická e-mailová upozornění při přiřazení kolegy ke kontrole poznámky.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<Note>
**Přímé označování členů týmu v poznámkách zatím není podporováno.** Tato funkce je plánována na druhou polovinu roku 2026. Mezitím tento pracovní postup poskytuje praktické náhradní řešení.
</Note>
## Problém
Chcete v poznámce označit kolegu, aby obdržel upozornění na její kontrolu. V současnosti Twenty nepodporuje @zmínky v poznámkách ani úkolech.
## Náhradní řešení
Místo označování v textu poznámky můžete:
1. Vytvořte relační pole **Reviewer** u objektu Poznámky
2. Při vytváření nebo úpravě poznámky přiřaďte recenzenta
3. Mít pracovní postup automaticky poslat recenzentovi e-mail s odkazem na poznámku
<Warning>
**Omezení**: Tento přístup umožňuje přiřadit na jedno pole pouze jednoho recenzenta. Pokud potřebujete upozornit více osob, vytvořte další relační pole (např. Reviewer 1, Reviewer 2). Toto nebude dobře škálovat, pokud potřebujete najednou označit mnoho spolupracovníků.
</Warning>
## Nastavení krok za krokem
### Krok 1: Vytvořte pole Reviewer
<img src="/images/user-guide/workflows/reviewer-field-for-note.png" style={{width:'100%'}} />
1. Přejděte do **Nastavení → Datový model → Poznámky**
2. Klikněte na **Add Field**
3. Nakonfigurujte:
| Nastavení | Hodnota |
| ---------------------- | ----------------------------------------------- |
| **Name** | Reviewer |
| **Typ** | Vztah |
| **Související objekt** | Člen pracovního prostoru |
| **Typ vztahu** | Mnoho poznámek → Jeden člen pracovního prostoru |
4. Uložte pole
### Krok 2: Vytvořte pracovní postup
<VimeoEmbed videoId="1151897168" title="Ukázka videa" />
#### Vytvořte spouštěč pracovního postupu
1. Přejděte do hlavního zobrazení a vytvořte nový pracovní postup
2. Vyberte jako spouštěč **Record Updated**
3. Jako objekt vyberte **Note** a určete pole Reviewer.
4. Spouštěč se aktivuje kdykoli je u poznámky aktualizován recenzent.
#### Přidejte filtr, který ověří, že byl recenzent právě přiřazen
Přidejte akci **Filtr**, aby pracovní postup pokračoval pouze tehdy, když je přiřazen recenzent:
| Podmínka | Hodnota |
| ------------ | ------------ |
| **Reviewer** | není prázdné |
#### Vyhledejte člena pracovního prostoru
1. Přidejte akci **Vyhledat záznamy**
2. Vyberte **Člen pracovního prostoru** (v části pokročilé objekty)
3. Přidejte filtr:
| Podmínka | Hodnota |
| -------- | ------------------------------ |
| **ID** | se rovná `{{note.reviewerId}}` |
Tím získáte celý záznam člena pracovního prostoru včetně jeho e-mailové adresy a jména.
#### Odešlete upozorňovací e-mail
1. Přidejte akci **Odeslat e-mail**
2. Nakonfigurujte:
| Pole | Hodnota |
| --------------- | --------------------------------------------------- |
| **Komu** | Search Record → First Workspace Member → User Email |
| **Předmět** | Poznámka vyžaduje vaši kontrolu |
| **Text zprávy** | Viz příklad níže |
**Příklad textu e-mailu:**
```text
Hi {{searchRecord.firstWorkspaceMember.name.firstName}},
You've been assigned to review a note.
View the note here:
https://yourSubDomain.twenty.com/object/note/{{recordIsUpdated.id}}
Best,
Twenty
```
<Note>
Nahraďte `yourSubDomain` skutečnou subdoménou vašeho pracovního prostoru Twenty.
</Note>
#### Otestujte a aktivujte
1. Klikněte na **Test** a spusťte pracovní postup ručně
2. Vytvořte nebo upravte poznámku a přiřaďte recenzenta
3. Zkontrolujte doručenou poštu recenzenta, zda dorazil upozorňovací e-mail
4. Aktivujte pracovní postup
## Použití
Po nastavení může váš tým tento pracovní postup používat takto:
1. Vytvořením nové poznámky (nebo úpravou existující)
2. Výběrem kolegy v poli **Reviewer**
3. Kolega automaticky obdrží e-mail s přímým odkazem na poznámku
## Související
* [Spouštěče pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-triggers)
* [Odesílání e-mailů z pracovních postupů](/l/cs/user-guide/workflows/capabilities/send-emails-from-workflows)
* [Vytvořit vlastní pole](/l/cs/user-guide/data-model/how-tos/create-custom-fields)
* [Vytvořit relační pole](/l/cs/user-guide/data-model/how-tos/create-relation-fields)

View File

@@ -0,0 +1,106 @@
---
title: Odesílejte e-mailová upozornění na úkoly s blížícím se termínem
description: Automaticky upozorňujte členy týmu na jejich blížící se nebo zpožděné úkoly.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<img src="/images/user-guide/workflows/email_tasks_due.png" style={{width:'100%'}} />
Posílejte každému členovi týmu denní e-mailová připomenutí na úkoly, které mají termín dnes.
## Přehled
Tento pracovní postup běží podle plánu a:
1. Načte všechny členy pracovního prostoru
2. Projde každého člena
3. Najde jejich úkoly, které mají termín dnes
4. Naformátuje a odešle personalizovaný e-mail
## Nastavení krok za krokem
<VimeoEmbed videoId="1147463514" title="Ukázka videa" />
### Krok 1: Nakonfigurujte spouštěč
1. Přejděte do **Nastavení → Pracovní postupy** a vytvořte nový pracovní postup
2. Vyberte **Podle plánu** jako spouštěč
3. Použijte výraz cron pro denní spuštění v 8:00: `0 8 * * *`
### Krok 2: Vyhledejte všechny členy pracovního prostoru
1. Přidejte akci **Vyhledat záznamy**
2. Vyberte **Členové pracovního prostoru** (v části pokročilé objekty)
3. Filtry nejsou potřeba — toto vrátí všechny členy
### Krok 3: Přidejte iterátor
1. Přidejte akci **Iterator**
2. Nastavte vstupní pole na členy pracovního prostoru z předchozího kroku
3. Všechny akce uvnitř iterátoru se spustí jednou pro každého člena
### Krok 4: Vyhledejte úkoly s termínem dnes (uvnitř iterátoru)
1. Uvnitř iterátoru přidejte akci **Vyhledat záznamy**
2. Vyberte jako objekt **Úkoly**
3. Přidejte filtry:
* **Přiřazený** = aktuální člen pracovního prostoru (z iterátoru)
* **Termín splnění** = dnes
### Krok 5: Naformátujte úkoly do těla e-mailu (uvnitř iterátoru)
Přidejte akci **Code** pro naformátování úkolů do čitelného seznamu s odkazy:
```javascript
export const main = async (params: {
tasksDue?: Array<{ id: string; title: string }> | null | string;
}) => {
const tasksDue =
typeof params.tasksDue === "string"
? JSON.parse(params.tasksDue)
: params.tasksDue;
if (!Array.isArray(tasksDue) || tasksDue.length === 0) {
return {
formattedTasks: "No tasks due today."
};
}
const formattedTasks = tasksDue
.map(
t =>
`${t.title}\nhttps://yourSubDomain.twenty.com/object/task/${t.id}`
)
.join("\n\n");
return { formattedTasks };
};
```
<Note>
Nahraďte `yourSubDomain` skutečnou subdoménou vašeho pracovního prostoru Twenty.
</Note>
### Krok 6: Odešlete e-mail (uvnitř iterátoru)
1. Přidejte akci **Odeslat e-mail** (stále uvnitř iterátoru)
2. Nakonfigurujte:
| Pole | Hodnota |
| --------------- | ----------------------------------------------------------------------- |
| **Komu** | `{{iterator.currentItem.userEmail}}` (e-mail člena pracovního prostoru) |
| **Předmět** | Vaše úkoly s termínem dnes |
| **Text zprávy** | `{{code.formattedTasks}}` |
### Krok 7: Otestujte a aktivujte
1. Klikněte na **Test** a spusťte pracovní postup ručně
2. Zkontrolujte doručenou poštu, zda e-maily dorazily
3. Aktivujte pracovní postup
## Související
* [Akce pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-actions)
* [Odesílání e-mailů z pracovních postupů](/l/cs/user-guide/workflows/capabilities/send-emails-from-workflows)
* [Práce s poli v akcích Code](/l/cs/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,21 @@
---
title: Profesionální služby
description: Získejte profesionální pomoc s vytvářením složitých pracovních toků a automatizací od týmu Twenty a certifikovaných partnerů.
---
## Kdy potřebujete profesionální pomoc?
Zvažte profesionální služby pro:
* Složitá více-systémová integrace
* Pokročilá obchodní logika a pravidla automatizace
* Velkoplošné pracovní postupy pro zpracování dat
* Vývoj vlastních API
* Školení týmu a optimalizace pracovního toku
* Když nemáte interní zdroje
## Možnosti služeb
### Implementační partneři
Spolupracujte s certifikovanými partnery na pokročilých úpravách. Kontaktujte nás na [contact@twenty.com](mailto:contact@twenty.com), abyste se spojili s našimi [implementačními partnery](https://twenty.com/partners).

View File

@@ -0,0 +1,170 @@
---
title: Řešení problémů s workflow
description: Běžné problémy s pracovními postupy a jak je vyřešit.
---
## Běžné problémy a řešení
### Workflow se nespouští
**Příznaky**: Váš pracovní postup se nespustí, když to očekáváte.
**Možné příčiny**:
1. **Pracovní postup není aktivován**: Ujistěte se, že je pracovní postup nastaven na "Active", ne na "Draft"
2. **Podmínky spouštěče nesplněny**: Ověřte, že spouštěč odpovídá očekávané události
3. **Pole není sledováno**: U spouštěčů "Record is Updated" se ujistěte, že je dané pole sledováno
4. **Oprávnění**: Zkontrolujte, že máte oprávnění spouštět pracovní postupy
**Řešení**:
* Ověřte stav pracovního postupu v seznamu pracovních postupů
* Otestujte to konkrétní akcí, u které očekáváte, že jej spustí
* Zkontrolujte konfiguraci spouštěče
* Kontaktujte svého administrátora ohledně oprávnění
### Spouštění pracovního postupu příliš brzy (prázdná pole)
**Příznaky**: Při ručním vytváření záznamu v UI se váš pracovní postup spustí dříve, než máte čas vyplnit všechna pole. Pracovní postup běží převážně s prázdnými hodnotami polí.
**Proč k tomu dochází**: Twenty ukládá vše v reálném čase — neexistuje oddělený režim "edit" vs "read". Když vytvoříte záznam, ihned se uloží, což vyvolá událost "Record is created" dříve, než stihnete vyplnit další pole.
**Kdy se "Record is created" hodí**:
* Záznamy vytvořené přes volání API (pole jsou vyplněna v jednom požadavku)
* Záznamy vytvořené pomocí importu
* Automatické vytváření záznamů z jiných pracovních postupů
**Řešení**: Pro záznamy vytvořené ručně v UI použijte jako spouštěč místo toho **"Record is created or updated"**. Tímto způsobem:
* Pracovní postup se spustí poté, co uživatel dokončí vyplňování polí a jejich uložení
* Získáte kompletní data namísto prázdných hodnot
<Tip>
Pokud chcete, aby se pracovní postup spustil jen jednou na záznam, přidejte akci Filter, která zkontroluje pole jako `createdAt equals updatedAt` (první uložení), nebo použijte vlastní zaškrtávací pole ke sledování, zda už pracovní postup běžel.
</Tip>
### Selhávající akce
**Příznaky**: Pracovní postup běží, ale některé akce selhávají.
**Možné příčiny**:
1. **Chybějící data**: Povinná pole jsou prázdná
2. **Neplatné odkazy**: Proměnné z předchozích kroků neexistují
3. **Chyby API**: Externí služby vracejí chyby
4. **Problémy s oprávněními**: Akce vyžaduje oprávnění, která nemáte
**Řešení**:
* Zkontrolujte podrobnosti běhu pracovního postupu kvůli chybovým zprávám
* Ověřte, že všechna povinná pole mají hodnoty
* Otestujte připojení k API samostatně
* Projděte oprávnění rolí
### Chyby požadavků HTTP
**Příznaky**: Akce HTTP Request selhávají nebo vracejí neočekávané výsledky.
**Běžné chybové kódy**:
* **400**: Neplatný požadavek - zkontrolujte formát těla požadavku
* **401**: Neautorizováno - ověřte klíč API
* **403**: Zakázáno - zkontrolujte oprávnění API
* **404**: Nenalezeno - ověřte URL endpointu
* **429**: Příliš mnoho požadavků - zaveďte omezení četnosti požadavků
* **500**: Chyba serveru - problém v externí službě
**Řešení**:
* Ověřte URL endpointu API
* Zkontrolujte autentizační hlavičky
* Nejprve otestujte volání API mimo Twenty
* Přidejte zpracování chyb v akcích Code
### Chyby akcí Code
**Příznaky**: Kód JavaScriptu se nedaří spustit.
**Běžné problémy**:
1. **Syntaktické chyby**: Překlepy nebo neplatný JavaScript
2. **Nedefinované proměnné**: Odkazování na proměnné, které neexistují
3. **Chyby typů**: Operace na nesprávných datových typech
4. **Vypršení časového limitu**: Kód se spouští příliš dlouho
**Řešení**:
* Použijte vestavěnou validaci editoru kódu
* Nejprve otestujte logiku kódu v konzoli JavaScriptu
* Přidejte výpisy console.log pro ladění
* Zjednodušte složité operace
### E-mail se neodesílá
**Příznaky**: Akce Send Email nedoručuje e-maily.
**Možné příčiny**:
1. **Není připojen e-mailový účet**: Zkontrolujte Nastavení → Účty
2. **Neplatná e-mailová adresa**: E-mail příjemce má neplatný formát
3. **Limity odesílání**: Byly dosaženy limity poskytovatele e-mailu
4. **Spamové filtry**: E-maily jsou blokovány
**Řešení**:
* Ověřte připojení e-mailového účtu
* Ověřte e-mailové adresy příjemců
* Zkontrolujte limity poskytovatele e-mailu
* Zkontrolujte obsah e-mailu kvůli spouštěčům spamu
## Ladění pracovních postupů
### Používání běhů pracovního postupu
1. Přejděte do editoru pracovního postupu
2. Otevřete panel **Runs**
3. Najděte neúspěšný běh
4. Klikněte pro zobrazení podrobných informací krok za krokem
5. Projděte chybové zprávy a výstupní data
### Testování jednotlivých kroků
1. U akcí Code použijte tlačítko **Test**
2. U požadavků HTTP otestujte endpoint samostatně
3. Vytvářejte testovací záznamy pro spuštění pracovních postupů
4. Pro řízené testování použijte manuální spouštěče
### Běžné vzory ladění
**Přidejte logování**:
Použijte akce Code k zaznamenávání mezilehlých hodnot pro ladění.
**Izolujte kroky**:
Testujte každý krok samostatně, abyste identifikovali selhání.
**Zkontrolujte tok dat**:
Ověřte, že každý krok dostává očekávaná vstupní data.
## Osvědčené postupy k předcházení problémům
### Před aktivací
* Důkladně testujte v režimu konceptu
* Ověřte všechna připojení k API
* Pečlivě zkontrolujte podmínky spouštěče
* Zdokumentujte očekávané chování
### Během vývoje
* Používejte výstižné názvy kroků
* Přidejte komentáře v akcích Code
* Testujte s realistickými daty
* Plánujte i okrajové případy
### Po aktivaci
* Pečlivě sledujte počáteční běhy
* Nastavte upozornění na selhání
* Pravidelně procházejte historii běhů
* Udržujte pracovní postupy co nejjednodušší

View File

@@ -0,0 +1,236 @@
---
title: Často kladené otázky k pracovním postupům.
description: Často kladené otázky k pracovním postupům v Twenty.
---
<AccordionGroup>
<Accordion title="Proč nemohu aktivovat pracovní postup?">
Pravděpodobně jde o problém s oprávněními. K vytváření a aktivaci potřebujete přístup k pracovním postupům.
**Řešení**: Kontaktujte správce pracovního prostoru, aby vám v **Settings → Members → Roles** udělil přístup k pracovním postupům.
Pokud v postranním panelu vůbec nevidíte sekci Pracovní postupy, potvrzuje to, že jde o problém s oprávněními.
</Accordion>
<Accordion title="Proč nevidím tlačítko ručního pracovního postupu v horní navigační liště?">
Ruční pracovní postupy se v navigační liště zobrazují jen při správné konfiguraci:
1. Pracovní postup musí být **aktivní** (ne v režimu konceptu)
2. Umístění v navigační liště musí být nastaveno na **Pinned**
3. Pro spouštěče Single/Bulk musíte být na správné stránce objektu
**Jak ověřit**: Otevřete pracovní postup → klikněte na spouštěč → ověřte, že "Navbar placement" je nastaveno na "Pinned".
K ručním pracovním postupům se vždy dostanete přes **Cmd + K** (nebo **Ctrl + K**) bez ohledu na nastavení navigační lišty.
</Accordion>
<Accordion title="Jaký je rozdíl mezi ručními spouštěči Single, Global a Bulk?">
| Typ | Požadované záznamy | Běhy průběhu práce |
| --- | ------------------ | ------------------ |
\| **Global** | Žádné | Jednou, bez vstupu záznamu |
\| **Single** | Jeden nebo více vybraných | Jednou na každý vybraný záznam |
\| **Bulk** | Jeden nebo více vybraných | Jednou, se všemi záznamy jako pole |
* **Global**: Použijte, když pracovní postup nepotřebuje kontext žádného záznamu (např. vygenerování reportu)
* **Single**: Použijte, když chcete zpracovat každý vybraný záznam samostatně (např. poslat jednotlivé e-maily)
* **Bulk**: Použijte, když potřebujete zpracovávat záznamy společně nebo optimalizovat využití kreditů (vyžaduje akci Iterator)
Podrobnosti viz [Spouštěče pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-triggers).
</Accordion>
<Accordion title="Nevidím uzel If/Else. Co mám dělat?">
Explicitní uzel If/Else zatím není dostupný, ale je na naší roadmapě.
**Aktuální řešení**: Vytvořte z kroku více větví, každou začněte akcí **Filter**:
```
Step 1
│
├── Branch A: Filter (condition = true) → Actions...
│
└── Branch B: Filter (condition = false) → Actions...
```
Pouze větev, ve které podmínka filtru projde, provede své následné akce.
Viz [Jak používat větve](/l/cs/user-guide/workflows/capabilities/workflow-branches) pro podrobný návod.
</Accordion>
<Accordion title="Běží větve pracovního postupu paralelně?">
**Ano**, větve ve výchozím nastavení běží paralelně.
Pokud chcete spustit pouze jednu větev:
* Na začátek každé větve přidejte akci **Filter**
* Nastavte opačné podmínky (např. Větev A: status = "Open", Větev B: status ≠ "Open")
Větve, které nesplní podmínku filtru, se zastaví, ostatní pokračují.
</Accordion>
<Accordion title="Mohu větve znovu sloučit dohromady?">
**Ano**. Po dokončení paralelních větví můžete přidat krok, na který se obě větve napojí.
V editoru pracovního postupu:
1. Dokončete akce ve větvích
2. Přidejte nový krok za větve
3. Přetáhněte spojení z konce každé větve do tohoto nového kroku
Sloučený krok se provede po dokončení všech připojených větví.
</Accordion>
<Accordion title="Jaký je limit výsledků akce Search Records?">
**Search Records vrací maximálně 200 záznamů.**
Pokud potřebujete zpracovat více:
* Přidejte konkrétnější filtry pro zmenšení výsledků
* Použijte plánované pracovní postupy ke zpracování po dávkách
* Zvažte použití API pro hromadné operace
Pro většinu pracovních postupů je 200 záznamů dostačující. Pokud na tento limit narážíte pravidelně, zvažte přepracování své automatizace.
</Accordion>
<Accordion title="Mohu přidávat adresáty do kopie (CC) v e-mailech z pracovních postupů?">
**Zatím ne.** Pole CC a BCC pro akci Send Email jsou na naší roadmapě.
**Aktuální řešení**: Přidejte více akcí Send Email pro odeslání dalším příjemcům nebo použijte HTTP Request k odeslání přes externí e-mailovou službu, která podporuje CC.
</Accordion>
<Accordion title="Jak použiji výstupy z předchozích kroků?">
Každá akce vytváří výstupní data, která lze použít v následujících krocích.
**Jak odkazovat na data z předchozích kroků**:
* Při konfiguraci pole použijte výběr proměnné
* Nebo napište přímo `{{stepName.fieldName}}`
**Příklady**:
* Data spouštěče: `{{trigger.object.email}}`
* Výsledky hledání: `{{searchRecords[0].name}}`
* Výstup kódu: `{{code.calculatedValue}}`
Najetím myší na libovolné pole v konfiguraci akce uvidíte dostupné proměnné z předchozích kroků.
</Accordion>
<Accordion title="Proč můj Iterator selhává?">
**Iterator vyžaduje vstup typu pole (array).** Časté problémy:
1. **Vstup není pole (array)**: Ujistěte se, že předáváte výsledky z akce Search Records nebo jiné akce, která vrací pole
2. **Pole je prázdné**: Před Iterator přidejte filtr pro kontrolu `{{searchRecords.length}} > 0`
3. **Zvolená špatná proměnná**: Ujistěte se, že vybíráte samotné pole, ne jeden záznam
**Správné nastavení**:
1. Search Records (vrací pole)
2. Filtr: length > 0
3. Iterator: vyberte `{{searchRecords}}`
4. Akce uvnitř iteratoru používají `{{iterator.currentItem.fieldName}}`
</Accordion>
<Accordion title="Jaký je maximální čas spuštění pro akce Code?">
Akce Code (logické funkce) mají **výchozí časový limit 5 minut** (300 sekund).
Maximální nastavitelný časový limit je **15 minut** (900 sekund).
Pokud váš kód tento limit překročí, akce selže s chybou vypršení časového limitu.
**Tipy, jak se vyhnout vypršení časových limitů**:
* Rozdělte velké operace na menší části pomocí Iteratoru
* Vyhněte se náročným výpočtům; pro intenzivní zpracování použijte externí služby přes HTTP Request
* Optimalizujte svůj kód pro zkrácení doby běhu
* Pokud potřebujete delší zpracování, zvažte použití plánovaných pracovních postupů, které zpracovávají data po dávkách
</Accordion>
<Accordion title="Jak číst spuštění pracovních postupů?">
Spuštění pracovních postupů zobrazují historii provádění a pomáhají s laděním problémů.
**Přístup ke spuštěním**:
* V editoru pracovního postupu → panel **Runs** vpravo
* Nebo přejděte v postranním panelu do **Workflow Runs**
**Porozumění spuštění**:
* **Stav**: Running, Completed, Failed, Waiting
* **Kroky**: Zobrazte, které kroky se provedly, a jejich výstup
* **Chyby**: Klikněte na neúspěšné kroky a zobrazíte chybové zprávy
* **Data**: Zobrazte vstupní/výstupní data v jednotlivých krocích
Podrobnosti viz [Spuštění pracovních postupů](/l/cs/user-guide/workflows/capabilities/workflow-runs).
</Accordion>
<Accordion title="Proč nevidím svá spuštění pracovních postupů?">
Spuštění pracovních postupů mohou selhávat okamžitě kvůli limitům rychlosti. Twenty uplatňuje pevný limit 5 000 spuštění za hodinu na pracovní prostor.
Pokud tento limit překročíte, pracovní postupy jsou okamžitě označeny jako neúspěšné a v seznamu spuštění se nezobrazí.
**Běžné scénáře, které tento limit překročí**:
* Výběr více než 5 000 záznamů pomocí ručního spouštěče Single
* Současné spuštění více pracovních postupů napříč vaším pracovním prostorem
* Časté automatické spouštěče (např. Record Updated na vytíženém objektu)
**Řešení**:
* Použijte spouštěče **Bulk** místo Single pro zpracování mnoha záznamů v jednom spuštění
* Rozložte velké dávkové operace v čase
* Používejte filtry ke snížení frekvence spouštění
* Náročné pracovní postupy plánujte mimo špičku
</Accordion>
<Accordion title="Jaké jsou limity rychlosti pro pracovní postupy?">
Twenty má dva limity rychlosti pro zajištění stability systému:
| Limit | Hodnota | Chování |
| ----- | ------- | ------- |
\| **Soft limit** | 100 spuštění/minuta | Spuštění se zařadí do fronty se stavem "Not Started" a jsou zpracovávána postupně |
\| **Hard limit** | 5 000 spuštění/hodina | Spuštění okamžitě selžou |
**Soft limit (100/min)**: Vaše pracovní postupy neselžou—pouze čekají ve frontě a jsou postupně zpracovávány. Můžete spustit více než 100 záznamů; provádění bude pomalejší.
**Hard limit (5 000/hod)**: Týká se celého vašeho pracovního prostoru. Pokud všechny vaše pracovní postupy dohromady překročí 5 000 spuštění za hodinu, další spuštění okamžitě selžou.
**Tipy, jak zůstat v rámci limitů**:
* Pro velké dávky použijte spouštěče Bulk s Iterator místo spouštěčů Single
* Kombinujte související automatizace do menšího počtu pracovních postupů
* Používejte plánované pracovní postupy k rozložení zátěže v čase
</Accordion>
<Accordion title="Mohu znovu spustit neúspěšné spuštění pracovního postupu?">
**Ne, v tuto chvíli není k dispozici automatická funkce opakování.**
Pokud spuštění pracovního postupu selže, je potřeba:
1. Zkontrolujte chybu v **Settings → Workflows → [Your Workflow] → Runs**
2. Opravte problém (data, konfigurace nebo externí služba)
3. Ručně znovu spusťte pracovní postup u dotčených záznamů
**Tipy, jak snížit počet selhání**:
* Přidejte uzly **Filter** pro ověření dat před akcemi
* Použijte **Search Records** ke kontrole, zda existují související záznamy
* Před hromadnými operacemi důkladně otestujte s několika záznamy
Funkce automatického opakování je v našem plánu pro budoucí vydání.
</Accordion>
<Accordion title="Mám před importy CSV deaktivovat pracovní postupy?">
**Ano, pokud se vaše pracovní postupy spouštějí vytvořením nebo aktualizací záznamu.**
Při importu dat pomocí CSV může každý vytvořený nebo aktualizovaný záznam spustit pracovní postupy. Velký import (tisíce záznamů) může:
* Dosáhnout limitu 5 000 spuštění/hodinu
* Spotřebovat značné množství kreditů pracovních postupů
* Odeslat neočekávané e-maily nebo oznámení
* Vytvořit duplicitní úkoly nebo záznamy
**Před hromadným importem**:
1. Přejděte na **Nastavení → Pracovní postupy**
2. Identifikujte pracovní postupy spouštěné objektem, který importujete
3. **Deaktivujte** je dočasně
4. Spusťte import CSV
5. **Znovu aktivujte** pracovní postupy po dokončení
**Alternativa**: Pokud potřebujete, aby se pracovní postupy spouštěly na importovaných datech, importujte v menších dávkách, abyste zůstali v rámci limitů.
</Accordion>
<Accordion title="Jak vyčistit rozvržení pracovního postupu?">
Pokud vaše plátno pracovního postupu vypadá nepořádně a uzly jsou rozházené, můžete jej automaticky uspořádat:
1. Klikněte pravým tlačítkem kamkoli na plátno pracovního postupu
2. Klikněte na **Tidy up workflow**
Tím se všechny uzly automaticky přeuspořádají do čistého, uspořádaného rozvržení.
</Accordion>
</AccordionGroup>