تصفح الدليل

أدوات MCP

ملفات العطاء والمهام الخلفية

أدوات MCP لتوليد ملفات التقديم (ملف الرد وملف المرفقات وخطاب التغطية) ومتابعة المهام الخلفية للملفات الكبيرة.

تولد هذه الأدوات الملفات التي تقدمها مع العطاء: ملف رد نوبكو، وملف مرفقات نوبكو، وخطاب التغطية العربي. يبنى كل ملف مما حفظته في المنصة: أسعار بنود المنافسة، والبنود المعلمة بالمشاركة، والمنتجات المختارة لها، وعروض الأسعار التي أنشأتها. وأربع أدوات أخرى تتابع المهام الخلفية للملفات التي تستغرق وقتا. وتشرح ملفات العطاء كيف تنشأ الملفات نفسها من التطبيق. وللعروض على بوابة iNUPCO نفسها يوجد دليل خطوة بخطوة.

نصيحة:الترتيب الذي يعمل: سعر البنود بـ`bid_pricing_set_batch` أو `sheet_import`، ثم أنشئ عروض أسعارها بـ`tender_quotations_generate`، ثم اعتمدها بـ`quotations_set_approval`، ثم ولد الملفات بمعرفات العروض المعتمدة من `tender_quotations_list`.
ملاحظة:تشمل الملفات الثلاثة البنود المسعرة بأكثر من صفر والمعلمة بالمشاركة فقط. والبند المسعر الذي أزيلت علامة مشاركته يستبعد ويحسب في التقرير priced_items_not_participating، وتعيد علامته `tender_item_participation_set_batch`. والبند المسعر بصفر يستبعد مهما كانت علامته ويحسب zero_priced_items، فالصفر ليس سعر عطاء.

تأخذ الأدوات الثلاث اختياريا quotation_ids، فتغطي الملفات البنود التي تسعرها تلك العروض وتشير إليها وحدها. وأسعار العطاء المحفوظة هي المرجع دائما: عرض سعر محدد يذكر سعرا مختلفا يبلغ عنه التقرير ولا يغير الملف. وتأخذ كل أداة report: true لتعيد تقريرا بصيغة JSON بدل الملف، فاستخدمه أولا حين تريد معرفة ما ينقص. والأدوات الثلاث للخطة الاحترافية وخطة المؤسسات.

الأداةما تفعله
tenders_nupco_response_fillتعبئة ملف رد نوبكو
tenders_nupco_attachments_fillتوليد ملف مرفقات نوبكو
tenders_cover_letter_pdfتوليد خطاب تغطية المنافسة
generation_jobs_listعرض المهام الخلفية
generation_jobs_getعرض مهمة خلفية
generation_jobs_partتنزيل جزء من مهمة خلفية
generation_jobs_cancelإلغاء مهمة خلفية

ملفات العطاء الثلاثة

لا تغير هذه الأدوات سجلاتك: تقرأ أسعارك المحفوظة وتولد ملفا منها.

tenders_nupco_response_fill

يعبئ ملف الرد الذي نزلته من بوابة نوبكو بأسعارك المحفوظة والضريبة والمنتجات المختارة لمنافسة واحدة، ويعيد الملف نفسه معبأ. والقالب يجب أن يكون ملف البوابة نفسه لهذه المنافسة: لا يصنع من الصفر، ويرفض ملف منافسة أخرى.

للقراءة فقط · الصلاحية bids.read · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات

