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,167 @@
---
title: إرسال رسائل البريد الإلكتروني عبر سير العمل
description: أرسل رسائل بريد إلكتروني مُخصّصة تلقائياً باستخدام إجراءات سير العمل.
---
أرسل رسائل البريد الإلكتروني تلقائياً عند حدوث أحداث معيّنة في نظام إدارة علاقات العملاء (CRM) لديك—رحّب بجهات الاتصال الجديدة، وتابع الفرص، أو أخطر أعضاء الفريق.
## المتطلبات الأساسية
قبل أن تتمكن من إرسال رسائل البريد الإلكتروني من سير العمل:
1. وصّل حساب بريد إلكتروني ضمن **الإعدادات → الحسابات**
2. تأكد من أن الحساب لديه أذونات إرسال مفعّلة
## سير عمل أساسي للبريد الإلكتروني
### مثال: رسالة ترحيب لجهات الاتصال الجديدة
**الهدف**: إرسال رسالة ترحيب عند إضافة شخص جديد إلى نظام إدارة علاقات العملاء (CRM).
**الإعداد**:
1. **إنشاء سير عمل**: انتقل إلى **الإعدادات → سير العمل** ثم انقر **+ سير عمل جديد**
2. **إضافة مشغّل**: اختر **تم إنشاء سجل** → **الأشخاص**
3. **إضافة إجراء إرسال بريد إلكتروني**:
* انقر **+** لإضافة إجراء
* اختر **إرسال بريد إلكتروني**
* قم بتهيئة البريد الإلكتروني:
| الحقل | القيمة |
| ----------- | -------------------------------------- |
| **إلى** | `{{trigger.object.email}}` |
| **الموضوع** | `مرحبا بك في {{Your Company Name}}` |
| **المحتوى** | `Hi {{trigger.object.firstName}}, ...` |
4. **الاختبار والتفعيل**: اختبر باستخدام سجل عينة، ثم فعِّل
## استخدام المتغيرات في رسائل البريد الإلكتروني
استدعِ البيانات من الخطوات السابقة باستخدام صيغة `{{variable}}`:
```text
Hi {{trigger.object.firstName}},
Thank you for connecting with us!
Your company, {{trigger.object.company.name}}, is now in our system.
Best regards,
The Team
```
### المتغيرات المتاحة من المشغّلات
| نوع المُحفِز | المتغيرات الشائعة |
| ------------------------ | -------------------------------------- |
| **تم إنشاء/تحديث السجل** | `{{trigger.object.fieldName}}` |
| **يدوي** | `{{trigger.selectedRecord.fieldName}}` |
| **الويب هوك** | `{{trigger.body.fieldName}}` |
## متقدم: رسائل بريد إلكتروني مشروطة
### مثال: رسائل بريد إلكتروني مختلفة بناءً على مصدر العميل المحتمل
**الهدف**: إرسال رسائل ترحيب مختلفة بناءً على مصدر قدوم العميل المحتمل.
**الإعداد**:
1. **المشغّل**: تم إنشاء سجل (الأشخاص)
2. **إضافة إجراء تصفية**:
* الشرط: `{{trigger.object.source}}` يساوي `"Website"`
* إذا كان صحيحاً → المتابعة إلى رسالة الترحيب الخاصة بالموقع الإلكتروني
3. **فرع للمصادر الأخرى**:
* أنشئ فروعاً متوازية لمصادر مختلفة
* لكل فرع إجراء إرسال بريد إلكتروني خاص به
## إرسال رسائل البريد الإلكتروني إلى عدة مستلمين
### مثال: إشعار الفريق عند إغلاق الصفقة
**الهدف**: إرسال بريد إلكتروني إلى مندوب المبيعات ومديره عند ربح فرصة.
**الإعداد**:
1. **المشغّل**: تم تحديث السجل (الفرص، المرحلة = "Closed Won")
2. **البحث في السجلات**: اعثر على مدير مالك الفرصة
3. **إرسال بريد إلكتروني #1**: إلى مالك الفرصة
* إلى: `{{trigger.object.owner.email}}`
* الموضوع: `تهانينا على إغلاق {{trigger.object.name}}!`
4. **إرسال بريد إلكتروني #2**: إلى المدير
* إلى: `{{searchRecords.manager.email}}`
* الموضوع: `تم ربح الصفقة: {{trigger.object.name}}`
## رسائل متابعة مجدولة
### مثال: متابعة بعد 3 أيام من الاجتماع
**الهدف**: إرسال رسالة متابعة عبر البريد الإلكتروني بعد 3 أيام من تسجيل اجتماع.
**الإعداد**:
1. **المشغّل**: تم إنشاء سجل (الأنشطة، النوع = "اجتماع")
2. **إجراء تأخير**: الانتظار 3 أيام
3. **إرسال البريد الإلكتروني**:
* إلى: مشارك الاجتماع
* الموضوع: متابعة لمحادثتنا
* المحتوى: الإشارة إلى تفاصيل الاجتماع من المشغّل
## مرفقات البريد الإلكتروني
يمكنك إرفاق ملفات برسائل البريد الإلكتروني المرسلة من سير العمل. المرفق ملف ثابت تقوم برفعه عند تهيئة سير العمل.
### كيفية إضافة مرفق
1. في إجراء **إرسال بريد إلكتروني**، انقر على زر **المرفقات**
2. انقر لرفع ملف من جهازك
3. سيتم إرفاق الملف بجميع رسائل البريد الإلكتروني التي يرسلها هذا الإجراء
### الاستخدامات الشائعة
| حالة الاستخدام | ملف نموذجي |
| --------------------------------------- | -------------------------------- |
| **رسائل الترحيب عبر البريد الإلكتروني** | كتيب الشركة (PDF) |
| **تسلسلات الانضمام** | دليل البدء |
| **متابعات المبيعات** | كتالوج المنتجات أو قائمة الأسعار |
| **تأكيدات الفعاليات** | تفاصيل الفعالية أو جدول الأعمال |
<Note>
المرفقات ثابتة—يتم إرسال الملف نفسه إلى جميع المستلمين. بالنسبة للمستندات الديناميكية (مثل عروض الأسعار المخصصة)، أنشئ الملفات وأرفقها باستخدام [وظيفة منطقية](/l/ar/user-guide/workflows/how-tos/connect-to-other-tools/generate-pdf-from-twenty).
</Note>
## أفضل الممارسات
### محتوى البريد الإلكتروني
* اجعل سطور الموضوع موجزة وذات صلة
* خصص الرسالة باسم المستلم
* ضمّن دعوة واضحة للإجراء
* اختبر رسائل البريد الإلكتروني قبل التفعيل
### قابلية التسليم
* لا ترسل عدداً كبيراً من الرسائل بسرعة كبيرة
* استخدم تواقيع بريد إلكتروني احترافية
* تجنب كلمات تُحفّز مرشحات البريد العشوائي
* احرص على توفير خيارات إلغاء الاشتراك لرسائل التسويق الإلكترونية
### استكشاف الأخطاء وإصلاحها
* تحقّق من أن حساب البريد الإلكتروني متصل وفعّال
* تحقّق من صحة عنوان البريد الإلكتروني للمستلم
* راجِع عمليات تشغيل سير العمل بحثاً عن رسائل الخطأ
* اختبر باستخدام عنوان بريدك الإلكتروني أولاً
## ذات صلة
* [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,88 @@
---
title: استخدام الفروع في سير العمل
description: افهم كيف تعمل الفروع وكيف تتحكم في المسار الذي يتم تنفيذه.
---
## كيف تعمل الفروع
في محرر سير العمل، يمكنك إنشاء مسارات متعددة (فروع) تنطلق من عقدة واحدة. يُمكّنك هذا من إنشاء أتمتة معقدة بنتائج مختلفة.
**مهم**: عند تشغيل سير العمل، **تُنفَّذ جميع الفروع بالتوازي افتراضيًا**. لا توجد بنية منطقية مدمجة "if/else" لاختيار فرع على آخر — كل مسار سيعمل في الوقت نفسه.
## التحكم في الفرع الذي يعمل
لتنفيذ فرع واحد فقط بناءً على شروط محددة، **أضِف عقدة Filter في بداية كل فرع**.
### مثال على الإعداد
1. أنشئ سير العمل الخاص بك بفروع متعددة من عقدة واحدة
2. أضِف عقدة **Filter** كأول خطوة في كل فرع
3. عيِّن شروطًا على كل Filter لتحديد متى يجب أن يواصل ذلك الفرع
4. سيتابع فقط الفرع أو الفروع التي تستوفي شروط Filter
### كيف تعمل عُقد Filter
* إذا كان شرط Filter **متحققًا**: يتابع الفرع التنفيذ
* إذا كان شرط Filter **غير متحقق**: يتوقف الفرع عند عقدة Filter
يُنشئ هذا عمليًا منطقًا شرطيًا بحيث لا يعمل إلا الفرع المناسب بناءً على بياناتك.
## مثال: التوجيه حسب حجم الصفقة
**السيناريو**: عند إغلاق صفقة، أرسِل إشعارات مختلفة حسب حجم الصفقة.
1. **المشغّل**: تم تحديث الفرصة (المرحلة = Closed Won)
2. **الفرع 1**: شرط Filter للمبلغ > $10,000 → إرسال رسالة Slack إلى #big-deals
3. **الفرع 2**: شرط Filter للمبلغ ≤ $10,000 → إرسال بريد إلكتروني إلى مدير المبيعات
يبدأ الفرعان، لكن الفرع الذي يطابق مبلغ الصفقة فقط سيستمر بعد عقدة Filter.
## إنشاء الفروع
<Note>
لإنشاء فرع جديد من خطوة موجودة، انقر زر **+** على الخطوة وأضِف الإجراء الخاص بك. يمكنك إضافة عدة فروع بالنقر على **+** عدة مرات.
</Note>
1. في محرر سير العمل، حدِّد الخطوة التي تريد التفريع منها
2. انقر **+** لإضافة إجراء
3. سيؤدي هذا إلى إنشاء فرع واحد
4. انقر **+** مرة أخرى على نفس الخطوة لإنشاء فروع إضافية
5. يمكن لكل فرع أن يكون له تسلسل إجراءات خاص به
## دمج الفروع معًا مرة أخرى
بعد أن تُكمل الفروع المتوازية عملها، يمكنك دمجها مرة أخرى في مسار واحد:
1. أكمل إجراءات الفروع
2. أضِف خطوة جديدة ينبغي أن تعمل بعد جميع الفروع
3. اسحب اتصالًا من الخطوة الأخيرة لكل فرع إلى هذه الخطوة الجديدة
4. تنتظر الخطوة المدمجة اكتمال جميع الفروع المتصلة قبل التنفيذ
### مثال: المعالجة ثم الإشعار
```
Trigger
│
├── Branch A: Update Customer Record
│
└── Branch B: Create Support Ticket
↘ ↙
Merged Step: Send Confirmation Email
```
يتم إرسال رسالة تأكيد البريد الإلكتروني فقط بعد أن يتم تحديث العميل وإنشاء التذاكر.
## أفضل الممارسات
* استخدم دائمًا **عُقد Filter** في بداية الفروع عندما تريد تنفيذًا شرطيًا
* اجعل شروط الفروع **متبادلة الإقصاء** لتجنّب الإجراءات المكررة
* اختبر سير العمل لديك ببيانات مختلفة للتأكد من تشغيل الفروع الصحيحة
* **أعد تسمية خطوات الفروع** بطريقة وصفية ليكون واضحًا ما يفعله كل مسار
* **ادمج الفروع** عندما تحتاج إلى إجراء نهائي بعد المعالجة المتوازية
## ذات صلة
* [الأسئلة الشائعة حول سير العمل](/l/ar/user-guide/workflows/how-tos/need-more-help/workflows-faq) — إجابات حول التنفيذ المتوازي
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions) — الإجراءات المتاحة للفروع

View File

@@ -0,0 +1,183 @@
---
title: استخدم المكرّر
description: قم بالتكرار عبر مصفوفات السجلات لتنفيذ إجراءات على كل عنصر.
---
يتيح لك المكرّر التكرار عبر مصفوفة من السجلات وتنفيذ إجراءات على كلٍ منها. وهو ضروري لتدفّقات العمل التي تحتاج إلى معالجة سجلات متعددة أُرجعت بواسطة Search Records أو استُلِمت عبر ربط الويب.
## متى تستخدم المكرّر
| السيناريو | مثال |
| -------------------------------- | --------------------------------------------- |
| **معالجة نتائج البحث** | إرسال بريد إلكتروني إلى كل شخص تم العثور عليه |
| **التعامل مع مصفوفات ربط الويب** | إنشاء سجلات لكل عنصر بالتسلسل |
| **التحديثات الدفعيّة** | تحديث عدة سجلات بقيم محسوبة |
| **إشعارات** | تنبيه عدة أشخاص بخصوص حدثٍ ما |
## فهم المكرّر
يتوقع المكرّر إدخالاً عبارة عن **مصفوفة**. ثم يقوم بما يلي:
1. يأخذ أول عنصر من المصفوفة
2. تشغيل جميع الإجراءات داخل المربع مع هذا العنصر
3. ينتقل إلى العنصر التالي
4. يكرّر حتى تتم معالجة جميع العناصر
### اختيار المصفوفة المطلوب التكرار عليها
يمكن اختيار معظم مصادر المصفوفات (بحث السجلات، حقل مصفوفة لويب هوك، مشغّل يدوي دفعي) مباشرةً من منتقي المتغيّرات.
عندما تُرجِع خطوة **Code** أو **Logic Function** *مصفوفة من المستوى الأعلى*، يظهر ناتجها في منتقي المتغيّرات كعناصر مفهرسة (`0`، `1`، `2`، …). للتكرار على المصفوفة بالكامل، اختر خيار **Whole list** لتلك الخطوة — عندها يستنتج عنصر Iterator شكل كل عنصر من القائمة تلقائيًا.
## الإعداد الأساسي
### مثال: إرسال بريد إلكتروني للجميع ضمن نتائج البحث
**الهدف**: العثور على جميع جهات الاتصال في شركة محددة وإرسال بريد إلكتروني مخصص لكلٍ منهم.
### الخطوة 1: البحث عن سجلات
1. أضف إجراء **Search Records**
2. الكائن: **People**
3. عامل التصفية: Company يساوي "Acme Inc"
4. يُرجِع هذا مصفوفة من الأشخاص
### الخطوة 2: التحقق من وجود نتائج
1. أضف إجراء **Filter**
2. الشرط: `{{searchRecords.length}}` أكبر من 0
3. يمنع هذا أخطاء المكرّر عند كون النتائج فارغة
### الخطوة 3: إضافة Iterator
1. أضف إجراء **Iterator**
2. مدخل المصفوفة: اختر `{{searchRecords}}`
3. هذا ينشئ حلقة تكرار
### الخطوة 4: إضافة إجراءات داخل المكرّر
الإجراءات الموضوعة بعد Iterator تُشغَّل لكل عنصر:
1. إضافة إجراء **إرسال البريد الإلكتروني** (داخل الترتيب)
2. إلى: `{{iterator.currentItem.email}}`
3. الموضوع: مرحباً `{{iterator.currentItem.firstName}}`!
4. المتن: رسالة مخصّصة باستخدام حقول العنصر الحالي
### النتيجة
إذا أعاد Search Records 5 أشخاص، فسيقوم المكرّر بما يلي:
* يرسل بريداً إلكترونياً إلى الشخص 1
* يرسل بريداً إلكترونياً إلى الشخص 2
* ... يستمر لكل الأشخاص الخمسة
## الوصول إلى بيانات العنصر الحالي
داخل المكرّر، استخدم `{{iterator.currentItem}}` للوصول إلى السجل الحالي:
| المتغيّر | الوصف |
| --------------------------------------- | -------------------------------------- |
| `{{iterator.currentItem}}` | كائن السجل الحالي بالكامل |
| `{{iterator.currentItem.id}}` | معرّف السجل |
| `{{iterator.currentItem.email}}` | حقل البريد الإلكتروني |
| `{{iterator.currentItem.company.name}}` | اسم الشركة المرتبطة |
| `{{iterator.index}}` | الموضع الحالي في المصفوفة (بدءاً من 0) |
في منتقي المتغيّرات، يمكنك إما التعمّق في حقل معيّن من العنصر الحالي، أو اختيار **Use the whole item** للإشارة إلى العنصر الحالي بالكامل (`{{iterator.currentItem}}`). يكون اختيار العنصر بالكامل مفيدًا عندما تريد تمرير سجل كامل مباشرةً إلى خطوة لاحقة في خط التدفق بدلًا من إعادة بنائه حقلًا بحقل.
## أنماط شائعة
### تحديث عدة سجلات
**الهدف**: وضع علامة "متأخر" على جميع المهام المتأخرة عن موعدها
```
1. Search Records (Tasks, Due Date < Today, Status ≠ Completed)
2. Filter (length > 0)
3. Iterator (searchRecords)
└── Update Record
- Object: Tasks
- Record: {{iterator.currentItem.id}}
- Status: Late
```
### إنشاء سجلات من مصفوفة
**الهدف**: يتلقى الويبهوك طلباً يتضمن عدة عناصر، وإنشاء سجل لكل عنصر
```
1. Webhook Trigger (receives items array)
2. Filter (items.length > 0)
3. Iterator (trigger.body.items)
└── Create Record
- Object: Order Items
- Name: {{iterator.currentItem.name}}
- Quantity: {{iterator.currentItem.qty}}
- Related Order: {{trigger.body.orderId}}
```
### معالجة مشروطة داخل الحلقة
**الهدف**: إرسال بريد إلكتروني فقط لجهات الاتصال ذات العناوين الصالحة
```
1. Search Records (People)
2. Iterator (searchRecords)
└── Filter (currentItem.email is not empty)
└── Send Email
- To: {{iterator.currentItem.email}}
```
## استكشاف الأخطاء وإصلاحها
### "المكرّر يتوقع مصفوفة"
**السبب**: مرّرت سجلاً مفرداً بدلاً من مصفوفة.
**الإصلاح**: تأكّد من أنك تمرّر ناتج Search Records أو حقلاً من نوع مصفوفة، وليس سجلاً مفرداً.
```
✅ Correct: {{searchRecords}}
❌ Wrong: {{searchRecords[0]}}
```
### المكرّر لا يعمل
**السبب**: المصفوفة فارغة.
**الإصلاح**: أضف عامل تصفية قبل Iterator للتحقق من طول المصفوفة:
```
Filter: {{searchRecords.length}} > 0
```
### الإجراءات تُشغَّل مرات كثيرة جداً
**السبب**: أعاد Search Records سجلات أكثر مما هو متوقّع.
**الإصلاح**:
* أضف عوامل تصفية أكثر تحديداً إلى Search Records
* عيّن حداً في Search Records (بحد أقصى 200)
* أضف عامل تصفية داخل المكرّر لشروط إضافية
## اعتبارات الأداء
* **استخدام الأرصدة**: كل دورة تستهلك أرصدة لإجراءاتها
* **الوقت**: تستغرق المصفوفات الكبيرة وقتاً أطول للمعالجة
* **القيود**: فكّر في تنفيذ العمليات الكبيرة جداً على دفعات
* **قيود المعدّل**: قد تصل استدعاءات واجهات برمجة التطبيقات الخارجية إلى حدود المعدّل مع كثرة التكرارات
## أفضل الممارسات
1. **تحقق دائماً من طول المصفوفة** قبل Iterator لتجنّب الأخطاء
2. **أضف عوامل تصفية داخل الحلقات** عندما لا تحتاج جميع العناصر إلى معالجة
3. **أعد تسمية خطوة Iterator** لوصف ما تقوم بالتكرار عليه
4. **اختبر باستخدام مصفوفات صغيرة** قبل معالجة مجموعات بيانات كبيرة
5. **راقب تشغيلات سير العمل** لضمان اكتمال التكرارات كما هو متوقّع
## ذات صلة
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [كيفية استخدام التفرعات](/l/ar/user-guide/workflows/capabilities/use-branches-in-workflows)
* [الأسئلة الشائعة حول سير العمل](/l/ar/user-guide/workflows/how-tos/need-more-help/workflows-faq)

