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: Code Eylemlerinde Dizileri İşleme
description: İş akışındaki Code eylemlerinde dizi girdilerini doğru şekilde nasıl ele alacağınızı öğrenin.
---
Code eylemlerinde dizilerle çalışırken iki yaygın sorunla karşılaşabilirsiniz:
1. **String olarak iletilen diziler** — harici sistemlerden veya önceki adımlardan gelen veriler gerçek bir dizi yerine string olarak gelir
2. **Tekil öğeleri seçememe** — içindeki belirli alanları değil, yalnızca tüm diziyi seçebilirsiniz
Her ikisi de bir Code düğümüyle çözülebilir.
## Stringlerden Dizileri Ayrıştırma
Diziler, iş akışı adımları arasında sıklıkla yerel diziler yerine string veya JSON olarak iletilir. Şu durumlarda gerçekleşir:
* HTTP Request aracılığıyla harici API'lerden veri alma
* Webhook yüklerini işleme
* İş akışı adımları arasında veri aktarma
**Çözüm**: Bu kalıbı Code eyleminizin başına ekleyin:
```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(),
})),
};
};
```
Önemli satır `typeof users === "string" ? JSON.parse(users) : users` girdinin bir string olup olmadığını kontrol eder, gerekirse ayrıştırır veya zaten bir dizi ise doğrudan kullanır.
## Dizilerden Tekil Alanlar Çıkarma
Bir webhook `answers: [...]` gibi bir dizi döndürebilir, ancak sonraki iş akışı adımlarında içindeki tek tek öğeleri değil — yalnızca tüm diziyi seçebilirsiniz.
**Çözüm**: Belirli alanları çıkarmak ve bunları yapılandırılmış bir nesne olarak döndürmek için bir Code düğümü ekleyin:
```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
}
};
};
```
Code düğümü bir dizi yerine yapılandırılmış bir nesne döndürür. Sonraki adımlarda, değişken seçiciden `answer.firstname` ve `answer.name` gibi tekil alanları artık seçebilirsiniz.
<Tip>
**Dizinin alanlarını çıkarmak yerine dizi üzerinde döngü yapmak mı istiyorsunuz?** Bir Code veya Logic Function adımı en üst düzeyde bir dizi döndürdüğünde, bunu doğrudan bir [Iterator](/l/tr/user-guide/workflows/capabilities/use-iterator) içine verebilirsiniz: Iterator'ın girdisi olarak adımın **Whole list** seçeneğini belirleyin ve ardından döngü içinde her bir öğeye `{{iterator.currentItem}}` ile başvurun. Bu durumda diziyi bir nesneye yeniden yapılandırmanız gerekmez.
</Tip>
<Tip>
Kod düzenleyicisinin sağ üst kısmındaki kare simgeye tıklayarak tam ekranda görüntüleyin — varsayılan düzenleyici genişliği sınırlı olduğundan faydalıdır.
</Tip>

View File