المعاملالنوعمطلوبالوصف
tender_idintegerنعممعرف المنافسة، ويأتي من tenders_list.
template_base64stringنعمملف الرد بصيغة .xlsx كما نزل من بوابة نوبكو، بترميز base64. السقف العملي نحو 3 ميغابايت لأن الخادم يرفض أي طلب يتجاوز نحو 4.5 ميغابايت. وعلى واتساب يمرر المساعد مرجع المرفق بدل المحتوى.
filenamestringلااسم الملف الأصلي، حتى 300 حرف.
vat_percentnumberلانسبة الضريبة الافتراضية، من 0 إلى 100، للصفوف التي لا تحدد منتجاتها المختارة نسبة. تؤخذ 15 إن حذفت. ونسبة المنتج نفسه تتقدم دائما.
quotation_idsinteger[]لامعرفات عروض الأسعار، وتأتي من `tender_quotations_list` وهي عادة العروض المعتمدة. يغطي الملف البنود التي تسعرها هذه العروض وحدها ويشير إليها بالذات. يجب أن يكون كل معرف لعرض سعر في مؤسستك على هذه المنافسة، وإلا رد الخادم بـ400 quotation_tender_mismatch. من 1 إلى 5000 معرف. وإن حذفت الحقل شمل الملف كل بند مسعر مشارك في المنافسة.
reportbooleanلاtrue يعيد تقرير التعبئة بصيغة JSON مع رابط لتنزيل الملف بدل الملف نفسه.
{
  "tender_id": 48213,
  "template_base64": "UEsDBBQABgAIAAAAIQAk3kP1...",
  "filename": "NPT0024-26-response.xlsx",
  "vat_percent": 15,
  "quotation_ids": [
    5312,
    5313
  ],
  "report": true
}
مثال على المعاملات

ما يعيده: الملف المعبأ (filename وcontent_type وsize_bytes وbase64). ومع report: true كائن فيه filename وdownload_url وتقرير التعبئة report.

  • تعبأ صفوف البنود المسعرة بأكثر من صفر والمعلمة بالمشاركة فقط. والصفوف بلا سعر محفوظ تبقى كما هي وتعود مخفية لا محذوفة، فتقرأها بوابة نوبكو عند الرفع. والصف الذي لا تستطيع التعبئة البت فيه (رمز مادة تشترك فيه عدة صفوف، أو حقل إلزامي ناقص، أو منتج غير مختار) يبلغ عنه التقرير برقم صفه دون تخمين، ويبقى ظاهرا.
  • يحمل report الحقول template_rows وfilled_rows وhidden_rows وissues وmissing_mandatory (الصف والرمز والحقول الناقصة) وnot_applicable (بنود الخدمات: الخلايا التي تصف سلعا ولا تنطبق عليها، كالمصنع ورقم الكتالوج، وليست ناقصة) وunmatched_priced_codes، وأعداد priced_items_not_participating وzero_priced_items وpriced_items_outside_selection. ومع quotation_ids يضاف quotation_scope ومشكلات الصفوف: quotation_price_mismatch (عرض محدد يذكر سعرا غير سعر العطاء المحفوظ، والمكتوب في الملف هو سعر العطاء) وquotation_not_approved (عرض ما زال مسودة) وmultiple_quotations (عدة عروض محددة تغطي بندا واحدا، ويعتمد أحدث المعتمدة منها).
  • يرد الخادم بـ400 مع wrong_template_tender إن كان الملف لمنافسة أخرى، وinvalid_file_type إن لم يكن xlsx، وmissing_columns وتسميها detail، وno_participating_items إن وجدت أسعار ولا بند معلم بالمشاركة، وno_bid_pricing إن لم يسعر بند بأكثر من صفر، وquotation_scope_empty إن لم تسعر العروض المحددة أي بند من المنافسة. والمنافسة التي لا تراها مؤسستك ترد بـ404 tender_not_found.

tenders_nupco_attachments_fill

يبني حزمة مرفقات نوبكو لمنافسة واحدة من الصفر: الملف النصي المفصول بعلامات تبويب الذي تقبله بوابة SRM، وأعمدته تسمي ملفات PDF، مع كل ملف PDF يذكره بالاسم المذكور بالضبط، فتكون الملفات المفكوكة هي مجموعة الرفع. يبنى في الخلفية، وتنتظره الأداة وتعيد الملف أو المهمة إن طال.