View File

@@ -0,0 +1,332 @@
---
title: إجراءات سير العمل
description: تعرّف على الإجراءات المتاحة في عمليات سير العمل في Twenty.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
## حول الإجراءات
تحدد الإجراءات ما يحدث بعد تنفيذ الزناد. يمكنك تسلسل عدة إجراءات معًا لبناء عمليات أتمتة معقدة.
<Tip>
* استخدم منتقي المتغيرات (انقر أيقونة `(x+)`) لاستعراض البيانات المتاحة من الخطوات السابقة
* مرّر المؤشر فوق أي حقل إدخال لمعرفة الخطوة التي يأتي منها المتغير — وهو أمر مفيد عندما يوجد الحقل نفسه (مثلًا، ID) في عدة خطوات سابقة
* امنح كل إجراء اسمًا وصفيًا لتسهيل الصيانة
</Tip>
## إجراءات السجل
<img src="/images/user-guide/workflows/workflow_actions.png" style={{width:'100%'}} />
### إنشاء سجل
يضيف سجل جديد إلى كائن محدد.
**الإعداد**:
* اختر الكائن المستهدف
* املأ الحقول الضرورية والاختيارية
* استخدم البيانات من الخطوات السابقة أو أدخِل القيم يدويًا لملء الحقول
**المخرجات**: بيانات السجل المنشأ حديثاً متاحة للاستخدام في الخطوات التالية.
### تحديث السجل
يقوم بتعديل سجل موجود في كائن محدد.
<img src="/images/user-guide/workflows/update_record.png" style={{width:'100%'}} />
**الإعداد**:
* اختر الكائن المستهدف
* اختر السجل المحدد لتحديثه.
* يمكنك إما اختيار سجل ثابت، باستخدام القائمة المنسدلة التي تعرض جميع السجلات المتاحة.
* أو يمكنك اختيار السجل ديناميكيًا بتحديد سجل تم العثور عليه في خطوة سابقة، باستخدام `(x+)`. لا يمكنك البحث عن السجل بناءً على معايير مختلفة في هذه المرحلة. إذا لم تكن قد حدّدت السجل بعد، فأضِف خطوة `Search Record` قبل خطوة `Update Record`.
* اختر الحقول لتعديل القيم وأدخل القيم الجديدة
**المخرجات**: بيانات السجل المحدثة متاحة للاستخدام في الخطوات التالية.
### حذف السجل
يزيل سجلاً من كائن محدد.
**التكوين**:
* اختر الكائن المستهدف
* اختر السجل المحدد لحذفه
**المخرجات**: تظل بيانات السجل المحذوف متاحة للاستخدام في الخطوات التالية.
### البحث في السجلات
يجد السجلات داخل كائن معين باستخدام شروط التصفية.
**التكوين**:
* اختر الكائن للبحث
* حدد معايير التصفية لتضييق النتائج
* قم بتكوين الفرز والقيود
**المخرجات**: تعيد السجلات المطابقة التي يمكن استخدامها في الخطوات اللاحقة.
<Note>
**الحد**: تعيد Search Records بحد أقصى **200 سجل**. إذا كنت بحاجة إلى معالجة المزيد، فأضِف عوامل تصفية محددة لتقليل النتائج أو استخدم عمليات سير عمل مجدولة للمعالجة على دفعات.
</Note>
**أفضل الممارسات**: استخدم [الفروع](/l/ar/user-guide/workflows/capabilities/workflow-branches) بعد Search Records للتعامل مع سيناريوهات "تم العثور" مقابل "لم يتم العثور".
### إدراج أو تحديث سجل
ينشئ سجلًا جديدًا أو يحدّث سجلًا موجودًا استنادًا إلى معايير المطابقة. يكون هذا مفيدًا عندما لا تكون متأكدًا مما إذا كان السجل موجودًا بالفعل.
<img src="/images/user-guide/workflows/upsert_double_identifier.png" style={{width:'100%'}} />
**التكوين**:
* اختر الكائن المستهدف
* لاحظ الحقول التي يمكن استخدامها للمطابقة: email لـ People، وdomain لـ Companies، وID لأي كائن، أو أي حقل مُعلَّم كـ Unique. ستحتاج إلى تعبئة واحد على الأقل من هذه الحقول أدناه.
* املأ قيم الحقول. لا تنسَ تعبئة معرّف فريد واحد على الأقل.
<Note>
**تعمل المطابقة عادةً بشكل أفضل عند إضافة معرّف فريد واحد فقط.** على سبيل المثال، ستطابق لقطة الشاشة أدناه الشركات استنادًا إلى domain الخاص بها. لا تكون قيمة ID مطلوبة بالضرورة.
</Note>
<img src="/images/user-guide/workflows/upsert_simple_identifier.png" style={{width:'100%'}} />
* استخدم البيانات من الخطوات السابقة لملء الحقول
**كيف يعمل**:
1. يبحث عن سجل يطابق معاييرك
2. إذا تم العثور عليه → يحدّث السجل الموجود
3. إذا لم يُعثر عليه → ينشئ سجلًا جديدًا
**المخرجات**: بيانات السجل التي تم إنشاؤها أو تحديثها متاحة للاستخدام في الخطوات التالية.
## إجراءات التدفق
### مكرر
**يتكرر عبر مصفوفة من السجلات** المُعادة من خطوة سابقة، مما يتيح لك تنفيذ إجراءات على كل سجل بشكل فردي.
**التكوين**:
* حدد مجموعة من السجلات من خطوة سابقة (على سبيل المثال، النتائج من سجلات البحث، من المشغل اليدوي مع توفر الكبريت، من عقدة البرمجة). عندما تُرجِع خطوة Code أو دالة منطقية مصفوفة من المستوى الأعلى، حدِّد خيار **Whole list** للتكرار عبر الإخراج بالكامل.
* حدد الإجراءات لتنفيذها على كل سجل في الحلقة.
<Note>
- يمكنك إضافة عدة إجراءات داخل ترتير.
- عند استخدام الفروع داخل ترتير، تأكد من أن الخطوة الأخيرة من كل فرع تتصل بعودة إلى ترتور لإغلاق الحلقة التكرارية.
</Note>
* الوصول إلى حقول `Current Item`: لاستخدام حقول السجل الجاري معالجته، انقر على خطوة **المُكرِّر**، ثم اختر **العنصر الحالي**. ستُعرَض قائمة الحقول المتاحة من ذلك السجل ويمكن اختيارها لاستخدامها في الإجراءات اللاحقة. يمكنك أيضًا تحديد **Use the whole item** لتمرير العنصر الحالي بالكامل إلى خطوة لاحقة.
<VimeoEmbed videoId="1146577247" title="عرض توضيحي بالفيديو" />
### تصفية
يقوم بتصفية السجلات بناءً على الشروط المحددة، مما يسمح فقط للسجلات التي تلبي المعايير بالمرور.
**التكوين**:
* اختر السجل لتصفيته
* حدد شروط ومعايير التصفية
* قم بتكوين السجلات التي يجب أن تمر إلى الخطوات اللاحقة
<Note>
1. **المخرجات**: عُقد التصفية لا تُرجِع بيانات — فهي تعمل كبوابات. إذا تم استيفاء الشروط، يتابع سير العمل. وإلا سيتوقف سير العمل عند ذلك الفرع.
2. يمكن استخدام العامل `IS` مع الحقول الرقمية. يعمل كأنه `EQUAL`.
</Note>
### التأخير
يُوقف تنفيذ سير العمل لمدة محددة أو حتى تاريخ/وقت معين.
**أنواع التأخير**:
| النوع | الوصف |
| ---------------- | ----------------------------------------------------- |
| **المدة** | الانتظار لمدة زمنية محددة (أيام، ساعات، دقائق، ثوانٍ) |
| **تاريخ مُجدول** | الانتظار حتى تاريخ ووقت محددين |
**إعدادات المدة**:
* تعيين الأيام والساعات والدقائق و/أو الثواني
* دمج وحدات متعددة (مثل يومين و4 ساعات)
**إعدادات التاريخ المُجدول**:
* اختر تاريخًا ووقتًا
* يمكن الإشارة إلى حقل تاريخ من خطوة سابقة (مثل المتابعة بعد 3 أيام من اجتماع)
**حالات الاستخدام**:
* انتظر 24 ساعة قبل إرسال بريد متابعة إلكتروني
* إيقاف مؤقت حتى تاريخ إغلاق الفرصة
* جدولة الإجراءات ضمن ساعات العمل
<Note>
لا يمكن أن يكون التاريخ المُجدول في الماضي. إذا استُخدم حقل تاريخ من خطوة سابقة وكان التاريخ قد مضى بالفعل، فسيفشل سير العمل.
</Note>
**الحدود والرصيد**:
* **لا يوجد حد أقصى للمدة** — يمكنك تعيين تأخيرات بالدقائق أو الأيام أو الأسابيع أو أكثر
* **يُستهلَك رصيد واحد** عند تنفيذ عقدة التأخير، بغض النظر عن المدة
* **لا يُستهلك أي رصيد** أثناء الانتظار — تأخير 5 دقائق يكلف مثل تأخير 5 أيام
## إجراءات الاتصال
### إرسال البريد الإلكتروني
يرسل بريدًا إلكترونيًا من سير العمل الخاص بك. هذا رائع لرسائل البريد الجماعية المعتمدة على قوالب. ستبدو رسائل البريد الإلكتروني مثل تلك التي ترسلها من صندوق بريدك.
وهو غير مناسب للنشرات الإخبارية (التي تتطلب تنسيقا أغنى) أو تسلسل البريد الإلكتروني الآلي.
**المتطلبات الأساسية**: أضف حساب بريد إلكتروني في الإعدادات → الحسابات
**التكوين**:
* اختر حساب البريد الإلكتروني المُرسل
<Note>
يمكنك إرسال رسائل البريد الإلكتروني فقط من صناديق بريد متزامنة مع حساب Twenty الخاص بك. إرسال الرسائل من صناديق بريد أعضاء الفريق الآخرين (مثل بريد مالك الحساب) ضمن الخطة المستقبلية.
</Note>
في جميع الخطوات التالية، يمكنك الرجوع إلى متغيرات من الخطوات السابقة لأغراض التخصيص.
* ادخل عنوان البريد الإلكتروني المستلم.
<Note>
حاليًا يمكن اختيار مستلم واحد فقط.
</Note>
* اضبط سطر الموضوع.
* قم بإنشاء نص الرسالة. يمكنك تنسيق الروابط، وإنشاء قوائم رقمية، وقوائم نقاط الرصاص، وإضافة مرفقات.
<Note>
إضافة توقيعات HTML غير ممكنة في الوقت الحالي.
</Note>
### نموذج
يعرض نموذجاً أثناء تنفيذ سير العمل لجمع مدخلات المستخدم. يمكن بعد ذلك استخدام الردود في الخطوات اللاحقة لإنشاء سجلات أو إرسال رسائل بريد إلكتروني أو تنفيذ أي إجراء آخر بناءً على المُدخل.
<Warning>
**تم تصميم النماذج للمشغلات اليدوية فقط**. بالنسبة لمهام سير العمل مع محركات أخرى (سجل تم إنشاؤه، تم تحديثه، إلخ)، يمكن الوصول إلى النماذج فقط من خلال واجهة تشغيل سير العمل، وهو ليس التجربة المتوقعة. وسيصدر مركز للإخطار في عام 2026 لتقديم الدعم المناسب لاستمارات تدفق العمل الآلي.
</Warning>
**التكوين**:
* قم بتهيئة الحقول التي سيُطلب من المستخدمين تعبئتها. لكل حقل، اختر
* نوعًا من بين: نص، رقم، تاريخ، سجل مُعطى، حقل اختيار. الحقول من جميع الكائنات متاحة للاختيار.
* تسمية
* قيمة افتراضية ضمن `Placeholder` (اختياري)
* حرّر عنوان النموذج
**المخرجات**: استجابات النموذج متاحة للاستخدام في الخطوات اللاحقة.
**مثال**: سير العمل "الرصاص السريع" متاح بشكل افتراضي في جميع مساحات العمل، متاح في أي مكان في قائمة الأوامر 'Cmd+K\`.
**كيفية تعبئة النموذج**:
* تفعيل سير العمل اليدوي الخاص بك من قائمة الأوامر `Cmd+K`
* املأ النموذج المعروض في اللوحة الجانبية ثم انقر `Submit`.
<Note>
لا يمكن جعل الحقول إلزامية.
</Note>
<VimeoEmbed videoId="1147277989" title="عرض توضيحي بالفيديو" />
## إجراءات التكامل
### كود
يشغل جافا سكريبت مخصص ضمن سير العمل الخاص بك.
في الخلفية، يستند كل إجراء Code إلى **دالة منطقية** خاصة به — وهي دالة TypeScript على جانب الخادم تعمل على منصة Twenty. عندما تضيف إجراء Code، يقوم Twenty بإنشاء دالة منطقية مخصَّصة لتلك الخطوة ويُظهِر محرِّرها مضمَّنًا، بحيث يكون الكود الذي تكتبه جزءًا من سير العمل.
**التكوين**:
* الوصول إلى المتغيرات من الخطوات السابقة. يمكنك تعديل أسماء المتغيرات بشكل ديناميكي.
<VimeoEmbed videoId="1147281795" title="عرض توضيحي بالفيديو" />
* اكتب شيفرة جافا سكريبت في المحرر
* إرجاع المتغيرات للاستخدام في الخطوات اللاحقة
* اختبر الكود مباشرة في الخطوة
<Note>
إذا كنت بحاجة إلى استخدام مفاتيح API خارجية في كودك، فيجب إدخالها مباشرةً في جسم الدالة. لا يمكنك تكوين مفاتيح API في مكان آخر والإشارة إليها في الدالة المنطقية.
</Note>
<Tip>
**هل تعمل مع المصفوفات؟** قد تأتي المصفوفات من أنظمة خارجية أو من خطوات سابقة على هيئة سلاسل نصية. راجع [كيفية التعامل مع المصفوفات في إجراءات Code](/l/ar/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions) للحل.
</Tip>
<Tip>
انقر على أيقونة المربع في أعلى يمين محرر الكود لعرضه بملء الشاشة — فهذا مفيد لأن عرض المحرر الافتراضي محدود.
</Tip>
#### إعادة استخدام دالة منطقية عبر سير عمل متعددة
إجراء Code المضمَّن ممتاز للمنطق لمرة واحدة، لكن الكود الذي يحتويه يخص تلك الخطوة الواحدة فقط. عندما تريد مشاركة المنطق نفسه عبر عدة سير عمل — أو الاحتفاظ به كمصدر مُدار بالإصدارات ضمن تطبيق — عرِّف **دالة منطقية قابلة لإعادة الاستخدام** بدلًا من نسخ ولصق الكود في كل إجراء Code.
يتم تعريف دالة منطقية مرة واحدة في تطبيق (باستخدام `defineLogicFunction` في حزمة SDK) وتُتاح في مُنشئ سير العمل عن طريق إضافة `workflowActionTriggerSettings`. بمجرد تثبيت تطبيقك، تظهر تلك الدالة كإجراء مستقل في مُنشئ سير العمل، جنبًا إلى جنب مع الإجراءات المضمَّنة. يؤدي اختيارها إلى عرض حقول الإدخال التي صرَّحتَ عنها (مع منتقي المتغيّرات، تمامًا مثل الإجراءات الأخرى) وتشغيل الكود المشترك — دون الحاجة إلى JavaScript مضمَّن.
| | إجراء Code | دالة منطقية قابلة لإعادة الاستخدام |
| ------------------- | --------------------------------------------- | ----------------------------------------------------------------------- |
| **مكان وجود الكود** | محرِّر مضمَّن، مرتبط بخطوة واحدة في سير العمل | يُعرَّف في تطبيق، مع إدارة الإصدارات في نظام التحكم في الشيفرة المصدرية |
| **إعادة الاستخدام** | يتم نسخه ولصقه لكل خطوة | يُضاف كإجراء في أي سير عمل |
| **المدخلات** | متغيّرات موصولة في المحرِّر | حقول تُعرَض من مخطط الإدخال الذي صرَّحتَ عنه |
| **الأفضل لـ** | منطق سريع خاص بسير عمل معيّن | منطق مشترك يُستخدَم عبر عدة سير عمل |
كلاهما يعمل على بيئة تشغيل الدالة المنطقية نفسها، لذا يمكن ترقية إجراء Code الذي جرَّبته مضمَّنًا لاحقًا إلى دالة منطقية قابلة لإعادة الاستخدام مع تغييرات طفيفة.
<Tip>
للاطّلاع على مرجع موجَّه للمطوّرين حول تعريف الدوال المنطقية وإتاحتها في مُنشئ سير العمل، راجع صفحة [Logic Functions](/l/ar/developers/extend/apps/logic/logic-functions) — وخصوصًا قسم **Exposing a function as an AI tool or workflow action** و `workflowActionTriggerSettings`.
</Tip>
### طلب HTTP
يرسل طلبًا إلى واجهة برمجية خارجية كجزء من سير العمل الخاص بك.
<img src="/images/user-guide/workflows/http_action.png" style={{width:'100%'}} />
**التكوين**:
* ادخل عنوان رابط واجهة برمجية. يمكن استخدام معاملات من خطوات سابقة.
* اختر طريقة HTTP (GET, POST, PUT, PATCH, DELETE)
* أضف الرؤوس والقيم المطلوبة
* قدّم مثالًا للمخرجات لمعاينة البنية
## إجراءات الذكاء الاصطناعي
### وكيل ذكاء اصطناعي - قريبًا
يشغّل وكيل ذكاء اصطناعي داخل سير العمل لديك لتنفيذ مهام ذكية.
**التكوين**:
* **الوكيل**: اختر وكيلاً للذكاء الاصطناعي موجودًا أو استخدم الوكيل الافتراضي
* **المطالبة**: اكتب التعليمات لوكيل الذكاء الاصطناعي
* ارجع إلى متغيرات من خطوات سابقة داخل المطالبة
**ما الذي يمكن لوكلاء الذكاء الاصطناعي فعله**:
* تحليل البيانات وتلخيصها
* تصنيف السجلات أو توزيعها ضمن فئات
* إنشاء محتوى نصي
* اتخاذ قرارات بناءً على البيانات
* التفاعل مع بيانات نظام إدارة علاقات العملاء لديك باستخدام الأدوات
**المخرجات**: رد وكيل الذكاء الاصطناعي متاح للاستخدام في الخطوات التالية. إذا كان للوكيل مخطط مخرجات مُهيكل، فسيتبع الرد ذلك التنسيق.
<Note>
تستهلك إجراءات وكيل الذكاء الاصطناعي أرصدة سير العمل بناءً على نموذج الذكاء الاصطناعي المستخدم. راجع [أرصدة سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-credits) للحصول على التفاصيل.
</Note>
<Note>
يحترم وكلاء الذكاء الاصطناعي الأذونات المستندة إلى الأدوار. يمكنك تعيين أدوار محددة للوكلاء ضمن **الإعدادات → الأعضاء → الأدوار** للتحكم في البيانات التي يمكنهم الوصول إليها. راجع [الأذونات](/l/ar/user-guide/permissions-access/capabilities/permissions) للحصول على التفاصيل.
</Note>

View File