@@ -0,0 +1,182 @@
---
title: Ürün Verilerini Twenty'ye Aktarın
description: Ürün katalog verilerini bir veri ambarından CRM'inize bir programa göre eşitleyin.
---
Veri ambarınızdaki ürün verileriyle Twenty'yi senkron tutmak için bu kalıbı kullanın (örn. Snowflake, BigQuery, PostgreSQL).
## İş Akışı Yapısı
1. **Tetikleyici**: Zamanlanmış
2. **Kod**: Veri ambarınızı sorgulayın
3. **Kod** (isteğe bağlı): Veriyi dizi olarak biçimlendirin
4. **Yineleyici**: Her ürün üzerinde döngü kurun
5. **Kaydı Ekle/Güncelle**: Twenty'de oluşturun veya güncelleyin
<img src="/images/user-guide/workflows/create_users_workflow.png" style={{width:'100%'}} />
## Adım 1: Tetiklemeyi Zamanlayın
İş akışını, veri tazelik gereksinimlerinize uygun bir sıklıkta çalışacak şekilde ayarlayın:
* Neredeyse gerçek zamanlı eşitleme için her 5 dakikada bir
* Daha az kritik veriler için saatte bir
* Toplu güncellemeler için günlük
## Adım 2: Veri Ambarınızı Sorgulayın
En son verileri almak için bir **Kod** eylemi ekleyin:
```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>
`updated_at >= last X minutes` ile filtreleyerek yalnızca yakın zamanda değişen kayıtları alın. Bu, eşitlemeyi verimli tutar.
</Tip>
## Adım 3: Verileri Biçimlendirin (İsteğe Bağlı)
Veri ambarınız dönüştürme gerektiren bir biçimde veri döndürüyorsa, başka bir **Kod** eylemi ekleyin. Yaygın dönüşümler arasında tür dönüştürmeleri, alan yeniden adlandırma ve veri temizleme bulunur.
### Örnek: Boolean ve Durum Alanlarına Sahip Kullanıcı Verileri
```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),
})),
};
};
```
### Örnek: Tür Dönüşümleri Olan Ürün Verileri
```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
}))
};
};
```
### Örnek: Tarih ve Para Birimi Biçimlendirme
```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, " ")
}))
};
};
```
### Yaygın Dönüşümler
| Kaynak Format | Hedef Format | Kod |
| -------------------- | ---------------- | ---------------------------------------- |
| `"true"` / `"false"` | `true` / `false` | `v === true \|\| v === "true"` |
| `"123.45"` | `123.45` | `parseFloat(value)` |
| `"active"` | `"ACTIVE"` | `value.toUpperCase()` |
| `1704067200` (Unix) | ISO tarihi | `new Date(v * 1000).toISOString()` |
| `"$1,234.56"` | `1234.56` | `parseFloat(v.replace(/[^0-9.-]/g, ""))` |
| `null` / `undefined` | `""` | `value \|\| ""` |
## Adım 4: Ürünler Üzerinde Yineleyin
Bir **Iterator** eylemi ekleyin:
* Girdi: `{{code.products}}`
Bu, dizideki her ürün üzerinde döngü kurar.
## Adım 5: Her Kaydı Ekle/Güncelleyin
Yineleyici içinde bir **Kaydı Ekle/Güncelle** eylemi ekleyin:
| Ayar | Değer |
| ---------------------- | ------------------------------------------ |
| **Nesne** | Özel Ürün nesneniz |
| **Şuna göre eşleştir** | Harici ID veya SKU (benzersiz tanımlayıcı) |
| **Ad** | `{{iterator.item.name}}` |
| **SKU** | `{{iterator.item.sku}}` |
| **Fiyat** | `{{iterator.item.price}}` |
<Tip>
Oluşturma ve güncelleme için ayrı dallar oluşturmak yerine **Upsert** (güncelle veya oluştur) kullanın. Oluşturmak daha hızlı ve hata ayıklamak daha kolaydır.
</Tip>
## Örnek Kullanım Durumları
| Kaynak | Veri |
| ----------------------- | ---------------------------------------------- |
| **ERP sistemi** | Ürün kataloğu, fiyatlandırma, envanter |
| **E-ticaret platformu** | Siparişler, müşteriler, ürün güncellemeleri |
| **Veri ambarı** | Toplanmış metrikler, zenginleştirilmiş veriler |
| **Envanter sistemi** | Stok seviyeleri, yeniden sipariş uyarıları |
## İlgili
* [İş Akışı Tetikleyicileri](/l/tr/user-guide/workflows/capabilities/workflow-triggers)
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)
* [Kod Eylemlerinde Dizileri Ele Alma](/l/tr/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,130 @@
---
title: Typeform Yanıtlarını Twenty'ye Aktarın
description: Form yanıtlarından potansiyel müşteriler oluşturmak için Typeform'un webhook yükünü işleyin.
---
Standart webhook kurulumu için bkz. [Bir Webhook Tetikleyicisi Kurun](/l/tr/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). Bu makale, Typeform'un özel yük yapısı için gereken özel işlemeyi kapsar.
### Adım 1: Bir Webhook İş Akışı Oluşturun
1. **Ayarlar → İş Akışları** bölümüne gidin
2. **+ Yeni İş Akışı**'na tıklayın
3. Tetikleyici olarak **Webhook**'u seçin
4. Webhook URL'sini kopyalayın
### Adım 2: Typeform'u Yapılandırın
1. Typeform'da formunuzu açın
2. **Connect → Webhooks** bölümüne gidin
3. Twenty webhook URL'nizi yapıştırın
4. Kaydet
### Adım 3: Typeform Yükünü Anlayın
Typeform iç içe geçmiş bir JSON yapısı gönderir. İşte basitleştirilmiş bir örnek:
```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" }
}
]
}
}
```
Dikkat edilmesi gereken başlıca noktalar:
* Form verileri `form_response` altında iç içe yapıdadır
* **Yanıtlar bir dizi olarak döndürülür**, adlandırılmış alanlar olarak değil
* Her yanıt, referans için alan türünü ve başlığını içerir
### Adım 4: Yanıtlar Dizisinden Alanları Çıkarın
`answers` bir dizi olduğundan, sonraki adımlarda yalnızca tüm diziyi seçebilirsiniz — tek tek alanları değil. Gerekli alanları çıkarmak için bir **Kod** eylemi ekleyin:
```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
}
};
};
```
Sonraki adımlarda, değişken seçiciden `contact.firstName` ve `contact.email` gibi tekil alanları artık seçebilirsiniz.
<Tip>
Kod eylemlerinde dizileri ele alma hakkında daha fazla ayrıntı için bkz. [Kod Eylemlerinde Dizileri Ele Alma](/l/tr/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions).
</Tip>
### Adım 5: Kaydı Oluşturun
**Kayıt Oluştur** eylemini ekleyin:
| Alan | Değer |
| ----------- | ------------------------------------------------------- |
| **Nesne** | İnsanlar |
| **Ad** | `{{code.contact.firstName}}` |
| **Soyadı** | `{{code.contact.lastName}}` |
| **E-posta** | `{{code.contact.email}}` |
| **Şirket** | `{{code.contact.company}}` temelinde ara veya oluşturun |
### Adım 6: Test Edin ve Etkinleştirin
1. Typeform'da bir test yanıtı gönderin
2. Verilerin yakalandığını doğrulamak için iş akışı çalıştırmasını kontrol edin
3. İş akışını etkinleştirin
## İlgili
* [Bir Webhook Tetikleyicisi Kurun](/l/tr/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger)
* [Kod Eylemlerinde Dizileri Ele Alma](/l/tr/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,263 @@
---
title: Twenty'den bir PDF oluşturun
description: Bir kayda PDF (ör. bir teklif) oluşturup eklemek için bir iş akışı oluşturun.
---
Twenty'de PDF'yi otomatik olarak oluşturun veya edinin ve bir kayda ekleyin. Bu, Şirketler, Fırsatlar veya diğer nesnelere bağlı teklif, fatura ya da raporlar oluşturmak için yaygın olarak kullanılır.
## Genel Bakış
Bu iş akışı, kullanıcıların seçilen herhangi bir kayıt için isteğe bağlı olarak PDF oluşturabilmesi için **Manuel Tetikleyici** kullanır. Bir **Mantıksal İşlev** şunları gerçekleştirir:
1. PDF'yi bir URL'den indirme (bir PDF oluşturma hizmetinden)
2. Dosyayı Twenty'ye yükleme
3. Kayda bağlı bir ek oluşturma
## Ön Gereksinimler
İş akışını kurmadan önce:
1. **Bir API Anahtarı oluşturun**: **Ayarlar → API'ler**'e gidin ve yeni bir API anahtarı oluşturun. Mantık İşlevi için bu belirtece ihtiyacınız olacak.
2. **Bir PDF oluşturma hizmeti kurun** (isteğe bağlı): PDF'leri dinamik olarak oluşturmak istiyorsanız (ör. teklifler), PDF'yi oluşturmak ve bir indirme URL'si almak için Carbone, PDFMonkey veya DocuSeal gibi bir hizmet kullanın.
## Adım Adım Kurulum
### Adım 1: Tetikleyiciyi Yapılandırın
1. **İş Akışları**'na gidin ve yeni bir iş akışı oluşturun
2. **Manuel Tetikleyici**'yi seçin
3. PDF'leri eklemek istediğiniz nesneyi seçin (ör. **Company** veya **Opportunity**)
<Tip>
Manuel Tetikleyici ile kullanıcılar, bir kayıt seçildiğinde sağ üstte görünen bir düğmeyi kullanarak bu iş akışını çalıştırıp bir PDF oluşturabilir ve ekleyebilir; bu, PDF oluşturmak ve eklemek için iş akışını çalıştırır.
</Tip>
### Adım 2: Bir Mantıksal İşlev ekleyin
1. Bir **Kod** eylemi (Mantık İşlevi) ekleyin
2. Aşağıdaki kodla yeni bir işlev oluşturun
3. Girdi parametrelerini yapılandırın
#### Girdi Parametreleri
| Parametre | Değer |
| ----------- | ----------------------- |
| `companyId` | `{{trigger.object.id}}` |
<Note>
Farklı bir nesneye (Person, Opportunity vb.) ekliyorsanız, parametreyi buna göre yeniden adlandırın (ör. `personId`, `opportunityId`) ve mantıksal işlevi güncelleyin.
</Note>
#### Mantıksal İşlev Kodu
```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;
};
```
### Adım 3: Kullanım Senaryonuza Göre Özelleştirin
#### Farklı bir nesneye eklemek için
`targetCompanyId` değerini uygun alanla değiştirin:
| Nesne | Alan Adı |
| ---------- | -------------------------- |
| Şirket | `targetCompanyId` |
| Kişi | `targetPersonId` |
| Fırsat | `targetOpportunityId` |
| Özel Nesne | `targetYourCustomObjectId` |
Ek oluşturma mutasyonunda hem işlev parametresini hem de `variables.data` nesnesini güncelleyin.
#### Dinamik bir PDF URL'si kullanmak için
Bir PDF oluşturma hizmeti kullanıyorsanız şunları yapabilirsiniz:
1. Önce PDF'yi oluşturmak için bir HTTP İsteği eylemi yapın
2. Döndürülen PDF URL'sini mantıksal işleve bir parametre olarak iletin
```typescript
export const main = async (
params: { companyId: string; pdfUrl: string; filename: string },
) => {
const { companyId, pdfUrl, filename } = params;
// ... rest of the function
};
```
### Adım 4: Test Edin ve Etkinleştirin
1. İş akışını kaydedin
2. Bir Company kaydına gidin
3. **⋮** menüsüne tıklayın ve iş akışınızı seçin
4. PDF'nin eklendiğini doğrulamak için kayıttaki **Attachments** bölümünü kontrol edin
5. İş akışını etkinleştirin
## PDF Oluşturma Hizmetleriyle Birleştirme
Dinamik teklifler veya faturalar oluşturmak için:
### Örnek: Teklif Oluştur → PDF'yi Ekle
| Adım | Eylem | Amaç |
| ---- | ---------------------------- | ------------------------------------------------ |
| 1 | Manuel Tetikleyici (Company) | Kullanıcı bir kayıtta başlatır |
| 2 | Kayıt Ara | Opportunity veya satır öğesi ayrıntılarını alın |
| 3 | HTTP İsteği | Kayıt verileriyle PDF oluşturma API'sini çağırın |
| 4 | Mantık İşlevi | Oluşturulan PDF'yi indirin ve ekleyin |
### Popüler PDF Oluşturma Hizmetleri
* **Carbone** - Şablon tabanlı belge oluşturma
* **PDFMonkey** - Şablonlardan dinamik PDF oluşturma
* **DocuSeal** - Belge otomasyon platformu
* **Documint** - API-öncelikli belge oluşturma
Her hizmet, bir PDF URL'si döndüren bir API sağlar; ardından bunu Mantık İşlevi'ne iletebilirsiniz.
## Sorun Giderme
| Sorun | Çözüm |
| ------------------------ | -------------------------------------------------------------------------------- |
| "PDF indirilemedi" | PDF URL'sinin erişilebilir olduğunu ve geçerli bir PDF döndürdüğünü kontrol edin |
| "Yükleme başarısız" | API anahtarınızın geçerli olduğunu ve yazma izinlerine sahip olduğunu doğrulayın |
| "Ek oluşturma başarısız" | Nesne kimliği alan adının hedef nesnenizle eşleştiğinden emin olun |
## İlgili
* [İş Akışı Tetikleyicileri](/l/tr/user-guide/workflows/capabilities/workflow-triggers)
* [Mantıksal İşlevler](/l/tr/user-guide/workflows/capabilities/workflow-actions#code)
* [Twenty'den Teklif veya Fatura Oluşturun](/l/tr/user-guide/workflows/how-tos/connect-to-other-tools/generate-quote-or-invoice-from-twenty)

View File

@@ -0,0 +1,144 @@
---
title: Twenty'den Teklif veya Fatura Oluşturun
description: Fırsatlar kapandığında harici araçlarda otomatik olarak faturalar oluşturun.
---
Fırsat verilerini faturalama sisteminize (Stripe, QuickBooks, Xero, vb.) otomatik olarak gönderin bir fırsat kazanıldığında.
## İş Akışı Yapısı
1. **Tetikleme**: Kayıt Güncellendi (Fırsat)
2. **Filtre**: Aşama = Closed Won
3. **Kayıt Ara**: Şirket ayrıntılarını alın
4. **Kod** (isteğe bağlı): Yükü biçimlendirin
5. **HTTP İsteği**: Faturalama sistemine gönderin
## Adım 1: Tetiklemeyi Ayarlayın
1. Yeni bir iş akışı oluşturun
2. **Kayıt Güncellendi** tetikleyicisini seçin
3. Nesne olarak **Fırsat**'ı seçin
## Adım 2: Closed Won için filtreleyin
Yalnızca fırsat kazanıldığında devam etmek için bir **Filtre** eylemi ekleyin:
| Ayar | Değer |
| --------- | -------------------------------- |
| **Alan** | Aşama |
| **Koşul** | Eşittir |
| **Değer** | `CLOSED_WON` (veya aşama adınız) |
<Tip>
Tetikleyici, herhangi bir Fırsat güncellemesinde tetiklenir. Filtre, aşama Closed Won olduğunda iş akışının devam etmesini sağlar.
</Tip>
## Adım 3: Şirket Ayrıntılarını Alın
Fırsat kaydı, fatura için ihtiyaç duyduğunuz tüm Şirket alanlarını içermeyebilir. Bir **Kayıt Ara** eylemi ekleyin:
| Ayar | Değer |
| ---------------------- | --------------------------------------------------- |
| **Nesne** | Şirket |
| **Şuna göre eşleştir** | ID, `{{trigger.object.companyId}}` değerine eşittir |
Bu, fatura adresi, vergi kimliği vb. ile birlikte tam Şirket kaydını getirir.
## Adım 4: Yükü Biçimlendirin (İsteğe Bağlı)
Faturalama sisteminiz belirli bir biçim bekliyorsa bir **Kod** eylemi ekleyin:
```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
}
}
};
};
```
## Adım 5: Faturalama Sistemine Gönderin
Bir **HTTP İsteği** eylemi ekleyin:
| Ayar | Değer |
| ------------- | ------------------------------------------------- |
| **Yöntem** | POST |
| **URL** | Faturalama API uç noktanız |
| **Başlıklar** | `Authorization: Bearer YOUR_API_KEY` |
| **Gövde** | `{{code.invoice}}` veya alanları doğrudan eşleyin |
### Örnek: Stripe Faturası
```
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
```
### Örnek: QuickBooks Faturası
```
POST https://quickbooks.api.intuit.com/v3/company/{realmId}/invoice
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Body: {{code.invoice}}
```
## Tam İş Akışı Özeti
| Adım | Eylem | Amaç |
| ---- | ---------------------------- | --------------------------------------------- |
| 1 | Tetikleme: Kayıt Güncellendi | Herhangi bir Fırsat değiştiğinde tetiklenir |
| 2 | Filtre | Yalnızca Aşama = Closed Won ise devam edin |
| 3 | Kayıt Ara | Faturalama için tam Şirket ayrıntılarını alın |
| 4 | Kod | Faturalama API'si için verileri biçimlendirin |
| 5 | HTTP İsteği | Harici sistemde fatura oluşturun |
## İpuçları
* **Harici kimlikleri saklayın**: API tarafından döndürülen fatura kimliğini bir **Kayıt Güncelle** eylemi kullanarak Fırsat'a geri kaydedin
* **Hata işleme**: HTTP isteği başarısız olursa bir bildirim göndermek için bir dal ekleyin
* **Önce test edin**: Canlıya almadan önce faturalama sisteminizin sandbox/test modunu kullanın
## İlgili
* [Twenty'den bir PDF oluşturun](/l/tr/user-guide/workflows/how-tos/connect-to-other-tools/generate-pdf-from-twenty) — oluşturulan PDF'leri kayıtlara ekleyin
* [İş Akışı Tetikleyicileri](/l/tr/user-guide/workflows/capabilities/workflow-triggers)
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)
* [Kazanıldı Otomasyonları](/l/tr/user-guide/workflows/how-tos/crm-automations/closed-won-automations)

View File

@@ -0,0 +1,170 @@
---
title: Bir Webhook Tetikleyicisi Ayarlayın
description: İş akışlarını tetiklemek için harici hizmetlerden veri alın.
---
Webhook tetikleyicileri, harici hizmetlerin benzersiz bir URL'ye veri göndererek iş akışlarınızı başlatmasına olanak tanır. Formları, üçüncü taraf uygulamaları ve özel entegrasyonları bağlamak için bunları kullanın.
## Webhook'lar Ne Zaman Kullanılır
| Kullanım alanı | Örnek |
| ----------------------------- | -------------------------------------------------------- |
| **Web formları** | İletişim formu gönderimleri potansiyel müşteri oluşturur |
| **Üçüncü taraf uygulamalar** | Stripe ödemesi → müşteri kaydı oluşturur |
| **Özel entegrasyonlar** | Uygulamanız → Twenty otomasyonu |
| **Kod gerektirmeyen araçlar** | Zapier, Make, n8n bağlantıları |
## Adım adım kurulum
### Adım 1: İş akışını oluşturun
1. **Ayarlar → İş Akışları** bölümüne gidin
2. **+ Yeni İş Akışı**'na tıklayın
3. Adlandırın (ör. "Website Form Submission")
### Adım 2: Webhook tetikleyicisini yapılandırın
1. Tetikleyici bloğuna tıklayın
2. **Webhook**'u seçin
3. Şuna benzer benzersiz bir webhook URL'si alacaksınız:
```
https://api.twenty.com/webhooks/workflow/abc123...
```
4. Bu URL'yi kopyalayın—harici hizmetiniz için buna ihtiyacınız olacak
### Adım 3: Beklenen veri yapısını tanımlayın
**POST** istekleri için beklenen gövde yapısını tanımlayın:
1. **Beklenen gövdeyi tanımla**'ya tıklayın
2. Hizmetinizin göndereceğiyle eşleşen örnek bir JSON girin:
```json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"company": "Acme Inc",
"message": "Interested in your product"
}
```
3. **Kaydet**'e tıklayın—bu, sonraki adımlarda kullanabileceğiniz değişkenler oluşturur
### Adım 4: Eylemler ekleyin
Şimdi webhook verisini kullanan eylemler ekleyin:
**Örnek: Bir Kişi kaydı oluşturun**
1. **Kayıt Oluştur** eylemini ekleyin
2. **Kişiler** nesnesini seçin
3. Alanları eşleyin:
| Alan | Değer |
| ------- | ------------------------------------------------------- |
| İsim | `{{trigger.body.firstName}}` |
| Soyadı | `{{trigger.body.lastName}}` |
| E-posta | `{{trigger.body.email}}` |
| Şirket | `{{trigger.body.company}}` temelinde ara veya oluşturun |
### Adım 5: Webhook'u test edin
Etkinleştirmeden önce, webhook'unuzu test edin:
**cURL kullanarak**:
```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"}'
```
**Postman veya benzerini kullanarak**:
1. Webhook URL'nize bir POST isteği oluşturun
2. Content-Type üst bilgisini `application/json` olarak ayarlayın
3. Test JSON gövdenizi ekleyin
4. Gönderin ve iş akışı çalıştırmalarını kontrol edin
### Adım 6: Etkinleştir
Test edildikten sonra, iş akışını yayına almak için **Etkinleştir**'e tıklayın.
## Farklı veri yapılarıyla çalışma
### İç içe veri
Webhook'unuz iç içe veri gönderiyorsa:
```json
{
"contact": {
"name": "John Doe",
"email": "john@example.com"
},
"source": "website"
}
```
Şu şekilde referans verin: `{{trigger.body.contact.email}}`
### Diziler
Veri diziler içeriyorsa:
```json
{
"items": [
{"name": "Product A", "qty": 2},
{"name": "Product B", "qty": 1}
]
}
```
Dizileri nasıl ele alacağınız kullanım durumunuza bağlıdır:
**Bilinmeyen öğe sayısı → Iterator kullanın**
Dizideki her öğeyi işlemeniz gerekiyorsa (ör. her biri için bir kayıt oluşturmak), diziyi ayrıştırmak için bir **Kod** eylemi ekleyin, ardından **Iterator** kullanın:
```javascript
export const main = async (params: { items: any }) => {
const items = typeof params.items === "string"
? JSON.parse(params.items)
: params.items;
return { items };
};
```
Ardından döngü için Iterator kullanın: `{{code.items}}`
**Bilinen/belirli alanlar → Adlandırılmış alanlara ayıklayın**
Dizi, ayrı ayrı erişmek istediğiniz belirli alanlar içeriyorsa (ör. konum 0 her zaman "first name", konum 1 her zaman "last name" ise), bunları ayıklamak için bir **Kod** eylemi ekleyin:
```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
}
};
};
```
Artık sonraki adımlarda `product.name` ve `product.qty` öğelerini ayrı ayrı seçebilirsiniz.
<Tip>
Dizileri ele alma hakkında daha fazla ayrıntı için bkz. [Kod Eylemlerinde Dizileri Ele Alma](/l/tr/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions).
</Tip>
## İlgili
* [İş Akışı Tetikleyicileri](/l/tr/user-guide/workflows/capabilities/workflow-triggers)
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,121 @@
---
title: Gelen E-postalara Otomatik Yanıt
description: Gelen e-postaları önceliklendirmek için Yapay Zeka (YZ) kullanan ve ileti dizisi içinde yanıtları otomatik olarak gönderen bir iş akışı oluşturun.
---
Gelen e-postalara saatler değil, saniyeler içinde yanıt verin. Bu iş akışı, gereksiz iletileri (bültenler, spam, otomatik yanıtlar) ayıklamak ve gerçek iletiler için kişiselleştirilmiş bir yanıt taslağı oluşturmak üzere bir YZ aracısı kullanır. Ardından yapay zekâ, bunu orijinal konuşmadaki ileti dizisinde bir yanıt olarak gönderir.
## E-posta İleti Dizisi Nasıl Çalışır
Her e-posta, göndericinin posta sunucusu tarafından atanan benzersiz bir parmak izi olan gizli bir `Message-ID` üstbilgisi taşır. Bir e-postayı yanıtladığınızda, posta istemciniz o parmak izine referans veren bir `In-Reply-To` başlığı ayarlar. Gmail, Outlook ve diğer tüm istemciler iletileri bu şekilde ileti dizilerine gruplandırır.
Twenty’de, bu parmak izi Message nesnesinde `headerMessageId` olarak saklanır. İş akışınız bunu alır ve E-posta Gönder eyleminin In-Reply-To alanına aktarır.
## İş akışını oluşturma
### Adım 1: Yeni bir İş Akışı oluşturun
**Ayarlar -> İş Akışları** bölümüne gidin ve **+ Yeni İş Akışı**'na tıklayın.
### Adım 2: Gelen iletilerde tetikleyin
**When a Record is Created** seçeneğini seçin ve **Messages**'ı seçin.
Her e-posta Twenty'ye ulaştığında bu tetiklenir.
<img src="/images/user-guide/workflows/auto-reply/workflow-overview.png" style={{width:'100%'}} />
### Adım 3: Kimin gönderdiğini bulun
Bir **Kayıtları Ara** eylemi ekleyin.
Gönderenin adresi iletinin üzerinde değil — ilgili Message Participant kaydında.
| Alan | Değer |
| ---------- | ------------------------------- |
| **Nesne** | Mesaj Katılımcıları |
| **Filtre** | Message **is** `{{trigger.id}}` |
| **Filtre** | Role **is** From |
| **Sınır** | 1 |
Bu, size gönderenin e-posta adresini `handle` içinde ve adını `displayName` içinde verir.
<img src="/images/user-guide/workflows/auto-reply/find-sender.png" style={{width:'100%'}} />
### Adım 4: Yapay zekâ ile triyaj ve yanıt taslağı oluşturma
Bir **AI Agent** eylemi ekleyin. Bu tek adım iki şey yapar: e-postanın yanıtı hak edip etmediğine karar verir ve eğer ediyorsa bir yanıt yazar.
Şuna benzer bir istem kullanın:
```
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, yanıtını sonraki adımların başvurabileceği `response` alanına yazar.
<img src="/images/user-guide/workflows/auto-reply/ai-triage.png" style={{width:'100%'}} />
### Adım 5: Yapay zekâ kararına göre dallandırın
Yapay zekânın yanıtlamaya mı yoksa atlamaya mı karar verdiğini kontrol etmek için bir **If/Else** eylemi ekleyin.
| Alan | Değer |
| ----------- | ----------------------------------------------- |
| **Koşul** | AI Agent `response` **does not contain** `SKIP` |
| **If true** | E-posta Gönder adımına devam edin |
| **Else** | Hiçbir şey yapmayın (iş akışı sona erer) |
Spam, bültenler ve otomatik oluşturulan iletiler atlanır. Diğer her şey bir sonraki adıma geçer.
<img src="/images/user-guide/workflows/auto-reply/should-reply.png" style={{width:'100%'}} />
### Adım 6: İleti dizisine bağlı bir yanıt gönderin
"if true" dalına bir **E-posta Gönder** eylemi ekleyin. **Advanced options**'a tıklayın, ardından **Add In-Reply-To**.
| Alan | Değer |
| --------------- | -------------------------------------- |
| **Kime** | `{{Find Sender.first.handle}}` |
| **Konu** | `Re: {{trigger.subject}}` |
| **Gövde** | `{{AI Triage & Draft Reply.response}}` |
| **In-Reply-To** | `{{trigger.headerMessageId}}` |
In-Reply-To alanı, bunun yeni bir konuşma yerine bir yanıt olmasını sağlar. Alıcı, Gmail, Outlook veya diğer herhangi bir istemcide bunu özgün e-postanın altında dizili olarak görür.
<img src="/images/user-guide/workflows/auto-reply/send-email.png" style={{width:'100%'}} />
<Tip>
**In-Reply-To**, tetikleyiciden bir `message.headerMessageId` bekler — bu bir alıcı adresi değil, e-postanın benzersiz parmak izidir. Bunu boş bırakırsanız e-posta yine de gönderilir, yalnızca bağımsız bir ileti olarak.
</Tip>
<Warning>
Gmail, iletileri diziler halinde gruplamak için konu satırını kullanır. Gmail’in yanıtı özgün dizinin içinde göstermesi için konu mutlaka `Re:` ile başlamalıdır (iki nokta ve boşluk dahil). Bu olmadan, In-Reply-To başlığı doğru ayarlanmış olsa bile yanıt ayrı bir konuşma olarak görünür.
</Warning>
### Adım 7: Test Edin ve Etkinleştirin
**Test**'e basın, ardından e-posta istemcinizi kontrol edin. Yanıt, özgün iletinin altında dizili olarak görünmelidir.
İçinize sindiğinde etkinleştirin.
## Geliştirmek için fikirler
* **Yalnızca VIP'lere yanıt verin** — gönderenin alan adını veya Twenty’de bir Contact olarak bulunup bulunmadığını kontrol eden bir dal ekleyin
* **Niyete göre yönlendirin** — satış sorgularını destek taleplerinden farklı şekilde ele almak için ayrı AI Agent istemleri kullanın
* **Yanıtlamadan önce zenginleştirin** — daha kişiselleştirilmiş yanıtlar için gönderenin şirketini veya anlaşma geçmişini AI istemine çekmek üzere bir Search Records adımı ekleyin