للقراءة فقط · الصلاحية bids.read · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات

المعاملالنوعمطلوبالوصف
tender_idintegerنعممعرف المنافسة، ويأتي من tenders_list.
rfx_response_numberstringنعمرقم رد RFx في SRM كما يظهر على العطاء في بوابة نوبكو، مثل 5000061479. يطبع على كل سطر في الملف فيجب أن يكون الرقم الحقيقي، فاطلبه من صاحب العطاء ولا تخترعه. نص عادي من 1 إلى 40 حرفا.
quotation_idsinteger[]لامعرفات عروض الأسعار، وتأتي من `tender_quotations_list` وهي عادة العروض المعتمدة. يغطي الملف البنود التي تسعرها هذه العروض وحدها ويشير إليها بالذات. يجب أن يكون كل معرف لعرض سعر في مؤسستك على هذه المنافسة، وإلا رد الخادم بـ400 quotation_tender_mismatch. من 1 إلى 5000 معرف. وإن حذفت الحقل شمل الملف كل بند مسعر مشارك في المنافسة.
reportbooleanلاtrue يعيد المهمة مع تقريرها، وفيه الملفات الناقصة لكل سطر وقائمة الملفات وروابط الأجزاء، بدل تسليم الملف.
wait_secondsintegerلاعدد الثواني التي تنتظر فيها الأداة اكتمال الحزمة قبل أن تعيد المهمة: الافتراضي 40 والأقصى 120. والحزمة الصغيرة تنتهي عادة خلالها.
{
  "tender_id": 48213,
  "rfx_response_number": "5000061479",
  "quotation_ids": [
    5312,
    5313
  ],
  "wait_seconds": 60
}
مثال على المعاملات

ما يعيده: إن اكتملت الحزمة خلال wait_seconds في ملف ZIP واحد أقل من 4 ميغابايت جاء الملف (filename وcontent_type وsize_bytes وbase64) مع report. وإلا جاءت المهمة: job_id وstatus وprogress وparts (لكل جزء download_url صالح لساعة بعد نجاح المهمة) وreport وnext_step.

  • تأتي الحزمة الكبيرة في عدة أجزاء ZIP (نحو 47 ميغابايت للجزء)، فنزل كل جزء بـ`generation_jobs_part` وفك الأجزاء كلها في مجلد واحد. والحزمة التي ما زالت تبنى ترد بـjob_id وتقدمها وتواصل البناء في الخلفية، فتابعها بـ`generation_jobs_get` أو تجدها في بطاقة الملفات المنشأة في صفحة عروض الأسعار.
  • تبنى حزمة واحدة لكل منافسة في الوقت نفسه. فإن كانت حزمة قيد البناء ردت الأداة بتلك المهمة مع already_running: true، وقد تكون لتحديد مختلف أو لرقم RFx مختلف. ألغها بـ`generation_jobs_cancel` لتبدأ من جديد.
  • كل سطر في الملف لبند مسعر بأكثر من صفر ومعلم بالمشاركة، وعليه خيار التغيير C. ولكل بند تذكر الحزمة ملف عرض السعر الخاص به، وخطاب غلاف (ملخص سطر عرض السعر في صفحة واحدة يليه كتالوج المنتج المحفوظ، وإن لم يوجد كتالوج محفوظ خرج الغلاف وحده ونبه التقرير بـcatalog_pages_missing)، ومستند MDMA أو هيئة الغذاء والدواء، وهو الشهادة المحفوظة أو خطاب امتثال يولد إن كان المنتج قيد التسجيل أو بلا شهادة، ويذكر في عمودي شهادات SFDA وملحق MDMA معا. وكل ملف PDF اسمه item-<serial>-<slot>.pdf (والخانات quote وcatalog وsfda وmdma) وطوله أقل من 40 حرفا.
  • يسرد report لكل سطر ما ينقصه في missing_files وكل ملف في files، وفي not_applicable_files خانات بنود الخدمات التي لا تحمل كتالوجا ولا شهادة (ليست ناقصة)، مع أعداد الاستبعاد ومشكلات العروض نفسها المذكورة في ملف الرد. وتفشل الفحوص السريعة قبل بدء أي مهمة: invalid_rfx_response_number وno_bid_pricing وno_participating_items وquotation_scope_empty، والمنافسة التي لا تراها مؤسستك ترد بـ404 tender_not_found.

