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 3s

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,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)