View File

@@ -0,0 +1,179 @@
---
title: Closed Won Otomasyonları
description: Fırsatlar kazanılarak kapandığında kazanım sonrası faaliyetleri otomatikleştirin.
---
Bir anlaşma kapandığında birden çok şeyin olması gerekir: şirket durumunu güncelleyin, ekip üyelerini bilgilendirin, müşteri işe alıştırma görevleri oluşturun. Bunların tümünü tek bir iş akışıyla otomatikleştirin.
## Sorun
Bir fırsat "Closed Won" aşamasına geçtiğinde:
* Şirket türünün "Prospect"'ten "Customer"'a değişmesi gerekir
* Onboarding görevleri oluşturulmalıdır
* Müşteri başarı ekibinin bilgilendirilmesi gerekir
* Satış temsilcisinin onay alması gerekir
Bunu elle yapmak zaman alıcıdır ve hataya açıktır.
## Çözüm
Kazanım sonrası tüm faaliyetleri otomatik olarak yöneten bir iş akışı oluşturun.
## Tam İş Akışı Kurulumu
### Adım 1: İş akışını oluşturun
1. **Ayarlar → İş Akışları** bölümüne gidin
2. **+ Yeni İş Akışı**'na tıklayın
3. Adını "Deal Won - Post-Win Automation" olarak verin
### Adım 2: Tetikleyiciyi yapılandırın
1. **Kayıt Güncellendi**'yi seçin
2. **Fırsatlar**'ı seçin
3. "Fields to monitor" altında, **Stage**'i seçin
### Adım 3: Aşama Filtresi ekleyin
1. **Filtre** eylemi ekleyin
2. Koşul: `{{trigger.object.stage}}` "Closed Won" değerine eşittir
### Adım 4: Şirket Türünü Güncelleyin
1. **Kayıt Güncelle** eylemini ekleyin
2. Alanı Yapılandır:
| Alan | Değer |
| ---------------------- | ------------------------------- |
| **Nesne** | Şirketler |
| **Kayıt** | `{{trigger.object.company.id}}` |
| **Tür** | Müşteri |
| **İlk Anlaşma Tarihi** | `{{trigger.object.closedAt}}` |
| **Hesap Sahibi** | `{{trigger.object.owner.id}}` |
### Adım 5: Onboarding Görevi Oluşturun
1. **Kayıt Oluştur** eylemini ekleyin
2. Alanı Yapılandır:
| Alan | Değer |
| ----------------- | ------------------------------------------------------------------------------------------------------------- |
| **Nesne** | Görevler |
| **Başlık** | `Onboarding: {{trigger.object.name}}` |
| **Atanan kişi** | Müşteri başarı ekibi üyesi |
| **Bitiş Tarihi** | Şu andan itibaren 3 gün |
| **Öncelik** | Yüksek |
| **İlgili Şirket** | `{{trigger.object.company.id}}` |
| **İlgili Fırsat** | `{{trigger.object.id}}` |
| **Açıklama** | `{{trigger.object.company.name}} için yeni müşteri uyumlandırması. Anlaşma değeri: {{trigger.object.amount}}` |
### Adım 6: Müşteri Başarı Ekibini Bilgilendirin
1. **E-posta Gönder** eylemini ekleyin
2. Alanı Yapılandır:
| Alan | Değer |
| --------- | -------------------------------------------------- |
| **Kime** | customer-success@yourcompany.com |
| **Konu** | `🎉 Yeni Müşteri: {{trigger.object.company.name}}` |
| **Gövde** | Aşağıdaki örneğe bakın |
**E-posta gövdesi örneği**:
```
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!
```
### Adım 7: Satış temsilcisine onay gönderin
1. Bir tane daha **E-posta Gönder** eylemi ekleyin
2. Alanı Yapılandır:
| Alan | Değer |
| --------- | --------------------------------------------------------------------------------------------------- |
| **Kime** | `{{trigger.object.owner.email}}` |
| **Konu** | `✅ Anlaşma Kapandı: {{trigger.object.name}}` |
| **Gövde** | Tebrikler! Anlaşmanız işleme alındı. Müşteri başarı ekibi bilgilendirildi ve onboarding başlatıldı. |
### Adım 8: Test Edin ve Etkinleştirin
1. Bir test fırsatını "Closed Won" aşamasına taşıyarak test edin
2. Doğrula:
* Şirket türü "Customer" olarak değiştirildi
* Onboarding görevi oluşturuldu
* CS ekibi e-postayı aldı
* Satış temsilcisi onayı aldı
3. Hazır olduğunuzda etkinleştirin
## Closed Lost'u Yönetme
Kaybedilen anlaşmalar için benzer bir iş akışı oluşturun:
### Tetikleyici
* Kayıt Güncellendi (Fırsatlar, Aşama = "Closed Lost")
### Eylemler
1. **Kayıt Oluştur**: "Lost Deal Analysis" için görev
2. **Kayıt Güncelle**: Şirket kaydına kaybetme nedenini ekleyin
3. **E-posta Gönder**: Kaybedilen anlaşmayı yöneticiye bildirin
## Gelişmiş: Çok Aşamalı Onboarding
Karmaşık onboarding için birden fazla görev oluşturun:
```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 };
};
```
Diziden her bir görevi oluşturmak için **Iterator** kullanın.
## Özelleştirme Fikirleri
### Diğer araçlarınızı güncel tutun
* Faturalama sisteminde bir **HTTP Request** ile müşteri oluşturun
### Koşullu Eylemler
**Filtre** eylemlerini şunlar için kullanın:
* Kurumsal ve KOBİ için farklı onboarding
* Bölgeye göre farklı atanan kişiler
* Küçük anlaşmalar için bildirimleri atlayın
### Anlaşma Ayrıntılarını Dahil Edin
Biçimlendirmek için **Kod** eylemini kullanın:
* Anlaşma özet belgeleri
* CS ekibi için devir notları
* Özel onboarding kontrol listeleri
## İlgili
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)
* [İş Akışlarından E-posta Gönderme](/l/tr/user-guide/workflows/capabilities/send-emails-from-workflows)