tenders_cover_letter_pdf

يولد خطاب التغطية العربي الذي يقدمه المورد مع عطائه، بصيغة PDF. يخاطب الجهة المشترية، ويبين العرض مع تفصيل الضريبة، ويتضمن إقرار الالتزام بالأنظمة. وعدد البنود والمبالغ تقرأ من عطائك المحفوظ ولا تكتب.

للقراءة فقط · الصلاحية bids.read · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات

المعاملالنوعمطلوبالوصف
tender_idintegerنعممعرف المنافسة، ويأتي من tenders_list.
letter_numberstringلارقم خطابك الصادر كما في سجل مراسلات مؤسستك، مثل DPC-1909، ويطبع في سطر رقم الخطاب. إن حذف ترك السطر. لا تخترع رقما: المنصة لا تحتفظ بسجل للمراسلات الصادرة، ورقم مختلق قد يتعارض مع رقم حقيقي عندك. حتى 60 حرفا.
recipientstringلاسطر المخاطب بالعربية. إن حذف خوطبت الجهة المشترية المذكورة في المنافسة. حتى 300 حرف.
recipient_departmentstringلاسطر المخاطب الثاني بالعربية، مثل إدارة العقود والمشتريات. حتى 300 حرف.
notesstringلافقرة عربية إضافية تطبع قبل الخاتمة، حتى 1000 حرف.
quotation_idsinteger[]لامعرفات عروض الأسعار، وتأتي من `tender_quotations_list` وهي عادة العروض المعتمدة. يغطي الملف البنود التي تسعرها هذه العروض وحدها ويشير إليها بالذات. يجب أن يكون كل معرف لعرض سعر في مؤسستك على هذه المنافسة، وإلا رد الخادم بـ400 quotation_tender_mismatch. من 1 إلى 5000 معرف. وإن حذفت الحقل شمل الملف كل بند مسعر مشارك في المنافسة.
reportbooleanلاtrue يعيد عدد البنود والعرض والضريبة والإجمالي بصيغة JSON مع رابط لتنزيل الملف بدل الملف نفسه.
{
  "tender_id": 48213,
  "letter_number": "DPC-1909",
  "recipient_department": "إدارة العقود والمشتريات",
  "quotation_ids": [
    5312,
    5313
  ],
  "report": true
}
مثال على المعاملات