@@ -0,0 +1,66 @@
---
title: تفرعات سير العمل
description: أنشئ مسارات متوازية ومنطقًا شرطيًا في سير العمل لديك.
---
تتيح لك التفرعات تقسيم سير العمل إلى مسارات متعددة يمكن أن تعمل بالتوازي أو بشكل شرطي استنادًا إلى بياناتك.
<img src="/images/user-guide/workflows/branches.png" style={{width:'100%'}} />
## كيفية عمل التفرعات
عند إنشاء عدة اتصالات من عقدة واحدة، يصبح كل مسار تفرعًا. افتراضيًا، **تُنفَّذ جميع التفرعات بالتوازي**—ولا تنتظر بعضها بعضًا.
## إنشاء التفرعات
### إضافة تفرع جديد
1. **انقر بزر الماوس الأيمن على اللوحة الرئيسية** لسير العمل (وليس على عقدة موجودة)
2. انقر على **إضافة عقدة**
3. اختر نوع العقدة لتفرعك الجديد
4. اسحب سهمًا من أسفل الخطوة السابقة إلى أعلى هذا الإجراء الجديد
5. كرّر لإضافة مزيد من التفرعات من العقدة نفسها
<Note>
كل تفرع مستقل. إن إضافة تفرع لا يؤثر في المسارات الأخرى الموجودة من تلك العقدة.
</Note>
### التخطيط المرئي
تظهر التفرعات كمسارات متوازية في محرر سير العمل. يمكنك سحب العقد لإعادة ترتيب التخطيط المرئي دون التأثير في التنفيذ.
## التفرعات الشرطية
نظرًا إلى أن جميع التفرعات تعمل افتراضيًا، استخدم عقد **عامل التصفية** للتحكم في المسارات التي تُنفَّذ فعليًا:
| التفرع | شرط عامل التصفية | الإجراء |
| ------ | ----------------------- | --------------------------- |
| A | المرحلة = "Won" | إرسال بريد إلكتروني للتهنئة |
| B | المرحلة = "Lost" | إنشاء مهمة متابعة |
| C | المرحلة = "Negotiation" | إخطار المدير |
1. أنشئ تفرعات من المشغّل لديك أو الإجراء
2. أضف عقدة **عامل التصفية** بوصفها الخطوة الأولى في كل تفرع
3. قم بإعداد كل عامل تصفية بشروط متبادلة الاستبعاد
4. أضف إجراءاتك بعد كل عامل تصفية
سيتابع التنفيذ فقط التفرع/التفرعات التي يتحقق فيها شرط عامل التصفية.
## دمج التفرعات
**لا تُدمَج التفرعات تلقائيًا.** يعمل كل تفرع بشكل مستقل حتى ينتهي. لديك مرونة كاملة في كيفية التعامل مع ذلك:
* **الخيار 1: إبقاء التفرعات منفصلة**
يتولى كل تفرع إجراءات المتابعة الخاصة به بشكل مستقل. هذه أبسط مقاربة عندما لا تحتاج التفرعات إلى الالتقاء.
* **الخيار 2: دمج التفرعات يدويًا**
عند إنشاء سير العمل، يمكنك توصيل عدة تفرعات يدويًا بالإجراء اللاحق نفسه. ما عليك سوى سحب الأسهم من نهاية كل تفرع إلى عقدة مشتركة.
<Note>
بينما يمكنك استخدام عقدة [Delay](/l/ar/user-guide/workflows/capabilities/workflow-actions#delay) لإيقاف التنفيذ مؤقتًا، إلا أنه لا يمكن ضبطها حاليًا للانتظار "حتى ينتهي تفرع آخر".
</Note>
## ذات صلة
* [كيفية استخدام التفرعات في سير العمل](/l/ar/user-guide/workflows/capabilities/use-branches-in-workflows) - دليل خطوة بخطوة
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions) - الإجراءات المتاحة بما في ذلك عامل التصفية

View File

@@ -0,0 +1,75 @@
---
title: رصيد سير العمل
description: فهم استهلاك أرصدة سير العمل وإدارتها.
---
أرصدة سير العمل تدعم عمليات الأتمتة لديك في Twenty. فهم كيفية عملها يساعدك على تحسين التكاليف وإدارة ميزانية الأتمتة بفعالية.
## تخصيص الأرصدة
تخصص أرصدة سير العمل بناء على دورة الفوترة لديك، وليس على مستوى خطتك:
| دورة الفوترة | الأرصدة |
| --------------- | ---------------- |
| **اشتراك شهري** | 5 أرصدة في الشهر |
| **اشتراك سنوي** | 50 رصيد في السنة |
<Note>
تعد 5 أرصدة في الشهر سخية لعمليات الأتمتة القياسية. لن تتجاوز معظم الفرق هذا الحد مع استخدام سير العمل النموذجي. تكون الحاجة إلى أرصدة إضافية أساسًا لإجراءات Code المتقدمة ولعمليات سير العمل المدعومة بالذكاء الاصطناعي.
</Note>
## كيف يعمل استهلاك الرصيد
يتم استهلاك الأرصدة عند تنفيذ عمليات سير العمل، وليس عند إنشائها. يستهلك كل إجراء سير عمل الرصيد بناءً على تعقيده.
### استهلاك الرصيد حسب نوع الإجراء
* **العمليات الأساسية الداخلية**: استهلاك رصيد منخفض جدًا
* البحث في السجلات
* إنشاء سجل
* تحديث السجل
* حذف السجل
* إجراءات النماذج
* **عمليات معقدة**: استهلاك أعلى للأرصدة
* إجراءات الكود (تنفيذ JavaScript)
* طلبات HTTP إلى الخدمات الخارجية
* **ميزات الذكاء الاصطناعي**: استهلاك أعلى للأرصدة
* تستهلك إجراءات وكيل الذكاء الاصطناعي الأرصدة بناء على نموذج الذكاء الاصطناعي المستخدم
* تستخدم المطالبات الأكثر تعقيدا والمخرجات الأطول أرصدة أكثر
* **إجراءات التأخير**: استهلاك ضئيل للأرصدة
* تستهلك عقدة Delay **رصيد واحد** عند التنفيذ
* **لا تستهلك أي أرصدة** خلال فترة الانتظار
* التأخير لمدة 5 دقائق يكلف المقدار نفسه مثل التأخير لمدة 5 أيام
### الخصم في الوقت الحقيقي
يتم خصم الرصيد في الوقت الفعلي عند تنفيذ سير العمل. هذا يعني:
* لا تستهلك مسودات سير العمل أرصدة.
* لا تستخدم مخصص الأرصدة لديك إلا عمليات سير العمل النشطة والجارية.
* تظل عمليات سير العمل الفاشلة تستهلك أرصدة مقابل الخطوات المكتملة.
## إدارة الرصيد
### التحقق من استخدام الرصيد
1. اذهب إلى **الإعدادات → الفواتير**
2. اعرض استهلاكك الحالي من الأرصدة والرصيد المتبقي
3. راقب أنماط الاستخدام لتحسين عمليات سير العمل لديك
### شراء رصيد إضافي
إذا كنت بحاجة إلى المزيد من الأرصدة بما يتجاوز مخصص خطتك:
1. اذهب إلى **الإعدادات → الفواتير**
2. اضغط على الخيار لشراء رصيد إضافي. توفر باقات بأحجام مختلفة.
3. يتم إضافة الرصيد إلى الرصيد الحالي الخاص بك.
## أفضل الممارسات
* **تجهيز الدفعات**: استخدم العمليات الضخمة وإجراءات الترميز بكفاءة لتقليل المكالمات الفردية
* **تحسين المشغلات اليدوية**: بالنسبة للمشغلات اليدوية، اختر خيار التوفر `Bulk` لمعالجة سجلات متعددة في تشغيل واحد لسير عمل
* تحسين إجراءات الكود للكفاءة

View File