View File

@@ -0,0 +1,136 @@
---
title: Durağan Fırsatları Tespit Et
description: Fırsatlar güncellenmediğinde yöneticileri otomatik olarak bilgilendirin.
---
Fırsatlar durağanlaştığında yöneticileri uyararak satış boru hattınızı sağlıklı tutun. Bu iş akışı, belirli sayıda gündür güncellenmeyen fırsatları kontrol eder.
## Sorun
Güncellenmeden bekleyen fırsatlar şunlara yol açar:
* Anlaşmaların soğuması
* Güvenilmez tahminler
* Kaybedilen gelir
## Çözüm
Durağan fırsatları bulan ve yöneticilerine e-posta gönderen zamanlanmış bir iş akışı oluşturun.
## Adım adım kurulum
### Adım 1: İş akışını oluşturun
1. **Ayarlar → İş Akışları** bölümüne gidin
2. **+ Yeni İş Akışı**'na tıklayın
3. Adını "Durağan Fırsat Uyarısı" koyun
### Adım 2: Tetikleyiciyi yapılandırın
1. **Zamanlanmış Olarak** seçin
2. Günlük çalışacak şekilde ayarlayın (ör. her gün saat 08:00'de)
### Adım 3: Durağan Fırsatları Ara
1. **Kayıt Ara** eylemini ekleyin
2. Alanı Yapılandır:
| Alan | Değer |
| ---------- | ------------------------------------------------ |
| **Nesne** | Fırsatlar |
| **Filtre** | Updated At, (bugün - 7 gün) tarihinden önce |
| **Filtre** | Stage, "Closed Won" DEĞİL VE "Closed Lost" DEĞİL |
| **Sınır** | 100 |
### Adım 4: Bulunup Bulunmadığını Kontrol Edin
1. **Filtre** eylemi ekleyin
2. Koşul: `{{searchRecords.length}}` 0'dan büyüktür
3. Durağan fırsat yoksa iş akışı burada durur
### Adım 5: Uyarıyı Biçimlendirin (Kod Eylemi)
E-postayı biçimlendirmek için bir **Kod** eylemi ekleyin:
```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
};
};
```
### Adım 6: Uyarı E-postası Gönderin
**E-posta Gönder** eylemini ekleyin:
| Alan | Değer |
| ---------- | ----------------------------------------------------------- |
| **Kime** | sales-manager@yourcompany.com |
| **Konu** | `🚨 {{code.totalCount}} Stale Opportunities Need Attention` |
| **İçerik** | `{{code.summary}}` |
### Adım 7: Test Edin ve Etkinleştirin
1. İş akışını çalıştırmak için **Test**'e tıklayın
2. E-postanın doğru verileri içerdiğini kontrol edin
3. Hazır olduğunuzda etkinleştirin
## Özelleştirme Seçenekleri
### Durağanlık Eşiğini Değiştirin
7 günü tercih ettiğiniz süreyle değiştirmek için Kayıt Ara filtresini düzenleyin:
* Hızlı tempolu satışlar için 3 gün
* Kurumsal anlaşmalar için 14 gün
* Uzun satış döngüleri için 30 gün
### Bireysel Temsilcileri Uyarın
Tek bir yönetici e-postası yerine, her temsilciye kendi durağan anlaşmaları hakkında kişiselleştirilmiş e-postalar göndermek için **Iterator** kullanın.
### Eskalasyon Ekle
Artan ciddiyette birden fazla iş akışı oluşturun:
1. Gün 7: Temsilciye e-posta
2. Gün 14: Temsilciye + yöneticiye e-posta
3. Gün 21: Müdahale etmesi için yöneticiye görev oluşturun
### Slack'e Dahil Edin
E-postaya ek olarak veya yerine, bir Slack webhook'una gönderi yapmak için **HTTP Request** kullanın.
## İlgili
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)
* [İş Akışlarından E-posta Gönderme](/l/tr/user-guide/workflows/capabilities/send-emails-from-workflows)

View File