ما يعيده: الخطاب بصيغة PDF (filename وcontent_type وsize_bytes وbase64). ومع report: true كائن فيه filename وdownload_url والتقرير report وفيه item_count وsubtotal وvat وtotal وvat_review وquotation_scope وquotation_price_review.

  • الخطاب بالعربية وحدها ولا يعدد المستندات المرفقة، لأن المنصة لا ترى ما رفع إلى البوابة. وهو يصلح لأي منافسة، لا لمنافسات نوبكو وحدها.
  • يذكر الخطاب البنود المسعرة بأكثر من صفر والمعلمة بالمشاركة (ضمن quotation_ids إن أرسلتها). وتجمع الضريبة لكل سطر بنسبة المنتج المختار للبند: 15٪ إن لم يحدد المنتج نسبة أو لم يختر منتج، و0٪ للمنتج الذي يعفيه الكتالوج، كما يحسبها ملف رد نوبكو بالضبط، فلا يتناقض الملفان. والإجمالي المذكور يشمل الضريبة ويكتب كذلك بالحروف، فوق جدول يفصل العرض عن الضريبة.
  • راجع vat_review قبل الإرسال: يسرد السطور التي تناقض نسبة ضريبتها وسم المنتج الطبي، في الاتجاهين (منتج غير طبي معفى وهذا ينقص العطاء، أو منتج طبي بالنسبة العادية)، مع الضريبة التي سيغيرها كل سطر. والخطاب يطبع النسبة نفسها التي يكتبها ملف الرد، فصحح ضريبة المنتج في الكتالوج أولا. ويسرد quotation_price_review العروض المحددة التي تذكر سعر وحدة غير سعر العطاء المحفوظ الذي يجمعه الخطاب.
  • يرد الخادم بـ400 مع no_participating_items إن وجدت أسعار ولا بند معلم بالمشاركة، وno_bid_pricing إن لم يسعر بند بأكثر من صفر، وquotation_scope_empty إن لم تسعر العروض المحددة أي بند من المنافسة. والمنافسة التي لا تراها مؤسستك ترد بـ404 tender_not_found.

المهام الخلفية

نوعان من الملفات أكبر من أن يبنيا في طلب واحد، فيبنيان في الخلفية مهمتين: حزمة مرفقات نوبكو (nupco_attachments، تبدأها `tenders_nupco_attachments_fill`) وحزمة عروض الأسعار (quotation_packages، تبدأها `quotation_packages_bundle`). حالة المهمة queued أو running أو succeeded أو failed أو cancelled. والمهام ملك المؤسسة فترى ما بدأه زملاؤك، وتبقى المهمة المنتهية 24 ساعة. تبنى حزمة واحدة لكل منافسة، وحزمة عروض واحدة لكل عضو، في الوقت نفسه. والملف الجاهز جزء ZIP أو أكثر، فافتح كل الأجزاء في مجلد واحد.

generation_jobs_list

يعرض مهام مؤسستك الخلفية في آخر 24 ساعة، الأحدث أولا، أيا كان من بدأها، لكل مهمة حالتها وتقدمها. استخدمه لتجد مهمة بدأها زميلك أو بدأتها أنت ونسيت معرفها.

للقراءة فقط · الصلاحية bids.read أو quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات

المعاملالنوعمطلوبالوصف
tender_idintegerلايعرض مهام هذه المنافسة وحدها.
kindstringلايعرض مهام نوع واحد: nupco_attachments لحزم المرفقات، أو quotation_packages لحزم عروض الأسعار.

ما يعيده: jobs: قائمة، لكل مهمة job_id وkind وstatus وprogress (done وtotal وunit) وparts (الرقم والاسم والحجم) وexpires_at بعد النجاح وerror عند الفشل وتلميح next_step. بلا تقرير ولا روابط تنزيل، فاقرأ المهمة الواحدة بـgeneration_jobs_get.

  • تعيد الأداة 30 مهمة على الأكثر. ويرى المفتاح الأنواع التي تغطيها صلاحياته: bids.read لحزم المرفقات وquotations.read لحزم عروض الأسعار، وطلب نوع لا تغطيه صلاحياتك يرد بـ403.

generation_jobs_get

يقرأ مهمة واحدة: حالتها وتقدمها، وبعد نجاحها تقريرها وأجزاء ZIP. ويمكنه أن ينتظر اكتمالها حتى 120 ثانية. وتسلم أجزاء المهمة المنتهية بـgeneration_jobs_part.

للقراءة فقط · الصلاحية bids.read أو quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات

المعاملالنوعمطلوبالوصف
job_idstringنعممعرف المهمة (UUID)، وهو job_id في رد الأداة التي بدأتها أو في generation_jobs_list.
wait_secondsintegerلاينتظر الخادم اكتمال المهمة حتى هذا العدد من الثواني، من 0 إلى 120. الافتراضي 0: يرد فورا.

