أدوات MCP
عروض الأسعار ومندوبو المبيعات
أدوات MCP لإنشاء عروض الأسعار وتعديلها واعتمادها وتوليدها من منافسة وتنزيلها، ولسجل مندوبي المبيعات.
عرض السعر هو العرض المسعر الذي تقدمه مؤسستك لجهة مشترية: ترويسة فيها الجهة المخاطبة وفترة الصلاحية ومدة التوريد وشروط الدفع وشخص للتواصل، وبنود بكمية وسعر وحدة وضريبة. ويبقى مسودة حتى يعتمد. وختم المؤسسة وتوقيع مندوب المبيعات لا يطبعان على ملف PDF إلا والعرض معتمد، وأي تغيير في المحتوى يعيده مسودة. وسجل مندوبي المبيعات هو قائمة الأشخاص الذين يختار منهم شخص التواصل المطبوع. وتجد صفحات التطبيق في عروض الأسعار ومندوبو المبيعات.
| الأداة | ما تفعله |
|---|---|
| quotations_list | عرض عروض الأسعار |
| quotations_get | عرض سعر واحد |
| quotations_create | إنشاء عرض سعر |
| quotations_update | تعديل عرض سعر |
| quotations_delete | حذف عرض سعر |
| quotations_bulk_update | تعديل ترويسات عدة عروض |
| quotations_set_approval | اعتماد عروض الأسعار أو إلغاء اعتمادها |
| quotations_defaults_get | عرض القيم الافتراضية لعروض الأسعار |
| tender_quotations_list | عرض عروض منافسة |
| tender_quotations_generate | توليد عروض أسعار لمنافسة |
| tender_quotation_pdf_bundle | تنزيل ملفات PDF لعروض منافسة |
| quotation_pdf | تنزيل ملف PDF لعرض سعر |
| quotation_package | تنزيل حزمة ملفات عرض سعر |
| quotation_packages_bundle | تنزيل حزم عدة عروض |
| quotation_product_document_prefill | عرض القيم المعبأة لمستند المنتج |
| quotation_product_document | توليد مستند المنتج |
| sales_persons_list | عرض مندوبي المبيعات |
| sales_persons_get | عرض مندوب مبيعات |
| sales_persons_create | إضافة مندوب مبيعات |
| sales_persons_update | تعديل مندوب مبيعات |
| sales_persons_delete | حذف مندوب مبيعات |
عروض الأسعار
إنشاء عرض السعر وقراءته وتعديله وحذفه، واعتماد العروض، وقراءة القيم الافتراضية التي تبدأ منها العروض الجديدة.
quotations_list
يعرض عروض أسعار مؤسستك من الأحدث إلى الأقدم، ويرشحها بمنافسة واحدة عند الحاجة. ويضيف summary إجمالي العروض في كل عملة.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
tender_id | integer | لا | يقصر النتائج على عروض هذه المنافسة. |
summary | boolean | لا | true يضيف summary إلى الرد: عدد العروض count وإجماليها لكل عملة في totals_by_currency، عن كل العروض المطابقة لا عن الصفحة وحدها. |
page | integer | لا | رقم الصفحة، ويبدأ من 1. |
page_size | integer | لا | عدد النتائج في الصفحة: 20 افتراضيا، وحده الأقصى 100. |
ما يعيده: صفحة من العروض في data مع total وpage وpage_size وtotal_pages، وsummary إن طلبته. لكل عرض id وquote_number وcustomer_name وapproval_status وcurrency والإجماليات total_subtotal وtotal_vat وtotal_grand، ومنافسته في tenders.
- القائمة لا تحمل البنود. للبنود استخدم
quotations_get.
quotations_get
يقرأ عرض سعر كاملا: الترويسة والبنود وبيانات الشركة المجمدة عند الإنشاء وشخص التواصل المطبوع ومنافسته. استخدمه قبل التعديل لتعرف ما يحمله العرض بالضبط.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف عرض السعر، ويأتي من quotations_list. |
ما يعيده: quotation (الترويسة وapproval_status وapproved_at وsalesperson_snapshot وcompany_snapshot وفيه logo_url وstamp_url برابطين جديدين)، وitems بمعرف كل بند، وtender (agency_name وtender_name أو null)، وitemImages برابط صورة الغلاف لكل بند عليه منتج بصور.
- معرف البند هنا هو ما يطلبه
quotation_product_documentفيitem_idوفي مفاتيحfields. - العرض الذي ليس في مؤسستك يرد بخطأ 404.
quotations_create
ينشئ عرض سعر واحدا: إما مستقلا باسم جهة مخاطبة، أو مربوطا بمنافسة تصير جهتها هي المخاطبة. يعطيه رقما من عداد مؤسستك ويبدأ مسودة، وتجمد بيانات شركتك فيه لحظة الإنشاء.
يغير البيانات · الصلاحية quotations.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
tender_id | integer | لا | معرف المنافسة المربوطة، وتصير جهتها هي المخاطبة ما لم تسم غيرها. يجب أن تكون منافسة ظاهرة لمؤسستك. احذفه أو أرسل null لعرض بلا منافسة. |
customer_id | integer | لا | معرف ملف عميل من customers_list. يطبع اسمه جهة مخاطبة إن لم تعط customer_name. والعميل الذي ليس من مؤسستك يرد بخطأ 404. |
customer_name | string | لا | الجهة المخاطبة المطبوعة، حتى 200 حرف. تغلب اسم جهة المنافسة المربوطة. وفي عرض بلا منافسة أعط هذا الحقل أو customer_id ليكون للعرض جهة مخاطبة. |
rfq_no | string | لا | رقم طلب التسعير عند الجهة المشترية، حتى 100 حرف. |
quote_validity_days | integer | لا | مدة صلاحية العرض بالأيام، من 1 إلى 3650. إن حذفتها فالقيمة الافتراضية في إعدادات مؤسستك (انظر quotations_defaults_get). |
delivery_period_days | integer | لا | مدة التوريد بالأيام، من 1 إلى 3650. إن حذفتها فالقيمة الافتراضية في إعدادات مؤسستك. |
payment_terms | string | لا | الشروط المطبوعة، حتى 500 حرف: إحدى الصيغ الجاهزة advance_100 أو advance_50_balance_on_delivery أو on_delivery أو net_30 أو net_60 أو net_90 (تطبع بالعربية والإنجليزية)، أو نص حر يطبع كما كتبته. إن حذفتها فشروط الدفع الافتراضية في إعدادات مؤسستك، وnull يطبع العرض بلا شروط دفع. |
currency | string | لا | رمز العملة، من 1 إلى 8 أحرف. الافتراضي SAR. |
notes | string | لا | ملاحظات تطبع على العرض، حتى 2000 حرف. إن حذفتها طبعت العبارة الختامية المعتادة «Looking forward for your business». |
sales_person_id | integer | لا | معرف مندوب من سجل المبيعات، ويأتي من sales_persons_list. بياناته تملأ كل حقل salesperson_* تحذفه، وتستطيع قائمة عروض الأسعار الترشيح باسمه. والمعرف الذي ليس في سجلك يرد بخطأ sales_person_not_found. |
salesperson_name | string | لا | الاسم المطبوع لشخص التواصل، حتى 200 حرف. إن حذفته أخذ اسم المندوب المختار، وإلا اسم العضو الذي ربط الاتصال. وnull يطبع بلا اسم. |
salesperson_phone | string | لا | الهاتف المطبوع لشخص التواصل، حتى 50 حرفا. إن حذفته أخذ هاتف المندوب المختار، وإلا هاتف العضو الذي ربط الاتصال. وnull يطبع بلا هاتف. |
salesperson_email | string | لا | البريد الإلكتروني المطبوع لشخص التواصل، بعنوان صالح وحتى 320 حرفا. إن حذفته أخذ بريد المندوب المختار، وإلا بريد العضو الذي ربط الاتصال. وnull يطبع بلا بريد. |
items | object[] | نعم | بنود العرض، من 1 إلى 500. |
items[].tender_item_id | integer | لا | معرف بند المنافسة الذي يغطيه هذا البند، ويأتي من بنود المنافسة في tenders_get. يستعمل في العروض المربوطة بمنافسة فقط. |
items[].product_id | integer | لا | معرف المنتج في كتالوجك، ويأتي من products_list. المنتج المربوط يعطي رقم الكتالوج إن تركته فارغا، ونسبة الضريبة إن حذفتها، ثم يمد مستند المنتج بالكتالوج والشهادات. |
items[].manufacturer_id | integer | لا | معرف الشركة المصنعة التي يقدم البند باسمها، ويأتي من manufacturers_list، ويجب أن تكون من شركات مؤسستك. إن حذفته أخذ الشركة الافتراضية للمنتج. وnull يتركه تلقائيا فتختار الشركة عند توليد المستندات. وهو ما يحدد اسم الشركة وخطاب التفويض ونوع الوكالة في مستند المنتج. |
items[].description | string | نعم | وصف البند كما يطبع، من 1 إلى 4000 حرف. |
items[].stock_no | string | لا | رقم المخزون أو رمز نوبكو، حتى 100 حرف. |
items[].catalog_no | string | لا | رقم الكتالوج، حتى 100 حرف. |
items[].unit | string | لا | وحدة القياس، حتى 50 حرفا. |
items[].quantity | number | نعم | الكمية، صفر أو أكثر. |
items[].unit_price | number | نعم | سعر الوحدة بعملة العرض، صفر أو أكثر. |
items[].vat_rate | number | لا | نسبة ضريبة القيمة المضافة من 0 إلى 100. إن حذفتها كانت 0 للبند الذي منتجه المربوط طبي، و15 لغيره، ومنه البند بلا منتج. |
{
"tender_id": 48213,
"rfq_no": "RFQ-2026-0417",
"quote_validity_days": 90,
"delivery_period_days": 30,
"payment_terms": "net_30",
"sales_person_id": 6,
"items": [
{
"tender_item_id": 902114,
"product_id": 3381,
"description": "Disposable syringe 5 ml, Luer lock, sterile",
"stock_no": "4111610529900",
"unit": "Box",
"quantity": 200,
"unit_price": 24.5
}
]
}ما يعيده: quotation_id وquote_number الذي أعطي للعرض، وlogo_url وstamp_url برابطين للشعار والختم.
- إنشاء العرض يحتسب من حصة الخطة الشهرية: 50 عرضا في خطة البداية وبلا حد في الاحترافية. وعند بلوغها ترد الأداة بالخطأ
plan_limit_reachedمعlimitوcurrent. - تملأ الحقول الفارغة من بياناتك: بند مربوط ببند منافسة بلا منتج يأخذ المنتج الذي اخترته لذلك البند، ورقم الكتالوج الفارغ يؤخذ من المنتج، والرقم الفارغ للمخزون يؤخذ من رمز مادة بند المنافسة. وما كتبته أنت لا يستبدل أبدا.
- المنافسة غير الظاهرة لمؤسستك ترد بخطأ 404، والشركة المصنعة التي ليست لمؤسستك ترد بالخطأ
manufacturer_not_found.
quotations_update
يعدل ترويسة عرض السعر أو بنوده. كل حقل اختياري وما لم ترسله يبقى كما هو، فتعديل ترويسة وحدها لا يحتاج إلى إرسال البنود. وأي تغيير يعيد العرض مسودة.
يغير البيانات · الصلاحية quotations.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف عرض السعر، ويأتي من quotations_list. |
quote_number | string | لا | الرقم المطبوع على العرض، من 1 إلى 100 حرف. فريد داخل المؤسسة. |
tender_id | integer | لا | يربط العرض بهذه المنافسة، وهي منافسة ظاهرة لمؤسستك. أرسل null لفك الربط. |
customer_id | integer | لا | يربط العرض بملف عميل، أو null لفك الربط. هذا يضبط الربط وحده، ولتغيير الجهة المخاطبة المطبوعة أرسل customer_name. |
customer_name | string | لا | الجهة المخاطبة المطبوعة، حتى 200 حرف. أرسل null لتعود إلى جهة المنافسة المربوطة. |
rfq_no | string | لا | رقم طلب التسعير عند الجهة المشترية، حتى 100 حرف. أرسل null لمسحه. |
quote_validity_days | integer | لا | مدة صلاحية العرض بالأيام، من 1 إلى 3650. أرسل null لمسحها. |
delivery_period_days | integer | لا | مدة التوريد بالأيام، من 1 إلى 3650. أرسل null لمسحها. |
payment_terms | string | لا | شروط الدفع المطبوعة، حتى 500 حرف: إحدى الصيغ الجاهزة advance_100 أو advance_50_balance_on_delivery أو on_delivery أو net_30 أو net_60 أو net_90 (تطبع بالعربية والإنجليزية)، أو نص حر يطبع كما كتبته. أرسل null ليطبع العرض بلا شروط دفع. |
currency | string | لا | رمز العملة الجديد، من 1 إلى 8 أحرف. |
notes | string | لا | ملاحظات تطبع على العرض، حتى 2000 حرف. أرسل null لمسحها. |
sales_person_id | integer | لا | معرف مندوب من سجل المبيعات، ويأتي من sales_persons_list. بياناته تملأ كل حقل salesperson_* لا ترسله في الاستدعاء نفسه، وتستطيع قائمة عروض الأسعار الترشيح باسمه. أرسل null لفك الربط، وتبقى بيانات التواصل المطبوعة كما هي. |
salesperson_name | string | لا | الاسم المطبوع لشخص التواصل، حتى 200 حرف. يدمج في بيانات التواصل المحفوظة فما لم ترسله يبقى كما هو. أرسل null ليطبع بلا اسم. |
salesperson_phone | string | لا | الهاتف المطبوع لشخص التواصل، حتى 50 حرفا. أرسل null ليطبع بلا هاتف. |
salesperson_email | string | لا | البريد الإلكتروني المطبوع لشخص التواصل، بعنوان صالح وحتى 320 حرفا. أرسل null ليطبع بلا بريد. |
items | object[] | لا | المجموعة الكاملة الجديدة من البنود، من 1 إلى 500. إن أرسلتها استبدلت كل البنود القائمة وأعيد حساب الإجماليات، وإن حذفتها بقيت البنود والإجماليات كما هي. |
items[].tender_item_id | integer | لا | معرف بند المنافسة الذي يغطيه هذا البند، ويأتي من بنود المنافسة في tenders_get. يستعمل في العروض المربوطة بمنافسة فقط. |
items[].product_id | integer | لا | معرف المنتج في كتالوجك، ويأتي من products_list. المنتج المربوط يعطي رقم الكتالوج إن تركته فارغا، ونسبة الضريبة إن حذفتها، ثم يمد مستند المنتج بالكتالوج والشهادات. |
items[].manufacturer_id | integer | لا | معرف الشركة المصنعة التي يقدم البند باسمها، ويأتي من manufacturers_list، ويجب أن تكون من شركات مؤسستك. إن حذفته أخذ الشركة الافتراضية للمنتج. وnull يتركه تلقائيا فتختار الشركة عند توليد المستندات. وهو ما يحدد اسم الشركة وخطاب التفويض ونوع الوكالة في مستند المنتج. |
items[].description | string | نعم | وصف البند كما يطبع، من 1 إلى 4000 حرف. |
items[].stock_no | string | لا | رقم المخزون أو رمز نوبكو، حتى 100 حرف. |
items[].catalog_no | string | لا | رقم الكتالوج، حتى 100 حرف. |
items[].unit | string | لا | وحدة القياس، حتى 50 حرفا. |
items[].quantity | number | نعم | الكمية، صفر أو أكثر. |
items[].unit_price | number | نعم | سعر الوحدة بعملة العرض، صفر أو أكثر. |
items[].vat_rate | number | لا | نسبة ضريبة القيمة المضافة من 0 إلى 100. إن حذفتها كانت 0 للبند الذي منتجه المربوط طبي، و15 لغيره، ومنه البند بلا منتج. |
{
"id": 311,
"customer_name": "Acme Medical Supplies",
"quote_validity_days": 60,
"payment_terms": null
}ما يعيده: quotation_id للعرض بعد التعديل.
- أي تغيير في الترويسة أو البنود يعيد العرض مسودة، فيتوقف ختم المؤسسة والتوقيع عن الطباعة حتى تعتمده من جديد بـquotations_set_approval.
- إرسال
itemsيستبدل كل البنود، فمصفوفة ناقصة تبتر المستند. وعلى خلاف الإنشاء لا يملأ التعديل رقم الكتالوج ولا رقم المخزون الفارغين من بياناتك، فأرسلهما كاملين مع كل بند. أما نسبة الضريبة المحذوفة والشركة المصنعة المحذوفة فتحددان كما في الإنشاء. - الرقم المأخوذ يرد بخطأ 409
quote_number_taken. والعرض الذي ليس من مؤسستك أو المنافسة غير الظاهرة لها يردان بخطأ 404. - بيانات شركتك المجمدة لا تتغير بالتعديل أبدا.
quotations_delete
يحذف عرض السعر وبنوده نهائيا. لا يمكن التراجع عن ذلك.
يحذف بيانات أو يستبدلها · الصلاحية quotations.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف عرض السعر، ويأتي من quotations_list. |
ما يعيده: تأكيد الحذف ok: true.
- العرض الذي ليس من مؤسستك يرد بخطأ 404.
quotations_bulk_update
يعدل ترويسات حتى 200 عرض في استدعاء واحد: الرقم والجهة المخاطبة والصلاحية والتوريد والعملة والملاحظات وربط المنافسة والمندوب وبيانات التواصل. لا يقبل البنود، فلا يبتر مستندا أبدا. ولتعديل البنود استخدم quotations_update لكل عرض.
يغير البيانات · الصلاحية quotations.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
updates | object[] | نعم | عرض في كل عنصر، من 1 إلى 200. يحمل كل عنصر id والمفاتيح التي تريد تغييرها فقط: ما لم يرسل يبقى، وnull الصريح يمسح الحقل. |
updates[].id | integer | نعم | معرف عرض السعر، ويأتي من quotations_list. |
updates[].quote_number | string | لا | الرقم الجديد، من 1 إلى 100 حرف. والرقم المأخوذ يفشل في هذا الصف وحده. |
updates[].tender_id | integer | لا | يربط العرض بهذه المنافسة. أرسل null لفك الربط. |
updates[].customer_name | string | لا | الجهة المخاطبة المطبوعة، حتى 200 حرف. أرسل null لتعود إلى جهة المنافسة. |
updates[].rfq_no | string | لا | رقم طلب التسعير عند الجهة المشترية، حتى 100 حرف. أرسل null لمسحه. |
updates[].quote_validity_days | integer | لا | مدة صلاحية العرض بالأيام، من 1 إلى 3650. أرسل null لمسحها. |
updates[].delivery_period_days | integer | لا | مدة التوريد بالأيام، من 1 إلى 3650. أرسل null لمسحها. |
updates[].payment_terms | string | لا | شروط الدفع المطبوعة، حتى 500 حرف: إحدى الصيغ الجاهزة advance_100 أو advance_50_balance_on_delivery أو on_delivery أو net_30 أو net_60 أو net_90 (تطبع بالعربية والإنجليزية)، أو نص حر يطبع كما كتبته. أرسل null ليطبع العرض بلا شروط دفع. |
updates[].currency | string | لا | رمز العملة الجديد، من 1 إلى 8 أحرف. |
updates[].notes | string | لا | ملاحظات تطبع على العرض، حتى 2000 حرف. أرسل null لمسحها. |
updates[].sales_person_id | integer | لا | معرف مندوب من سجل المبيعات، ويأتي من sales_persons_list. بياناته تملأ كل حقل salesperson_* لا ترسله في الاستدعاء نفسه، وتستطيع قائمة عروض الأسعار الترشيح باسمه. أرسل null لفك الربط، وتبقى بيانات التواصل المطبوعة كما هي. |
updates[].salesperson_name | string | لا | الاسم المطبوع لشخص التواصل، حتى 200 حرف. يدمج في بيانات التواصل المحفوظة فما لم ترسله يبقى كما هو. أرسل null ليطبع بلا اسم. |
updates[].salesperson_phone | string | لا | الهاتف المطبوع لشخص التواصل، حتى 50 حرفا. أرسل null ليطبع بلا هاتف. |
updates[].salesperson_email | string | لا | البريد الإلكتروني المطبوع لشخص التواصل، بعنوان صالح وحتى 320 حرفا. أرسل null ليطبع بلا بريد. |
{
"updates": [
{
"id": 311,
"sales_person_id": 6,
"payment_terms": "net_30"
},
{
"id": 312,
"sales_person_id": 6,
"payment_terms": "net_30"
}
]
}ما يعيده: updated وهي معرفات العروض التي تغيرت، وfailed وهي قائمة من id وerror للصفوف التي فشلت.
- تعالج الصفوف كل على حدة والاستدعاء ينجح ولو فشل بعضها: ما نجح يبقى محفوظا، ويسمى كل صف فاشل مع سببه، مثل
quote_number_takenوsales_person_not_found. فاقرأfailedدائما. - كل عرض تغير يعود مسودة، فأعد اعتماده بـquotations_set_approval.
- لتقديم عدة عروض باسم شخص واحد كرر
sales_person_idنفسه في كل صف: يملأ اسمه وهاتفه وبريده خانة التواصل المطبوعة في كل عرض، ويطبع توقيعه بعد إعادة الاعتماد.
quotations_set_approval
يعتمد عرضا أو عدة عروض، أو يعيدها مسودات. العرض المعتمد وحده يطبع عليه ختم المؤسسة وتوقيع مندوب المبيعات المرتبط به إن كان له توقيع محفوظ، والاعتماد لا يتوقف على وجود توقيع.
يغير البيانات · الصلاحية quotations.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
ids | integer[] | نعم | معرفات العروض، من 1 إلى 200. |
approved | boolean | نعم | true يعتمد العروض، وfalse يعيدها مسودات. |
{
"ids": [
311,
312,
313
],
"approved": true
}ما يعيده: updated وهي معرفات العروض التي تغيرت، وfailed وهي معرفات لم توجد في مؤسستك مع الخطأ not_found.
- أي تعديل في المحتوى، سواء بـ
quotations_updateأو بإعادة توليد العروض من المنافسة، يرجع العرض مسودة، فاعتمده من جديد بعد التعديل. - في التطبيق يقتصر زر الاعتماد على المالك والمدير. أما هذه الأداة فمتاحة لكل دور يستطيع تعديل عروض الأسعار، كما يبين سطر الأدوار أعلاه.
quotations_defaults_get
يقرأ القيم التي يبدأ منها عرض السعر الجديد في مؤسستك، وبيانات التواصل التي سيأخذها العرض إن لم تحدد شخصا. استخدمه قبل quotations_create لتعرف ما سيطبع إن تركت الحقول فارغة.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات
لا معاملات.
ما يعيده: validityDays وdeliveryDays (90 إن لم تضبط مؤسستك قيمة) وpaymentTerms (أو null)، وsalesperson وفيه full_name وphone وemail للعضو الذي ربط الاتصال، وcompany وهي ترويسة مؤسستك التي يطبعها العرض الجديد: الاسمان القانونيان وأرقام السجل والضريبة والعنوان ووسائل التواصل، مع رابطين مؤقتين للشعار والختم.
عروض الأسعار على منافسة
أدوات تعمل على عروض منافسة واحدة: قائمتها، وتوليد عروضها من بنودها، وتنزيل ملفاتها.
tender_quotations_list
يعرض كل عروض مؤسستك على منافسة واحدة، الأحدث أولا، برقم كل عرض وإجمالياته.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
tender_id | integer | نعم | معرف المنافسة. |
ما يعيده: قائمة quotations، لكل عرض id وquote_number وrfq_no وcurrency وtotal_subtotal وtotal_vat وtotal_grand وcreated_at.
- هذه القائمة لا تذكر حالة الاعتماد. لمعرفتها استخدم
quotations_listمعtender_id.
tender_quotations_generate
يولد عروض أسعار على منافسة من البنود التي ترسلها: per_item يعطي كل بند عرضه، وcombined يجمع البنود كلها في عرض واحد. وإعادة الإرسال آمنة: البنود التي يغطيها عرض قائم تحدث في مكانها بدل أن يتكرر العرض.
يغير البيانات · الصلاحية quotations.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
tender_id | integer | نعم | معرف المنافسة، وهي منافسة ظاهرة لمؤسستك. |
mode | string | لا | per_item عرض لكل بند، وهو الافتراضي، وcombined عرض واحد لكل البنود. |
rfq_no | string | لا | رقم طلب التسعير عند الجهة المشترية، حتى 100 حرف. |
quote_validity_days | integer | لا | مدة صلاحية العرض بالأيام، من 1 إلى 3650. إن حذفتها فالقيمة الافتراضية في إعدادات مؤسستك (انظر quotations_defaults_get). |
delivery_period_days | integer | لا | مدة التوريد بالأيام، من 1 إلى 3650. إن حذفتها فالقيمة الافتراضية في إعدادات مؤسستك. |
payment_terms | string | لا | الشروط المطبوعة، حتى 500 حرف: إحدى الصيغ الجاهزة advance_100 أو advance_50_balance_on_delivery أو on_delivery أو net_30 أو net_60 أو net_90 (تطبع بالعربية والإنجليزية)، أو نص حر يطبع كما كتبته. إن حذفتها فشروط الدفع الافتراضية في إعدادات مؤسستك، وnull يطبع العرض بلا شروط دفع. |
currency | string | لا | رمز العملة، من 1 إلى 8 أحرف. الافتراضي SAR. |
notes | string | لا | ملاحظات تطبع على العرض، حتى 2000 حرف. إن حذفتها طبعت العبارة الختامية المعتادة «Looking forward for your business». |
sales_person_id | integer | لا | معرف مندوب من سجل المبيعات، ويأتي من sales_persons_list. بياناته تملأ كل حقل salesperson_* تحذفه، وتستطيع قائمة عروض الأسعار الترشيح باسمه. والمعرف الذي ليس في سجلك يرد بخطأ sales_person_not_found. |
salesperson_name | string | لا | الاسم المطبوع لشخص التواصل، حتى 200 حرف. إن حذفته أخذ اسم المندوب المختار، وإلا اسم العضو الذي ربط الاتصال. وnull يطبع بلا اسم. |
salesperson_phone | string | لا | الهاتف المطبوع لشخص التواصل، حتى 50 حرفا. إن حذفته أخذ هاتف المندوب المختار، وإلا هاتف العضو الذي ربط الاتصال. وnull يطبع بلا هاتف. |
salesperson_email | string | لا | البريد الإلكتروني المطبوع لشخص التواصل، بعنوان صالح وحتى 320 حرفا. إن حذفته أخذ بريد المندوب المختار، وإلا بريد العضو الذي ربط الاتصال. وnull يطبع بلا بريد. |
items | object[] | نعم | البنود المراد تقديمها، من 1 إلى 500. |
items[].tender_item_id | integer | لا | معرف بند المنافسة الذي يغطيه هذا البند، ويأتي من بنود المنافسة في tenders_get. يستعمل في العروض المربوطة بمنافسة فقط. |
items[].product_id | integer | لا | معرف المنتج في كتالوجك، ويأتي من products_list. المنتج المربوط يعطي رقم الكتالوج إن تركته فارغا، ونسبة الضريبة إن حذفتها، ثم يمد مستند المنتج بالكتالوج والشهادات. |
items[].manufacturer_id | integer | لا | معرف الشركة المصنعة التي يقدم البند باسمها، ويأتي من manufacturers_list، ويجب أن تكون من شركات مؤسستك. إن حذفته أخذ الشركة الافتراضية للمنتج. وnull يتركه تلقائيا فتختار الشركة عند توليد المستندات. وهو ما يحدد اسم الشركة وخطاب التفويض ونوع الوكالة في مستند المنتج. |
items[].description | string | نعم | وصف البند كما يطبع، من 1 إلى 4000 حرف. |
items[].stock_no | string | لا | رقم المخزون أو رمز نوبكو، حتى 100 حرف. |
items[].catalog_no | string | لا | رقم الكتالوج، حتى 100 حرف. |
items[].unit | string | لا | وحدة القياس، حتى 50 حرفا. |
items[].quantity | number | نعم | الكمية، صفر أو أكثر. |
items[].unit_price | number | نعم | سعر الوحدة بعملة العرض، صفر أو أكثر. |
items[].vat_rate | number | لا | نسبة ضريبة القيمة المضافة من 0 إلى 100. إن حذفتها كانت 0 للبند الذي منتجه المربوط طبي، و15 لغيره، ومنه البند بلا منتج. |
{
"tender_id": 48213,
"mode": "per_item",
"payment_terms": "net_30",
"sales_person_id": 6,
"items": [
{
"tender_item_id": 902114,
"product_id": 3381,
"description": "Disposable syringe 5 ml, Luer lock, sterile",
"unit": "Box",
"quantity": 200,
"unit_price": 24.5
},
{
"tender_item_id": 902115,
"product_id": 3390,
"description": "Surgical gloves, nitrile, size M",
"unit": "Box",
"quantity": 500,
"unit_price": 31
}
]
}ما يعيده: قائمة quotations، لكل عرض quotation_id وquote_number وupdated: true للعرض الذي حدث في مكانه وfalse للعرض الجديد.
- في
per_itemيحدث العرض القائم لبند المنافسة نفسه بالرقم نفسه، وفيcombinedيحدث العرض الذي يغطي مجموعة بنود المنافسة نفسها بالضبط. لا يحدث العرض إلا إن غطت بنودك كل بنوده، وإلا صارت بنودك عروضا جديدة وبقي العرض القائم كما هو. وكل ما لا يجد عرضا قائما ينشأ جديدا. - أعط كل بند
tender_item_id: البند بلا بند منافسة لا يمكن مطابقته بعرض سابق، فتنشئ كل مرة عرضا جديدا. - حقول الترويسة تسري على العروض الجديدة وحدها، والعرض المحدث يحتفظ بترويسته. وكل عرض محدث يعود مسودة فيلزم اعتماده من جديد.
- العروض الجديدة وحدها تحتسب من حصة الخطة الشهرية (50 في البداية وبلا حد في الاحترافية)، ويفحص الحد كله قبل أن يبدأ التوليد، فيرد بالخطأ
plan_limit_reachedولا ينشأ شيء. أما فشل عرض في وسط الدفعة فيوقفها، وتبقى العروض التي سبقته.
tender_quotation_pdf_bundle
يولد ملف PDF لكل عرض سعر على منافسة ويعيدها في أرشيف ZIP واحد. وهو يعمل في طلب واحد، فلمنافسة عروضها كثيرة استخدم quotation_packages_bundle مع pdf_only، فهو يبني الملف في الخلفية.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
tender_id | integer | نعم | معرف المنافسة. |
ما يعيده: ملف ZIP فيه ملف PDF لكل عرض: filename وcontent_type وsize_bytes وbase64.
- المنافسة التي لا عرض لمؤسستك عليها ترد بخطأ 404 ورسالة
No quotations to download. - يطبع كل ملف ختم المؤسسة وتوقيع المندوب إن كان عرضه معتمدا، وبدونهما إن كان مسودة.
ملفات عرض السعر
الملف الأساسي هو عرض السعر المطبوع. ومستند المنتج ملفات إضافية لكل بند، تقدم مع العرض: خطاب غلاف مع الكتالوج، والكتالوج وحده، وشهادة SFDA أو خطاب امتثال مولد، وخطاب تفويض الشركة المصنعة، وملف نصي بحقول التسجيل في بوابة المشتري. وما ليس له مصدر في بياناتك يغيب من الأرشيف دون خطأ. تجد الشرح في عروض الأسعار.
quotation_pdf
يولد ملف PDF لعرض سعر واحد ويعيده. هو المستند المطبوع نفسه: يحمل ختم المؤسسة وتوقيع المندوب إن كان العرض معتمدا، ويطبع المسودة بلا ختم وبعبارة أنها غير سارية.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف عرض السعر، ويأتي من quotations_list. |
ما يعيده: ملف PDF: filename وcontent_type وsize_bytes وbase64.
- اسم الملف هو رقم العرض، إلا العرض ببند واحد على منافسة نوبكو فيسمى بالرقم المرجعي للمنافسة ثم رقم العرض ثم تسلسل البند.
- العرض الذي ليس من مؤسستك يرد بخطأ 404.
quotation_package
يعيد كل ما تنتجه المنصة لعرض واحد في أرشيف ZIP واحد: ملف PDF للعرض، ولكل بند ملفات مستند المنتج. حقول المستند فيه هي القيم المعبأة تلقائيا بلا تعديل. ولتعديل حقل استخدم quotation_product_document.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف عرض السعر، ويأتي من quotations_list. |
ما يعيده: ملف ZIP: filename وcontent_type وsize_bytes وbase64.
- لكل بند حتى خمسة ملفات: خطاب الغلاف مع الكتالوج، والكتالوج وحده، وشهادة SFDA أو خطاب الامتثال المولد، وخطاب التفويض، والملف النصي. وتغيب الملفات التي لا مصدر لها: فبند بلا كتالوج مخزن يخرج غلافه بلا صفحات كتالوج، وبند لشركة مصنعة بلا خطاب تفويض محفوظ يخرج بلا هذا الخطاب.
- تسمى الملفات برقم العرض ورقم البند في العرض، فتبقى متميزة خارج الأرشيف.
quotation_packages_bundle
يجمع حزم عدة عروض في أرشيفات ZIP مسطحة، كل عرض بملف PDF وملفات مستند منتجه جنبا إلى جنب. هذا هو «تنزيل كل الملفات» في قائمة عروض الأسعار. ويبنى في الخلفية: تبدأه الأداة وتنتظر مدة wait_seconds ثم تعيد الملف إن اكتمل، أو المهمة إن لم يكتمل. لا يغير شيئا في بياناتك، ويحفظ الملف المنتج 24 ساعة بعد اكتماله.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
ids | integer[] | نعم | معرفات العروض المراد تنزيلها، من 1 إلى 100. |
pdf_only | boolean | لا | true يضم ملف PDF العرض وحده لكل عرض، بلا ملفات مستند المنتج. وهو «تنزيل ملفات PDF لعروض الأسعار» في القائمة. |
report | boolean | لا | true يعيد المهمة (حالتها وتقريرها وأجزاءها) بدل الملف نفسه. |
wait_seconds | integer | لا | عدد الثواني التي تنتظر فيها الأداة اكتمال الحزمة قبل أن تعيد المهمة، من 0 إلى 120. الافتراضي 40، وتكفي عادة لعدد قليل من العروض. |
{
"ids": [
311,
312,
313
],
"pdf_only": true,
"wait_seconds": 60
}ما يعيده: إن اكتمل الأرشيف جزءا واحدا داخل مدة الانتظار فالملف: filename وcontent_type وsize_bytes وbase64 مع report. وإلا فالمهمة: job_id وstatus (queued أو running أو succeeded أو failed أو cancelled) وprogress وparts وreport عند النجاح وnext_step بما يلزم بعدها.
- الحزمة الكبيرة تأتي في عدة أجزاء ZIP، كل عرض كاملا في جزء، فاستخرج كل الأجزاء في مجلد واحد. وتنزل الأجزاء بـgeneration_jobs_part، وتتابع المهمة بـgeneration_jobs_get.
- يبنى للعضو حزمة واحدة في كل مرة. فإن كانت له حزمة قيد البناء ردت الأداة بتلك المهمة مع
already_running(وقد تكون لاختيار آخر)، ولبدء حزمة جديدة ألغها بـgeneration_jobs_cancel. - يسمي تقرير المهمة المنتهية كل عرض في
includedمع جزئه، وكل عرض لم ينتج شيئا فيfailedبرقمه وسببه:not_foundأوrender_failedأوtoo_large(ملفاته وحدها تتجاوز أرشيفا واحدا). ولا يسقط عرض بصمت. - إن لم يكن أي من المعرفات عرضا في مؤسستك ردت الأداة بخطأ 404. ولمجموعة ملفات نوبكو للرفع في البوابة فضل tenders_nupco_attachments_fill، فحزمتها مكتفية بذاتها.
- هذه الأداة غير متاحة لدور المشاهد.
quotation_product_document_prefill
يعرض لكل بند في عرض السعر القيم التي سيعبأ بها مستند المنتج تلقائيا، وهل له كتالوج مخزن. استخدمه لترى ما سيطبع أو لتبني fields قبل استدعاء quotation_product_document.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف عرض السعر، ويأتي من quotations_list. |
ما يعيده: quote_number وlines، لكل بند item_id وlabel وfields (القيم بمفاتيحها) وhas_catalog وcatalog_name.
- العرض الذي ليس من مؤسستك يرد بخطأ 404.
quotation_product_document
يولد مستند المنتج لعرض سعر في أرشيف ZIP من ملفات منفصلة: لكل بند خطاب الغلاف مع الكتالوج، والكتالوج وحده، وشهادة SFDA أو خطاب الامتثال المولد، وخطاب تفويض الشركة المصنعة، وملف نصي بحقول التسجيل في بوابة المشتري. يغطي كل البنود أو بندا واحدا، ويقبل تعديل القيم لكل بند.
للقراءة فقط · الصلاحية quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف عرض السعر، ويأتي من quotations_list. |
mode | string | نعم | combined يغطي كل بنود العرض، وsingle يغطي بندا واحدا تحدده بـitem_id. |
item_id | integer | لا | معرف بند في عرض السعر نفسه، ويأتي من quotations_get. مطلوب مع single، ويتجاهل مع combined. |
fields | object | لا | تعديلات على القيم المعبأة. المفتاح معرف البند في العرض (نص رقمي مثل "4807")، وقيمته كائن مفاتيحه أسماء الحقول وقيمه نصوص حتى 2000 حرف. ما لم ترسله يبقى كما عبئ، والقيمة الفارغة تمسح ذلك الصف. ومفتاح الحقل المكتوب خطأ يتجاهل دون خطأ، فخذ المفاتيح من quotation_product_document_prefill. |
{
"id": 311,
"mode": "single",
"item_id": 4807,
"fields": {
"4807": {
"product_title": "Disposable syringe 5 ml",
"min_order_qty": "1000"
}
}
}ما يعيده: ملف ZIP: filename وcontent_type وsize_bytes وbase64. وأسماء الملفات تبدأ برقم العرض ورقم البند، ثم cover أو catalog أو sfda أو authorization أو info.
- حقول صفحة الغلاف:
serialوnupcoوcompany_nameوmanufacturer_nameوproduct_titleوdescriptionوcatalogueوmdmaوlisting. وحقول الملف النصي:mdma_numberوmdma_expiryوmin_order_qtyوshelf_life_yearsوauthorization_validityوvolumeوvolume_unitوpackage_typeوpackage_sizeوpacking_uomوweightوweight_unitوunit_priceوfoc_percentوvatوnet_priceوadditional_infoوagency_type. - لا يمكن رفع كتالوج عبر هذه الأداة: تضم الكتالوجات المخزنة لمنتجات البنود تلقائيا. وإن لم يوجد لبند كتالوج مخزن خرج غلافه وحده، وإن لم تكن لشركته المصنعة شهادة أو خطاب تفويض محفوظ غاب ملفه من الأرشيف دون خطأ.
- المنتج المسجل على أنه قيد التسجيل يأخذ خطاب الامتثال المولد بدل أي شهادة محفوظة. والبند الذي لا يوجد في العرض في
singleيرد بخطأ 404، وغيابitem_idمعsingleيرد بخطأ 400. وهذه الأداة غير متاحة لدور المشاهد.
مندوبو المبيعات
السجل ملك المؤسسة كلها: ما يضيفه زميلك تراه. والسطر فيه ليس حساب دخول، بل اسم وبريد وهاتف يملؤها اختيار الشخص في خانة التواصل المطبوعة على عرض السعر.
sales_persons_list
يعرض مندوبي المبيعات في سجل مؤسستك من الأحدث إلى الأقدم. يخفي غير النشطين ما لم تطلبهم، ويستطيع أن يعرض معهم أعضاء الفريق الذين لم يضافوا إلى السجل بعد.
للقراءة فقط · الصلاحية sales_persons.read · كل الأدوار · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
include_inactive | boolean | لا | true يعرض غير النشطين أيضا. |
include_team | boolean | لا | true يضيف team_members: أعضاء المؤسسة الذين لم يضافوا إلى السجل، لتضيفهم بـsales_persons_create ومعرف العضو user_id. |
page | integer | لا | رقم الصفحة، ويبدأ من 1. |
page_size | integer | لا | عدد النتائج في الصفحة: 20 افتراضيا، وحده الأقصى 100. |
ما يعيده: صفحة من المندوبين في data مع total وpage وpage_size وtotal_pages. لكل مندوب id وname وemail وphone وuser_id (للمرتبط بعضو فريق) وis_active. ومع include_team يضاف team_members بـuser_id وname وemail وphone لكل عضو.
team_membersلا يعود إلا للأدوار التي تعدل عروض الأسعار (المالك والمدير والمبيعات والمشتريات)، ويتجاهل الطلب لغيرها دون خطأ، لأن القائمة تكشف بيانات تواصل الأعضاء.
sales_persons_get
يقرأ مندوبا واحدا من سجل مؤسستك: اسمه وبريده وهاتفه وحالته، وهل هو مرتبط بعضو فريق. استخدمه للتحقق مما سيملؤه اختياره في عرض سعر.
للقراءة فقط · الصلاحية sales_persons.read · كل الأدوار · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف المندوب، ويأتي من sales_persons_list. |
ما يعيده: المندوب sales_person، ومعرفه الذي تضعه عروض الأسعار في sales_person_id.
- المعرف الذي ليس في سجل مؤسستك يرد بخطأ 404.
sales_persons_create
يضيف شخصا إلى سجل مبيعات مؤسستك: إما باسمه وبريده وهاتفه، وإما بمعرف عضو فريق فتؤخذ بياناته من ملفه الشخصي ويبقى السطر مرتبطا به. لا ينشأ حساب دخول في الحالتين.
يغير البيانات · الصلاحية sales_persons.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
name | string | لا | الاسم الكامل كما يطبع، من 1 إلى 200 حرف. مطلوب ما لم ترسل user_id. |
email | string | لا | البريد الإلكتروني المطبوع على العروض، بعنوان صالح وحتى 320 حرفا. |
phone | string | لا | الهاتف المطبوع على العروض، حتى 50 حرفا. |
user_id | string | لا | معرف عضو فريق (UUID) من team_members في sales_persons_list. يملأ ملفه الشخصي ما لم ترسله من الاسم والبريد والهاتف، ويحدث السطر تلقائيا كلما عدل العضو ملفه. |
{
"name": "Omar Al-Qahtani",
"email": "omar@acme-medical.example",
"phone": "+966501234567"
}ما يعيده: المندوب الجديد sales_person.
- لكل عضو سطر واحد في السجل: تكراره يرد بخطأ 409
already_on_roster. وuser_idلمن ليس عضوا في مؤسستك يرد بخطأ 400not_a_team_member، وغيابnameوuser_idمعا يرد بخطأ 400. - توقيع العضو المحفوظ في إعداداته لا يطبع على العرض المعتمد إلا إذا كان المندوب المختار مرتبطا بذلك العضو.
sales_persons_update
يعدل اسم المندوب أو بريده أو هاتفه، أو يعطله ويعيد تفعيله. لا يتغير إلا ما ترسله. ولا يعيد كتابة عروض الأسعار التي اختارته من قبل، فلكل عرض نسخته من بيانات التواصل.
يغير البيانات · الصلاحية sales_persons.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف المندوب، ويأتي من sales_persons_list. |
name | string | لا | الاسم الكامل، من 1 إلى 200 حرف. |
email | string | لا | البريد الإلكتروني، بعنوان صالح وحتى 320 حرفا. أرسل null لمسحه. |
phone | string | لا | الهاتف، حتى 50 حرفا. أرسل null لمسحه. |
is_active | boolean | لا | false يخفي المندوب من قوائم الاختيار وقائمة السجل الافتراضية، وtrue يعيده. |
{
"id": 6,
"phone": "+966551234567",
"is_active": true
}ما يعيده: المندوب sales_person بعد التعديل.
- المندوب المرتبط بعضو فريق تتجدد بياناته من ملف العضو كلما عدله، فقد يحل تعديلك هنا محله تعديل لاحق في الملف.
- يلزم إرسال حقل واحد على الأقل، والمعرف الذي ليس في سجلك يرد بخطأ 404.
sales_persons_delete
يحذف المندوب من السجل، وإن كان أي عرض سعر مرتبطا به عطله بدل الحذف، ويبين الرد أي الأمرين حدث. وتبقى بيانات التواصل المطبوعة في العروض في الحالتين.
يحذف بيانات أو يستبدلها · الصلاحية sales_persons.write · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات
| المعامل | النوع | مطلوب | الوصف |
|---|---|---|---|
id | integer | نعم | معرف المندوب، ويأتي من sales_persons_list. |
ما يعيده: ok: true وdeactivated: true إن عطل المندوب بدل حذفه، وfalse إن حذف.
- الحذف النهائي لا يتراجع عنه، أما التعطيل فيعاد بـ
sales_persons_updateوis_activeيساويtrue. والمعرف الذي ليس في سجلك يرد بخطأ 404.