@@ -0,0 +1,93 @@
---
title: عمليات تشغيل سير العمل
description: راقِب وأدِر عمليات تنفيذ سير العمل.
---
## حول عمليات التشغيل
**تشغيل** هو سجل لتنفيذ سير العمل. في كل مرة يتم فيها تشغيل سير عمل—سواءً بواسطة حدث سجل، أو جدول زمني، أو إجراء يدوي، أو خطاف ويب—يتم إنشاء عملية تشغيل جديدة.
## عرض عمليات التشغيل
### من محرر سير العمل
1. افتح سير العمل الذي تريد مراقبته
2. انقر على لوحة **التشغيل** في الجانب الأيمن
3. اطلع على قائمة بأحدث عمليات التشغيل مع حالتها
### من عرض عمليات تشغيل سير العمل
1. انتقل إلى **عمليات تشغيل سير العمل** في الشريط الجانبي
2. اعرض عمليات التشغيل عبر جميع سير العمل
3. رشّح حسب الحالة أو سير العمل أو التاريخ
## حالات التشغيل
| الحالة | الوصف |
| ---------------- | ----------------------------------------------------------------- |
| **جارٍ التنفيذ** | سير العمل قيد التنفيذ حاليًا |
| **مكتمل** | انتهى سير العمل بنجاح |
| **فشل** | واجه سير العمل خطأً وتوقّف |
| **في انتظار** | سير العمل متوقف مؤقتًا (مثال: ينتظر إجراء التأخير أو إرسال نموذج) |
## تفاصيل عملية التشغيل
انقر على أي عملية تشغيل للاطلاع على:
* **الحالة**: الوضع الحالي لعملية التشغيل
* **وقت البدء**: وقت بدء عملية التشغيل
* **المدة**: الوقت الذي استغرقته عملية التشغيل
* **بيانات المُشغِّل**: المُدخل الذي بدأ سير العمل
* **مخرجات الخطوة**: البيانات التي ترجعها كل خطوة
* **رسائل الخطأ**: إذا فشلت عملية التشغيل، ما الخطأ الذي حدث
## تنفيذ خطوة بخطوة
تعرض كل عملية تشغيل التقدم خلال سير عملك:
1. اطلع على الخطوات التي اكتملت بنجاح
2. حدّد مواضع حدوث الفشل
3. اعرض البيانات الممررة بين الخطوات
4. استكشف المشكلات وأصلحها بفحص مدخلات الخطوات ومخرجاتها
## التعامل مع الأخطاء
عند فشل عملية تشغيل:
1. افتح عملية التشغيل الفاشلة
2. حدّد الخطوة التي تسببت في الفشل
3. تحقق من رسالة الخطأ للتفاصيل
المشكلات الشائعة:
* الحقول المطلوبة المفقودة
* تنسيق بيانات غير صالح
* أخطاء واجهة برمجة التطبيقات الخارجية
* مشكلات الصلاحيات
## إعادة تشغيل سير العمل
إذا فشلت عملية تشغيل، يمكنك:
* إصلاح المشكلة الأساسية وانتظار المحفّز التالي
* بالنسبة لسير العمل اليدوي، أعد تشغيله باستخدام البيانات نفسها أو بيانات محدّثة
* راجع منطق سير العمل لمنع الإخفاقات المستقبلية
## نصائح الأداء
### إدارة سجل التشغيل
* يتم الاحتفاظ بالأنابيب للمراجع التاريخية
* قد يتم أرشفة التطبيقات القديمة جداً تلقائيًا
* تصدير بيانات التشغيل إذا كنت بحاجة إلى الاحتفاظ بسجلات
### رصد أفضل الممارسات
* التحقق من التشغيل بانتظام بعد تفعيل سير العمل الجديد
* مراجعة عمليات التشغيل الفاشلة لتحديد الأنماط
## ذات صلة
* [محفّزات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [استكشاف الأخطاء في سير العمل](/l/ar/user-guide/workflows/how-tos/need-more-help/workflow-troubleshooting)

View File

@@ -0,0 +1,137 @@
---
title: محفزات سير العمل
description: تعرّف على المحفزات المختلفة التي تُشغِّل سير العمل لديك.
---
## حول المحفزات
تبدأ سير العمل دائمًا بمحفز واحد يحدد متى ينبغي تشغيل الأتمتة.
<img src="/images/user-guide/workflows/workflow_triggers.png" style={{width:'100%'}} />
<Tip>
**الكائنات المتقدمة مدعومة!** إلى جانب كائنات CRM القياسية (الأشخاص، الشركات، الفرص)، يمكنك أيضًا تشغيل سير العمل وتنفيذ إجراءات على:
* أعضاء مساحة العمل
* أحداث التقويم
* الرسائل (رسائل البريد الإلكتروني)
* المهام، والملاحظات، والعديد من كائنات النظام الأخرى
يفتح هذا المجال لأتمتة قوية مثل إشعار أعضاء الفريق عند إنشاء أحداث التقويم، أو معالجة رسائل البريد الإلكتروني الواردة تلقائيًا.
</Tip>
## إنشاء سجل
يبدأ سير العمل عندما يتم إنشاء سجل جديد في كائن محدد (أشخاص أو شركات أو فرص أو أي كائن مخصص).
**التكوين**: حدد نوع الكائن لمراقبة السجلات الجديدة.
<Note>
* هذا المشغل رائع للسجلات التي تم إنشاؤها بواسطة CSV، علبة البريد ومزامنة التقويم، أو API.
* **لا يُنصح به للسجلات التي تُنشأ يدويًا**: مع هذا المحفز، تبدأ عمليات سير العمل فور إنشاء السجل. نظرًا لأن واجهة المستخدم العشرين توفر الحفظ التلقائي على متن الطائرة (لا يوجد وضع تحرير ثم التحقق لحفظ السجلات)، سيتم تشغيل سير العمل قبل أن يقوم المستخدم بإدخال جميع الحقول.
لتشغيل سير العمل هذا على السجلات التي تم إنشاؤها يدويًا، يُوصى باستخدام المحفز `Record is created or updated` بدلًا من ذلك.
</Note>
## تحديث السجل
يبدأ سير العمل عندما يتم إجراء تغييرات على سجل موجود.
**التكوين**:
* اختر نوع الكائن
* اختر الحقول التي تريد مراقبتها للتغييرات بشكل اختياري
## تحديث أو إنشاء سجل
يبدأ سير العمل عندما يتم إنشاء أو تحديث سجل في كائن محدد.
**أهمية الموضوع**: هذا المحفز مهم بشكل خاص لأن السجلات التي تنشأ بطرق مختلفة تتصرف بشكل مختلف:
* **استيراد API/CSV**: يتم إنشاء السجلات مع ملء جميع الحقول فورًا
* **الإنشاء اليدوي**: يتم إنشاء السجلات أولاً، ثم يتم إضافة الحقول في التحديثات اللاحقة
**التكوين**:
* اختر نوع الكائن لمراقبته
* اختر الحقول التي تريد مراقبتها للتغييرات بشكل اختياري
* سيتم تشغيل سير العمل في كل من الإنشاء الأولي وأي تحديثات لاحقة
## حذف السجل
يبدأ سير العمل عندما يتم إزالة سجل من كائن.
**التكوين**: حدد نوع الكائن لمراقبة عمليات الحذف.
## المحفز اليدوي
يبدأ سير العمل عندما يتم تشغيله بواسطة إجراء المستخدم. يمكن الوصول إلى هذا المحفز من خلال قائمة `Cmd+K` أو عبر زر مخصص سيُعرض في شريط التنقل العلوي بعد تحديد سجل/سجلات.
<img src="/images/user-guide/workflows/add_to_newsletter_button.png" style={{width:'100%'}} />
**إعداد التوفر**:
اختر كيفية التعامل مع تحديد السجل في سير العمل:
* **العالمي**: لا يتطلب أي سجل لتشغيل سير العمل هذا. يتم تشغيل سير العمل من قائمة الأوامر 'Cmd+K' في أي مكان (من أي كائن)، ولا يستخدم السجل (السجلات) كمدخل.
لتوفر **واحد** و **السائب** ، سيتم تمرير السجلات المحددة إلى سير العمل الخاص بك. تم تكوين هذا لكائن معين، ويمكن تحديد عدة سجلات قبل تشغيل سير العمل.
* **واحد**: سير العمل سيتم تشغيله من البداية إلى النهاية أكبر عدد من المرات التي يتم فيها اختيار السجلات.
<Note>
**حد مرن: 100 عملية تشغيل/دقيقة**. بعد ذلك، تظل عمليات سير العمل في حالة "Not Started" ويتم معالجتها تدريجيًا—إما بواسطة مهمة خلفية أو عندما يدخل سير عمل آخر قائمة الانتظار. هذا يعني أنه يمكنك تحديد أكثر من 100 سجل باستخدام محفز واحد؛ ستكون عملية التنفيذ أبطأ فقط.
</Note>
* **سباب**: سير العمل سيتم تشغيله مرة واحدة، مع توفير قائمة السجلات بأكملها كمدخل. هذا يعني أن سير العمل يحتاج إلى احتواء [إجراء المُكرِّر](/l/ar/user-guide/workflows/capabilities/workflow-actions#iterator).
<Note>
هذا أكثر تقدمًا، وهو الأفضل لمن يرغبون في تحسين عدد مرات تشغيل سير العمل.
</Note>
<img src="/images/user-guide/workflows/manual_trigger.png" style={{width:'100%'}} />
**تكوين إضافي**:
* حدد الكائن المستهدف (للتوفر الفردي والشامل)
* اختر رمز الأمر لتفعيل سير العمل
* قم بتكوين موضع شريط التنقل (مثبت أو غير مثبت)
**طرق الوصول**:
* قائمة `Cmd+K` للعثور على وتشغيل عمليات سير العمل اليدوية
* زر مخصص في شريط التنقل العلوي (إذا تم تكوينه)
## محفز قائم على الوقت: وفق جدول زمني
يبدأ سير العمل على أساس دوري تحدده.
**التكوين**:
* اختر وحدة الوقت (الدقائق، الساعات، الأيام)
* أدخل قيمة أو استخدم تعبيرات كرون مخصصة للجدولة المتقدمة
<Note>
**المنطقة الزمنية**: تعمل عمليات سير العمل المجدولة وفق **UTC**. عند تعيين الساعات للجداول اليومية، حوّل وقتك المحلي إلى UTC.
</Note>
## محفز خارجي: ويب هوك
يبدأ سير العمل عندما يتم استقبال طلب GET أو POST من خدمة خارجية.
<img src="/images/user-guide/workflows/webhook_trigger.png" style={{width:'100%'}} />
**التكوين**:
* يوفر سير العمل عنوان URL فريدًا لويب هوك—انسخه وأضفه إلى نظامك الخارجي كنقطة نهاية للاستدعاء.
* بالنسبة لطلبات POST، حدِّد البنية المتوقعة لمحتوى الطلب حتى يعرف Twenty ما البيانات المتوقع تلقيها. أضف هنا الحقول التي ستستلمها والتي ستكون مطلوبة أدناه في سير العمل لديك.
* قم بتكوين المصادقة (قريبًا).
## اختيار المحفز المناسب
| حالة الاستخدام | المحفز الموصى به |
| ------------------------------------------ | ------------------------ |
| العملاء المحتملون الجدد يحتاجون إلى معالجة | إنشاء سجل |
| تغييرات البيانات تحتاج إلى مزامنة | تحديث السجل |
| استيراد/معالجة البيانات يدويًا | تحديث أو إنشاء سجل |
| التنظيف بعد الحذف | حذف السجل |
| إجراء يبدأه المستخدم | التشغيل يدويًا |
| تقارير متكررة | بجدول زمني |
| تكامل خارجي | ويب هوك أو وفق جدول زمني |

View File

@@ -0,0 +1,84 @@
---
title: إصدارات سير العمل
description: إدارة إصدارات ومسودات سير العمل.
---
## حول الإصدارات
في كل مرة تقوم فيها بتنشيط سير عمل، يتم إنشاء إصدار جديد. يتيح لك ذلك تتبُّع التغييرات بمرور الوقت والرجوع إلى التكوينات السابقة عند الحاجة.
## حالات الإصدارات
| الحالة | الوصف |
| --------- | ----------------------------------- |
| **مسودة** | قيد التحرير، ولم تُنشَر بعد |
| **نشط** | إصدار فعّال يستجيب للمحفِّزات |
| **معطل** | كان نشطًا مسبقًا ولكن أُوقِف يدويًا |
| **مؤرشف** | إصدارات سابقة محفوظة للسجلّ |
## العمل مع المسودات
عند تحرير سير عمل نشط، تُحفَظ تغييراتك كـ **مسودة**. يستمر الإصدار النشط في العمل أثناء عملك على التحديثات.
بعد الانتهاء من التحرير، يمكنك:
* **تنشيط**: نشر المسودة كالإصدار النشط الجديد (يُؤرشف الإصدار السابق)
* **تجاهل**: حذف المسودة والاحتفاظ بالإصدار النشط الحالي
## سجل الإصدارات
### عرض الإصدارات السابقة
1. افتح سير العمل
2. انقر فوق علامة التبويب **الإصدارات**
3. اعرض جميع الإصدارات السابقة مع الطوابع الزمنية
### استعادة إصدار
1. اعثر على الإصدار الذي تريد استعادته
2. انقر **استخدام كمسودة**
3. يُنسَخ الإصدار إلى مسودة جديدة
4. أجرِ أي تحديثات لازمة
5. قم بالتنشيط عند الاستعداد
## أفضل الممارسات
### إدارة الإصدارات
* قم بالتنشيط فقط عند الجاهزية للبيئة الإنتاجية
* حافظ على التغييرات ذات المغزى بين الإصدارات
* وثّق التغييرات الكبرى في أسماء أو أوصاف سير العمل
* اختبر في وضع المسودة قبل التنشيط
### التراجع عن التغييرات
* إذا تسبب إصدار جديد في مشاكل، فاستعد الإصدار السابق
* استخدم سجل الإصدارات لتتبُّع ما تغيّر
* اختبر دائمًا الإصدارات المُستعادة قبل التنشيط
## سير العمل الشائعة
### تحرير سريع
1. أجرِ تغييرات طفيفة على سير عمل نشط
2. اختبر في وضع المسودة
3. قم بتنشيط الإصدار الجديد
### مراجعة رئيسية
1. استخدم الإصدار السابق كنقطة انطلاق
2. أجرِ تغييرات كبيرة في المسودة
3. اختبر جميع السيناريوهات بشكل شامل
4. قم بالتنشيط عندما تكون واثقًا
### الرجوع إلى إصدار سابق
1. حدِّد المشكلة في الإصدار الحالي
2. اعثر على آخر إصدار يعمل في السجل
3. انقر **استخدام كمسودة**
4. قم بالتنشيط لاستعادة السلوك السابق
## ذات صلة
* [البدء مع سير العمل](/l/ar/user-guide/workflows/overview)
* [تشغيلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-runs)

View File

@@ -0,0 +1,82 @@
---
title: التعامل مع المصفوفات في إجراءات Code
description: تعلّم كيفية التعامل بشكل صحيح مع مُدخلات المصفوفات في إجراءات Code في سير العمل.
---
عند العمل مع المصفوفات في إجراءات Code، قد تواجه تحديين شائعين:
1. **مصفوفات مُمرَّرة كسلاسل نصية** — تصل البيانات من الأنظمة الخارجية أو من الخطوات السابقة كسلسلة نصية بدلاً من أن تكون مصفوفة فعلية
2. **لا يمكن تحديد عناصر فردية** — يمكنك تحديد المصفوفة كاملة فقط، وليس الحقول المحددة داخلها
يمكن حل كلا الأمرين باستخدام عقدة Code.
## تحليل المصفوفات من السلاسل النصية
غالباً ما تُمرَّر المصفوفات بين خطوات سير العمل كسلاسل نصية أو JSON بدلاً من مصفوفات أصلية. يحدث هذا عندما:
* استقبال البيانات من واجهات برمجة التطبيقات الخارجية عبر HTTP Request
* معالجة حمولات خطافات الويب
* تمرير البيانات بين خطوات سير العمل
**الحل**: أضف هذا النمط في بداية إجراء Code الخاص بك:
```javascript
export const main = async (params: {
users: any;
}): Promise<object> => {
const { users } = params;
// Handle input that may come as a string or an array
const usersFormatted = typeof users === "string" ? JSON.parse(users) : users;
// Now you can safely work with usersFormatted as an array
return {
users: usersFormatted.map((user) => ({
...user,
activityStatus: String(user.activityStatus).toUpperCase(),
})),
};
};
```
السطر الأساسي `typeof users === "string" ? JSON.parse(users) : users` يتحقق مما إذا كان الإدخال سلسلة نصية، ويُجري تحليله إذا لزم الأمر، أو يستخدمه مباشرة إذا كان مصفوفة بالفعل.
## استخراج الحقول الفردية من المصفوفات
قد يُرجِع خطّاف ويب مصفوفةً مثل `answers: [...]`، ولكن في خطوات سير العمل اللاحقة يمكنك تحديد **المصفوفة بأكملها** فقط — وليس العناصر الفردية داخلها.
**الحل**: أضف عقدة Code لاستخراج حقول محددة وإرجاعها ككائن منظَّم:
```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 كائناً منظَّماً بدلاً من مصفوفة. في الخطوات اللاحقة، يمكنك الآن تحديد حقول فردية مثل `answer.firstname` و`answer.name` من منتقي المتغيرات.
<Tip>
**تريد التكرار على المصفوفة بدلًا من استخراج الحقول؟** عندما تُرجِع خطوة Code أو Logic Function مصفوفة على المستوى الأعلى، يمكنك تمريرها مباشرة إلى [Iterator](/l/ar/user-guide/workflows/capabilities/use-iterator): اختر خيار **Whole list** للخطوة كمُدخل لـ Iterator، ثم ارجع إلى كل عنصر باستخدام `{{iterator.currentItem}}` داخل الحلقة. في هذه الحالة، لا تحتاج إلى إعادة هيكلة المصفوفة إلى كائن.
</Tip>
<Tip>
انقر على أيقونة المربع في أعلى يمين محرر الكود لعرضه بملء الشاشة — فهذا مفيد لأن عرض المحرر الافتراضي محدود.
</Tip>

View File

@@ -0,0 +1,182 @@
---
title: جلب بيانات المنتج إلى Twenty
description: زامِن بيانات كتالوج المنتجات من مستودع بيانات إلى نظام إدارة علاقات العملاء (CRM) لديك وفق جدول زمني.
---
استخدم هذا النمط للحفاظ على مزامنة Twenty مع بيانات المنتجات من مستودع البيانات لديك (مثل Snowflake وBigQuery وPostgreSQL).
## بنية سير العمل
1. **المحفّز**: وفق جدول زمني
2. **Code**: الاستعلام عن مستودع البيانات لديك
3. **Code** (اختياري): تنسيق البيانات كمصفوفة
4. **Iterator**: التكرار عبر كل منتج
5. **Upsert Record**: أنشئ أو حدّث في Twenty
<img src="/images/user-guide/workflows/create_users_workflow.png" style={{width:'100%'}} />
## الخطوة 1: جدولة المُحفّز
اضبط سير العمل ليعمل بتواتر يتوافق مع احتياجاتك من حداثة البيانات:
* كل 5 دقائق لمزامنة شبه فورية
* كل ساعة للبيانات الأقل أهمية
* يوميًا للتحديثات الدفعية
## الخطوة 2: الاستعلام عن مستودع البيانات لديك
أضِف إجراء **Code** لجلب البيانات الحديثة:
```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` لاسترجاع السجلات التي تغيّرت حديثًا فقط. هذا يحافظ على كفاءة المزامنة.
</Tip>
## الخطوة 3: تنسيق البيانات (اختياري)
إذا كان مستودعك يُرجع البيانات بتنسيق يحتاج إلى تحويل، فأضف إجراء **Code** آخر. تشمل التحويلات الشائعة تحويل الأنواع، وإعادة تسمية الحقول، وتنظيف البيانات.
### مثال: بيانات المستخدم مع حقول منطقية وحقول الحالة
```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),
})),
};
};
```
### مثال: بيانات المنتج مع تحويلات الأنواع
```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
}))
};
};
```
### مثال: تنسيق التاريخ والعملة
```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, " ")
}))
};
};
```
### التحويلات الشائعة
| تنسيق المصدر | تنسيق الهدف | كود |
| -------------------- | ---------------- | ---------------------------------------- |
| `"true"` / `"false"` | `true` / `false` | `v === true \|\| v === "true"` |
| `"123.45"` | `123.45` | `parseFloat(value)` |
| `"active"` | `"ACTIVE"` | `value.toUpperCase()` |
| `1704067200` (Unix) | تاريخ ISO | `new Date(v * 1000).toISOString()` |
| `"$1,234.56"` | `1234.56` | `parseFloat(v.replace(/[^0-9.-]/g, ""))` |
| `null` / `undefined` | `""` | `value \|\| ""` |
## الخطوة 4: التكرار عبر المنتجات
أضِف إجراء **Iterator**:
* المدخل: `{{code.products}}`
يقوم هذا بالتكرار عبر كل منتج في المصفوفة.
## الخطوة 5: إجراء Upsert لكل سجل
داخل المُكرِّر، أضف إجراء **Upsert Record**:
| الإعداد | القيمة |
| ---------------- | ------------------------------------ |
| **الكائن** | كائن المنتج المخصص لديك |
| **المطابقة حسب** | المعرّف الخارجي أو SKU (مُعرّف فريد) |
| **الاسم** | `{{iterator.item.name}}` |
| **SKU** | `{{iterator.item.sku}}` |
| **السعر** | `{{iterator.item.price}}` |
<Tip>
استخدم **Upsert** (تحديث أو إنشاء) بدلًا من إنشاء فروع منفصلة للإنشاء مقابل التحديث. إنه أسرع في الإنشاء وأسهل في استكشاف الأخطاء وإصلاحها.
</Tip>
## أمثلة لحالات الاستخدام
| المصدر | بيانات |
| ---------------------------------- | ------------------------------------ |
| **نظام تخطيط موارد المؤسسة (ERP)** | كتالوج المنتجات، التسعير، المخزون |
| **منصة التجارة الإلكترونية** | الطلبات، العملاء، تحديثات المنتجات |
| **مستودع البيانات** | مقاييس مجمّعة، بيانات مُثرَاة |
| **نظام إدارة المخزون** | مستويات المخزون، تنبيهات إعادة الطلب |
## ذات صلة
* [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [التعامل مع المصفوفات في إجراءات Code](/l/ar/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,130 @@
---
title: جلب عمليات إرسال Typeform إلى Twenty
description: التعامل مع حمولة webhook الخاصة بـ Typeform لإنشاء عملاء محتملين من عمليات إرسال النماذج.
---
لإعداد webhook القياسي، راجع [إعداد مشغّل Webhook](/l/ar/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger). يتناول هذا المقال المعالجة المحددة المطلوبة لبنية الحمولة المخصصة الخاصة بـ Typeform.
### الخطوة 1: إنشاء سير عمل Webhook
1. انتقل إلى **الإعدادات → سير العمل**
2. انقر **+ سير عمل جديد**
3. حدد **Webhook** كمشغّل
4. انسخ عنوان URL الخاص بالـ webhook
### الخطوة 2: تهيئة Typeform
1. في Typeform، افتح نموذجك
2. انتقل إلى **Connect → Webhooks**
3. الصق عنوان URL للـ webhook الخاص بـ Twenty
4. حفظ
### الخطوة 3: فهم حمولة Typeform
يرسل Typeform بنية JSON متداخلة. إليك مثال مبسط:
```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" }
}
]
}
}
```
أمور رئيسية يجب ملاحظتها:
* بيانات النموذج متداخلة تحت `form_response`
* **تُعاد الإجابات كمصفوفة**، وليست كحقول مسماة
* تتضمن كل إجابة نوع الحقل وعنوانه للرجوع إليه
### الخطوة 4: استخراج الحقول من مصفوفة الإجابات
بما أن `answers` مصفوفة، يمكنك اختيار المصفوفة كاملة فقط في الخطوات اللاحقة — وليس حقول فردية. أضف إجراء **Code** لاستخراج الحقول التي تحتاجها:
```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
}
};
};
```
الآن في الخطوات اللاحقة، يمكنك تحديد `contact.firstName` و`contact.email` وغيرها من منتقي المتغيرات.
<Tip>
لمزيد من التفاصيل حول التعامل مع المصفوفات في إجراءات Code، راجع [التعامل مع المصفوفات في إجراءات Code](/l/ar/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions).
</Tip>
### الخطوة 5: إنشاء السجل
أضف إجراء **Create Record**:
| الحقل | القيمة |
| --------------------- | ------------------------------------------------ |
| **الكائن** | الأشخاص |
| **الاسم الأول** | `{{code.contact.firstName}}` |
| **الاسم الأخير** | `{{code.contact.lastName}}` |
| **البريد الإلكتروني** | `{{code.contact.email}}` |
| **الشركة** | ابحث أو أنشئ بناء على `{{code.contact.company}}` |
### الخطوة 6: الاختبار والتفعيل
1. أرسل ردا تجريبيا في Typeform
2. تحقق من تشغيل سير العمل للتأكد من التقاط البيانات
3. فعّل سير العمل
## ذات صلة
* [إعداد مشغّل Webhook](/l/ar/user-guide/workflows/how-tos/connect-to-other-tools/set-up-a-webhook-trigger)
* [التعامل مع المصفوفات في إجراءات Code](/l/ar/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,263 @@
---
title: إنشاء ملف PDF من Twenty
description: أنشئ سير عمل لإنشاء ملف PDF (مثل عرض سعر) وإرفاقه بسجل.
---
أنشئ أو اجلب ملف PDF تلقائيًا وأرفقه بسجل في Twenty. يُستخدم هذا عادةً لإنشاء عروض أسعار أو فواتير أو تقارير مرتبطة بالشركات أو الفرص أو كائنات أخرى.
## نظرة عامة
يستخدم سير العمل هذا **المحفز اليدوي** بحيث يتمكن المستخدمون من إنشاء ملف PDF عند الطلب لأي سجل محدد. تتولى **الوظيفة المنطقية** ما يلي:
1. تنزيل ملف PDF من عنوان URL (من خدمة إنشاء PDF)
2. رفع الملف إلى Twenty
3. إنشاء مرفق مرتبط بالسجل
## المتطلبات الأساسية
قبل إعداد سير العمل:
1. **أنشئ مفتاح API**: انتقل إلى **الإعدادات → واجهات برمجة التطبيقات** ثم أنشئ مفتاح API جديدًا. ستحتاج إلى هذا الرمز لوظيفة المنطق.
2. **قم بإعداد خدمة إنشاء PDF** (اختياري): إذا كنت تريد إنشاء ملفات PDF ديناميكيًا (مثل عروض الأسعار)، فاستخدم خدمة مثل Carbone أو PDFMonkey أو DocuSeal لإنشاء ملف PDF والحصول على رابط تنزيل.
## إعداد خطوة بخطوة
### الخطوة 1: تهيئة المشغّل
1. انتقل إلى **سير العمل** وأنشئ سير عمل جديدًا
2. اختر **المحفز اليدوي**
3. اختر الكائن الذي تريد إرفاق ملفات PDF به (مثل **شركة** أو **فرصة**)
<Tip>
مع محفز يدوي، يمكن للمستخدمين تشغيل سير العمل هذا باستخدام زر يظهر في الجزء العلوي الأيمن بمجرد تحديد سجل - وهذا يعمل على تشغيل سير العمل لإنشاء وإرفاق PDF.
</Tip>
### الخطوة 2: إضافة وظيفة منطقية
1. إضافة إجراء **الكود** (الدالة المنطقية)
2. أنشئ وظيفة جديدة باستخدام الكود أدناه
3. قم بتهيئة معلمات الإدخال
#### معلمات الإدخال
| المعلمة | القيمة |
| ----------- | ----------------------- |
| `companyId` | `{{trigger.object.id}}` |
<Note>
إذا كنت تُرفِقه بكائن مختلف (شخص، فرصة، إلخ)، فأعد تسمية المعلمة وفقًا لذلك (مثلًا، `personId`، `opportunityId`) وحدّث الوظيفة المنطقية.
</Note>
#### كود الوظيفة المنطقية
```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;
};
```
### الخطوة 3: خصّص وفق حالة الاستخدام الخاصة بك
#### لإرفاقه بكائن مختلف
استبدل `targetCompanyId` بالحقل المناسب:
| كائن | اسم الحقل |
| ---------- | -------------------------- |
| الشركة | `targetCompanyId` |
| شخص | `targetPersonId` |
| الفرصة | `targetOpportunityId` |
| كائن مخصّص | `targetYourCustomObjectId` |
حدّث كل من معلمة الوظيفة وكائن `variables.data` في عملية الـ mutation الخاصة بالمرفق.
#### لاستخدام رابط PDF ديناميكي
إذا كنت تستخدم خدمة إنشاء PDF، يمكنك:
1. أولًا، أنشئ إجراء طلب HTTP لإنشاء ملف PDF
2. مرّر رابط ملف PDF المُعاد إلى الوظيفة المنطقية كمعلمة
```typescript
export const main = async (
params: { companyId: string; pdfUrl: string; filename: string },
) => {
const { companyId, pdfUrl, filename } = params;
// ... rest of the function
};
```
### الخطوة 4: الاختبار والتفعيل
1. احفظ سير العمل
2. انتقل إلى سجل شركة
3. انقر على قائمة **⋮** واختر سير العمل الخاص بك
4. تحقّق من قسم **المرفقات** في السجل للتأكد من أنه تم إرفاق ملف PDF
5. فعّل سير العمل
## الدمج مع خدمات إنشاء ملفات PDF
لإنشاء عروض أسعار أو فواتير ديناميكية:
### مثال: إنشاء عرض سعر → إرفاق ملف PDF
| الخطوة | الإجراء | الغرض |
| ------ | ---------------------- | ---------------------------------------------------------- |
| 1 | المحفز اليدوي (الشركة) | يبدأ المستخدم التنفيذ على سجل |
| 2 | البحث عن سجل | الحصول على تفاصيل الفرصة أو بنود السطر |
| 3 | طلب HTTP | استدعِ واجهة برمجة تطبيقات إنشاء PDF باستخدام بيانات السجل |
| 4 | دالة منطقية | تنزيل وإرفاق ملف PDF المُنشأ |
### خدمات شائعة لإنشاء ملفات PDF
* **Carbone** - إنشاء مستندات يعتمد على القوالب
* **PDFMonkey** - إنشاء PDF ديناميكي من القوالب
* **DocuSeal** - منصة أتمتة المستندات
* **Documint** - إنشاء مستندات يعتمد على واجهة برمجة التطبيقات أولًا
توفر كل خدمة API الذي يعيد رابط PDF الذي يمكنك انتقاله إلى الدالة المنطقية.
## استكشاف الأخطاء وإصلاحها
| المشكلة | الحل |
| ------------------- | -------------------------------------------------------- |
| "فشل تنزيل ملف PDF" | تحقق من أن رابط ملف PDF قابل للوصول ويعيد ملف PDF صالحًا |
| "فشل الرفع" | تحقق من أن مفتاح API صالح ولديه أذونات كتابة |
| "فشل إنشاء المرفق" | تأكد من أن اسم حقل معرّف الكائن يطابق الكائن المستهدف |
## ذات صلة
* [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [الوظائف المنطقية](/l/ar/user-guide/workflows/capabilities/workflow-actions#code)
* [إنشاء عرض سعر أو فاتورة من Twenty](/l/ar/user-guide/workflows/how-tos/connect-to-other-tools/generate-quote-or-invoice-from-twenty)

View File

@@ -0,0 +1,144 @@
---
title: إنشاء عرض سعر أو فاتورة من Twenty
description: إنشاء فواتير تلقائياً في الأدوات الخارجية عند إغلاق الصفقات.
---
إرسال بيانات الصفقة تلقائياً إلى نظام الفوترة لديك (Stripe وQuickBooks وXero، إلخ) عند ربح فرصة.
## بنية سير العمل
1. **المحفّز**: يتم تحديث السجل (الفرصة)
2. **التصفية**: المرحلة = Closed Won
3. **Search Record**: الحصول على تفاصيل الشركة
4. **Code** (اختياري): تنسيق الحمولة
5. **HTTP Request**: الإرسال إلى نظام الفوترة
## الخطوة 1: إعداد المُحفّز
1. إنشاء سير عمل جديد
2. اختر المُحفّز **Record is Updated**
3. اختر **Opportunity** بوصفه الكائن
## الخطوة 2: التصفية من أجل Closed Won
أضف إجراء **Filter** للمتابعة فقط عند ربح الصفقة:
| الإعداد | القيمة |
| ---------- | ---------------------------------- |
| **الحقل** | المرحلة |
| **الشرط** | يساوي |
| **القيمة** | `CLOSED_WON` (أو اسم المرحلة لديك) |
<Tip>
يتم تشغيل المُحفّز عند أي تحديث للفرصة. تضمن التصفية أن يستمر سير العمل فقط عندما تتغير المرحلة إلى Closed Won.
</Tip>
## الخطوة 3: الحصول على تفاصيل الشركة
قد لا يتضمن سجل الفرصة جميع حقول الشركة التي تحتاجها للفاتورة. أضف إجراء **Search Record**:
| الإعداد | القيمة |
| ---------------- | -------------------------------------------- |
| **الكائن** | الشركة |
| **المطابقة حسب** | المعرّف يساوي `{{trigger.object.companyId}}` |
يؤدي ذلك إلى استرجاع سجل الشركة الكامل متضمناً عنوان الفوترة، ومعرّف الضريبة، وما إلى ذلك.
## الخطوة 4: تنسيق الحمولة (اختياري)
إذا كان نظام الفوترة لديك يتطلب تنسيقاً محدداً، فأضف إجراء **Code**:
```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
}
}
};
};
```
## الخطوة 5: الإرسال إلى نظام الفوترة
أضف إجراء **HTTP Request**:
| الإعداد | القيمة |
| ------------- | ------------------------------------------------ |
| **الطريقة** | POST |
| **عنوان URL** | نقطة نهاية واجهة برمجة تطبيقات الفوترة الخاصة بك |
| **الرؤوس** | `Authorization: Bearer YOUR_API_KEY` |
| **المحتوى** | `{{code.invoice}}` أو قم بربط الحقول مباشرةً |
### مثال: فاتورة Stripe
```
POST https://api.stripe.com/v1/invoices
Headers:
Authorization: Bearer sk_live_xxx
Content-Type: application/x-www-form-urlencoded
Body:
customer: {{company.stripeCustomerId}}
collection_method: send_invoice
days_until_due: 30
```
### مثال: فاتورة QuickBooks
```
POST https://quickbooks.api.intuit.com/v3/company/{realmId}/invoice
Headers:
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Body: {{code.invoice}}
```
## الملخص الكامل لسير العمل
| الخطوة | الإجراء | الغرض |
| ------ | -------------------- | ----------------------------------------------- |
| 1 | المحفّز: تحديث السجل | يتم تشغيله عند حدوث أي تغيير في أي فرصة |
| ٢ | تصفية | المتابعة فقط إذا كانت المرحلة = Closed Won |
| 3 | البحث عن سجل | الحصول على تفاصيل الشركة الكاملة لأغراض الفوترة |
| 4 | كود | تنسيق البيانات لواجهة برمجة تطبيقات الفوترة |
| 5 | طلب HTTP | إنشاء فاتورة في نظام خارجي |
## نصائح
* **تخزين المعرّفات الخارجية**: احفظ معرّف الفاتورة الذي تُرجعه واجهة برمجة التطبيقات إلى الفرصة باستخدام إجراء **Update Record**
* **التعامل مع الأخطاء**: أضف فرعاً لإرسال إشعار إذا فشل طلب HTTP
* **اختبر أولاً**: استخدم وضع sandbox/test في نظام الفوترة قبل الإطلاق
## ذات صلة
* [إنشاء PDF من عشرين سنتي](/l/ar/user-guide/workflows/how-tos/connect-to-other-tools/generate-pdf-from-twenty) - إرفاق ملفات PDFs التي تم إنشاؤها بالسجلات
* [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [أتمتة Closed Won](/l/ar/user-guide/workflows/how-tos/crm-automations/closed-won-automations)

View File

@@ -0,0 +1,170 @@
---
title: إعداد مشغّل ربط الويب
description: استقبل بيانات من خدمات خارجية لتشغيل عمليات سير العمل.
---
تتيح مشغّلات ربط الويب للخدمات الخارجية بدء تشغيل عمليات سير العمل لديك عبر إرسال بيانات إلى عنوان URL فريد. استخدمها لربط النماذج والتطبيقات من جهات خارجية والتكاملات المخصّصة.
## متى تستخدم ربط الويب
| حالة الاستخدام | مثال |
| ----------------------- | ---------------------------------------------- |
| **نماذج الويب** | تُنشئ عمليات إرسال نموذج الاتصال عملاء محتملين |
| **تطبيقات جهات خارجية** | دفعة Stripe → إنشاء سجل عميل |
| **تكاملات مخصّصة** | تطبيقك → أتمتة Twenty |
| **أدوات بدون كود** | اتصالات Zapier وMake وn8n |
## إعداد خطوة بخطوة
### الخطوة 1: إنشاء سير العمل
1. اذهب إلى **الإعدادات → سير العمل**
2. انقر **+ سير عمل جديد**
3. قم بتسميته (مثلًا، "إرسال نموذج الموقع")
### الخطوة 2: تهيئة مشغّل ربط الويب
1. انقر على كتلة المشغّل
2. اختر **ربط الويب**
3. ستتلقى عنوان URL فريدًا لربط الويب مثل:
```
https://api.twenty.com/webhooks/workflow/abc123...
```
4. انسخ هذا العنوان URL - ستحتاج إليه لخدمتك الخارجية
### الخطوة 3: تحديد بنية البيانات المتوقعة
بالنسبة لطلبات **POST**، حدِّد بنية جسم الطلب المتوقعة:
1. انقر **تحديد الجسم المتوقع**
2. أدخل JSON نموذجيًا يطابق ما سترسله خدمتك:
```json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"company": "Acme Inc",
"message": "Interested in your product"
}
```
3. انقر **حفظ** - سيؤدي هذا إلى إنشاء متغيّرات يمكنك استخدامها في الخطوات اللاحقة
### الخطوة 4: إضافة إجراءات
أضف الآن إجراءات تستخدم بيانات ربط الويب:
**مثال: إنشاء سجل شخص**
1. أضف إجراء **إنشاء سجل**
2. حدِّد كائن **الأشخاص**
3. عيّن الحقول:
| الحقل | القيمة |
| ----------------- | ------------------------------------------------- |
| الاسم الأول | `{{trigger.body.firstName}}` |
| الاسم الأخير | `{{trigger.body.lastName}}` |
| البريد الإلكتروني | `{{trigger.body.email}}` |
| الشركة | ابحث أو أنشئ بناءً على `{{trigger.body.company}}` |
### الخطوة 5: اختبار ربط الويب
قبل التفعيل، اختبر ربط الويب لديك:
**باستخدام cURL**:
```bash
curl -X POST https://api.twenty.com/webhooks/workflow/abc123... \
-H "Content-Type: application/json" \
-d '{"firstName":"Test","lastName":"User","email":"test@example.com"}'
```
**باستخدام Postman أو ما شابهه**:
1. أنشئ طلب POST إلى عنوان ربط الويب الخاص بك
2. عيّن ترويسة Content-Type إلى `application/json`
3. أضف جسم JSON الاختباري الخاص بك
4. أرسل وتحقّق من تشغيلات سير العمل
### الخطوة 6: التفعيل
بعد الاختبار، انقر **تفعيل** لجعل سير العمل فعّالًا.
## التعامل مع بُنى بيانات مختلفة
### بيانات متداخلة
إذا كان ربط الويب يرسل بيانات متداخلة:
```json
{
"contact": {
"name": "John Doe",
"email": "john@example.com"
},
"source": "website"
}
```
أشر إليها باستخدام: `{{trigger.body.contact.email}}`
### المصفوفات
إذا كانت البيانات تتضمن مصفوفات:
```json
{
"items": [
{"name": "Product A", "qty": 2},
{"name": "Product B", "qty": 1}
]
}
```
تعتمد طريقة تعاملك مع المصفوفات على حالة الاستخدام لديك:
**عدد العناصر غير معروف → استخدم Iterator**
إذا كنت بحاجة إلى معالجة كل عنصر في المصفوفة (مثلًا، إنشاء سجل لكل عنصر)، أضف إجراء **Code** لتحليل المصفوفة، ثم استخدم **Iterator**:
```javascript
export const main = async (params: { items: any }) => {
const items = typeof params.items === "string"
? JSON.parse(params.items)
: params.items;
return { items };
};
```
ثم استخدم Iterator للتكرار عبر: `{{code.items}}`
**حقول معروفة/محددة → استخرجها إلى حقول مسماة**
إذا كانت المصفوفة تحتوي على حقول محددة تريد الوصول إليها بشكل فردي (مثلًا، إجابات نموذج حيث الموضع 0 دائمًا هو "الاسم الأول"، والموضع 1 دائمًا هو "اسم العائلة")، فأضف إجراء **Code** لاستخراجها:
```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
}
};
};
```
يمكنك الآن اختيار `product.name` و`product.qty` بشكل فردي في الخطوات اللاحقة.
<Tip>
لمزيد من التفاصيل حول التعامل مع المصفوفات، راجع [التعامل مع المصفوفات في إجراءات Code](/l/ar/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions).
</Tip>
## ذات صلة
* [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,121 @@
---
title: الرد التلقائي على رسائل البريد الإلكتروني الواردة
description: أنشئ سير عمل يستخدم الذكاء الاصطناعي لفرز رسائل البريد الإلكتروني الواردة وإرسال ردود ضمن سلسلة المحادثة تلقائيًا.
---
استجب لرسائل البريد الإلكتروني الواردة خلال ثوانٍ — وليس ساعات. يستخدم سير العمل هذا وكيل AI لتصفية الضوضاء (الرسائل الإخبارية، الرسائل غير المرغوب فيها، الردود التلقائية) وصياغة استجابة مخصصة للرسائل الحقيقية. ثم تقوم منظمة العفو الدولية بإرسالها كرد متسلل داخل المحادثة الأصلية.
## كيف يعمل تسلسل رسائل البريد الإلكتروني
تحمل كل رسالة بريد إلكتروني ترويسة `Message-ID` مخفية — بصمة فريدة يعيّنها خادم بريد المرسل. عند الرد على بريد إلكتروني، يقوم عميل البريد لديك بتعيين ترويسة `In-Reply-To` التي تُشير إلى تلك البصمة. بهذه الطريقة يقوم Gmail وOutlook وكل عميل آخر بتجميع الرسائل في سلاسل المحادثات.
في Twenty، تُخزَّن تلك البصمة كـ `headerMessageId` على كائن Message. يلتقطه سير العمل لديك ويمرّره إلى حقل In-Reply-To لإجراء Send Email.
## بناء سير العمل
### الخطوة 1: إنشاء سير عمل جديد
توجّه إلى **Settings -> Workflows** وانقر **+ New Workflow**.
### الخطوة 2: التشغيل عند الرسائل الواردة
اختر **When a Record is Created** ثم **Messages**.
في كل مرة يصل فيها بريد إلكتروني إلى Twenty، يُشغَّل هذا.
<img src="/images/user-guide/workflows/auto-reply/workflow-overview.png" style={{width:'100%'}} />
### الخطوة 3: البحث عن المُرسِل
أضِف إجراء **Search Records**.
عنوان المُرسِل ليس في الرسالة نفسها — بل في سجل Message Participant المرتبط.
| الحقل | القيمة |
| ---------- | ---------------------------------- |
| **الكائن** | المشاركون في الرسالة |
| **تصفية** | Message **يساوي** `{{trigger.id}}` |
| **تصفية** | Role **يساوي** From |
| **الحد** | 1 |
سيمنحك هذا بريد المُرسِل الإلكتروني في `handle` واسمه في `displayName`.
<img src="/images/user-guide/workflows/auto-reply/find-sender.png" style={{width:'100%'}} />
### الخطوة 4: التكرار وصياغة رد مع الذكاء الاصطناعي
أضِف إجراء **AI Agent**. تقوم هذه الخطوة الواحدة بأمرين: تقرر ما إذا كان البريد الإلكتروني يستحق الرد، وإن كان كذلك، تصوغ ردًا.
استخدم موجهًا مثل:
```
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 استجابته في الحقل `response` الذي يمكن للخطوات التالية الرجوع إليه.
<img src="/images/user-guide/workflows/auto-reply/ai-triage.png" style={{width:'100%'}} />
### الخطوة 5: التفريع بناءً على قرار الذكاء الاصطناعي
أضِف إجراء **If/Else** للتحقق مما إذا كان الذكاء الاصطناعي قرر الرد أم التخطي.
| الحقل | القيمة |
| ------------------ | ------------------------------------------- |
| **الشرط** | AI Agent `response` **لا يحتوي على** `SKIP` |
| **إذا كان صحيحًا** | المتابعة إلى Send Email |
| **وإلا** | لا تفعل شيئًا (ينتهي سير العمل) |
يتم تجاهل الرسائل غير المرغوب فيها والنشرات البريدية والرسائل المُنشأة تلقائيًا. كل ما عدا ذلك ينتقل إلى الخطوة التالية.
<img src="/images/user-guide/workflows/auto-reply/should-reply.png" style={{width:'100%'}} />
### الخطوة 6: إرسال رد ضمن سلسلة المحادثة
أضِف إجراء **Send Email** على فرع "if true". انقر **Advanced options** ثم **Add In-Reply-To**.
| الحقل | القيمة |
| --------------- | -------------------------------------- |
| **إلى** | `{{Find Sender.first.handle}}` |
| **الموضوع** | `Re: {{trigger.subject}}` |
| **المحتوى** | `{{AI Triage & Draft Reply.response}}` |
| **In-Reply-To** | `{{trigger.headerMessageId}}` |
حقل In-Reply-To هو ما يجعل هذا ردًا بدلًا من محادثة جديدة. سيراه المستلِم ضمن سلسلة تحت البريد الأصلي في Gmail أو Outlook أو أي عميل آخر.
<img src="/images/user-guide/workflows/auto-reply/send-email.png" style={{width:'100%'}} />
<Tip>
**In-Reply-To** يتوقّع `message.headerMessageId` من المشغّل — إنها البصمة الفريدة للبريد الإلكتروني، وليست عنوان المستلم. إذا تركته فارغًا، فسيُرسَل البريد الإلكتروني على أي حال، ولكن كرسالة مستقلة.
</Tip>
<Warning>
يستخدم Gmail سطر الموضوع لتجميع الرسائل في سلاسل المحادثات. يجب أن يبدأ الموضوع بـ `Re:` (بما في ذلك النقطتان والمسافة) ليعرض Gmail الرد داخل سلسلة المحادثة الأصلية. بدون ذلك، سيظهر الرد كمحادثة منفصلة — حتى إذا تم تعيين ترويسة In-Reply-To بشكل صحيح.
</Warning>
### الخطوة 7: الاختبار والتفعيل
اضغط **Test**، ثم تحقّق من عميل البريد لديك. يجب أن يظهر الرد متداخلًا تحت الرسالة الأصلية.
فعِّل عندما تكون راضيًا عنه.
## أفكار للبناء عليها
* **الرد على كبار الشخصيات فقط** — أضِف فرعًا يتحقق من مجال المُرسِل أو مما إذا كان موجودًا كجهة اتصال في Twenty
* **التوجيه حسب النية** — استخدم موجهات AI Agent منفصلة للتعامل مع استفسارات المبيعات بشكل مختلف عن طلبات الدعم
* **الإثراء قبل الرد** — أضِف خطوة Search Records لجلب شركة المُرسِل أو سجل الصفقات إلى الموجه الخاص بالذكاء الاصطناعي للحصول على ردود أكثر تخصيصًا