ما يعيده: المهمة: job_id وkind وstatus وprogress وparts (لكل جزء index وfilename وsize_bytes وdownload_url صالح لساعة)، وwaiting إن لم يحركها أحد منذ فترة، وبعد النجاح report وexpires_at، وعند الفشل error برمزه وتفصيله، وnext_step. وعلى واتساب تحذف الروابط، فاستخدم generation_jobs_part لإرسال الجزء مستندا.

  • قراءة المهمة تحرك عملها أيضا: إن لم يكن أحد يعمل عليها بدأت القراءة مرحلة العمل التالية. والمهمة التي لم يحركها شيء 30 دقيقة تفشل برمز stalled.
  • تقرير حزمة المرفقات هو الموصوف في أداتها. وتقرير حزمة عروض الأسعار يسمي كل عرض ضمن الحزمة مع الجزء الذي فيه، وكل عرض لم ينتج شيئا برقمه وسببه: not_found أو render_failed أو too_large.
  • المهمة المجهولة أو التي تخص مؤسسة أخرى ترد بـ404، والمفتاح الذي لا يحمل صلاحية نوع المهمة يرد بـ403: bids.read لحزمة المرفقات وquotations.read لحزمة عروض الأسعار.

generation_jobs_part

يسلم جزء ZIP واحدا من مهمة انتهت، برقم الجزء كما تسرده generation_jobs_get. على واتساب يصل الجزء إلى الشخص مستندا، وفي غيرهما يأتي بترميز base64 إن كان أقل من 4 ميغابايت، وإلا جاء رابط تنزيل صالح لساعة.

للقراءة فقط · الصلاحية bids.read أو quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات، المشاهد · الخطة الاحترافية وخطة المؤسسات

المعاملالنوعمطلوبالوصف
job_idstringنعممعرف المهمة (UUID).
partintegerلارقم الجزء بدءا من 1، الافتراضي 1. والجزء غير الموجود يرد بـ404.

ما يعيده: الجزء ملفا (filename وcontent_type وsize_bytes وbase64) إن كان أقل من 4 ميغابايت. وإلا filename وsize_bytes وdownload_url صالح لساعة مع ملاحظة بأن الملف أكبر من أن يضمن في الرد.

  • الجزء يسلم في كل استدعاء، فالحزمة ذات الأجزاء الثلاثة تحتاج ثلاثة استدعاءات، وتفك الأجزاء كلها في مجلد واحد.
  • المهمة التي لم تنته ترد بـ409 job_not_finished، فلا توجد الأجزاء إلا بعد النجاح. وتلزم صلاحية نوع المهمة: bids.read لحزمة المرفقات وquotations.read لحزمة عروض الأسعار، وغيرها يرد بـ403.

generation_jobs_cancel

يوقف مهمة في الانتظار أو قيد العمل. تحذف الأجزاء التي بنيت حتى الآن، وتبقى المهمة في القائمة ملغاة 24 ساعة. استخدمه قبل بدء حزمة مرفقات جديدة لمنافسة حزمتها قيد البناء، أو حزمة عروض جديدة وآخر حزمة لك ما زالت تبنى.

يحذف بيانات أو يستبدلها · الصلاحية bids.read أو quotations.read · الأدوار: المالك، المدير، المبيعات، المشتريات · الخطة الاحترافية وخطة المؤسسات

المعاملالنوعمطلوبالوصف
job_idstringنعممعرف المهمة (UUID).

ما يعيده: المهمة بعد الإلغاء، وحالتها cancelled.

  • المهمة التي لم تعد في الانتظار ولا قيد العمل ترد بـ409 job_not_active مع المهمة نفسها. وتلزم صلاحية نوع المهمة: bids.read لحزمة المرفقات وquotations.read لحزمة عروض الأسعار.
  • يتوقف العمل الجاري عند أول حفظ له، وما بني من الأجزاء يحذف ولا يمكن استرجاعه.