📋 سجل التحديثات
v1.39.0 13-10-2026
  • جديد🔴 أداة الجرد دخلت الهب — Inventory-Audit-Updater.html (الاسم مطابق لاسم ريبو الـ Worker). الأقسام التلاتة (جرد فردي · أولويات الجرد · جرد جماعي) وسجل العمليات زي ما هم بالحرف، والـ Worker ما اتلمسش.
  • تغييرالدخول بقى مرة واحدة في الهب — شاشة الدخول والـ PIN اتشالوا من الصفحة دي، والاسم بيوصل من الجلسة. الريفريش مابقاش بيطلّعك.
  • تغيير🔴 السر بقى سر مجموعة warehouse_ops (مفتاح warehouse_ops_worker_secret) بدل stockaudit_worker_secret. ⚠️ لازم WORKER_SECRET على inventory-audit-updater-worker يبقى بقيمة المجموعة وPromote — من غيره كل نداء بيرجّع 401.
  • تغييرالخروج التلقائي بعد 60 دقيقة اتشال (الهب بقرار مابيطلّعش الموظف بالوقت). بدله: الخروج وقفل التاب بيسألوك لو الجرد الجماعي فيه مسحات ما اتنفّذتش، والخروج ممنوع أثناء تنفيذ دفعة.
  • تغييرلون النص الثانوي أفتح شوية (#6b7280 بدل #4b5563) — توكنز الهب هي المعتمدة. وشارة P2 اتثبّتت على --orange-dark عشان التباين فضل زي ما كان.
6.14.3 13-10-2026
  • ملاحظةآخر نسخة من الأداة المستقلة (واجهة v6.14.3 · Worker v6.2.2) — ريبو Inventory-Audit-Updater لسه شغّال كنقطة رجوع. سجل تغييرات 6.x الكامل في CLAUDE.md بتاع الريبو ده.
ℹ️ عن الأداة — جرد المخزون
📋 وصف الأداة

أداة مراجعة وضبط الجرد — بتعرض أولويات الجرد تلقائيًا (P0–P6) بفلاتر متقدمة وجرد متسلسل، وبتستثني من الـ Worker المنتجات غير المتتبعة (inventoryItem.tracked = false) وكل المنتج أو المقاس الموقوف (custom.suspended = true).

المستخدمون

موظفو المخزن — جرد المنتجات وضبط الكميات ومتابعة الأولويات.

كيف تعمل

  1. تاب أولويات الجرد 🎯: بيجيب كل المنتجات المتتبعة ويرتّبها P0–P6.
  2. الضغط على SKU بينقل لتاب الجرد 📦 ويحمّل الصنف.
  3. البحث بالـ SKU أو بمسح الباركود بالسكانر — مع حارس طول على القيمة المسحوبة.
  4. وضع العد بالسكانر: كل مسح = قطعة، والإجمالي بيتقارن بالرصيد المتوقع.
  5. تطابق → «✅ الجرد مظبوط» · فرق → لوحة تعديل الكمية بالرقم معبّأ.
  6. كل عملية بتتسجّل في D1 بنتيجتها (extra.result) وبتظهر في تاب السجل.

🧾 تاب الجرد الجماعي (v6.0.0)

  1. ① حمّل الباركودات — كل المتغيّرات الصالحة للجرد (باركود · SKU · آخر جرد) في نداء واحد. كل مسحة بعد كده بحث محلي مش نداء شبكة. الأرصدة بتيجي معاها كمان بس كأرقام مبدئية للعرض — القرار مابيتبناش عليها.
  2. جلسة المسح — مسح متواصل لرفوف كاملة. الكود المجهول أو المتكرر على أكتر من صنف بيروح لقايمة حمرا وبيقفل التنفيذ لحد ما تتفضى.
  3. النطاق (ثابت) — اللي اتمسح + باقي مقاسات نفس المنتج: لو المنتج اتمسح منه مقاس واحد على الأقل، باقي مقاساته بتتحسب معدودها صفر — يعني «🔴 عجز» لو شوبيفاي شايفة منها رصيد (ومتحدّدة تلقائيًا). المنتج اللي ما اتلمسش خالص مش بيظهر. التجميع بـ productId — في المتجر ده كل لون منتج مستقل في شوبيفاي والمتغيّرات هي المقاسات (GT1 / Black منتج · GT1 / White منتج تاني)، فالتجميع ده بيدّي «باقي مقاسات نفس اللون» بالظبط.
  4. ③ قارن بشوبيفاي — 🔴 هنا بالظبط بتتقرا الأرقام الحقيقية: الأرصدة الحيّة على LOCATION_ID والقطع المغلَّفة في نفس النداء ونفس اللحظة (at بترجع في الرد)، وللأصناف اللي اتعدّت بس. المتوقع = available + committed − المغلَّف. أي صف ما اتقارنش مش بيتنفّذ ورقمه بيتعرض بعلامة «؟».
  5. ④ التنفيذ — بالمجموعات مع شريط تقدّم حقيقي وقفل على كل نقط التعديل، والصف اللي اتنفّذ بيتنزع سلاحه فورًا.

⚠️ فرق جوهري في الكتابة الجماعية

الجرد الفرديالجرد الجماعي
الميوتيشنinventoryAdjustQuantitiesinventorySetQuantities
القيمةفرق نسبيرقم مطلق + changeFromQuantity
إعادة التنفيذبتضاعف التعديل ⛔بتترفض من شوبيفاي بلا أي أثر ✅
رصيد اتغيّر أثناء الجلسةالتعديل بيتطبّق على رقم تانيالصنف بيترفض ويرجع للموظف

الـ Endpoints

actionبيعمل إيه
get_employeesقايمة الموظفين — لفلتر الموظف في تاب السجل بس (الدخول في الهب، والأداة مابتنادش check_employee/verify_employee/log_logout)
list_skusبحث عن SKU / منتج
lookup_barcodeبحث بالباركود (سكانر)
get_detailsالأوردرات الغير مجهّزة لصنف — بيرجّع orderId الرقمي كمان
get_audit_dateآخر تاريخ/موظف/ملاحظات جرد لصنف
get_audit_prioritiesقايمة أولويات الجرد + truncated
adjust_inventory (POST)تصحيح الرصيد + تسجيل تاريخ الجرد
set_audit_date (POST)تأكيد إن الجرد مظبوط من غير تعديل
get_bulk_indexباركودات الجرد الجماعي + أرصدة مبدئية + dupBarcodes + truncated + السقوف
bulk_compare (POST)الأرصدة الحيّة + المغلَّف في نداء واحد ولحظة واحدة (at) — استعلام الأوردرات الغالي للأصناف اللي عليها حجز بس
bulk_adjust (POST)الكتابة الجماعية بقيمة مطلقة + تحقق من الرصيد الحالي (CAS) + صف D1 لكل عنصر
get_logs / get_logs_count / get_logs_exportالسجل: صفحة · عدّ · تصدير بـ cap/total/truncated
diag / get_configفحص ذاتي · نسخة الـ Worker

⚙️ نتيجة كل عملية كتابة

الحالةمعناهاالإجراءات المصاحبة
✓ تم (success)الفعل تم واتأكد من شوبيفايتعديل الكمية + كتابة الميتافيلد + صف D1
⚠ تم جزئيًا (warning)الكمية اتعدّلت، لكن تاريخ الجرد ما اتكتبشتعديل الكمية + صف D1 + تحذير بالإجراء اليدوي — ومتعيدش التعديل
✗ فشل (error)النداء وصل لشوبيفاي واترفض — مفيش أي أثرصف D1 بـ result=error بس
🔧 تشريح الكود

FEATURE MAP

  • §CONFIG — requireSession() · currentEmployee · apiGet/apiPost فوق wocApi(WOC_WORKERS.audit) (مهلة ٩٠ ث + إلغاء يدوي) · onBeforeLogout · دوال التوقيت (Intl)
  • shared/shell.js — الإعدادات · التوست · النسخة · الفحص الذاتي (wocRunDiag) · الهيدر · الخروج · playBeep (ومعاه نغمة alarm) — نسخة واحدة مضمّنة للهب كله
  • §AUTH-JS / §IDLE-JS — اتشالوا: الدخول في index.html بس، ومفيش خروج تلقائي بالوقت في الهب
  • §SCAN — handleBarcodeScan · handleScanCountInput · §SCAN::plausibility
  • §TOOL-JS — الأولويات · بطاقة المنتج · لوحة التعديل · العد بالسكانر · كارت الأوردرات غير المشحونة (عرض فقط — مفيش أي فعل عليها من الأداة دي)
  • §BULK-JS — loadBulkIndex · processBulkScanCode · computeBulkRows · runBulkCompare · executeBulk · bms* (فلاتر التاب) · exportBulkXLSX
  • §PRIORITY-JS — إعداد جدول الأولويات (PRIO_T) · applyPriorityFilters · sortPriorityRows
  • §TBL-JS — محرّك الجدول الموحّد: tblReg · tblOpenPop · tblRefresh · tblEnsureW (فلاتر رأس العمود + عرض الأعمدة)
  • §LOG-JS — logParams · fetchLog · renderLogTable · LOG_T · exportLogXLSX

الـ Workers اللي الصفحة دي بتناديهم

—

KEY VARIABLES

  • LS_SECRET = 'warehouse_ops_worker_secret' (الـ shell — مفتاح مجموعة warehouse_ops؛ القديم stockaudit_worker_secret مابقاش بيتقري) — السر الوحيد في localStorage. الاستثناء: تفضيل عرض الأعمدة stockaudit_col_widths_log_v1 / stockaudit_col_widths_bulk_v1 / stockaudit_col_widths_priority_v1 (تفضيل واجهة مش هوية — ارفع _v1 لو الأعمدة اتغيّرت)
  • WOC_WORKERS.audit.url (الـ shell) — constant مش حقل إعدادات (Standards #28)
  • TOOL_VERSION (الـ shell) — نسخة الهب كله، مصدر واحد لكل الصفحات
  • WOC_WORKERS.audit.min (الـ shell) — أقل نسخة Worker مقبولة. مالهاش أي علاقة بـ TOOL_VERSION
  • currentEmployee — { username, displayName } جاي من sessionStorage عبر requireSession()
  • LOG_PAGE_SIZE = 100 · LOG_T / BULK_T / PRIO_T — إعداد وحالة فلاتر كل جدول (قيم · بحث · تاريخ) لمحرّك §TBL-JS
  • bulkIndex · bulkScans · bulkLive · bulkDone — حالة الجلسة الجماعية، كلها في الذاكرة بس
  • bulkCaps — السقوف بتيجي من الـ Worker (chunkHint/maxBatch/compareChunkHint...) عشان مايبقاش فيه مصدرين بيتعتّقوا
  • bulkComparedAt · BULK_COMPARE_STALE_MS — لحظة آخر مقارنة وعتبة التنبيه
  • BULK_STATES — تمن حالات، كل واحدة بتقول هل الصف قابل للتنفيذ وهل بيتحدّد افتراضيًا. not_compared وcompare_failed الاتنين مش قابلين للتنفيذ

NOTES / QUIRKS

  • الفلاتر في رأس العمود: محرّك §TBL-JS واحد للجدولين. القايمة عائمة على body (position:fixed) وبتفضل مفتوحة بعد الاختيار (حارس document.contains). السجل بيبعت الفلاتر والترتيب للسيرفر، والجماعي بيفلتر في المتصفح.
  • عرض الأعمدة: بيتقاس أول مرة على صفوف حقيقية وبيتجمّد، وآخر عمود بيمتص الفراغ عشان الجدول يملا الكارت. التاب المخفي مابيتقاسش لحد ما يظهر.
  • الخروج: من زرار الاسم في الهيدر، وممنوع أثناء تنفيذ دفعة جماعية. لو جلسة الجرد الجماعي فيها مسحات ما اتنفّذتش، الخروج وقفل التاب بيسألوك الأول (و«🏠 الرئيسية» كمان). مفيش خروج تلقائي بالوقت في الهب — الجلسة بتموت بقفل التاب أو بالخروج بس. النسخة المستقلة كانت بتخرّج بعد 60 دقيقة بدون نشاط، والجزء ده اتشال مع شاشة الدخول.
  • الجرد والوقت: التوقيت محسوب بـ Intl على Africa/Cairo — مفيش إزاحة ثابتة، فنهاية التوقيت الصيفي مش محتاجة أي تدخل.
  • فلتر التاريخ بيقارن timestamp المخزّن (UTC) والعرض بالقاهرة — فرق الساعتين/التلاتة ممكن يحط عملية بعد ٩ مساءً في يوم UTC اللي بعده.
  • فلاتر السجل كلها server-side — العدّ والصفحات والتصدير من نفس logParams()، فالرقم المعروض هو رقم القاعدة مش رقم الصفحة.
  • التصدير بيقص عند 2000 صف (cap من الـ Worker) — والبانر الأصفر بيقول الرقمين لو حصل.
  • P0–P6 محسوبة من available وcommitted في الواجهة، والعتبة الزمنية للجرد قابلة للتغيير من التاب.
  • الصفوف الأقدم من v5.0.0 مالهاش extra.result — بتتعرض «—» مش «✓»، لأننا فعليًا مش عارفين.
  • الجرد الجماعي مافيهوش قيم type جديدة — بيكتب تحت adjustment وok زي الفردي، والفرق في extra.mode = 'bulk' وextra.batchId.
  • الصنف اللي onHand ≠ available + committed (عليه حالات مخزون تانية زي تالف أو فحص جودة) بيتشال من التنفيذ الجماعي — معادلة الرف مابتغطّيهاش.
  • الصنف بدون باركود بياخد حالة مستقلة «🚫 بدون باركود» ومش بيتصفّر — لأنه أصلاً مايتجردش بالسكانر.
  • المقاس اللي ما اتمسحش بيتحسب «عجز» (من v6.12.0) — حالة «مش متسكن» اتشالت. المقاس اللي شوبيفاي بتقول عنه صفر والرف فاضي = «✅ مظبوط»، وبيتسجّل إنه اتراجع.
  • الفهرس المقصوص بيطلّع لافتة تنبّه إن ممكن يكون فيه مقاسات مش في الفهرس.
  • 🔴 الأرقام المبدئية مقابل الأرقام المقارَنة: الفهرس بيتحمّل قبل العدّ، فأرقامه بتقدم أثناء جلسة المسح (بيعة · شحنة). عشان كده صفوف ما اتقارنتش بتتعرض بعلامة «؟» والتنفيذ عليها مقفول. الكتابة نفسها محميّة بالـ CAS، فالخطر مكانش على المخزون — كان إن الشاشة تعرض رقم قديم والموظف ياخد قرار عليه.
  • كل الباركودات في ذاكرة المتصفح — الجلسة بتضيع مع أي refresh. ده مقصود: مفيش عدّ بيتخزّن في localStorage.
  • إعادة تحميل الباركودات بتحافظ على المسحات — اللي بيتمسح هو نتيجة المقارنة، فالصفوف بترجع «لسه ما اتقارنش» لحد ما تضغط «قارن» تاني.
  • بعد ١٥ دقيقة من المقارنة بيظهر تنبيه، ونافذة التأكيد بتقول الأرقام اتسحبت من كام دقيقة. التنفيذ لسه مسموح — الـ CAS بيحمي المخزون.