View File

@@ -0,0 +1,179 @@
---
title: أتمتة الصفقات المغلقة الرابحة
description: أتمتة الأنشطة بعد الفوز عند إغلاق الفرص.
---
عند إغلاق صفقة، يجب أن تحدث أمور عدة: تحديث حالة الشركة، إشعار أعضاء الفريق، إنشاء مهام الإعداد. قم بأتمتة كل ذلك عبر سير عمل واحد.
## المشكلة
عند انتقال فرصة إلى "Closed Won":
* يجب تغيير نوع الشركة من "Prospect" إلى "Customer"
* يجب إنشاء مهام الإعداد
* يجب إشعار فريق نجاح العملاء
* يحتاج مندوب المبيعات إلى تأكيد
القيام بذلك يدويًا يستغرق وقتًا ومعرّض للأخطاء.
## الحل
أنشئ سير عمل يتولى تلقائيًا جميع الأنشطة بعد الفوز.
## إعداد سير العمل الكامل
### الخطوة 1: إنشاء سير العمل
1. اذهب إلى **الإعدادات → سير العمل**
2. انقر **+ سير عمل جديد**
3. قم بتسميته "تم ربح الصفقة - أتمتة ما بعد الفوز"
### الخطوة 2: تهيئة المشغّل
1. اختر **Record is Updated**
2. اختر **Opportunities**
3. ضمن "Fields to monitor"، اختر **Stage**
### الخطوة 3: إضافة عامل تصفية للمرحلة
1. أضف إجراء **Filter**
2. الشرط: `{{trigger.object.stage}}` يساوي "Closed Won"
### الخطوة 4: تحديث نوع الشركة
1. أضف إجراء **Update Record**
2. التكوين:
| الحقل | القيمة |
| ------------------ | ------------------------------- |
| **الكائن** | الشركات |
| **السجل** | `{{trigger.object.company.id}}` |
| **نوع** | العميل |
| **تاريخ أول صفقة** | `{{trigger.object.closedAt}}` |
| **مالك الحساب** | `{{trigger.object.owner.id}}` |
### الخطوة 5: إنشاء مهمة إعداد
1. أضف إجراء **Create Record**
2. التكوين:
| الحقل | القيمة |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| **الكائن** | المهام |
| **العنوان** | `Onboarding: {{trigger.object.name}}` |
| **المسند إليه** | عضو فريق نجاح العملاء |
| **تاريخ الاستحقاق** | بعد 3 أيام |
| **الأولوية** | عالية |
| **الشركة ذات الصلة** | `{{trigger.object.company.id}}` |
| **الفرصة ذات الصلة** | `{{trigger.object.id}}` |
| **الوصف** | `إعداد عميل جديد لشركة {{trigger.object.company.name}}. قيمة الصفقة: {{trigger.object.amount}}` |
### الخطوة 6: إشعار فريق نجاح العملاء
1. أضف إجراء **Send Email**
2. التكوين:
| الحقل | القيمة |
| ----------- | ----------------------------------------------- |
| **إلى** | customer-success@yourcompany.com |
| **الموضوع** | `🎉 عميل جديد: {{trigger.object.company.name}}` |
| **المحتوى** | انظر المثال أدناه |
**مثال على محتوى البريد الإلكتروني**:
```
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!
```
### الخطوة 7: تأكيد لمندوب المبيعات
1. أضف إجراء **Send Email** آخر
2. التكوين:
| الحقل | القيمة |
| ----------- | -------------------------------------------------------------------------- |
| **إلى** | `{{trigger.object.owner.email}}` |
| **الموضوع** | `✅ تم إغلاق الصفقة: {{trigger.object.name}}` |
| **المحتوى** | تهانينا! تمت معالجة صفقتك. تم إشعار فريق نجاح العملاء وبدأت عملية الإعداد. |
### الخطوة 8: الاختبار والتفعيل
1. اختبر بنقل فرصة اختبار إلى "Closed Won"
2. التحقق:
* تم تغيير نوع الشركة إلى "Customer"
* تم إنشاء مهمة الإعداد
* تلقى فريق نجاح العملاء بريدًا إلكترونيًا
* تلقى مندوب المبيعات تأكيدًا
3. فعّل عند الجاهزية
## التعامل مع "Closed Lost"
أنشئ سير عمل مشابهًا للصفقات الخاسرة:
### المشغّل
* تم تحديث السجل (Opportunities، Stage = "Closed Lost")
### الإجراءات
1. **Create Record**: مهمة "تحليل الصفقة الخاسرة"
2. **Update Record**: أضِف سبب الخسارة إلى سجل الشركة
3. **Send Email**: إخطار المدير بالصفقة الخاسرة
## متقدم: إعداد متعدد الخطوات
لعمليات الإعداد المعقدة، أنشئ مهام متعددة:
```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 };
};
```
استخدم **Iterator** لإنشاء كل مهمة من المصفوفة.
## أفكار للتخصيص
### أبقِ أدواتك الأخرى محدثة
* أنشئ عميلًا في نظام الفوترة بواسطة **HTTP Request**
### الإجراءات المشروطة
استخدم إجراءات **Filter** لـ:
* إعداد مختلف للمؤسسات مقابل الشركات الصغيرة والمتوسطة
* مُسندون مختلفون حسب المنطقة
* تخطي الإشعارات للصفقات الصغيرة
### تضمين تفاصيل الصفقة
استخدم إجراء **Code** للتنسيق:
* مستندات ملخص الصفقة
* ملاحظات التسليم لفريق نجاح العملاء
* قوائم تدقيق إعداد مخصصة
## ذات صلة
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [إرسال رسائل البريد الإلكتروني من سير العمل](/l/ar/user-guide/workflows/capabilities/send-emails-from-workflows)