@@ -0,0 +1,69 @@
---
title: Alınan E-posta Sayısını Görüntüle
description: Her bir kişiden alınan e-posta sayısını otomatik olarak sayıp görüntülemek için bir iş akışı oluşturun.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<img src="/images/user-guide/workflows/workflow-number-of-emails-received.png" style={{width:'100%'}} />
## Genel Bakış
Bu iş akışı, her yeni e-posta alındığında tetiklenir ve Kişi kaydındaki özel bir alanı, bu gönderenin e-postalarının toplam sayısıyla günceller.
## Ön Gereksinimler
Bu iş akışını kurmadan önce, **Kişiler** nesnesinde özel bir alan oluşturun:
1. **Ayarlar → Veri Modeli → Kişiler** bölümüne gidin
2. Yeni bir **Sayı** alanı ekleyin
3. Adını "Bu kişiden alınan e-posta sayısı" gibi koyun
## Adım Adım Kurulum
<VimeoEmbed videoId="1148700336" title="Video gösterimi" />
### Adım 1: Tetikleyiciyi Yapılandırın
1. **İş Akışları**'na gidin ve yeni bir iş akışı oluşturun
2. Tetikleyici olarak **Kayıt Oluşturuldu**'yu seçin
3. **Mesaj Katılımcıları**'nı seçin (Gelişmiş nesneler altında kullanılabilir)
<Note>
Bir Mesaj Katılımcısı, bir mesaj kimliği ile bir kişi kimliğinin birleşimidir ve mesaj başına tekil bir kayıt oluşturur. Bu, Mesajları doğrudan izlemekten daha kolaydır çünkü gönderenin (veya alıcının) e-posta adresini içeren `handle` alanına erişebiliriz.
</Note>
### Adım 2: Role göre filtreleyin
1. **Filtre** eylemi ekleyin
2. Koşulu ayarlayın: **Rol** **FROM**'a eşittir
Bu, yalnızca bu kişi tarafından gönderilen mesajları saymanızı ve onlara gönderilen mesajları saymamanızı sağlar.
### Adım 3: Aynı handle'a sahip tüm Mesaj Katılımcılarını arayın
1. Bir **Kayıtları Ara** eylemi ekleyin
2. Nesne olarak **Mesaj Katılımcıları**'nı seçin
3. Filtreler ekleyin: **Handle**, tetikleyicideki handle'a (gönderenin e-posta adresi) eşittir ve **Rol** **FROM**'a eşittir
4. **Limit** değerini 1'den **200**'e (maksimum) yükseltin
Bu, toplam sayıyı elde etmek için bu e-posta adresinden gelen tüm mesajları bulur.
<Note>
Kayıtları Ara eylemi en fazla 200 kayıt döndürmekle sınırlıdır. Ancak, yalnızca `totalCount` değerini (tek tek kayıtları değil) kullandığınız için bu adım, bu kişi tarafından gönderilen e-postaların toplam sayısını döndürecektir.
</Note>
### Adım 4: Kayıt Oluştur veya Güncelle eylemiyle Kişi kaydını güncelleyin
1. Bir **Kayıt Oluştur veya Güncelle** eylemi ekleyin
2. Nesne olarak **Kişiler**'i seçin
3. E-postasını Mesaj Katılımcısı'ndaki `handle` ile eşleştirerek kişiyi bulun.
4. Özel "Alınan e-posta sayısı" alanınızı `{{searchRecords.totalCount}}` olarak ayarlayın
Kayıtları Ara eyleminden gelen `totalCount` değeri, bu kişiden alınan e-postaların toplam sayısını ifade eder.
## İlgili
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)
* [Özel Alanlar Oluşturma](/l/tr/user-guide/data-model/how-tos/customize-your-data-model)
* [Kayıtları Ara Eylemi](/l/tr/user-guide/workflows/capabilities/workflow-actions#search-records)

View File

@@ -0,0 +1,170 @@
---
title: İlişkili Kayıt Verilerini Görüntüle
description: İş akışlarını kullanarak ilişkili kayıtlardaki verileri gösterin (ör. Fırsatlarda Şirket bilgileri).
---
İlişkili kayıtlardaki verileri doğrudan kendi kayıtlarınızda görüntüleyin — örneğin, bir Şirketin çalışan sayısını o Şirketin Fırsatlarında gösterin. İç içe alanlar yerel olarak kullanılabilir olana kadar bu iş akışı geçici çözümü faydalıdır.
## Ortak Kullanım Durumları
| Kaynak | Hedef | Kopyalanacak Alanlar |
| ------ | ------ | -------------------------------------- |
| Şirket | Fırsat | Sektör, Şirket Büyüklüğü, ARR |
| Kişi | Fırsat | E-posta, Telefon, Unvan |
| Fırsat | Şirket | Son Anlaşma Tutarı, Son Kazanma Tarihi |
## Temel Alan Kopyalama
### Örnek: İrtibat Kişisinin E-postasını Fırsata Kopyalama
**Hedef**: Bir fırsatta İletişim Noktası belirlerken, kolay erişim için e-postasını fırsata kopyalayın.
### Ön Gereksinim
İş akışını oluşturmadan önce **Ayarlar → Veri Modeli → Fırsatlar** içinde hedef alanları oluşturun:
* İrtibat E-postası (türü: E-posta)
* İrtibat Telefonu (türü: Telefon)
### Kurulum
1. **Tetikleyici**: Kayıt Güncellenir (Fırsatlar, İletişim Noktası alanı)
2. **Filtre**: İletişim Noktasının boş olmadığını kontrol edin
3. **Kayıtları Ara**: Bağlantılı kişiyi bulun
* Nesne: Kişiler
* Filtre: ID `{{trigger.object.pointOfContact.id}}` değerine eşittir
4. **Kayıt Güncelle**:
* Nesne: Fırsatlar
* Kayıt: `{{trigger.object.id}}`
* İrtibat E-postası: `{{searchRecords[0].email}}`
* İrtibat Telefonu: `{{searchRecords[0].phone}}`
## Birden Fazla Alanı Kopyalama
### Örnek: Şirket Bilgilerini Tüm İlişkili Fırsatlarla Senkronize Edin
**Hedef**: Şirket detayları değiştiğinde tüm ilişkili fırsatları güncelleyin.
### Kurulum
1. **Tetikleyici**: Kayıt Güncellenir (Şirketler)
* Alanlar: Sektör, Şirket Büyüklüğü, Yıllık Gelir
2. **Kayıtları Ara**: Bu şirket için tüm fırsatları bulun
* Nesne: Fırsatlar
* Filtre: Şirket ID'si `{{trigger.object.id}}` değerine eşittir
3. **Yineleyici**: Her fırsat üzerinde döngü kurun
4. **Kayıt Güncelle** (yineleyici içinde):
* Nesne: Fırsatlar
* Kayıt: `{{iterator.currentItem.id}}`
* Şirket Sektörü: `{{trigger.object.industry}}`
* Şirket Büyüklüğü: `{{trigger.object.companySize}}`
* Şirket ARR: `{{trigger.object.annualRevenue}}`
## Kayıt Oluşturma Sırasında Kopyalama
### Örnek: Fırsatı Şirket Verileriyle Önceden Doldurma
**Hedef**: Bir şirkete bağlı bir fırsat oluştururken, temel şirket bilgilerini otomatik olarak kopyalayın.
### Ön Gereksinim
Hedef alanları **Ayarlar → Veri Modeli → Fırsatlar** içinde oluşturun:
* Şirket Sektörü (türü: Metin)
* Şirket Büyüklüğü (türü: Sayı)
### Kurulum
1. **Tetikleyici**: Kayıt Oluşturulur (Fırsatlar)
* Filtre: Şirket boş değil
2. **Kayıtları Ara**: Bağlantılı şirketin detaylarını alın
* Nesne: Şirketler
* Filtre: ID `{{trigger.object.company.id}}` değerine eşittir
3. **Kayıt Güncelle**:
* Nesne: Fırsatlar
* Kayıt: `{{trigger.object.id}}`
* Şirket Sektörü: `{{searchRecords[0].industry}}`
* Şirket Büyüklüğü: `{{searchRecords[0].employees}}`
<Note>
**Görevler ve Notlar sınırlaması**: Görevler ve Notlar üzerindeki ilişkiler çoktan çoğa olarak sabit kodlanmıştır ve henüz iş akışı tetikleyicileri veya eylemlerinde mevcut değildir. Bu ilişkilere erişmek için bunun yerine [API](/l/tr/developers/extend/api) kullanın.
</Note>
## Çift Yönlü Senkronizasyon
### Örnek: Birincil İrtibatı Senkron Tutun
**Hedef**: Bir şirketin birincil irtibatı değiştiğinde, ilgili kişiyi güncelleyin. Bir kişi birincil olduğunda, şirketi güncelleyin.
### İş Akışı 1: Şirket → Kişi
1. **Tetikleyici**: Kayıt Güncellenir (Şirketler, Birincil İrtibat alanı)
2. **Kayıt Güncelle**: Kişinin "Birincil İrtibat mı" alanını true yapın
3. **Kayıtları Ara**: Önceki birincil irtibatı bulun
4. **Kayıt Güncelle**: Önceki irtibatın "Birincil İrtibat mı" alanını false yapın
### İş Akışı 2: Kişi → Şirket
1. **Tetikleyici**: Kayıt Güncellenir (Kişiler, Birincil İrtibat mı = true)
2. **Kayıt Güncelle**: Şirketin Birincil İrtibatını bu kişi olarak ayarlayın
<Note>
Sonsuz döngülerden kaçınmak için çift yönlü senkronizasyonlarda dikkatli olun. Güncellemeden önce değerin gerçekten değişip değişmediğini kontrol etmek için filtreler kullanın.
</Note>
## Karmaşık Eşleştirme için Kod Kullanma
### Örnek: Kopyalama Sırasında Verileri Dönüştürme
**Hedef**: Kişiden fırsata telefon numarasını kopyalayın ve biçimlendirin.
```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 };
};
```
## En İyi Uygulamalar
### Döngülerden Kaçının
* Birbirini sonsuza dek tetikleyen iş akışları oluşturmayın
* Belirli alan koşulları kullanın
* Değerin gerçekten değişip değişmediğini görmek için kontroller ekleyin
### Eksik Verileri Ele Alma
* Kopyalamadan önce kaynak kaydın var olup olmadığını daima kontrol edin
* İsteğe bağlı alanlar için varsayılan değerler sağlayın
* Kaynak alan boş olduğunda atlamak için filtreler kullanın
### Performans
* Birçok kayda kopyalama yaparken toplu güncellemeler kullanın
* Toplu senkronizasyon işlemleri için zamanlanmış iş akışları kullanın
* Birden fazla kayıt güncellemesi için Yineleyici kullanmayı değerlendirin
## İlgili
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)
* [İş Akışı Tetikleyicileri](/l/tr/user-guide/workflows/capabilities/workflow-triggers)

View File

