المرحلة ٤ أوصلت لوطات حيّة مفصولة بالمالك إلى توسعة الصف، وشارة «مستحق الإرجاع» إلى الترويسة — لكن صف القائمة نفسه ما زال أعمى للملكية: الكمية والقيمة والمتاح وأقرب انتهاء كلها فيزيائية تخلط بضاعتك ببضاعة عملائك. هذا الملف مراجعة مبنية على قراءة فعلية للكود المشحون (FE + BE)، يرتّب كل المشاكل بالخطورة، ويرسم التصوّر النهائي لكل جزء من الشاشة، ويسلّم خطة بناء مرتّبة بالقيمة.
توسعة اللوطات المشحونة (Surface 1) ممتازة بنيويًّا: مجموعات ملّاك بنفسجية، صف «غير مخصّص»، تذييل تطابق بسطرين — التصميم الأصلي وصل سليمًا إلى ٨٠٪. المشكلة أن الطابق الأعلى — صف القائمة وبطاقات الإحصاءات — لم يلحق بالمرحلة ٤: حاجز owned_value الذي أُصلح في تقرير التقييم (4.4) ما زال مثقوبًا هنا، في الشاشة التي يفتحها أمين المخزن كل يوم.
الـBE يشحن منذ 4.4 حقول owned_value / owned_quantity / consignment_value / consignment_quantity على كل صف رصيد (StockBalanceResource.php:57-60) — والواجهة لا تقرأها إطلاقًا: واجهة StockBalance في inventory.model.ts لا تعرّفها أصلًا. عمود «إجمالي القيمة» وبطاقة «إجمالي القيمة» يعرضان القيمة الفيزيائية شاملةً بضاعة العملاء — نفس التسريب التأسيسي («بضاعة العملاء بتضخّم قيمة مخزوني») الذي بنينا المرحلة ٤ كلها لإغلاقه. البيانات موجودة على السلك، ينقصها العرض فقط.
product_id_warehouse_id يتجاهل product_variant_id: منتج بمتغيّرين في نفس المخزن ⇒ صفّان بنفس المفتاح، توسعة أحدهما تفتح الاثنين، ولوحة اللوطات تخلط لوطات كل المتغيّرات وتطابقها ضد إجمالي المنتج بينما الصف يعرض كمية متغيّر واحد. حرج١) أكمِل حاجز الملكية إلى الطابق الأعلى: خلية رصيد مركّبة 105 +45 🤝، عمود قيمة يقرأ owned_value، بطاقة إحصاء بنفسجية للأمانة — كلها FE فقط، الحقول مشحونة بالفعل (خطوة B1، الأصغر والأعلى قيمة).
٢) انقل عدسة الملكية من التقارير إلى القائمة بنفس اللغة المشحونة (p-select + شريط بنفسجي دائم + URL) — يحتاج باراميتر owner على index في الـBE.
٣) وحّد مصدر «أقرب انتهاء» على سجل اللوطات (inventory_lot_balances) مع نسبة المالك — المرحلة ٤ بَنَت مصدر الحقيقة؛ القائمة ما زالت تقرأ الأنساب القديمة.
التحميل الكسول للوطات مع كاش لكل صف (أداء سليم) · ترتيب المجموعات: ملكنا أولًا ثم العملاء بالبنفسجي 🤝 · صف «غير مخصّص (ما قبل اللوطات)» غير مقصوص حتى لا يكذب التطابق · تذييل التطابق بسطرين · شارة «مستحق الإرجاع» في الترويسة بصمت-عند-الصفر · وسم ~ للتقديري مع تلميحة «أكّد بجرد» · فصل ألوان الصلاحية (أحمر/كهرماني) عن الملكية (بنفسجي) — القوانين الأربعة محترمة داخل التوسعة.
المسار: /app/core/stock-balances · الملفات: features/stock-balances/stock-balances.component.{ts,html,scss} + core/services/stock-balance.service.ts + BE StockBalanceController/StockBalanceResource
| الكود | الاسم | المتغيّر | المخزن | الكمية | المتاح | متوسط التكلفة | إجمالي القيمة | أقرب انتهاء | ||
|---|---|---|---|---|---|---|---|---|---|---|
| ▶ | YRN-040 | غزل قطن 40/1 | — | المخزن الرئيسي | 150.00 | 150.00 | 80.00 | 12,000.00 | ~2026-08-20 قارب على الانتهاء | 📊 🗓 |
| المكوّن | المشحون (من الكود) | التقييم |
|---|---|---|
| شريط الفلاتر | بحث (debounce 400ms) · مخزن · تصنيف/فرعي · «مسح الفلاتر» الشرطي | أبقِه — ناقصه عدسة الملكية وhide_zero |
| بطاقات الإحصاءات | ٤ بطاقات: منتجات (من meta.total) · قيمة (مجموع total_value للصفحة) · منخفض/صفري (للصفحة) | أصلِح — قيمة فيزيائية + نطاق صفحة |
| أعمدة الجدول | كود · اسم · متغيّر · مخزن · كمية · متاح · متوسط تكلفة · إجمالي قيمة · أقرب انتهاء · إجراءات (كارت صنف + تقرير انتهاء) | أصلِح — كلها عمياء للملكية؛ لا فرز |
| شارة الانتهاء | p-tag أحمر (منتهٍ) / كهرماني (≤ near_expiry_days) + وسم ~ للتقريبي مع تلميحة | أبقِه — أضِف نسبة المالك (§٩) |
| توسعة اللوطات | سهم لكل صف → تحميل كسول getProductLots + كاش · مجموعات ملّاك (ملكنا أولًا، العملاء بـ🤝 بنفسجي) · مستلَم/مصروف/متبقٍ · صف «غير مخصّص LEGACY» · «معلنة» تحت مجموعة العميل · تذييل تطابق بسطرين | أبقِه + صقل §٨ |
| تذييل التطابق | سطر ١: الإجمالي الفيزيائي ✓/⚠ · سطر ٢: ملكنا (كمية) · أمانة (كمية، «معلنة») | حسّن — بلا قيم مالية ولا جملة «التقييم يستخدم ملكنا فقط» (كانت في التصميم الأصلي §10.2) |
| شارة «مستحق الإرجاع» | due-back-badge في الترويسة: بنفسجية، تختفي عند الصفر، حلقة كهرمانية للتقادم، تنقل للاستلافات | أبقِه |
| الحالات | تحميل: سبينر p-table · فارغ: صف «لا توجد بيانات» · خطأ قائمة: Toast فقط · خطأ لوطات: Toast + لوحة فارغة تمامًا | أصلِح §١٠ |
استجابة GET inventory/stock-balances تحمل اليوم لكل صف: quantity وtotal_value (فيزيائي)، وowned_quantity/owned_value/consignment_quantity/consignment_value (حاجز 4.4)، وnearest_expiry+source+days_until_expiry، وmeta.near_expiry_days. أي أن ٩٠٪ من المستهدف في §٥ و§٧ لا يحتاج BE جديدًا.
كل مشكلة مُتحقَّق منها في الكود المشحون (سطر المرجع بجانبها). «الإصلاح» يشير إلى خطوة البناء في §١٤.
| الخطورة | # | المشكلة | لماذا تهم (أثرها على الثقة) | الإصلاح |
|---|---|---|---|---|
| حرج | P1 | تسريب القيمة على القائمة. عمود «إجمالي القيمة» = total_value الفيزيائي؛ حقول owned_*/consignment_* المشحونة من 4.4 غير معرّفة في نموذج الـFE أصلًا (inventory.model.ts:315). |
الرقم الذي يبني عليه المالك قراره اليومية يشمل بضاعة ليست ملكه. حاجز 4.4 أُغلق في التقارير وبقي مفتوحًا في أكثر شاشة استخدامًا — تناقض بين شاشتين يهدم الثقة في الاثنتين. | B1 |
| حرج | P2 | تصادم المتغيّرات. rowKey = product_id_warehouse_id (component.ts:227) يتجاهل product_variant_id؛ وproductLots في الـBE لا يقبل متغيّرًا ويجمع physical_total عبر كل المتغيّرات. |
منتج بمقاسين في نفس المخزن: توسعة صف تفتح الصفّين معًا (dataKey مكرّر في PrimeNG)، واللوحة تعرض لوطات المقاسين مخلوطة ويطابقها ضد إجمالي لا يساوي كمية الصف. أرقام «لا تطابق» ظاهرة للمستخدم = فقدان ثقة فوري. | B2 |
| عالٍ | P3 | لا عدسة ملكية على القائمة. لا فلتر «ملكنا / عميل محدد»، لا مؤشر بالصف قبل التوسعة، وindex في الـBE بلا باراميتر owner. |
سؤالا أمين المخزن اليوميان — «أي رف عليه بضاعة عملاء؟» و«ورّيني بضاعة شركة النور» — يستلزمان توسيع الصفوف واحدًا واحدًا. التقارير أخذت العدسة (4.4-FE P2) والقائمة لا: نمط موجود ومجرّب، فقط غير منقول. | B3 |
| عالٍ | P4 | بطاقات إحصاء بنطاق الصفحة. totalValue/lowStockCount/zeroStockCount تُحسب من items() = صفوف الصفحة الحالية فقط (component.ts:80-84). |
«إجمالي القيمة» يتغيّر وأنت تقلّب الصفحات — رقم يبدو إجماليًّا وهو عيّنة. أخطر أنواع الأرقام: الصادق شكلًا الكاذب نطاقًا. | B6 |
| عالٍ | P5 | «أقرب انتهاء» يقرأ مصادر ما قبل المرحلة ٤ وبلا مالك. الخريطة تُبنى من product_serials ثم أنساب الاستلام ثم mirror الحركات (Controller:130-232) — لا تقرأ inventory_lot_balances أبدًا. |
لوطات الأمانة تدخل عبر CRN ولا تمرّ على أنساب الاستلام ⇒ انتهاؤها قد لا يظهر في القائمة إطلاقًا؛ وإن ظهر عبر مصدر آخر يظهر بلا نسبة مالك فيُقرأ كخسارتك. المرحلة ٤ بنت مصدر حقيقة حيًّا والقائمة تتجاهله. | B5 |
| عالٍ | P6 | فشل تحميل اللوطات = لوحة فارغة بكماء. عند خطأ getProductLots: Toast + يبقى الصف موسّعًا على لا شيء (لا رسالة ولا زر إعادة) (component.ts:242 + قالب التوسعة). |
المستخدم يرى مساحة رمادية فارغة تحت الصف ويستنتج «لا لوطات» — استنتاج خاطئ عن البيانات بسبب حالة خطأ. (نفس ملاحظة Fable المؤجلة #3 على dialog التخصيص — العائلة كلها تحتاج نمط خطأ موحّدًا.) | B4 |
| متوسط | P7 | كاش اللوطات لا يُبطل عند التحديث. زر ⟳ يعيد تحميل القائمة لكن lotsCache يبقى — اللوحات الموسّعة تعرض أرقامًا قديمة بجانب صف محدَّث. |
رقمان متناقضان على الشاشة نفسها بعد ضغطة «تحديث» — بالضبط ما بُني تذييل التطابق لمنعه. | B4 |
| متوسط | P8 | تذييل التطابق ناقص المعلومة المالية والتفسير. سطر ٢ كميات فقط (التصميم الأصلي §10.2 نصّ على القيم + «التقييم والتكلفة يستخدمان ملكنا فقط»)؛ وحالة عدم التطابق أيقونة ⚠ بتلميحة COMMON.WARNING العامة بلا مقدار الفرق. |
التذييل هو «آلية الثقة» المعلنة للمرحلة ٤؛ نسخته المشحونة تقول «يوجد خلل» ولا تقول كم ولا ماذا تفعل. | B4 |
| متوسط | P9 | لا قيمة لكل لوط في التوسعة. unit_cost/declared_unit_cost تصل من الـAPI وتُهمل؛ التصميم الأصلي كان فيه عمود Value (ملكنا بالتكلفة، العميل «معلنة ⓘ»). |
بدون قيمة اللوط لا يمكن تقدير خسارة لوط منتهٍ أو قيمة عهدة عميل واحد من الشاشة. | B8 |
| متوسط | P10 | سهم التوسعة على كل صف حتى غير المتتبَّع. منتج خدمي/غير batch ⇒ توسعة تنتهي بـ«لا توجد بيانات لوطات بعد» — طريق مسدود. | التصميم نصّ على «صفر ضريبة على الـ٩٥٪»؛ السهم الموعود بلا شيء خلفه يعلّم المستخدم تجاهل الأسهم كلها. | B4 |
| متوسط | P11 | فجوات RTL/i18n في الجدول الرئيسي. خلايا الكمية/التكلفة/القيمة/تاريخ الانتهاء بلا dir="ltr" (لوحة اللوطات تفعلها صحيحًا)؛ وسم LEGACY نص إنجليزي ثابت في القالب؛ البنفسجي مكتوب بألوان صلبة عبر ::ng-deep بدل توكنات --moon-consign المعرّفة في 4.4. |
«~2026-08-20» بجوار نص عربي قابل للانعكاس البصري؛ وسم أجنبي في شاشة عربية-أولًا؛ ولون الملكية غير موحّد المصدر مع باقي السطوح. | B4/B8 |
| متوسط | P12 | لا مدخل جرد من الشاشة. تلميحة ~ تقول حرفيًّا «أكّد بجرد» ولا تعطي طريقًا إليه؛ شاشة الجرد لا تقرأ queryParams للتهيئة المسبقة. |
الشاشة تشخّص («تقديري — أكّد بجرد») ثم تترك العلاج في مبنى آخر. إغلاق الحلقة = ضغطة واحدة. | B7 |
| منخفض | P13 | قدرات جدول ناقصة. لا فرز بالأعمدة (لا pSortableColumn ولا فرز lazy)، لا hide_zero (الـBE يدعمه)، لا تصدير، وخطأ تحميل القائمة = Toast + «لا توجد بيانات» المضلِّلة. |
مضايقات تراكمية؛ «لا بيانات» عند الخطأ هي الأسوأ بينها (تكذب عن سبب الفراغ). | B8 |
| منخفض | P14 | كاشف تصادم التشغيلة الواحدة تحت مالكين غير مبني (⚠ في §10.2)، ولا زر «إظهار المستنفَد» (الـBE يقصّ اللوطات المستنفدة بـlive()). |
نفس رقم الدفعة عند مالكين = كارثة جرد صامتة؛ والمستنفَد أحيانًا مطلوب للمراجعة التاريخية. | B8 |
| منخفض | P15 | ملاحظات أداء BE. consignment_portion_map تُحسب لكل الشركة في كل طلب صفحة (Controller:104-108) لا لصفوف الصفحة فقط؛ غير مؤلم الآن، سيؤلم مع نمو لوطات الأمانة. |
تحسين نطاق لاحق — لا يغيّر العقد. | B5 |
نفس قوانين §10.1 الأربعة تُطبَّق الآن على الطابق الأعلى: الحقيقتان (فيزيائي/ملكنا) دائمًا ظاهرتان ولا تندمجان — الرقم الافتراضي في كل عمود قيمة هو «ملكنا» والفيزيائي بجانبه لا بداخله؛ البنفسجي للملكية فقط؛ لا رقم في الشاشة يساوي owned + declared أبدًا.
أهم تغيير في المراجعة كلها — وكل بياناته على السلك بالفعل. عمودا «الكمية/المتاح» يُستبدلان بعمود «الرصيد» المركّب + يتحوّل عمود القيمة إلى «القيمة (ملكنا)».
| الكود | الاسم | المخزن | الرصيد | المتاح (ملكنا) | متوسط التكلفة | القيمة (ملكنا) ⓘ | أقرب انتهاء | ||
|---|---|---|---|---|---|---|---|---|---|
| ▶ | SLK-102 | حرير طبيعي 22D | المخزن الرئيسي | 62.00 | 62.00 | 210.00 | 13,020.00 | — | 📊 🧮 |
| ▼ | YRN-040 | غزل قطن 40/1 | المخزن الرئيسي | 105.00 +45 🤝 | 105.00 | 80.00 | 8,400.00 | 2026-08-20 قارب 🤝 | 📊 🗓 🧮 |
| ▶ | PET-771 | خيوط بوليستر 150D | مخزن الأمانة | 0.00 +120 🤝 | 0.00 | — | 0.00 | 2026-07-25 منتهٍ قريبًا 🤝 | 📊 🗓 🧮 |
owned_quantity بخط غامق. إن كان consignment_quantity > 0 تُلحق شريحة بنفسجية +45 🤝 (p-tag بتوكنات --moon-consign*). منتج بلا أمانة يبدو تمامًا كما هو اليوم — صفر ضريبة على الـ٩٥٪.min(available_quantity, owned_quantity) مرحليًّا (المحجوز لا يقتطع من الأمانة منطقيًّا)؛ والقيمة الدقيقة تأتي لاحقًا من الـBE (owned_available) — انظر §١٢. المهم: لا يظهر أبدًا رقم «متاح» يتضمن بضاعة عميل — هذا العمود يقرؤه البائع.owned_value. الفيزيائي لا يُعرض كعمود إطلاقًا — يعيش في التلميحة وفي تذييل التوسعة (القانون: الفيزيائي بجانب «ملكنا» لا مكانه).getRowClass يتحول من quantity===0 إلى owned===0 && consignment===0 (صفري فعلًا) مع حالة وسيطة «أمانة فقط» بلا لون.نفس النمط المشحون في تقرير اللوطات المنتهية (4.4-FE P2) — نفس المفاتيح، نفس الشريط، نفس عقد owner: لا تخترع لغة ثانية.
| الكود | الاسم | المخزن | رصيد «شركة النور» | القيمة المعلنة ⓘ | أقرب انتهاء | ||
|---|---|---|---|---|---|---|---|
| ▶ | YRN-040 | غزل قطن 40/1 | المخزن الرئيسي | 30.00 | 2,100.00 | 2026-08-20 قارب | 📊 🧮 |
| ▶ | PET-771 | خيوط بوليستر 150D | مخزن الأمانة | 120.00 | 6,000.00 | 2026-07-25 منتهٍ قريبًا | 📊 🧮 |
null) · «ملكنا فقط» (0) · قائمة العملاء الذين لديهم لوطات فعلًا 🤝 اسم. مصدر القائمة: endpoint خفيف GET stock-balances/lot-owners (§١٢) — لا اعتماد على store الشركاء ولا «حصاد» يفشل مع pagination الخادم..owner-lens-banner في التقارير، role="status") بمفتاح INVENTORY.OWNER_LENS_BANNER الموجود. إعادة تسمية عمودَي الرصيد/القيمة كما في الموك.?owner=88 بـqueryParamsHandling: 'merge' وقراءتها في ngOnInit — رابط قابل للمشاركة، وأزرار «تقرير الانتهاء» تمرّر العدسة معها (tab=3&owner=88 يعمل هناك بالفعل).owner على index — §١٢)؛ فلترة client-side سترقص مع pagination.hide_zero=1 الموجود أصلًا في الـBE — سطران.قاعدتا الصدق: (أ) كل رقم يعلن نطاقه — إجمالي النطاق المفلتر كله من الخادم، لا مجموع صفحة؛ (ب) رقم القيمة الافتراضي «ملكنا»، والأمانة بطاقة بنفسجية منفصلة تظهر فقط عند وجودها.
meta.totals جديدة على index (§١٢): owned_value · consignment_declared_value · consignment_quantity · consignment_partners · low_stock · zero_stock — محسوبة على النطاق المفلتر كله.owned_value للصفوف الظاهرة — الصدق في التسمية فورًا، التوسيع لاحقًا. الكذبة الحالية (اسم إجمالي + نطاق صفحة + قيمة فيزيائية) لا تعيش يومًا آخر.البنية المشحونة صحيحة — نضيف: عمود القيمة، تذييلًا ماليًّا كاملًا بجملة الحسم، كاشف التصادم ⚠، «إظهار المستنفَد»، خطأً بإعادة محاولة، وأزرار فعل لكل مجموعة.
| الكود | الاسم | المخزن | الرصيد | القيمة (ملكنا) | أقرب انتهاء | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ▼ | YRN-040 | غزل قطن 40/1 | المخزن الرئيسي | 105.00 +45 🤝 | 8,400.00 | 2026-08-20 قارب 🤝 | 📊 🗓 🧮 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
ملكنا105.00 · قيمة 8,400.00
🤝 شركة النور أمانة — ليست ملكك
30.00 · معلنة ⓘ 2,100.00 ↩ رد للعميل
🤝 مصنع الأمل أمانة — ليست ملكك
15.00 · معلنة ⓘ 900.00 ↩ رد للعميل
ملكنا (دفتري): 105.00 — قيمة 8,400.00 · أمانة (ليست ملكك): 45.00 — معلنة 3,000.00
التقييم والتكلفة يستخدمان ملكنا (105) فقط.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
on_hand × unit_cost؛ العميل = on_hand × declared_unit_cost برأس «معلنة ⓘ» وتلميحة INVENTORY.VAL_DECLARED_HINT الموجودة. البيانات تصل اليوم وتُهمل (P9).batch_number في أكثر من مجموعة مالك ⇒ ⚠ كهرمانية بتلميحة «نفس الدفعة عند مالك آخر — افصلها في الجرد». يقي كارثة الجرد الصامتة.include_depleted=1 (§١٢)؛ الصفوف المستنفدة رمادية بلا حالة.production.consignment.return. مراسم العبور تبقى صريحة (القانون ٣) — الزر بوابة للمراسم لا اختصار يتجاوزها.INVENTORY.LEGACY_TAG: «قديم» / «Legacy») بدل النص الثابت، مع نص «جرد يمسحه ←» رابطًا إلى §١١.اللون يبقى للصلاحية (أحمر/كهرماني) — الملكية تغيّر النداء لا اللون. نفس مبدأ شِقّي «منتهي» في تقرير 4.4 (خسارة محتملة ↔ ليست خسارتك) يصل الآن إلى القائمة والتوسعة.
تلميحة: «خسارة محتملة — راجِع للإعدام أو تسوية جرد». الإجراء: تقرير الانتهاء / جرد. صف القائمة يلوَّن كما اليوم.
تلميحة: «بضاعة العميل — ليست خسارتك: أبلغ العميل أو أرجِعها». الإجراء: «↩ رد للعميل» (§٨.٥) أو تقرير الانتهاء بعدسة العميل (tab=3&owner=88 — يعمل اليوم).
~ كما اليوم، والخلية كلها dir="ltr" (إصلاح P11)inventory_lot_balances (حي، دقيق، يحمل المالك) كمصدر أول، بسقوط إلى السيريالات (للتسلسلي) ثم الأنساب (لِما قبل الترحيل). الاستجابة تكسب nearest_expiry_owner_id / nearest_expiry_owner_name و—الأهم— nearest_own_expiry حتى لا يحجب لوط عميل منتهٍ انتهاءَ لوطك القادم.اليوم: «لا توجد بيانات» تُعرض عند الفراغ الحقيقي، وعند فراغ الفلاتر، وعند فشل التحميل — ثلاث حقائق مختلفة بجملة واحدة. وخطأ اللوطات لوحة بكماء.
داخل بطاقة الجدول بدل صف «لا بيانات» — الـToast وحده يختفي ويترك فراغًا كاذبًا.
يتطلب حالة lotsError ثالثة بجانب cache/loading — «لا بيانات» ممنوعة عند الفشل (P6).
lotsCache وexpandedRows (إصلاح P7) — لوحة قديمة بجانب صف محدَّث أسوأ من إعادة جلب.الشاشة تقول اليوم «تقديري — أكّد بجرد» و«يوجد فرق» ثم تصمت. المستهدف: كل تشخيص يعرض علاجه بضغطة.
/core/inventory-counts?new=1&warehouse_id=13&product_id=17159reconciled=false.~ إلى مؤكد ويمتص القديم.queryParams وفتح dialog إنشاء العد مهيَّأً بالمخزن (والمنتج كسطر أول إن دعم النموذج ذلك) — لا منطق جرد جديدًا.inventory.counts — الزر يختفي بدونها (نمط PermissionService المعتاد).كل بنود الواجهة أعلاه تعمل بالمشحون الحالي ما عدا هذه الخمسة. النمط كسابقتها: الـFE يكتب دفاعيًّا (??) فلا يفرغ الصفحة أمام BE أقدم.
| # | التغيير | العقد | يخدم |
|---|---|---|---|
| D1 | باراميتر owner على index |
GET stock-balances?owner=88 — غائب = الكل · 0 = صفوف ملكنا فيها > 0 · id = صفوف لدى العميل لوطات حية فيها (join على inventory_lot_balances). تحت عدسة عميل تُضاف لكل صف owner_quantity/owner_declared_value. ⚠ نفس فخ 4.4: if ($owner) تُسقط owner=0 — اختبر بـ!== null. |
§٦ (B3) |
| D2 | meta.totals للنطاق المفلتر |
meta: { totals: { owned_value, consignment_declared_value, consignment_quantity, consignment_partners, low_stock, zero_stock } } — استعلام تجميعي واحد على نفس شروط الفلترة قبل الـpaginate. |
§٧ (B6) |
| D3 | lot-owners خفيف |
GET stock-balances/lot-owners → [{ partner_id, partner_name }] للملّاك ذوي لوطات حية (distinct، company-scoped). يغذي p-select العدسة. |
§٦ (B3) |
| D4 | مصدر أقرب-انتهاء = سجل اللوطات + مالك | buildNearestExpiryMap: المصدر الأول inventory_lot_balances الحية (batch)، السيريالات للتسلسلي، الأنساب fallback للقديم. الحقول الجديدة: nearest_expiry_owner_id/_name + nearest_own_expiry. وفي نفس الملف: قصّ portionMap على منتجات الصفحة (P15). |
§٩ (B5) |
| D5 | productLots: متغيّر + مستنفَد |
?product_variant_id=&include_depleted=1 — الفلترة بالمتغيّر تُصلح خلط اللوحة (P2)، وphysical_total يُحسب بنفس نطاق المتغيّر. المستنفَد يعود بوسم depleted: true. |
§٥/§٨ (B2, B8) |
لا إعدادات ولا صلاحيات جديدة في هذه الدلتا (نعيد استخدام inventory.stock.view وinventory.counts وproduction.consignment.*) ⇒ لا تغيير على seeders الـMoonStack. أي انحراف عن ذلك يستدعي قاعدة الـtracker: seeder التعريف + GrantRolePermissionsSeeder.
المفتاح (تحت INVENTORY) | ar | en |
|---|---|---|
BAL_ON_HAND | الرصيد | On hand |
BAL_OWNED_VALUE | القيمة (ملكنا) | Value (own) |
BAL_OWNED_VALUE_HINT | قيمة ملكيتك فقط — لا تشمل بضاعة الأمانة (معلنة {{declared}}) | Your owned value only — excludes consignment (declared {{declared}}) |
BAL_MIXED_HINT | الفيزيائي: {{physical}} — ملكنا {{owned}} + أمانة {{consignment}} (ليست ملكك) | Physical: {{physical}} — own {{owned}} + consignment {{consignment}} (not yours) |
BAL_AVAILABLE_OWN | المتاح (ملكنا) | Available (own) |
STAT_OWNED_VALUE | قيمة مخزونك (ملكنا) | Your stock value (own) |
STAT_OWNED_NOTE | لا تشمل بضائع الأمانة | Excludes consignment goods |
STAT_CONSIGN | 🤝 أمانة لدينا (معلنة) | 🤝 Consignment held (declared) |
STAT_CONSIGN_NOTE | {{qty}} وحدة · {{partners}} عميل · ليست ملكك | {{qty}} units · {{partners}} customers · not yours |
OWNER_BALANCE_COL | رصيد «{{name}}» | “{{name}}” balance |
HIDE_ZERO | إخفاء الأصفار | Hide zeros |
LEGACY_TAG | قديم | Legacy |
LOT_VALUE | القيمة | Value |
RECON_EXPLAINS | اللوطات تفسّر {{sum}} — فرق {{diff}} | Lots explain {{sum}} — difference {{diff}} |
RECON_OVERCLAIM_HINT | اللوطات تدّعي أكثر من الرصيد الفعلي — الغالب صرف لم يُخصم من لوطه | Lots claim more than the actual balance — likely an issue not drawn from its lot |
RECON_COSTING_NOTE | التقييم والتكلفة يستخدمان ملكنا ({{qty}}) فقط. | Valuation & costing use own ({{qty}}) only. |
SHOW_DEPLETED | إظهار المستنفَد ({{n}}) | Show depleted ({{n}}) |
BATCH_COLLISION_HINT | نفس الدفعة عند مالك آخر — افصلها في الجرد | Same batch under another owner — separate it in the count |
NEAREST_IS_CONSIGN_HINT | الأقرب انتهاءً لوط أمانة لـ«{{name}}» — ليست خسارتك؛ أقرب لوط لك: {{own}} | Nearest expiry is “{{name}}” consignment — not your loss; your nearest: {{own}} |
LOTS_FETCH_ERROR | تعذّر تحميل اللوطات | Failed to load lots |
NOT_BATCH_TRACKED | هذا المنتج بلا تتبع دفعات — الرصيد كله «ملكنا» بلا لوطات | Not batch-tracked — the whole balance is own, no lots |
COUNT_THIS_PRODUCT | ابدأ جردًا لهذا الصنف | Start a count for this item |
EMPTY_NO_BALANCES | لا أرصدة مخزون بعد | No stock balances yet |
EMPTY_NO_MATCH | لا نتائج تطابق الفلاتر | No results match the filters |
LOAD_ERROR | تعذّر تحميل الأرصدة | Failed to load balances |
مفاتيح تُعاد استخدامها كما هي: OWNER · OWNER_ALL · OWNER_OWN · OWNER_LENS_BANNER · VAL_DECLARED_HINT · DECLARED · CONSIGNMENT_NOT_YOURS · LOT_EXPIRED/LOT_NEAR_EXPIRY · UNASSIGNED_LEGACY · EXPIRED_CONSIGN_SUB («ليست خسارتك — أبلغ العميل / أرجِعها»).
<span dir="ltr"> — لوحة اللوطات ملتزمة؛ الجدول الرئيسي مخالف اليوم (P11). خلية «~تاريخ» كتلة LTR واحدة كي لا تنفصل ~ عن التاريخ.dir="auto" (موجود — يبقى)؛ اسم العميل داخل الشريحة البنفسجية dir="auto" لعملاء بأسماء لاتينية.margin-inline-*/gap فقط؛ لا left/right فيزيائية في أي كود جديد.--moon-consign* (معرّفة في styles.scss منذ 4.4) — وأثناء المرور، رحّل .lot-owner-tag الحالية من ألوانها الصلبة إليها (الـ«refactor opportunistically» المنصوص في السبيك).p-select بنفس بنية خيارات التقرير ({ label, value: null|0|id }) — انتبه لفخ if (owner) مع القيمة 0.p-tag بـstyleClass موحّد (consign-chip) بدل تكرار ::ng-deep.p-checkbox [binary]="true" + عنصر <label> منفصل (خاصية label أُزيلت في v21).pSortableColumn مع [lazy]="true" يمرّر sortField/sortOrder في onLazyLoad إلى باراميترات sort على الـindex (يتطلب دعمها في الـBE — اختياري ضمن B8).dataKey + expandedRowKeys — فقط المفتاح يصبح product_id_variantId_warehouse_id (B2).كل خطوة تُشحن مستقلة وتترك الشاشة أفضل. B1 وB2 لا تنتظران أي BE (عدا باراميتر المتغيّر الصغير في B2).
أضِف owned_*/consignment_* إلى واجهة StockBalance · خلية الرصيد المركّبة 105 +45 🤝 · عمود «القيمة (ملكنا)» = owned_value بتلميحة الفيزيائي · «المتاح (ملكنا)» · إصلاح تلوين الصف الصفري/أمانة-فقط · إعادة تسمية بطاقة القيمة إلى «قيمة الصفحة (ملكنا)» بجمع owned_value (الصدق الفوري قبل D2). هذا وحده يغلق التسريب التأسيسي على الشاشة.
rowKey يشمل product_variant_id · getProductLots يمرّر المتغيّر · الـBE يفلتر به ويحسب physical_total بنفس النطاق. اختبار القبول: منتج بمتغيّرين في مخزن واحد — توسعتان مستقلتان وتطابق صحيح لكلٍّ.
p-select (الكل الفعلي · ملكنا · 🤝 عملاء من lot-owners) · شريط OWNER_LENS_BANNER · إعادة تسمية الأعمدة تحت عدسة عميل · مزامنة ?owner= · تمرير العدسة لأزرار تقرير الانتهاء · «إخفاء الأصفار».
حالة lotsError + «⟳ إعادة» · إبطال الكاش عند ⟳/الفلاتر · تذييل عدم التطابق الناطق بالفرق + رابط الجرد · وسم «قديم» i18n · سهم التوسعة يتحوّل لرسالة NOT_BATCH_TRACKED للمنتجات غير المتتبَّعة (بيانات tracking_type على الصف إن وُجدت، وإلا رسالة التوسعة المحسّنة) · حالات فارغ/خطأ الثلاث للقائمة · dir="ltr" على أعمدة الجدول الرئيسي.
مصدر الخريطة = اللوطات الحية أولًا · حقول المالك وnearest_own_expiry · شارة 🤝 وتلميحة «ليست خسارتك» في القائمة · قصّ portionMap على الصفحة.
meta.totals يغذي: قيمة مخزونك (ملكنا) · 🤝 أمانة لدينا (تظهر عند > 0، تنقر فتفعّل العدسة) · منخفض/صفري على النطاق كله · بطاقات عهدة بديلة تحت عدسة عميل.
زر 🧮 بالصف + رابطا التذييل/غير المخصّص ← /core/inventory-counts?new=1&warehouse_id&product_id · دعم queryParams في شاشة الجرد.
عمود قيمة اللوط (تكلفة/معلنة ⓘ) · «إظهار المستنفَد» · كاشف التصادم ⚠ · زر «↩ رد للعميل» على مجموعة العميل · فرز أعمدة lazy · ترحيل البنفسجي للتوكنات · (اختياري) تصدير.
مالك مخزن عنده لوطاته + بضاعة عميلين على نفس الرفوف يفتح الشاشة فيقرأ — دون توسيع أي صف — كم يملك وكم يستضيف وقيمة كلٍّ منهما منفصلة؛ يفلتر بعميل فيحصل على بيان عهدة برابط قابل للمشاركة؛ يرى انتهاءً أحمر فيعرف فورًا أهو خسارته أم بلاغ لعميله؛ وحيثما قالت الشاشة «تقديري» أو «فرق» وجد زر الجرد بجانب الكلمة. ولا يوجد على الشاشة — ولا في تلميحة — رقم واحد يساوي owned + declared.
مراجعة Fable · Moon ERP — شاشة أرصدة المخزون (لوطات + أمانة) · 2026-07-11 · المصادر: الكود المشحون على hazemdev2 + phase4-per-lot-fefo.html §10 + phase4.4-fe-build-spec.md + phase4-execution-tracker.md