View File

@@ -0,0 +1,136 @@
---
title: اكتشاف الفرص الراكدة
description: إخطار المديرين تلقائيًا عند عدم تحديث الفرص.
---
حافظ على صحة خط أنابيب المبيعات من خلال تنبيه المديرين عندما تصبح الفرص راكدة. يتحقق سير العمل هذا من الفرص التي لم يتم تحديثها خلال عدد محدد من الأيام.
## المشكلة
الفرص التي تبقى دون تحديث تؤدي إلى:
* فتور الصفقات
* توقعات غير موثوقة
* إيرادات مفقودة
## الحل
أنشئ سير عملًا مُجدولًا يعثر على الفرص الراكدة ويرسل بريدًا إلكترونيًا إلى مديريها.
## إعداد خطوة بخطوة
### الخطوة 1: إنشاء سير العمل
1. اذهب إلى **الإعدادات → سير العمل**
2. انقر **+ سير عمل جديد**
3. قم بتسميته "تنبيه الفرص الراكدة"
### الخطوة 2: تهيئة المشغّل
1. حدد **وفق جدول**
2. عيّن التشغيل يوميًا (مثلاً، كل يوم الساعة 8 صباحًا)
### الخطوة 3: البحث عن الفرص الراكدة
1. أضف إجراء **Search Records**
2. التكوين:
| الحقل | القيمة |
| ---------- | ------------------------------------------- |
| **الكائن** | الفرص |
| **تصفية** | Updated At قبل (اليوم - 7 أيام) |
| **تصفية** | المرحلة ليست "Closed Won" ولا "Closed Lost" |
| **الحد** | 100 |
### الخطوة 4: التحقق مما إذا تم العثور على أي عناصر
1. أضف إجراء **تصفية**
2. الشرط: `{{searchRecords.length}}` أكبر من 0
3. إذا لم توجد فرص راكدة، يتوقف سير العمل هنا
### الخطوة 5: تنسيق التنبيه (إجراء Code)
أضف إجراء **Code** لتنسيق البريد الإلكتروني:
```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
};
};
```
### الخطوة 6: إرسال بريد التنبيه
أضف إجراء **Send Email**:
| الحقل | القيمة |
| ----------- | --------------------------------------------------- |
| **إلى** | sales-manager@yourcompany.com |
| **الموضوع** | `🚨 {{code.totalCount}} فرص راكدة تحتاج إلى اهتمام` |
| **المحتوى** | `{{code.summary}}` |
### الخطوة 7: الاختبار والتفعيل
1. انقر **Test** لتشغيل سير العمل
2. تحقق من أن البريد الإلكتروني يحتوي على البيانات الصحيحة
3. فعّل عند الجاهزية
## خيارات التخصيص
### تغيير عتبة الركود
عدّل عامل تصفية Search Records لتغيير 7 أيام إلى الفترة التي تفضّلها:
* 3 أيام للمبيعات سريعة الوتيرة
* 14 يومًا لصفقات المؤسسات
* 30 يومًا لدورات المبيعات الطويلة
### تنبيه المندوبين بشكل فردي
بدلًا من بريد مدير واحد، استخدم **Iterator** لإرسال رسائل مخصصة إلى كل مندوب حول صفقاته الراكدة.
### إضافة تصعيد
أنشئ عدة سير عمل بتدرّج في الشدة:
1. اليوم 7: بريد إلى المندوب
2. اليوم 14: بريد إلى المندوب + المدير
3. اليوم 21: إنشاء مهمة للمدير للتدخل
### التضمين في Slack
استخدم **HTTP Request** للنشر إلى Slack webhook بدلًا من البريد الإلكتروني أو بالإضافة إليه.
## ذات صلة
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [إرسال رسائل البريد الإلكتروني من سير العمل](/l/ar/user-guide/workflows/capabilities/send-emails-from-workflows)

View File

@@ -0,0 +1,69 @@
---
title: عرض عدد رسائل البريد الإلكتروني المستلمة
description: أنشئ سير عمل لحساب عدد رسائل البريد الإلكتروني المستلمة من كل جهة اتصال وعرضه تلقائيًا.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<img src="/images/user-guide/workflows/workflow-number-of-emails-received.png" style={{width:'100%'}} />
## نظرة عامة
يعمل سير العمل هذا في كل مرة يتم فيها استلام بريد إلكتروني جديد، ويحدّث حقلًا مخصصًا في سجل Person بالقيمة الإجمالية لعدد الرسائل من ذلك المرسِل.
## المتطلبات الأساسية
قبل إعداد سير العمل هذا، أنشئ حقلًا مخصصًا على كائن **People**:
1. اذهب إلى **الإعدادات → نموذج البيانات → People**
2. أضف حقل **Number** جديدًا
3. قم بتسميته بشيء مثل "عدد رسائل البريد الإلكتروني المستلمة من هذا الشخص"
## إعداد خطوة بخطوة
<VimeoEmbed videoId="1148700336" title="عرض توضيحي بالفيديو" />
### الخطوة 1: تهيئة المشغّل
1. انتقل إلى **سير العمل** وأنشئ سير عمل جديدًا
2. اختر **Record is Created** كالمشغّل
3. اختر **Message Participants** (متوفر ضمن الكائنات المتقدمة)
<Note>
يمثّل Message Participant مزيجًا بين معرّف الرسالة ومعرّف الشخص، ما ينشئ سجلًا فريدًا واحدًا لكل رسالة. يكون هذا أسهل في التتبع من Messages مباشرةً لأننا نستطيع الوصول إلى الحقل `handle` الذي يحتوي على عنوان البريد الإلكتروني للمرسل (أو المستلم).
</Note>
### الخطوة 2: التصفية حسب Role
1. أضف إجراء **Filter**
2. عيّن الشرط: **Role** يساوي **FROM**
يضمن هذا أن تحسب الرسائل المُرسلة من هذا الشخص فقط، وليس الرسائل المُرسلة إليه.
### الخطوة 3: البحث عن جميع Message Participants الذين لديهم نفس الـ Handle
1. أضف إجراء **Search Records**
2. حدّد **Message Participants** كالكائن
3. أضف عوامل تصفية: **Handle** يساوي الـ handle من المشغّل (عنوان البريد الإلكتروني للمرسل) و**Role** يساوي **FROM**
4. قم بزيادة **Limit** من 1 إلى **200** (الحد الأقصى)
هذا يعثر على جميع الرسائل من عنوان البريد الإلكتروني هذا للحصول على العدد الإجمالي.
<Note>
إجراء Search Records محدود بإرجاع 200 سجل كحد أقصى. ومع ذلك، بما أنك تستخدم قيمة `totalCount` فقط (وليس السجلات الفردية)، فستُرجِع هذه الخطوة إجمالي عدد رسائل البريد الإلكتروني المُرسلة من هذا الشخص.
</Note>
### الخطوة 4: تحديث سجل Person باستخدام إجراء Create or Update Record
1. أضف إجراء **Create or Update Record**
2. حدّد **People** كالكائن
3. اعثر على الشخص بمطابقة بريده الإلكتروني مع قيمة `handle` من Message Participant
4. عيّن الحقل المخصص "عدد رسائل البريد الإلكتروني المستلمة" إلى `{{searchRecords.totalCount}}`
تمثّل قيمة `totalCount` من إجراء Search Records إجمالي عدد رسائل البريد الإلكتروني المستلمة من هذا الشخص.
## ذات صلة
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [إنشاء حقول مخصصة](/l/ar/user-guide/data-model/how-tos/customize-your-data-model)
* [إجراء Search Records](/l/ar/user-guide/workflows/capabilities/workflow-actions#search-records)

View File

@@ -0,0 +1,170 @@
---
title: عرض بيانات السجل المرتبط
description: اعرض بيانات من سجلات مرتبطة (مثل معلومات الشركة على الفرص) باستخدام سير العمل.
---
اعرض بيانات من سجلات مرتبطة مباشرةً على سجلاتك — على سبيل المثال، اعرض عدد الموظفين من شركة على فرصها. هذا الحل عبر سير العمل مفيد حتى تصبح الحقول المتداخلة مدعومة أصلاً.
## الاستخدامات الشائعة
| المصدر | الوجهة | الحقول المطلوب نسخها |
| ------ | ------ | ------------------------------------------------- |
| الشركة | الفرصة | الصناعة، حجم الشركة، الإيراد السنوي المتكرر (ARR) |
| شخص | الفرصة | البريد الإلكتروني، الهاتف، المسمّى الوظيفي |
| الفرصة | الشركة | قيمة آخر صفقة، تاريخ آخر صفقة رابحة |
## نسخ أساسي للحقل
### مثال: نسخ البريد الإلكتروني لجهة الاتصال إلى الفرصة
**الهدف**: عند تعيين نقطة اتصال على فرصة، انسخ البريد الإلكتروني لجهة الاتصال إلى الفرصة لسهولة الوصول.
### المتطلبات الأساسية
أنشئ حقول الوجهة في **الإعدادات → نموذج البيانات → الفرص** قبل إنشاء سير العمل:
* البريد الإلكتروني لجهة الاتصال (النوع: Email)
* هاتف جهة الاتصال (النوع: Phone)
### إعداد
1. **المحفّز**: يتم تحديث السجل (الفرص، حقل نقطة الاتصال)
2. **الفلتر**: تحقّق من أن نقطة الاتصال غير فارغة
3. **البحث في السجلات**: اعثر على الشخص المرتبط
* الكائن: الأشخاص
* الفلتر: المعرّف يساوي `{{trigger.object.pointOfContact.id}}`
4. **تحديث السجل**:
* الكائن: الفرص
* السجل: `{{trigger.object.id}}`
* البريد الإلكتروني لجهة الاتصال: `{{searchRecords[0].email}}`
* هاتف جهة الاتصال: `{{searchRecords[0].phone}}`
## نسخ عدة حقول
### مثال: مزامنة معلومات الشركة مع جميع الفرص المرتبطة
**الهدف**: عند تغيّر تفاصيل الشركة، حدّث جميع الفرص المرتبطة.
### إعداد
1. **المحفّز**: يتم تحديث السجل (الشركات)
* الحقول: الصناعة، حجم الشركة، الإيراد السنوي
2. **البحث في السجلات**: اعثر على جميع الفرص الخاصة بهذه الشركة
* الكائن: الفرص
* الفلتر: معرّف الشركة يساوي `{{trigger.object.id}}`
3. **Iterator**: التكرار عبر كل فرصة
4. **تحديث السجل** (داخل الـ Iterator):
* الكائن: الفرص
* السجل: `{{iterator.currentItem.id}}`
* صناعة الشركة: `{{trigger.object.industry}}`
* حجم الشركة: `{{trigger.object.companySize}}`
* الإيراد السنوي المتكرر للشركة: `{{trigger.object.annualRevenue}}`
## النسخ عند إنشاء السجل
### مثال: تعبئة الفرصة مسبقًا ببيانات الشركة
**الهدف**: عند إنشاء فرصة مرتبطة بشركة، انسخ تلقائيًا معلومات الشركة الأساسية.
### المتطلبات الأساسية
أنشئ حقول الوجهة في **الإعدادات → نموذج البيانات → الفرص**:
* صناعة الشركة (النوع: Text)
* حجم الشركة (النوع: Number)
### إعداد
1. **المحفّز**: يتم إنشاء السجل (الفرص)
* الفلتر: الشركة ليست فارغة
2. **البحث في السجلات**: احصل على تفاصيل الشركة المرتبطة
* الكائن: الشركات
* الفلتر: المعرّف يساوي `{{trigger.object.company.id}}`
3. **تحديث السجل**:
* الكائن: الفرص
* السجل: `{{trigger.object.id}}`
* صناعة الشركة: `{{searchRecords[0].industry}}`
* حجم الشركة: `{{searchRecords[0].employees}}`
<Note>
**قيود المهام والملاحظات**: العلاقات في المهام والملاحظات مُحدّدة في الشفرة كعلاقات متعدّدة-لمتعدّدة وليست متاحة بعد في محفّزات أو إجراءات سير العمل. للوصول إلى هذه العلاقات، استخدم بدلًا من ذلك [API](/l/ar/developers/extend/api).
</Note>
## مزامنة ثنائية الاتجاه
### مثال: الحفاظ على تزامن جهة الاتصال الأساسية
**الهدف**: عند تغيّر جهة الاتصال الأساسية للشركة، حدّث جهة الاتصال. وعندما يصبح شخص ما جهة الاتصال الأساسية، حدّث الشركة.
### سير العمل 1: الشركة → الشخص
1. **المحفّز**: يتم تحديث السجل (الشركات، حقل جهة الاتصال الأساسية)
2. **تحديث السجل**: عيّن قيمة "Is Primary Contact" للشخص إلى true
3. **البحث في السجلات**: اعثر على جهة الاتصال الأساسية السابقة
4. **تحديث السجل**: عيّن قيمة "Is Primary Contact" لجهة الاتصال السابقة إلى false
### سير العمل 2: الشخص → الشركة
1. **المحفّز**: يتم تحديث السجل (الأشخاص، Is Primary Contact = true)
2. **تحديث السجل**: عيّن جهة الاتصال الأساسية للشركة إلى هذا الشخص
<Note>
كن حذرًا مع المزامنات ثنائية الاتجاه لتجنّب الحلقات اللانهائية. استخدم عوامل تصفية للتحقّق مما إذا كانت القيمة قد تغيّرت فعلاً قبل التحديث.
</Note>
## استخدام الشيفرة للتعيين المعقّد
### مثال: تحويل البيانات أثناء النسخ
**الهدف**: نسخ رقم الهاتف من الشخص إلى الفرصة وتنسيقه.
```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 };
};
```
## أفضل الممارسات
### تجنّب الحلقات
* لا تنشئ سير عمل تُحفّز بعضها بعضًا بلا نهاية
* استخدم شروطًا خاصة بالحقول
* أضف تحقّقات لمعرفة ما إذا كانت القيمة قد تغيّرت فعلاً
### التعامل مع البيانات المفقودة
* تحقّق دائمًا من وجود سجل المصدر قبل النسخ
* وفّر قيمًا افتراضية للحقول الاختيارية
* استخدم عوامل تصفية للتخطّي عندما يكون حقل المصدر فارغًا
### الأداء
* نفّذ تحديثات دفعية عند النسخ إلى العديد من السجلات
* استخدم سير عمل مجدولة لعمليات المزامنة بالجملة
* فكّر في استخدام Iterator لتحديثات متعددة للسجلات
## ذات صلة
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [محفّزات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)

View File

@@ -0,0 +1,202 @@
---
title: حقول الصيغ
description: أنشئ حقول الصيغ باستخدام سير العمل إلى حين توفّر الدعم الأصلي.
---
20 لا تدعم بعد حقول الصيغة الأصلية (القادمة في عام 2026)، ولكن يمكنك تحقيق نفس النتيجة باستخدام سير العمل. يتيح لك هذا الحل البديل حساب قيم الحقول وملؤها تلقائيًا — من عمليات الربط البسيطة إلى منطق الأعمال المعقّد.
## الاستخدامات الشائعة
| حالة الاستخدام | مثال على الصيغة |
| ------------------------ | ------------------------------- |
| **الاسم الكامل** | الاسم الأول + " " + اسم العائلة |
| **المبلغ المتوقع** | المبلغ × الاحتمال |
| **الأيام حتى الاستحقاق** | تاريخ الاستحقاق - اليوم |
| **الأيام في المرحلة** | اليوم - تاريخ دخول المرحلة |
| **درجة العميل المحتمل** | نقاط استنادًا إلى معايير متعددة |
<Tip>
للاطلاع على مثال كامل لتتبّع الوقت في مراحل خط الأنابيب، راجع [تتبّع مدة بقاء الفرص في كل مرحلة](/l/ar/user-guide/views-pipelines/how-tos/track-time-in-stage).
</Tip>
## صيغة أساسية: الربط
### مثال: تعبئة الاسم الكامل تلقائيًا
**الهدف**: دمج الاسم الأول واسم العائلة تلقائيًا في حقل الاسم الكامل.
### إعداد
1. **المشغّل**: يتم تحديث السجل أو إنشاؤه (الأشخاص)
2. **التصفية**: التحقق من تغيّر الاسم الأول أو اسم العائلة
3. **إجراء الكود**:
```javascript
export const main = async (params) => {
const { firstName, lastName } = params;
const fullName = [firstName, lastName]
.filter(Boolean)
.join(' ');
return { fullName };
};
```
4. **تحديث السجل**: عيّن الاسم الكامل إلى `{{code.fullName}}`
## صيغة رقمية: المبلغ المتوقع
### مثال: حساب الإيراد المتوقع
**الهدف**: ضرب مبلغ الفرصة في الاحتمال للحصول على المبلغ المتوقع.
اطلع على [كيفية إظهار المبلغ المتوقع في خط الأنابيب](/l/ar/user-guide/views-pipelines/how-tos/show-expected-amount-in-pipeline) للاطلاع على سير العمل الكامل.
### إعداد
1. **المشغّل**: يتم تحديث السجل (الفرص، حقل المبلغ أو الاحتمال)
2. **إجراء الكود**:
```javascript
export const main = async (params) => {
const { amount, probability } = params;
const expectedAmount = (amount || 0) * (probability || 0) / 100;
return { expectedAmount };
};
```
3. **تحديث السجل**: عيّن المبلغ المتوقع إلى `{{code.expectedAmount}}`
## صيغة التاريخ: حساب الأيام
### مثال: الأيام المتبقية حتى استحقاق المهمة
**الهدف**: حساب عدد الأيام المتبقية حتى تاريخ استحقاق المهمة.
### إعداد
1. **المشغّل**: يتم تحديث السجل أو إنشاؤه (المهام، حقل تاريخ الاستحقاق)
2. **إجراء الكود**:
```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. **تحديث السجل**: عيّن الأيام حتى الاستحقاق إلى `{{code.daysUntilDue}}`
<Note>
تشير القيم السالبة إلى مهام متأخرة عن موعدها. يمكنك استخدام هذا الحقل لتصفية المهام أو فرزها حسب الإلحاح.
</Note>
## صيغة شرطية: درجة العميل المحتمل
### مثال: حساب درجة العميل المحتمل بناءً على معايير
**الهدف**: منح نقاط للعملاء المحتملين استنادًا إلى حجم الشركة والصناعة والتفاعل.
### إعداد
1. **المشغّل**: يتم تحديث السجل (الأشخاص أو الشركات)
2. **إجراء الكود**:
```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. **تحديث السجل**: عيّن درجة العميل المحتمل إلى `{{code.leadScore}}`
## صيغة نصية: استخراج النطاق
### مثال: استخراج النطاق من البريد الإلكتروني
**الهدف**: استخراج نطاق البريد الإلكتروني وتخزينه تلقائيًا.
### إعداد
1. **المشغّل**: يتم تحديث السجل (الأشخاص، حقل البريد الإلكتروني)
2. **إجراء الكود**:
```javascript
export const main = async (params) => {
const { email } = params;
if (!email) return { domain: null };
const domain = email.split('@')[1]?.toLowerCase();
return { domain };
};
```
3. **تحديث السجل**: عيّن حقل النطاق إلى `{{code.domain}}`
## أفضل الممارسات
### الأداء
* فعّل المشغّل فقط عند تغيّر الحقول ذات الصلة
* استخدم عوامل التصفية لتجاوز السجلات التي لا تحتاج إلى حساب
* تجنّب الحسابات المعقّدة في عمليات سير عمل ذات حجم كبير
### التعامل مع الأخطاء
* تحقق من القيم null/undefined قبل إجراء الحسابات
* استخدم قيمًا افتراضية عند فقدان البيانات
* أعد رسائل خطأ واضحة عند فشل الحسابات
### "الاختبار"
* اختبر بحالات الحافة (حقول فارغة، قيم صفرية)
* تحقّق من الحسابات يدويًا قبل التفعيل
* راقب تشغيلات سير العمل لرصد النتائج غير المتوقعة
## ذات صلة
* [كيفية إظهار المبلغ المتوقع في خط الأنابيب](/l/ar/user-guide/views-pipelines/how-tos/show-expected-amount-in-pipeline)
* [كيفية تتبّع الوقت في المرحلة](/l/ar/user-guide/views-pipelines/how-tos/track-time-in-stage)
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)