@@ -0,0 +1,202 @@
---
title: Formül Alanları
description: Yerel destek sunulana kadar iş akışlarını kullanarak formül alanları oluşturun.
---
Twenty henüz yerel formül alanlarını desteklemiyor (2026'da geliyor), ancak aynı sonuca iş akışlarını kullanarak ulaşabilirsiniz. Bu geçici çözüm, basit birleştirmelerden karmaşık iş mantığına kadar alan değerlerini otomatik olarak hesaplayıp doldurmanızı sağlar.
## Ortak Kullanım Durumları
| Kullanım Senaryosu | Formül Örneği |
| ------------------------ | --------------------------------- |
| **Ad Soyad** | First Name + " " + Last Name |
| **Beklenen tutar** | Amount × Probability |
| **Son tarihe kalan gün** | Due Date - Today |
| **Aşamadaki gün sayısı** | Today - Stage Entry Date |
| **Lead skoru** | Birden çok kritere dayalı puanlar |
<Tip>
Boru hattı aşamalarında zamanı izlemeye dair eksiksiz bir örnek için bkz. [Fırsatların Her Aşamada Ne Kadar Kaldığını İzleme](/l/tr/user-guide/views-pipelines/how-tos/track-time-in-stage).
</Tip>
## Temel Formül: Birleştirme
### Örnek: Ad Soyad'ı Otomatik Doldur
**Amaç**: Ad ve soyadı otomatik olarak bir Ad Soyad alanında birleştirmek.
### Kurulum
1. **Tetikleyici**: Kayıt Güncellenir veya Oluşturulur (Kişiler)
2. **Filtre**: Adın veya soyadın değişip değişmediğini kontrol edin
3. **Kod eylemi**:
```javascript
export const main = async (params) => {
const { firstName, lastName } = params;
const fullName = [firstName, lastName]
.filter(Boolean)
.join(' ');
return { fullName };
};
```
4. **Kaydı Güncelle**: Ad Soyad'ı `{{code.fullName}}` olarak ayarla
## Sayısal Formül: Beklenen Tutar
### Örnek: Beklenen Geliri Hesapla
**Amaç**: Beklenen tutarı elde etmek için fırsat tutarını olasılıkla çarpın.
Tam iş akışı için [Boru Hattında Beklenen Tutar Nasıl Gösterilir](/l/tr/user-guide/views-pipelines/how-tos/show-expected-amount-in-pipeline) bölümüne bakın.
### Kurulum
1. **Tetikleyici**: Kayıt Güncellenir (Fırsatlar, Tutar VEYA Olasılık alanı)
2. **Kod eylemi**:
```javascript
export const main = async (params) => {
const { amount, probability } = params;
const expectedAmount = (amount || 0) * (probability || 0) / 100;
return { expectedAmount };
};
```
3. **Kaydı Güncelle**: Beklenen Tutar'ı `{{code.expectedAmount}}` olarak ayarla
## Tarih Formülü: Gün Hesaplaması
### Örnek: Görevin Son Tarihine Kalan Gün Sayısı
**Amaç**: Bir görevin son tarihine kaç gün kaldığını hesaplamak.
### Kurulum
1. **Tetikleyici**: Kayıt Güncellenir veya Oluşturulur (Görevler, Son Tarih alanı)
2. **Kod eylemi**:
```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. **Kaydı Güncelle**: Son Tarihe Kalan Gün'ü `{{code.daysUntilDue}}` olarak ayarla
<Note>
Negatif değerler, vadesi geçmiş görevleri belirtir. Bu alanı, görevleri aciliyetine göre filtrelemek veya sıralamak için kullanabilirsiniz.
</Note>
## Koşullu Formül: Lead Skoru
### Örnek: Kriterlere Göre Lead Skoru Hesapla
**Amaç**: Şirket büyüklüğü, sektör ve etkileşime göre lead'leri puanlamak.
### Kurulum
1. **Tetikleyici**: Kayıt Güncellenir (Kişiler veya Şirketler)
2. **Kod eylemi**:
```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. **Kaydı Güncelle**: Lead Skorunu `{{code.leadScore}}` olarak ayarla
## Metin Formülü: Alan Adı Çıkarma
### Örnek: E-postadan Alan Adı Çıkar
**Amaç**: E-posta alan adını otomatik olarak çıkarmak ve saklamak.
### Kurulum
1. **Tetikleyici**: Kayıt Güncellenir (Kişiler, E-posta alanı)
2. **Kod eylemi**:
```javascript
export const main = async (params) => {
const { email } = params;
if (!email) return { domain: null };
const domain = email.split('@')[1]?.toLowerCase();
return { domain };
};
```
3. **Kaydı Güncelle**: Alan Adı alanını `{{code.domain}}` olarak ayarla
## En İyi Uygulamalar
### Performans
* Yalnızca ilgili alan değişikliklerinde tetikleyin
* Hesaplama gerektirmeyen kayıtları atlamak için filtreler kullanın
* Yüksek hacimli iş akışlarında karmaşık hesaplamalardan kaçının
### Hata Yönetimi
* Hesaplamalardan önce null/undefined değerleri kontrol edin
* Veri eksikse varsayılan değerleri kullanın
* Hesaplamalar başarısız olduğunda açık hata mesajları döndürün
### Test
* Sınır durumlarıyla test edin (boş alanlar, sıfır değerler)
* Etkinleştirmeden önce hesaplamaları manuel olarak doğrulayın
* Beklenmeyen sonuçlar için iş akışı çalıştırmalarını izleyin
## İlgili
* [Boru Hattında Beklenen Tutar Nasıl Gösterilir](/l/tr/user-guide/views-pipelines/how-tos/show-expected-amount-in-pipeline)
* [Aşamadaki Süre Nasıl İzlenir](/l/tr/user-guide/views-pipelines/how-tos/track-time-in-stage)
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,127 @@
---
title: Gözden Geçirilecek Bir Not Hakkında Ekip Arkadaşlarını Bilgilendirin
description: Bir notu gözden geçirmesi için bir meslektaş atadığınızda otomatik e-posta bildirimleri gönderin.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<Note>
**Notların içinde ekip arkadaşlarını doğrudan etiketleme henüz desteklenmiyor.** Bu özellik 2026'nın ikinci yarısı için planlanmıştır. Bu arada, bu iş akışı pratik bir geçici çözüm sunar.
</Note>
## Zorluk
Bir notta bir meslektaşınızı etiketleyerek gözden geçirmesi için bildirim almasını istiyorsunuz. Bugün itibarıyla, Twenty notlarda veya görevlerde @bahsetmeleri desteklemiyor.
## Geçici Çözüm
Not metni içinde etiketlemek yerine şunları yapabilirsiniz:
1. Notlar nesnesinde bir **Gözden Geçiren** ilişki alanı oluşturun
2. Notu oluştururken veya düzenlerken gözden geçiren kişiyi atayın
3. Bir iş akışının, notun bağlantısını içeren bir e-postayı gözden geçirene otomatik olarak göndermesini sağlayın
<Warning>
**Sınırlama**: Bu yaklaşım, alan başına bir gözden geçiren atanmasına izin verir. Birden fazla kişiyi bilgilendirmeniz gerekiyorsa, ek ilişki alanları oluşturun (ör. Gözden Geçiren 1, Gözden Geçiren 2). Bu yöntem, aynı anda birçok işbirlikçiyi etiketlemeniz gerekirse iyi ölçeklenmez.
</Warning>
## Adım adım kurulum
### Adım 1: Gözden Geçiren Alanını Oluşturun
<img src="/images/user-guide/workflows/reviewer-field-for-note.png" style={{width:'100%'}} />
1. **Ayarlar → Veri Modeli → Notlar** bölümüne gidin
2. **Alan Ekle**'ye tıklayın
3. Alanı Yapılandır:
| Ayar | Değer |
| ------------------ | ------------------------------------ |
| **Ad** | Gözden Geçiren |
| **Tür** | İlişki |
| **İlişkili Nesne** | Çalışma Alanı Üyesi |
| **İlişki Türü** | Birçok Not → Bir Çalışma Alanı Üyesi |
4. Alanı kaydedin
### Adım 2: İş akışını oluşturun
<VimeoEmbed videoId="1151897168" title="Video gösterimi" />
#### İş Akışı Tetikleyicisini Oluşturun
1. Ana görünüme gidin ve yeni bir iş akışı oluşturun
2. Tetikleyici olarak **Kayıt Güncellendi**'yi seçin
3. Nesne olarak **Not**'u seçin ve Gözden Geçiren alanını belirtin.
4. Bu, bir notun gözden geçireni güncellendiğinde tetiklenecektir.
#### Gözden Geçirenin Az Önce Atandığını Kontrol Etmek İçin Bir Filtre Ekleyin
İş akışının yalnızca bir gözden geçiren atandığında devam etmesini sağlamak için bir **Filtre** eylemi ekleyin:
| Koşul | Değer |
| ------------------ | --------- |
| **Gözden Geçiren** | boş değil |
#### Çalışma Alanı Üyesini Arayın
1. Bir **Kayıtları Ara** eylemi ekleyin
2. (Gelişmiş Nesneler altında) **Çalışma Alanı Üyesi**'ni seçin
3. Bir filtre ekleyin:
| Koşul | Değer |
| ------ | ----------------------------- |
| **ID** | eşittir `{{note.reviewerId}}` |
Bu, e-posta adresi ve adı dahil olmak üzere çalışma alanı üyesinin tam kaydını getirir.
#### Bildirim E-postasını Gönderin
1. **E-posta Gönder** eylemi ekleyin
2. Alanı Yapılandır:
| Alan | Değer |
| ---------- | --------------------------------------------------------- |
| **Kime** | Kayıt Ara → İlk Çalışma Alanı Üyesi → Kullanıcı E-postası |
| **Konu** | Bir not gözden geçirmenizi bekliyor |
| **İçerik** | Aşağıdaki örneğe bakın |
**E-posta gövdesi örneği:**
```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>
`yourSubDomain` değerini, gerçek Twenty çalışma alanı alt alan adınızla değiştirin.
</Note>
#### Test Edin ve Etkinleştirin
1. İş akışını manuel olarak çalıştırmak için **Test**'e tıklayın
2. Bir not oluşturun veya düzenleyin ve bir gözden geçiren atayın
3. Bildirim e-postası için gözden geçirenin gelen kutusunu kontrol edin
4. İş akışını etkinleştirin
## Kullanım
Kurulum tamamlandıktan sonra ekibiniz bu iş akışını şu şekilde kullanabilir:
1. Yeni bir not oluşturarak (veya mevcut bir notu düzenleyerek)
2. **Gözden Geçiren** alanında bir meslektaş seçerek
3. Meslektaş, nota doğrudan bağlantı içeren bir e-postayı otomatik olarak alır
## İlgili
* [İş Akışı Tetikleyicileri](/l/tr/user-guide/workflows/capabilities/workflow-triggers)
* [İş Akışlarından E-posta Gönderme](/l/tr/user-guide/workflows/capabilities/send-emails-from-workflows)
* [Özel Alanlar Oluşturma](/l/tr/user-guide/data-model/how-tos/create-custom-fields)
* [İlişki Alanları Oluşturma](/l/tr/user-guide/data-model/how-tos/create-relation-fields)

View File

@@ -0,0 +1,106 @@
---
title: Süresi Gelen Görevler için E-posta Uyarıları Gönderin
description: Takım üyelerini yaklaşan veya gecikmiş görevleri hakkında otomatik olarak bilgilendirin.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<img src="/images/user-guide/workflows/email_tasks_due.png" style={{genişlik:'100%'}} />
Her takım üyesine, son tarihi bugün olan görevleri hakkında günlük e-posta hatırlatmaları gönderin.
## Genel Bakış
Bu iş akışı bir zamanlamaya göre çalışır ve:
1. Tüm çalışma alanı üyelerini getirir
2. Her bir üye üzerinde döner
3. Son tarihi bugün olan görevlerini bulur
4. Kişiselleştirilmiş bir e-postayı biçimlendirir ve gönderir
## Adım adım kurulum
<VimeoEmbed videoId="1147463514" title="Video gösterimi" />
### Adım 1: Tetikleyiciyi Yapılandırın
1. **Ayarlar → İş Akışları**'na gidin ve yeni bir iş akışı oluşturun
2. Tetikleyici olarak **Zamanlanmış Olarak**'ı seçin
3. Her gün saat 08:00 için bir cron ifadesi kullanın: `0 8 * * *`
### Adım 2: Tüm Çalışma Alanı Üyelerini Arayın
1. Bir **Kayıtları Ara** eylemi ekleyin
2. (Gelişmiş nesneler altında) **Çalışma Alanı Üyeleri**'ni seçin
3. Filtre gerekmez — bu, tüm üyeleri döndürür
### Adım 3: Bir Yineleyici Ekleyin
1. Bir **Iterator** eylemi ekleyin
2. Girdi dizisini önceki adımdaki çalışma alanı üyelerine ayarlayın
3. Yineleyici içindeki tüm eylemler, üye başına bir kez çalışır
### Adım 4: Bugün Son Tarihi Olan Görevleri Arayın (Yineleyici İçinde)
1. Yineleyici içinde bir **Kayıtları Ara** eylemi ekleyin
2. Nesne olarak **Görevler**'i seçin
3. Filtreler ekleyin:
* **Atanan** = mevcut çalışma alanı üyesi (yineleyiciden)
* **Son Tarih** = bugün
### Adım 5: Görevleri E-posta Gövdesine Biçimlendirin (Yineleyici İçinde)
Görevleri bağlantılarla okunabilir bir listeye dönüştürmek için bir **Kod** eylemi ekleyin:
```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>
`yourSubDomain` değerini, gerçek Twenty çalışma alanı alt alan adınızla değiştirin.
</Note>
### Adım 6: E-posta Gönderin (Yineleyici İçinde)
1. Bir **E-posta Gönder** eylemi ekleyin (halen yineleyici içinde)
2. Yapılandırın:
| Alan | Değer |
| ---------- | ----------------------------------------------------------------------- |
| **Kime** | `{{iterator.currentItem.userEmail}}` (çalışma alanı üyesinin e-postası) |
| **Konu** | Bugün Son Tarihi Olan Görevleriniz |
| **İçerik** | `{{code.formattedTasks}}` |
### Adım 7: Test Edin ve Etkinleştirin
1. İş akışını manuel olarak çalıştırmak için **Test**'e tıklayın
2. E-postalar için gelen kutularını kontrol edin
3. İş akışını etkinleştirin
## İlgili
* [İş Akışı Eylemleri](/l/tr/user-guide/workflows/capabilities/workflow-actions)
* [İş Akışlarından E-posta Gönderme](/l/tr/user-guide/workflows/capabilities/send-emails-from-workflows)
* [Kod Eylemlerinde Dizileri Ele Alma](/l/tr/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,21 @@
---
title: Profesyonel Hizmetler
description: Twenty'nin ekibi ve sertifikalı iş ortaklarından karmaşık iş akışları ve otomasyonlar oluşturmada profesyonel yardım alın.
---
## Ne Zaman Profesyonel Yardıma İhtiyacınız Var?
Aşağıdaki durumlar için profesyonel hizmetleri düşünün:
* Karmaşık çoklu sistem entegrasyonları
* Gelişmiş iş mantığı ve otomasyon kuralları
* Büyük ölçekli veri işleme iş akışları
* Özel API geliştirme
* Ekip eğitimi ve iş akışı optimizasyonu
* İç kaynaklarınız olmadığında
## Hizmet Seçenekleri
### Uygulama Ortakları
Gelişmiş özelleştirmeler için sertifikalı ortaklarla çalışın. [contact@twenty.com](mailto:contact@twenty.com) adresinden bizimle iletişime geçerek [uygulama iş ortaklarımız](https://twenty.com/partners) ile bağlantı kurun.

View File

@@ -0,0 +1,170 @@
---
title: İş Akışı Sorun Giderme
description: Yaygın iş akışı sorunları ve bunları çözme yöntemleri.
---
## Sık Görülen Sorunlar ve Çözümleri
### İş Akışı Tetiklenmiyor
**Belirtiler**: İş akışınız beklediğinizde çalışmıyor.
**Olası Nedenler**:
1. **İş akışı etkinleştirilmemiş**: İş akışının "Draft" değil "Active" olarak ayarlandığından emin olun
2. **Tetikleyici koşulları karşılanmıyor**: Tetikleyicinin beklediğiniz olaya uyduğunu doğrulayın
3. **Alan izlenmiyor**: "Record is Updated" tetikleyicileri için, belirli alanın izlendiğinden emin olun
4. **İzinler**: İş akışlarını çalıştırma iznine sahip olduğunuzu kontrol edin
**Çözümler**:
* İş akışı listesindeki iş akışı durumunu doğrulayın
* Tetiklemesini beklediğiniz belirli işlemle test edin
* Tetikleyici yapılandırmasını gözden geçirin
* İzinler konusunda yöneticinizle iletişime geçin
### İş Akışı Çok Erken Tetikleniyor (Boş Alanlar)
**Belirtiler**: Kullanıcı arayüzünde (UI) bir kaydı manuel olarak oluştururken, tüm alanları dolduracak zamanınız olmadan iş akışınız tetikleniyor. İş akışı, alan değerlerinin çoğu boşken çalışır.
**Bunun nedeni**: Twenty her şeyi gerçek zamanlı olarak kaydeder — ayrı bir "düzenleme" ve "okuma" modu yoktur. Bir kayıt oluşturduğunuzda, ek alanları doldurmadan önce "Record is created" olayını tetikleyerek hemen kaydedilir.
**"Record is created" ne zaman iyi çalışır**:
* API çağrılarıyla oluşturulan kayıtlar (alanlar tek bir istekte doldurulur)
* İçe aktarma yoluyla oluşturulan kayıtlar
* Diğer iş akışlarından otomatik kayıt oluşturma
**Çözüm**: UI'da manuel olarak oluşturulan kayıtlar için tetikleyici olarak **"Record is created or updated"** kullanın. Bu şekilde:
* Kullanıcı alanları doldurup kaydetmeyi bitirdikten sonra iş akışı tetiklenir
* Boş değerler yerine eksiksiz verileri alırsınız
<Tip>
Kayıt başına iş akışının yalnızca bir kez çalışmasını istiyorsanız, `createdAt equals updatedAt` (ilk kaydetme) gibi bir alanı kontrol etmek için bir Filtre eylemi ekleyin veya iş akışının daha önce çalışıp çalışmadığını izlemek için özel bir onay kutusu alanı kullanın.
</Tip>
### Eylemler Başarısız Oluyor
**Belirtiler**: İş akışı çalışıyor ancak bazı eylemler başarısız oluyor.
**Olası Nedenler**:
1. **Eksik veri**: Gerekli alanlar boş
2. **Geçersiz başvurular**: Önceki adımlardan gelen değişkenler mevcut değil
3. **API hataları**: Dış hizmetler hata döndürüyor
4. **İzin sorunları**: Eylem, sahip olmadığınız izinler gerektiriyor
**Çözümler**:
* Hata mesajları için iş akışı çalıştırma ayrıntılarını kontrol edin
* Gerekli tüm alanların dolu olduğunu doğrulayın
* API bağlantılarını bağımsız olarak test edin
* Rol izinlerini gözden geçirin
### HTTP İstek Hataları
**Belirtiler**: HTTP Request eylemleri başarısız oluyor veya beklenmeyen sonuçlar döndürüyor.
**Yaygın Hata Kodları**:
* **400**: Hatalı istek - istek gövdesi biçiminizi kontrol edin
* **401**: Yetkisiz - API anahtarını doğrulayın
* **403**: Yasak - API izinlerini kontrol edin
* **404**: Bulunamadı - endpoint URL'sini doğrulayın
* **429**: Çok fazla istek - hız sınırlaması uygulayın
* **500**: Sunucu hatası - harici hizmet sorunu
**Çözümler**:
* API endpoint URL'sini doğrulayın
* Kimlik doğrulama başlıklarını kontrol edin
* Önce API çağrısını Twenty dışında test edin
* Code eylemlerine hata işleme ekleyin
### Code Eylemi Hataları
**Belirtiler**: JavaScript kodu yürütülemiyor.
**Yaygın Sorunlar**:
1. **Sözdizimi hataları**: Yazım hataları veya geçersiz JavaScript
2. **Tanımsız değişkenler**: Var olmayan değişkenlere başvurma
3. **Tür hataları**: Yanlış veri türleri üzerinde işlemler
4. **Zaman aşımı**: Kodun çalıştırılması çok uzun sürüyor
**Çözümler**:
* Yerleşik kod düzenleyicisi doğrulamasını kullanın
* Önce JavaScript konsolunda kod mantığını test edin
* Hata ayıklama için console.log ifadeleri ekleyin
* Karmaşık işlemleri basitleştirin
### E-posta Gönderilmiyor
**Belirtiler**: Send Email eylemi e-postaları göndermiyor.
**Olası Nedenler**:
1. **Bağlı e-posta hesabı yok**: Settings → Accounts'ı kontrol edin
2. **Geçersiz e-posta adresi**: Alıcı e-posta adresi hatalı biçimlendirilmiş
3. **Gönderim sınırları**: E-posta sağlayıcısının hız sınırı aşıldı
4. **Spam filtreleri**: E-postalar engelleniyor
**Çözümler**:
* E-posta hesabı bağlantısını doğrulayın
* Alıcı e-posta adreslerini doğrulayın
* E-posta sağlayıcısı limitlerini kontrol edin
* Spam tetikleyicileri açısından e-posta içeriğini gözden geçirin
## İş Akışlarında Hata Ayıklama
### İş Akışı Çalıştırmalarını Kullanma
1. İş akışı düzenleyicisine gidin
2. **Runs** panelini açın
3. Başarısız olan çalıştırmayı bulun
4. Adım adım ayrıntıları görmek için tıklayın
5. Hata mesajlarını ve çıktı verilerini gözden geçirin
### Bireysel Adımları Test Etme
1. Code eylemleri için **Test** düğmesini kullanın
2. HTTP istekleri için endpoint'i ayrı olarak test edin
3. İş akışlarını tetiklemek için test kayıtları oluşturun
4. Kontrollü test için manuel tetikleyiciler kullanın
### Yaygın Hata Ayıklama Kalıpları
**Günlükleme ekleyin**:
Hata ayıklama için ara değerleri kaydetmek üzere Code eylemlerini kullanın.
**Adımları izole edin**:
Hataları belirlemek için her adımı bağımsız olarak test edin.
**Veri akışını kontrol edin**:
Her adımın beklenen giriş verilerini aldığını doğrulayın.
## Sorunlardan Kaçınmak İçin En İyi Uygulamalar
### Etkinleştirmeden Önce
* Taslak modunda kapsamlı şekilde test edin
* Tüm API bağlantılarını doğrulayın
* Tetikleyici koşullarını dikkatlice gözden geçirin
* Beklenen davranışı belgeleyin
### Geliştirme Sırasında
* Açıklayıcı adım adları kullanın
* Code eylemlerine yorum ekleyin
* Gerçekçi verilerle test edin
* Uç durumlar için plan yapın
### Etkinleştirmeden Sonra
* İlk çalıştırmaları yakından izleyin
* Başarısızlıklar için uyarılar ayarlayın
* Çalıştırma geçmişini düzenli olarak gözden geçirin
* Mümkün olduğunda iş akışlarını basit tutun

View File

@@ -0,0 +1,236 @@
---
title: İş Akışları SSS
description: Twenty'deki iş akışları hakkında sıkça sorulan sorular.
---
<AccordionGroup>
<Accordion title="Bir iş akışını neden etkinleştiremiyorum?">
Bu muhtemelen bir yetki sorunudur. İş akışlarını oluşturmak ve etkinleştirmek için iş akışlarına erişiminiz olmalıdır.
**Çözüm**: **Ayarlar → Üyeler → Roller** altında size iş akışı erişimi vermesi için çalışma alanı yöneticinizle iletişime geçin.
Kenar çubuğunuzda İş Akışları bölümünü hiç görmüyorsanız, bunun bir yetki sorunu olduğunu doğrular.
</Accordion>
<Accordion title="Üst gezinme çubuğunda manuel iş akışım düğmesini neden görmüyorum?">
Manuel iş akışları, doğru şekilde yapılandırılmışsa üst gezinme çubuğunda görünür:
1. İş akışı **etkinleştirilmiş** olmalıdır (taslak modunda olmamalı)
2. Üst gezinme çubuğu konumu **Pinned** olarak ayarlanmış olmalıdır
3. Single/Bulk tetikleyiciler için, doğru nesne sayfasında olmanız gerekir
**Kontrol etmek için**: iş akışını açın → tetikleyiciye tıklayın → "Navbar placement" alanının "Pinned" olarak ayarlandığını doğrulayın.
Üst gezinme çubuğu ayarlarından bağımsız olarak manuel iş akışlarına her zaman **Cmd + K** (veya **Ctrl + K**) ile erişebilirsiniz.
</Accordion>
<Accordion title="Single, Global ve Bulk manuel tetikleyiciler arasındaki fark nedir?">
| Tür | Gerekli Kayıtlar | İş Akışı Çalıştırmaları |
| --- | ---------------- | ----------------------- |
\| **Global** | Yok | Bir kez, kayıt girişi olmadan |
\| **Single** | Bir veya daha fazlası seçili | Seçilen her kayıt için bir kez |
\| **Bulk** | Bir veya daha fazlası seçili | Bir kez, tüm kayıtlar bir dizi olarak |
* **Global**: İş akışının herhangi bir kayıt bağlamına ihtiyaç duymadığı durumlarda kullanın (ör. bir rapor oluşturma)
* **Single**: Seçilen her kaydı bağımsız olarak işlemek istediğinizde kullanın (ör. bireysel e-postalar gönderme)
* **Bulk**: Kayıtları birlikte işlemeniz veya kredi kullanımını optimize etmeniz gerektiğinde kullanın (Iterator eylemi gerektirir)
Ayrıntılar için [İş Akışı Tetikleyicileri](/l/tr/user-guide/workflows/capabilities/workflow-triggers) bölümüne bakın.
</Accordion>
<Accordion title="Bir If/Else düğümü görmüyorum. Ne yapmalıyım?">
Açık bir If/Else düğümü henüz mevcut değil, ancak yol haritamızda yer alıyor.
**Geçici çözüm**: Adımınızdan birden fazla dal oluşturun; her biri bir **Filter** eylemiyle başlasın:
```
Step 1
│
├── Branch A: Filter (condition = true) → Actions...
│
└── Branch B: Filter (condition = false) → Actions...
```
Yalnızca filtre koşulu geçen dal, sonraki eylemlerini çalıştırır.
Adım adım bir kılavuz için [Dalları Nasıl Kullanılır](/l/tr/user-guide/workflows/capabilities/workflow-branches) bölümüne bakın.
</Accordion>
<Accordion title="İş akışı dalları paralel mi çalışıyor?">
**Evet**, dallar varsayılan olarak paralel çalışır.
Yalnızca bir dalın çalışmasını istiyorsanız:
* Her dalın başlangıcına bir **Filter** eylemi ekleyin
* Zıt koşullar ayarlayın (ör. Dal A: status = "Open", Dal B: status ≠ "Open")
Filtre koşulunu sağlamayan dallar çalışmayı durdurur, diğerleri devam eder.
</Accordion>
<Accordion title="Dalları yeniden birleştirebilir miyim?">
**Evet**. Paralel dallarınız tamamlandıktan sonra, her iki dalın da bağlanacağı bir adım ekleyebilirsiniz.
İş Akışı Düzenleyicisinde:
1. Dallanmış eylemlerinizi tamamlayın
2. Dallardan sonra yeni bir adım ekleyin
3. Her dalın sonundan bu yeni adıma bağlantıları sürükleyin
Birleştirilen adım, bağlı tüm dallar tamamlandıktan sonra çalışacaktır.
</Accordion>
<Accordion title="Search Records sonuçlarının sınırı nedir?">
**Search Records en fazla 200 kayıt döndürür.**
Daha fazlasını işlemeniz gerekiyorsa:
* Sonuçları azaltmak için daha spesifik filtreler ekleyin
* Toplu işlem yapmak için zamanlanmış iş akışlarını kullanın
* Toplu işlemler için API kullanmayı düşünün
Çoğu iş akışı için 200 kayıt yeterlidir. Bu sınıra düzenli olarak ulaşıyorsanız otomasyonunuzu yeniden yapılandırmayı düşünün.
</Accordion>
<Accordion title="İş akışı e-postalarında kişileri CC'ye ekleyebilir miyim?">
**Henüz değil.** Send Email eylemi için CC ve BCC alanları yol haritamızda.
**Geçici çözüm**: Ek alıcılara göndermek için birden fazla Send Email eylemi ekleyin veya CC'yi destekleyen harici bir e-posta hizmeti üzerinden göndermek için bir HTTP Request kullanın.
</Accordion>
<Accordion title="Önceki adımların çıktılarını nasıl kullanırım?">
Her eylem, sonraki adımlarda kullanılabilecek çıktı verileri üretir.
**Önceki adım verilerine başvurmak için**:
* Bir alanı yapılandırırken değişken seçiciyi kullanın
* Ya da doğrudan `{{stepName.fieldName}}` yazın
**Örnekler**:
* Tetikleyici verisi: `{{trigger.object.email}}`
* Arama sonuçları: `{{searchRecords[0].name}}`
* Kod çıktısı: `{{code.calculatedValue}}`
Eylem yapılandırmasında herhangi bir alanın üzerine gelerek önceki adımlardan kullanılabilir değişkenleri görebilirsiniz.
</Accordion>
<Accordion title="Iterator neden başarısız oluyor?">
**Iterator bir dizi girdisi gerektirir.** Yaygın sorunlar:
1. **Girdi bir dizi değil**: Search Records'tan veya bir dizi döndüren başka bir eylemden gelen sonuçları ilettiğinizden emin olun
2. **Dizi boş**: Iterator'dan önce `{{searchRecords.length}} > 0` kontrolü için bir filtre ekleyin
3. **Yanlış değişken seçildi**: Tek bir kayıt yerine dizinin kendisini seçtiğinizden emin olun
**Doğru kurulum**:
1. Search Records (dizi döndürür)
2. Filter: length > 0
3. Iterator: `{{searchRecords}}` öğesini seçin
4. Iterator içindeki eylemler `{{iterator.currentItem.fieldName}}` kullanır
</Accordion>
<Accordion title="Code eylemleri için en uzun yürütme süresi nedir?">
Code eylemlerinin (mantık fonksiyonları) **varsayılan zaman aşımı 5 dakikadır** (300 saniye).
Yapılandırılabilir en yüksek zaman aşımı **15 dakikadır** (900 saniye).
Kodunuz bu sınırı aşarsa, eylem zaman aşımı hatasıyla başarısız olur.
**Zaman aşımından kaçınma ipuçları**:
* Büyük işlemleri Iterator kullanarak daha küçük parçalara bölün
* Ağır hesaplamalardan kaçının; yoğun işlemler için HTTP Request üzerinden harici hizmetler kullanın
* Yürütme süresini azaltmak için kodunuzu optimize edin
* Daha uzun işlemeye ihtiyacınız varsa, verileri toplu olarak işleyen zamanlanmış iş akışlarını kullanmayı düşünün
</Accordion>
<Accordion title="İş akışı çalıştırmalarını nasıl incelerim?">
İş akışı çalıştırmaları yürütme geçmişini gösterir ve sorunları ayıklamanıza yardımcı olur.
**Çalıştırmalara erişim**:
* İş akışı düzenleyicisinde → sağdaki **Runs** paneli
* Ya da kenar çubuğunda **İş Akışı Çalıştırmaları**'na gidin
**Bir çalıştırmayı anlamak**:
* **Durum**: Running, Completed, Failed, Waiting
* **Adımlar**: Hangi adımların çalıştığını ve çıktısını görün
* **Hatalar**: Hata ile sonuçlanan adımlara tıklayarak hata mesajlarını görün
* **Veri**: Her adımda giriş/çıkış verilerini görüntüleyin
Ayrıntılar için [İş Akışı Çalıştırmaları](/l/tr/user-guide/workflows/capabilities/workflow-runs) bölümüne bakın.
</Accordion>
<Accordion title="İş akışı çalıştırmalarımı neden görmüyorum?">
İş akışı çalıştırmaları hız sınırları nedeniyle anında başarısız oluyor olabilir. Twenty, çalışma alanı başına saatte 5.000 çalıştırma için katı bir sınır uygular.
Bu sınırı aşarsanız, iş akışları derhal başarısız olarak işaretlenir ve çalıştırma listenizde görünmez.
**Bu sınıra ulaşan yaygın senaryolar**:
* Single manuel tetikleyici ile 5.000'den fazla kayıt seçmek
* Çalışma alanınız genelinde eşzamanlı olarak birden fazla iş akışının çalışması
* Yüksek frekanslı otomatik tetikleyiciler (ör. yoğun bir nesnede Record Updated)
**Çözümler**:
* Tek bir çalıştırmada birçok kaydı işlemek için Single yerine **Bulk** tetikleyicileri kullanın
* Büyük toplu işlemleri zamana yayın
* Tetikleyici frekansını azaltmak için filtreler kullanın
* Ağır iş akışlarını yoğun olmayan saatlerde zamanlayın
</Accordion>
<Accordion title="İş akışlarına ilişkin hız sınırları nelerdir?">
Twenty, sistem kararlılığını sağlamak için iki hız sınırına sahiptir:
| Sınır | Değer | Davranış |
| ----- | ----- | -------- |
\| **Yumuşak sınır** | dakikada 100 çalıştırma | Çalıştırmalar "Not Started" durumunda kuyruğa alınır, kademeli olarak işlenir |
\| **Katı sınır** | saatte 5.000 çalıştırma | Çalıştırmalar anında başarısız olur |
**Yumuşak sınır (100/dk)**: İş akışlarınız başarısız olmaz—sadece kuyruğa alınır ve zaman içinde işlenir. 100'den fazla kaydı tetikleyebilirsiniz; yürütme daha yavaş olacaktır.
**Katı sınır (5.000/saat)**: Bu, tüm çalışma alanınız için geçerlidir. Tüm iş akışlarınız toplamda bir saat içinde 5.000 çalıştırmayı aşarsa, ilave çalıştırmalar anında başarısız olur.
**Sınırlar içinde kalmak için ipuçları**:
* Büyük toplu işlemler için Single tetikleyiciler yerine Iterator ile birlikte Bulk tetikleyicileri kullanın
* İlgili otomasyonları daha az sayıda iş akışında birleştirin
* Yükü zamana yaymak için zamanlanmış iş akışlarını kullanın
</Accordion>
<Accordion title="Başarısız olmuş bir iş akışı çalıştırmasını yeniden deneyebilir miyim?">
**Hayır, şu anda otomatik yeniden deneme işlevi yok.**
Bir iş akışı çalıştırması başarısız olursa şunları yapmanız gerekir:
1. **Ayarlar → İş Akışları → [Your Workflow] → Runs** içinde hatayı inceleyin
2. Sorunu düzeltin (veri, yapılandırma veya harici hizmet)
3. Etkilenen kayıt(lar) üzerinde iş akışını manuel olarak yeniden tetikleyin
**Hataları azaltmak için ipuçları**:
* Eylemlerden önce veriyi doğrulamak için **Filter** düğümleri ekleyin
* İlgili kayıtların var olup olmadığını kontrol etmek için **Search Records** kullanın
* Toplu işlemlerden önce birkaç kayıtla kapsamlı şekilde test edin
Otomatik yeniden deneme işlevi gelecekteki bir sürüm için yol haritamızda.
</Accordion>
<Accordion title="CSV içe aktarmalarından önce iş akışlarını devre dışı bırakmalı mıyım?">
**Evet, iş akışlarınız kayıt oluşturma veya güncellemelerle tetikleniyorsa.**
CSV ile veri içe aktardığınızda, oluşturulan veya güncellenen her kayıt iş akışlarını tetikleyebilir. Büyük bir içe aktarma (binlerce kayıt) şunlara yol açabilir:
* Saatte 5.000 çalıştırma sınırına ulaşmak
* Önemli miktarda iş akışı kredisi tüketmek
* Beklenmedik e-postalar veya bildirimler göndermek
* Yinelenen görevler veya kayıtlar oluşturmak
**Toplu bir içe aktarmadan önce**:
1. **Ayarlar → İş Akışları** bölümüne gidin
2. İçe aktardığınız nesne tarafından tetiklenen iş akışlarını belirleyin
3. Bunları geçici olarak **devre dışı bırakın**
4. CSV içe aktarmanızı çalıştırın
5. İşiniz bittiğinde iş akışlarını **yeniden etkinleştirin**
**Alternatif**: İş akışlarının içe aktarılan veriler üzerinde çalışması gerekiyorsa, hız sınırları içinde kalmak için daha küçük partiler halinde içe aktarın.
</Accordion>
<Accordion title="İş akışı yerleşimimi nasıl temizlerim?">
İş akışı tuvaliniz etrafa dağılmış düğümlerle dağınık görünüyorsa, onu otomatik olarak düzenleyebilirsiniz:
1. İş akışı tuvalinde herhangi bir yere sağ tıklayın
2. **Tidy up workflow** öğesine tıklayın
Bu, tüm düğümleri otomatik olarak temiz ve düzenli bir yerleşime yeniden düzenleyecektir.
</Accordion>
</AccordionGroup>