View File

@@ -0,0 +1,127 @@
---
title: إشعار الزملاء بملاحظة للمراجعة
description: أرسل إشعارات بريد إلكتروني تلقائية عند إسناد زميل لمراجعة ملاحظة.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<Note>
**الإشارة إلى الزملاء مباشرةً داخل الملاحظات غير مدعومة بعد.** من المخطط طرح هذه الميزة في النصف الثاني من عام 2026. في هذه الأثناء، يوفّر سير العمل هذا حلاً عمليًا بديلاً.
</Note>
## التحدّي
تريد الإشارة إلى زميل في ملاحظة ليصله إشعار لمراجعتها. حاليًا، Twenty لا يدعم @mentions في الملاحظات أو المهام.
## الحل البديل
بدلًا من الإشارة في نص الملاحظة، يمكنك:
1. أنشئ حقل علاقة **Reviewer** على كائن Notes
2. عيّن المراجع عند إنشاء الملاحظة أو تحريرها
3. الحصول على سير العمل إرسال بريد إلكتروني تلقائياً إلى المستعرض مع رابط إلى الملاحظة
<Warning>
**قيد**: يتيح هذا الأسلوب تعيين مراجع واحد لكل حقل. إذا كنت بحاجة إلى إشعار عدة أشخاص، فأنشئ حقول علاقة إضافية (مثلًا: Reviewer 1، Reviewer 2). لن يكون ذلك قابلًا للتوسّع بشكلٍ جيد إذا احتجت إلى الإشارة إلى العديد من المتعاونين دفعةً واحدة.
</Warning>
## إعداد خطوة بخطوة
### الخطوة 1: إنشاء حقل المراجع
<img src="/images/user-guide/workflows/reviewer-field-for-note.png" style={{width:'100%'}} />
1. انتقل إلى **الإعدادات → نموذج البيانات → Notes**
2. انقر **إضافة حقل**
3. التكوين:
| الإعداد | القيمة |
| ------------------ | --------------------------------------------- |
| **Name** | Reviewer |
| **النوع** | علاقة |
| **الكائن المرتبط** | عضو في مساحة العمل |
| **نوع العلاقة** | العديد من الملاحظات → عضو واحد في مساحة العمل |
4. احفظ الحقل
### الخطوة 2: إنشاء سير العمل
<VimeoEmbed videoId="1151897168" title="عرض توضيحي بالفيديو" />
#### إنشاء مشغّل سير العمل
1. انتقل إلى العرض الرئيسي وأنشئ سير عمل جديدًا
2. اختر **Record Updated** كمشغِّل
3. اختر **Note** كالكائن وحدِّد حقل Reviewer.
4. سيؤدي ذلك إلى التشغيل كلما تم تحديث مُراجع الملاحظة.
#### أضِف عامل تصفية للتحقق من أنه تم تعيين المراجع للتو
أضِف إجراء **Filter** للتأكد من أن سير العمل يستمر فقط عند تعيين مراجع:
| الشرط | القيمة |
| ------------ | -------- |
| **Reviewer** | غير فارغ |
#### ابحث عن عضو مساحة العمل
1. أضف إجراء **Search Records**
2. حدِّد **Workspace Member** (ضمن الكائنات المتقدمة)
3. أضف عامل تصفية:
| الشرط | القيمة |
| ------ | --------------------------- |
| **ID** | يساوي `{{note.reviewerId}}` |
هذا يجلب سجل عضو مساحة العمل الكامل، بما في ذلك عنوان بريده الإلكتروني واسمه.
#### إرسال بريد الإشعار الإلكتروني
1. أضف إجراء **Send Email**
2. التكوين:
| الحقل | القيمة |
| ----------- | --------------------------------------------------- |
| **إلى** | Search Record → First Workspace Member → User Email |
| **الموضوع** | هناك ملاحظة تحتاج إلى مراجعتك |
| **المحتوى** | انظر المثال أدناه |
**مثال على محتوى البريد الإلكتروني:**
```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` بنطاقك الفرعي الفعلي لمساحة عمل Twenty.
</Note>
#### الاختبار والتفعيل
1. انقر **Test** لتشغيل سير العمل يدويًا
2. أنشئ ملاحظة (أو حرّر ملاحظة موجودة) وعيّن مراجعًا
3. تحقّق من بريد المراجع الوارد بحثًا عن رسالة الإشعار
4. فعّل سير العمل
## استخدام
بعد الإعداد، يمكن لفريقك استخدام سير العمل هذا عبر:
1. إنشاء ملاحظة جديدة (أو تحرير ملاحظة موجودة)
2. اختيار زميل في حقل **Reviewer**
3. سيتلقى الزميل تلقائيًا بريدًا إلكترونيًا يحتوي على رابط مباشر إلى الملاحظة
## ذات صلة
* [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [إرسال رسائل البريد الإلكتروني من سير العمل](/l/ar/user-guide/workflows/capabilities/send-emails-from-workflows)
* [إنشاء حقول مخصصة](/l/ar/user-guide/data-model/how-tos/create-custom-fields)
* [إنشاء حقول العلاقات](/l/ar/user-guide/data-model/how-tos/create-relation-fields)

View File

@@ -0,0 +1,106 @@
---
title: إرسال تنبيهات عبر البريد الإلكتروني بشأن المهام المستحقة
description: إخطار أعضاء الفريق تلقائيًا بمهامهم القادمة أو المتأخرة.
---
import { VimeoEmbed } from '/snippets/vimeo-embed.mdx';
<img src="/images/user-guide/workflows/email_tasks_due.png" style={{width:'100%'}} />
إرسال تذكيرات يومية عبر البريد الإلكتروني لكل عضو في الفريق بشأن المهام المستحقة اليوم.
## نظرة عامة
يعمل سير العمل هذا وفق جدول زمني ويقوم بما يلي:
1. يجلب جميع أعضاء مساحة العمل
2. يُنفِّذ حلقة على كل عضو
3. يعثر على مهامهم المستحقة اليوم
4. ينسّق ويرسل بريدًا إلكترونيًا مخصصًا
## إعداد خطوة بخطوة
<VimeoEmbed videoId="1147463514" title="عرض توضيحي بالفيديو" />
### الخطوة 1: تهيئة المشغّل
1. انتقل إلى **الإعدادات → سير العمل** وأنشئ سير عمل جديد
2. حدّد **وفق جدول** كمشغّل
3. استخدم تعبير cron للتشغيل يوميًا عند الساعة 8:00 صباحًا: `0 8 * * *`
### الخطوة 2: البحث عن جميع أعضاء مساحة العمل
1. أضف إجراء **Search Records**
2. حدّد **Workspace Members** (ضمن الكائنات المتقدمة)
3. لا حاجة إلى فلاتر — فهذا يعيد جميع الأعضاء
### الخطوة 3: إضافة Iterator
1. أضف إجراء **Iterator**
2. اضبط مصفوفة الإدخال على أعضاء مساحة العمل من الخطوة السابقة
3. ستُنفَّذ جميع الإجراءات داخل المكرّر مرة واحدة لكل عضو
### الخطوة 4: البحث عن المهام المستحقة اليوم (داخل المكرّر)
1. داخل المكرّر، أضف إجراء **Search Records**
2. حدّد **Tasks** كالكائن
3. أضف فلاتر:
* **Assignee** = عضو مساحة العمل الحالي (من المكرّر)
* **Due Date** = اليوم
### الخطوة 5: تنسيق المهام ضمن محتوى البريد الإلكتروني (داخل المكرّر)
أضف إجراء **Code** لتنسيق المهام في قائمة قابلة للقراءة مع روابط:
```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` بنطاقك الفرعي الفعلي لمساحة عمل Twenty.
</Note>
### الخطوة 6: إرسال بريد إلكتروني (داخل المكرّر)
1. أضف إجراء **Send Email** (ما زال داخل المكرّر)
2. التكوين:
| الحقل | القيمة |
| ----------- | ------------------------------------------------------------------------- |
| **إلى** | `{{iterator.currentItem.userEmail}}` (البريد الإلكتروني لعضو مساحة العمل) |
| **الموضوع** | مهامك المستحقة اليوم |
| **المحتوى** | `{{code.formattedTasks}}` |
### الخطوة 7: الاختبار والتفعيل
1. انقر **Test** لتشغيل سير العمل يدويًا
2. تحقّق من صناديق الوارد للرسائل الإلكترونية
3. فعّل سير العمل
## ذات صلة
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [إرسال رسائل البريد الإلكتروني من سير العمل](/l/ar/user-guide/workflows/capabilities/send-emails-from-workflows)
* [التعامل مع المصفوفات في إجراءات Code](/l/ar/user-guide/workflows/how-tos/advanced-configurations/handle-arrays-in-code-actions)

View File

@@ -0,0 +1,21 @@
---
title: خدمات احترافية
description: احصل على مساعدة احترافية لبناء مسارات عمل وأتمتة معقدة من فريق Twenty وشركائه المعتمدين.
---
## متى تحتاج إلى مساعدة احترافية؟
فكّر في الاستفادة من الخدمات الاحترافية من أجل:
* تكامل أنظمة متعددة ومعقدة
* منطق الأعمال المتقدم وقواعد الأتمتة
* مسارات عمل لمعالجة البيانات على نطاق واسع
* تطوير واجهة برمجة التطبيقات المخصصة
* تدريب الفريق وتحسين سير العمل
* عندما تكون الموارد الداخلية غير متوفرة
## خيارات الخدمة
### شركاء التنفيذ
اعمل مع شركاء معتمدين من أجل تخصيصات متقدمة. تواصل معنا عبر [contact@twenty.com](mailto:contact@twenty.com) للتواصل مع [شركائنا في التنفيذ](https://twenty.com/partners).

View File

@@ -0,0 +1,170 @@
---
title: استكشاف مشكلات سير العمل وإصلاحها
description: المشكلات الشائعة في سير العمل وكيفية حلّها.
---
## المشاكل الشائعة والحلول
### لم يتم تشغيل سير العمل
**الأعراض**: لا يعمل سير العمل كما تتوقع.
**الأسباب المحتملة**:
1. **لم يتم تفعيل سير العمل**: تأكّد من تعيين سير العمل إلى "Active" وليس "Draft"
2. **شروط المُحفِّز غير مستوفاة**: تحقّق من أن المُحفِّز يطابق الحدث الذي تتوقعه
3. **حقل غير مُراقَب**: بالنسبة لمُحفِّزات "Record is Updated"، تأكّد من مراقبة الحقل المحدد
4. **الأذونات**: تحقّق من أن لديك الإذن لتشغيل سير العمل
**حلول**:
* تحقّق من حالة سير العمل في قائمة سير العمل
* اختبر بالإجراء المحدد الذي تتوقع أن يُشغِّله
* راجِع إعداد المُحفِّز
* تواصَل مع المسؤول لديك بشأن الأذونات
### مُحفِّزات سير العمل تعمل مبكراً جداً (حقول فارغة)
**الأعراض**: عند إنشاء سجل يدوياً في واجهة المستخدم، يتم تشغيل سير العمل قبل أن تتمكّن من ملء جميع الحقول. يعمل سير العمل مع قيم حقول فارغة في الغالب.
**سبب حدوث هذا**: تقوم Twenty بحفظ كل شيء في الزمن الحقيقي — لا يوجد وضع منفصل "edit" مقابل "read". عند إنشاء سجل، يتم حفظه فوراً، مما يؤدي إلى تشغيل حدث "Record is created" قبل أن تتمكّن من ملء حقول إضافية.
**متى يعمل "Record is created" بشكل جيد**:
* السجلات التي تُنشأ عبر استدعاءات API (تُملأ الحقول في طلب واحد)
* السجلات التي تُنشأ عبر الاستيراد
* إنشاء السجلات تلقائياً من سير عمل أخرى
**الحل**: بالنسبة للسجلات التي تُنشأ يدوياً في واجهة المستخدم، استخدم **"Record is created or updated"** كمحفّز بدلاً من ذلك. بهذه الطريقة:
* سيتم تشغيل سير العمل بعد أن يُنهي المستخدم ملء الحقول وحفظها
* ستحصل على البيانات الكاملة بدلاً من القيم الفارغة
<Tip>
إذا كنت تريد تشغيل سير العمل مرة واحدة فقط لكل سجل، أضِف إجراء تصفية لفحص حقل مثل `createdAt equals updatedAt` (الحفظ الأول) أو استخدم حقلاً مخصصاً من نوع خانة اختيار لتتبع ما إذا كان سير العمل قد تم تشغيله بالفعل.
</Tip>
### فشل الإجراءات
**الأعراض**: يعمل سير العمل لكن بعض الإجراءات تفشل.
**الأسباب المحتملة**:
1. **بيانات مفقودة**: الحقول المطلوبة فارغة
2. **مراجع غير صالحة**: المتغيّرات من الخطوات السابقة غير موجودة
3. **أخطاء API**: تعيد الخدمات الخارجية أخطاء
4. **مشكلات الأذونات**: يتطلب الإجراء أذونات لا تملكها
**حلول**:
* راجِع تفاصيل تشغيل سير العمل بحثاً عن رسائل الخطأ
* تحقّق من أن جميع الحقول المطلوبة تحتوي على قيم
* اختبر اتصالات API بشكل مستقل
* راجِع أذونات الدور
### أخطاء طلبات HTTP
**الأعراض**: تفشل إجراءات طلب HTTP أو تُرجِع نتائج غير متوقعة.
**رموز الأخطاء الشائعة**:
* **400**: طلب غير صالح - تحقّق من تنسيق جسم الطلب
* **401**: غير مُخوَّل - تحقّق من مفتاح API
* **403**: محظور - تحقّق من أذونات API
* **404**: غير موجود - تحقّق من عنوان URL لنقطة النهاية
* **429**: عدد كبير جداً من الطلبات - نفّذ تحديداً لمعدل الطلبات
* **500**: خطأ في الخادم - مشكلة في خدمة خارجية
**حلول**:
* تحقّق من عنوان URL لنقطة نهاية API
* تحقّق من ترويسات المصادقة
* اختبر استدعاء API خارج Twenty أولاً
* أضِف معالجة للأخطاء في إجراءات الكود
### أخطاء إجراءات الكود
**الأعراض**: يفشل كود JavaScript في التنفيذ.
**المشكلات الشائعة**:
1. **أخطاء الصياغة**: أخطاء إملائية أو JavaScript غير صالح
2. **متغيّرات غير معرّفة**: الإشارة إلى متغيّرات غير موجودة
3. **أخطاء النوع**: إجراء عمليات على أنواع بيانات خاطئة
4. **انتهاء المهلة**: يستغرق الكود وقتاً طويلاً للتنفيذ
**حلول**:
* استخدم التحقق المدمج في محرر الكود
* اختبر منطق الكود في وحدة تحكم JavaScript أولاً
* أضِف عبارات console.log لأغراض تصحيح الأخطاء
* بسّط العمليات المعقّدة
### البريد الإلكتروني لا يُرسَل
**الأعراض**: لا يقوم إجراء إرسال البريد الإلكتروني بتسليم الرسائل.
**الأسباب المحتملة**:
1. **لا يوجد حساب بريد إلكتروني متصل**: تحقّق من الإعدادات → الحسابات
2. **عنوان بريد إلكتروني غير صالح**: عنوان بريد المستلم غير صحيح التنسيق
3. **قيود الإرسال**: تم الوصول إلى حدود معدل مزوّد البريد الإلكتروني
4. **مرشّحات البريد العشوائي**: يتم حظر الرسائل
**حلول**:
* تحقّق من اتصال حساب البريد الإلكتروني
* تحقّق من صحة عناوين بريد المستلمين
* تحقّق من حدود مزوّد البريد الإلكتروني
* راجِع محتوى البريد بحثاً عن عناصر قد تُحفِّز مرشّحات البريد العشوائي
## تصحيح أخطاء سير العمل
### استخدام عمليات تشغيل سير العمل
1. انتقل إلى محرر سير العمل
2. افتح لوحة **Runs**
3. اعثر على عملية التشغيل التي فشلت
4. انقر لعرض التفاصيل خطوة بخطوة
5. راجِع رسائل الخطأ وبيانات المخرجات
### اختبار الخطوات بشكل فردي
1. بالنسبة لإجراءات الكود، استخدم زر **Test**
2. بالنسبة لطلبات HTTP، اختبر نقطة النهاية بشكل منفصل
3. أنشئ سجلات اختبار لتشغيل سير العمل
4. استخدم المُحفِّزات اليدوية للاختبار المُتحكَّم فيه
### أنماط شائعة لتصحيح الأخطاء
**أضِف التسجيل**:
استخدم إجراءات الكود لتسجيل القيم الوسيطة لأغراض تصحيح الأخطاء.
**اعزل الخطوات**:
اختبر كل خطوة بشكل مستقل لتحديد مواضع الفشل.
**تحقّق من تدفق البيانات**:
تأكّد من أن كل خطوة تتلقى بيانات الإدخال المتوقعة.
## أفضل الممارسات لتجنّب المشكلات
### قبل التفعيل
* اختبر بدقة في وضع المسودة
* تحقّق من صحة جميع اتصالات API
* راجِع شروط المُحفِّز بعناية
* وثّق السلوك المتوقع
### أثناء التطوير
* استخدم أسماء خطوات وصفية
* أضِف تعليقات في إجراءات الكود
* اختبر ببيانات واقعية
* خطّط للحالات الحدّية
### بعد التفعيل
* راقِب عمليات التشغيل الأولى عن كثب
* قم بإعداد تنبيهات لحالات الفشل
* راجِع سجلّ التشغيل بانتظام
* اجعل سير العمل بسيطًا قدر الإمكان

View File

@@ -0,0 +1,236 @@
---
title: الأسئلة الشائعة حول سير العمل
description: الأسئلة الشائعة حول سير العمل في Twenty.
---
<AccordionGroup>
<Accordion title="لماذا لا أستطيع تفعيل سير عمل؟">
من المحتمل أن تكون مشكلة أذونات. تحتاج إلى صلاحية الوصول إلى سير العمل لإنشائها وتفعيلها.
**الحل**: تواصل مع مسؤول مساحة العمل لمنحك صلاحية الوصول إلى سير العمل ضمن **الإعدادات → الأعضاء → الأدوار**.
إذا لم ترَ قسم سير العمل إطلاقاً في الشريط الجانبي لديك، فهذا يؤكد أنها مشكلة أذونات.
</Accordion>
<Accordion title="لماذا لا أرى زر سير العمل اليدوي في شريط التنقل العلوي؟">
تظهر عمليات سير العمل اليدوية في شريط التنقل فقط إذا تم إعدادها بشكل صحيح:
1. يجب أن يكون سير العمل **مفعَّلاً** (ليس في وضع المسودة)
2. يجب تعيين موضع شريط التنقل إلى **Pinned**
3. بالنسبة لمشغلات Single/Bulk، يجب أن تكون في صفحة الكائن الصحيحة
**للتحقق**: افتح سير العمل → انقر المشغل → تأكد من أن "Navbar placement" معيّن إلى "Pinned".
يمكنك دائماً الوصول إلى عمليات سير العمل اليدوية عبر **Cmd + K** (أو **Ctrl + K**) بغض النظر عن إعدادات شريط التنقل.
</Accordion>
<Accordion title="ما الفرق بين المشغلات اليدوية Single وGlobal وBulk؟">
| النوع | السجلات المطلوبة | عمليات تشغيل سير العمل |
| ----- | ---------------- | ---------------------- |
\| **Global** | لا شيء | مرة واحدة، دون إدخال سجل |
\| **Single** | واحد أو أكثر محدد | مرة لكل سجل محدد |
\| **Bulk** | واحد أو أكثر محدد | مرة واحدة، مع جميع السجلات كمصفوفة |
* **Global**: استخدمه عندما لا يحتاج سير العمل إلى سياق أي سجل (مثال: إنشاء تقرير)
* **Single**: استخدمه عندما تريد معالجة كل سجل محدد بشكل مستقل (مثال: إرسال رسائل بريد إلكتروني فردية)
* **Bulk**: استخدمه عندما تحتاج إلى معالجة السجلات معاً أو تحسين استخدام الرصيد (يتطلب إجراء Iterator)
راجع [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers) للحصول على التفاصيل.
</Accordion>
<Accordion title="لا أرى عقدة If/Else. ماذا يجب أن أفعل؟">
عقدة If/Else صريحة غير متاحة بعد، لكنها ضمن خارطة الطريق لدينا.
**الحل المؤقت الحالي**: أنشئ عدة فروع من خطوتك، يبدأ كل منها بإجراء **Filter**:
```
Step 1
│
├── Branch A: Filter (condition = true) → Actions...
│
└── Branch B: Filter (condition = false) → Actions...
```
فقط الفرع الذي يمر فيه شرط التصفية سيُنفِّذ إجراءاته اللاحقة.
راجع [كيفية استخدام الفروع](/l/ar/user-guide/workflows/capabilities/workflow-branches) للحصول على دليل خطوة بخطوة.
</Accordion>
<Accordion title="هل تعمل فروع سير العمل بالتوازي؟">
**نعم**، تعمل الفروع بالتوازي افتراضياً.
إذا كنت تريد تنفيذ فرع واحد فقط:
* أضف إجراء **Filter** في بداية كل فرع
* عيّن شروطاً متعاكسة (مثال: Branch A: status = "Open", Branch B: status ≠ "Open")
الفروع التي لا تستوفي شرط التصفية تتوقف عن التنفيذ، بينما تستمر الفروع الأخرى.
</Accordion>
<Accordion title="هل يمكنني دمج الفروع معاً مرة أخرى؟">
**نعم**. بعد اكتمال فروعك المتوازية، يمكنك إضافة خطوة يتصل بها الفرعان.
في محرر سير العمل:
1. أكمل إجراءات الفروع
2. أضف خطوة جديدة بعد الفروع
3. اسحب الاتصالات من نهاية كل فرع إلى هذه الخطوة الجديدة
ستُنفَّذ الخطوة المدمجة بعد اكتمال جميع الفروع المتصلة.
</Accordion>
<Accordion title="ما الحد الأقصى لنتائج Search Records؟">
**تعيد Search Records بحد أقصى 200 سجل.**
إذا كنت بحاجة إلى معالجة المزيد:
* أضف عوامل تصفية أكثر تحديداً لتقليل النتائج
* استخدم سير عمل مجدولاً للمعالجة على دفعات
* فكّر في استخدام الـAPI للعمليات المجمّعة
بالنسبة لمعظم سير العمل، يكفي 200 سجل. إذا بلغت هذا الحد بشكل متكرر، فكر في إعادة هيكلة الأتمتة لديك.
</Accordion>
<Accordion title="هل يمكنني إضافة CC إلى الأشخاص في رسائل البريد الخاصة بسير العمل؟">
**ليس بعد.** حقولا CC وBCC لإجراء Send Email على خارطة الطريق لدينا.
**الحل المؤقت الحالي**: أضف عدة إجراءات Send Email للإرسال إلى مستلمين إضافيين، أو استخدم HTTP Request للإرسال عبر خدمة بريد إلكتروني خارجية تدعم CC.
</Accordion>
<Accordion title="كيف أستخدم مخرجات الخطوات السابقة؟">
كل إجراء ينتج بيانات مخرجات يمكن استخدامها في الخطوات اللاحقة.
**للإشارة إلى بيانات الخطوات السابقة**:
* استخدم أداة اختيار المتغير عند تكوين حقل
* أو اكتب `{{stepName.fieldName}}` مباشرةً
**أمثلة**:
* بيانات المشغل: `{{trigger.object.email}}`
* نتائج البحث: `{{searchRecords[0].name}}`
* مخرجات الكود: `{{code.calculatedValue}}`
مرّر المؤشر فوق أي حقل في تكوين الإجراء لرؤية المتغيرات المتاحة من الخطوات السابقة.
</Accordion>
<Accordion title="لماذا يفشل Iterator لدي؟">
**Iterator يتطلب مُدخلًا من نوع مصفوفة.** مشكلات شائعة:
1. **المدخل ليس مصفوفة**: تأكد من أنك تمرر نتائج من Search Records أو إجراء آخر يُرجع مصفوفة
2. **المصفوفة فارغة**: أضف عامل تصفية قبل Iterator للتحقق من `{{searchRecords.length}} > 0`
3. **تم اختيار متغير خاطئ**: تأكد من اختيارك للمصفوفة نفسها، وليس سجلاً واحداً
**الإعداد الصحيح**:
1. Search Records (تُرجع مصفوفة)
2. Filter: length > 0
3. Iterator: اختر `{{searchRecords}}`
4. الإجراءات داخل Iterator تستخدم `{{iterator.currentItem.fieldName}}`
</Accordion>
<Accordion title="ما أقصى وقت تنفيذ لإجراءات Code؟">
إجراءات Code (دوال منطقية) لديها **مهلة افتراضية قدرها 5 دقائق** (300 ثانية).
أقصى مهلة يمكن ضبطها هي **15 دقيقة** (900 ثانية).
إذا تجاوز الكود هذا الحد، سيفشل الإجراء بخطأ انتهاء المهلة.
**نصائح لتجنب انتهاء المهلة**:
* قسّم العمليات الكبيرة إلى أجزاء أصغر باستخدام Iterator
* تجنب العمليات الحسابية الثقيلة؛ استخدم خدمات خارجية عبر HTTP Request للمعالجة المكثفة
* حسّن الكود لديك لتقليل وقت التنفيذ
* إذا كنت بحاجة إلى معالجة أطول، ففكّر في استخدام سير عمل مجدول يعالج البيانات على دفعات
</Accordion>
<Accordion title="كيف أقرأ تشغيلات سير العمل؟">
تعرض تشغيلات سير العمل سجل التنفيذ وتساعدك على تصحيح المشكلات.
**الوصول إلى التشغيلات**:
* في محرر سير العمل → لوحة **التشغيلات** على اليمين
* أو انتقل إلى **تشغيلات سير العمل** في الشريط الجانبي
**فهم التشغيل**:
* **الحالة**: قيد التشغيل، مكتمل، فشل، في الانتظار
* **الخطوات**: اطّلِع على الخطوات التي تم تنفيذها ومخرجاتها
* **الأخطاء**: انقر الخطوات الفاشلة لرؤية رسائل الخطأ
* **البيانات**: اعرض بيانات الإدخال/الإخراج في كل خطوة
راجع [تشغيلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-runs) للحصول على التفاصيل.
</Accordion>
<Accordion title="لماذا لا أرى تشغيلات سير العمل الخاصة بي؟">
قد تفشل تشغيلات سير العمل فوراً بسبب حدود المعدل. تفرض Twenty حداً صارماً يبلغ 5,000 عملية تشغيل في الساعة لكل مساحة عمل.
إذا تجاوزت هذا الحد، ستُعلَّم عمليات سير العمل فوراً كفاشلة ولن تظهر في قائمة عمليات التشغيل لديك.
**سيناريوهات شائعة تصل إلى هذا الحد**:
* اختيار أكثر من 5,000 سجل باستخدام مشغل يدوي Single
* تشغيل عدة سير عمل بالتزامن عبر مساحة العمل
* مشغلات آلية عالية التكرار (مثال: Record Updated على كائن مزدحم)
**حلول**:
* استخدم مشغلات **Bulk** بدلاً من Single لمعالجة العديد من السجلات في تشغيل واحد
* وزّع العمليات الدفعية الكبيرة زمنياً
* استخدم عوامل تصفية لتقليل تكرار المشغل
* قم بجدولة سير العمل الثقيلة خلال ساعات خارج أوقات الذروة
</Accordion>
<Accordion title="ما هي حدود معدل سير العمل؟">
لدى Twenty حدّان للمعدل لضمان استقرار النظام:
| الحد | القيمة | السلوك |
| ---- | ------ | ------ |
\| **حد مرن** | 100 تشغيل/دقيقة | تُصفّ في قائمة الانتظار بحالة "Not Started" وتُعالَج تدريجياً |
\| **حد صارم** | 5,000 تشغيل/ساعة | تفشل التشغيلات فوراً |
**الحد المرن (100/دقيقة)**: لن تفشل سير العمل لديك—ستنتظر فقط في قائمة الانتظار وتُعالَج بمرور الوقت. يمكنك تشغيل أكثر من 100 سجل؛ سيكون التنفيذ أبطأ.
**الحد الصارم (5,000/ساعة)**: ينطبق هذا على مساحة العمل بالكامل. إذا تجاوز مجموع تشغيلات جميع سير العمل لديك 5,000 تشغيل في ساعة واحدة، فسوف تفشل التشغيلات الإضافية فوراً.
**نصائح للبقاء ضمن الحدود**:
* استخدم مشغلات Bulk مع Iterator بدلاً من مشغلات Single للدفعات الكبيرة
* ادمج الأتمتة ذات الصلة في عدد أقل من سير العمل
* استخدم سير عمل مجدولة لتوزيع الحمل بمرور الوقت
</Accordion>
<Accordion title="هل يمكنني إعادة محاولة تشغيل سير عمل فاشل؟">
**لا، لا توجد حالياً وظيفة إعادة المحاولة التلقائية.**
إذا فشل تشغيل سير عمل، فستحتاج إلى:
1. راجع الخطأ في **الإعدادات → سير العمل → [سير العمل الخاص بك] → التشغيلات**
2. أصلِح المشكلة (البيانات، الإعداد، أو الخدمة الخارجية)
3. قم بتشغيل سير العمل يدوياً مرة أخرى على السجل/السجلات المتأثرة
**نصائح لتقليل حالات الفشل**:
* أضف عقد **Filter** للتحقق من البيانات قبل الإجراءات
* استخدم **Search Records** للتحقق مما إذا كانت السجلات ذات الصلة موجودة
* اختبر بدقة باستخدام عدد قليل من السجلات قبل العمليات المجمّعة
وظيفة إعادة المحاولة التلقائية ضمن خارطة الطريق لإصدار مستقبلي.
</Accordion>
<Accordion title="هل يجب إلغاء تفعيل سير العمل قبل استيراد CSV؟">
**نعم، إذا كانت سير العمل لديك تُشغَّل بإنشاء السجلات أو تحديثها.**
عند استيراد البيانات عبر CSV، يمكن لكل سجل يتم إنشاؤه أو تحديثه تشغيل سير العمل. قد يؤدي الاستيراد الكبير (آلاف السجلات) إلى:
* بلوغ حد 5,000 تشغيل/ساعة
* استهلاك قدر كبير من اعتمادات سير العمل
* إرسال رسائل بريد إلكتروني أو إشعارات غير متوقعة
* إنشاء مهام أو سجلات مكررة
**قبل الاستيراد الكمي**:
1. اذهب إلى **الإعدادات → سير العمل**
2. حدّد سير العمل المُشغَّلة بواسطة الكائن الذي تقوم باستيراده
3. **عطِّلها** مؤقتاً
4. شغّل استيراد CSV الخاص بك
5. **أعد تفعيل** سير العمل عند الانتهاء
**بديل**: إذا كنت تحتاج إلى أن تعمل سير العمل على البيانات المستوردة، فقم بالاستيراد على دفعات أصغر للبقاء ضمن حدود المعدل.
</Accordion>
<Accordion title="كيف أرتّب مخطط سير العمل؟">
إذا بدا مخطط سير العمل لديك فوضوياً مع تشتت العقد، فيمكنك تنظيمه تلقائياً:
1. انقر بزر الفأرة الأيمن في أي مكان على مخطط سير العمل
2. انقر **Tidy up workflow**
سيؤدي ذلك إلى إعادة ترتيب جميع العقد تلقائياً في مخطط نظيف ومنظم.
</Accordion>
</AccordionGroup>

View File

@@ -0,0 +1,81 @@
---
title: سير العمل
description: تعرّف على كيفية إنشاء عمليات الأتمتة في Twenty.
---
## أهمية تدفقات العمل
تم تصميم Twenty لتوفير أقصى قدر من المرونة للمستخدمين. بدلاً من إجبارك على تكييف عمليات عملك مع ميزات ثابتة ومعدة مسبقًا، تتيح تدفقات العمل لك بناء الأتمتة التي تُنشئ نظام إدارة علاقات العملاء (CRM) الأنسب لحالات الاستخدام الفريدة الخاصة بك.
تدفقات العمل هي ميزة داخل تطبيق Twenty لبناء هذه الأتمتة. توفر لك لبنات البناء لإنشاء ما تحتاجه عملك تمامًا، عند الحاجة إليه.
## ماذا يمكنني أن أفعل مع تدفقات العمل؟
نوصي ببناء الأتمتة لغرضين رئيسيين:
1. **الأتمتة الداخلية لتسهيل العمل اليومي لفريقك**: قلل من كمية الإدخالات اليدوية والمهام المتكررة التي تبطئ فريقك.
2. **إدخال البيانات في Twenty وخارجها**: اربط Twenty من خلال النداءات البرمجية (API) وإشعارات الويب (webhooks) بقاعدة البيانات الخاصة بك والأدوات الأخرى.
## إنشاء سير العمل الأول لديك
### الخطوة 1: إنشاء سير عمل جديد
1. انتقل إلى **سير العمل** المتاح أسفل الكائنات الأخرى
2. انقر **+ سجل جديد**
3. امنح سير العمل اسمًا
### الخطوة 2: إضافة مشغل
يبدأ كل سير عمل بمشغل. اختر مما يلي:
* **أحداث السجل**: عند إنشاء سجل أو تحديثه أو حذفه
* **الجدولة**: التشغيل في أوقات محددة (يوميًا، أسبوعيًا، إلخ.)
* **يدوي**: يتم تشغيله بفعل من المستخدم
* **ويب هوك**: يتم تشغيله بواسطة ويب هوك
<img src="/images/user-guide/workflows/workflow_triggers.png" style={{width:'100%'}} />
### الخطوة 3: إضافة إجراءات
بعد المشغل، أضف إجراءً واحدًا أو أكثر:
* **إنشاء سجل**: إضافة سجلات جديدة إلى أي كائن
* **تحديث سجل**: تعديل بيانات السجل الحالي
* **حذف سجل**: إزالة السجلات من الكائنات
* **البحث في السجلات**: العثور على السجلات المطابقة للمعايير
* **إدراج أو تحديث سجل**: إنشاء أو تحديث بناءً على معايير المطابقة
* **Iterator**: التكرار عبر مصفوفات السجلات
* **تصفية**: تحديد السجلات التي تتابع التنفيذ
* **تأخير**: الانتظار قبل المتابعة (مدة أو تاريخ مجدول)
* **إرسال بريد إلكتروني**: إرسال رسائل البريد الإلكتروني عبر حسابك المتصل
* **كود**: تشغيل JavaScript مخصص
* **طلب HTTP**: استدعاء واجهات برمجة التطبيقات الخارجية
* **نموذج**: الحصول على مدخلات من المستخدمين ضمن واجهة مستخدم Twenty وقت التنفيذ
* **AI Agent** (قريبًا): تنفيذ مهام ذكاء اصطناعي ذكية
<img src="/images/user-guide/workflows/workflow_actions.png" style={{width:'100%'}} />
### الخطوة 4: الاختبار والتفعيل
1. استخدم زر **اختبار** لتشغيل سير العمل باستخدام بيانات نموذجية
2. راجع النتائج للتأكد من أنها تعمل كما هو متوقع
3. بدّل حالة سير العمل إلى **نشط** عندما تكون جاهزًا
## أفضل الممارسات في سير العمل
* **تحرير أسماء الخطوات**: أعد تسمية خطوات سير العمل بشكل واضح لبيان ما يقوم به كل منها. يساعد هذا في الصيانة ويجعل تسليمها إلى زملاء العمل سهلاً
* **استخدم بيانات الخطوة السابقة**: يمكنك استخدام الحقول من السجلات التي تمت إعادتها بواسطة أي خطوة سابقة في سير العمل
* **ابدأ ببساطة**: ابدأ بسير عمل بسيط وأضف التعقيد بمرور الوقت بينما تصبح أكثر راحة مع النظام
* **خطط قبل البناء**: قم برسم منطق سير العمل الخاص بك قبل البدء في البناء لتجنب التوقف في منتصف الطريق
## الخطوات التالية
* [مشغلات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-triggers)
* [إجراءات سير العمل](/l/ar/user-guide/workflows/capabilities/workflow-actions)
* [أتمتة إدارة علاقات العملاء](/l/ar/user-guide/workflows/how-tos/crm-automations/closed-won-automations)
## هل تحتاج إلى مساعدة؟
<Tip>
هل تريد مساعدة في أتمتة مسارات عملك؟ [اعثر على عشرين شريكا معتمدا](https://twenty.com/partners/list?categories=SOLUTIONING\&ref=docs-workflows) لتصميم وبناء أتمتاتك من النهاية إلى النهاية.
</Tip>