Moon ERP · Inventory + Manufacturing · تحليل معماري شامل مُعاد هيكلته

المرحلة ٤ — أرصدة اللوطات × الملكية + صرف «الأقرب انتهاءً» + بضاعة الأمانة

بُعدان متشابكان لكل رصيد في المخزن: اللوط (تشغيلة·صلاحية) والمالك (بضاعتنا أم بضاعة عميل على سبيل الأمانة). كل لوط باين لوحده برصيده الحيّ ومالكه، تجرده وتصرف منه أو تشتغل منه أو تردّه — بضاعة العميل تظهر بلا ما تختلط ببضاعتك ولا بحساباتك. مبني على قراءة فعلية للكود (٥ باحثين) وتصميم Fable.

📅 2026-07-11 · مُعاد هيكلته ليشمل الأمانة/التصنيع للغير 🌿 hazemdev2 🤝 يوحّد سيلو الأمانة مع نموذج اللوطات 🔗 يبني على تحليل الأمانة 2026-07-08

١ الخلاصة التنفيذية

هذه المرحلة تجمع طلبين مترابطين في نموذج واحد: (أ) كل تشغيلة (لوط) يكون لها رصيد حيّ مستقل وصرف بالأقرب انتهاءً، و(ب) بضاعة العملاء «الأمانة» (خاصة في التصنيع للغير) تظهر وتُجرَد وتُستهلك وتُرَدّ — دون أن تختلط ببضاعتك أو بحساباتك. الدراسة كشفت أن الطلبين ليسا منفصلين: كلاهما يحتاج نفس الشيء — بُعد على مستوى اللوط.

🛑
اكتشافان يعيدان تشكيل الخطة

١) طبقات التكلفة لا تصلح سجلًّا للوطات. وضع التكلفة الافتراضي «متوسط مرجّح» لا يستهلك الطبقات أبدًا، وهي «لكل سطر» بلا صلاحية — فنبني سجل لوطات مستقلًّا يُخصم دائمًا.

٢) نظام الأمانة موجود لكنه «سيلو مزدوج يتسرّب». بضاعة العميل تُكتب كمخزون حقيقي (StockService::increaseStock) و في دفتر منفصل (consignment_material_ledgers) — لكنهما يفترقان: استهلاك التصنيع للغير يخصم المخزون ولا يخصم الدفتر أبدًا (recordIssue كود ميت). أسوأ: بضاعة العميل تُقيَّم داخل مخزونك وتضخّم قيمته (استبعاد is_consignment وُعِد به في هجرة ولم يُبنَ)، ولا يوجد بُعد مالك على أي لوط، ولا مسار «رد للعميل».

🎯
القرار المحوري

نوحّد المسارين في نموذج «لوط مملوك» واحد: نضيف بُعد المالك (owner_partner_id، و٠ = الشركة) وعلَم «داخل الدفاتر» (on_book) على سجل أرصدة اللوطات. عندها بضاعة العميل تصير ببساطة «لوطات مملوكة للعميل X»: تظهر حسب المالك، تُجرَد مفصولةً، تُستهلك والمخزون والدفتر في تطابق لأنهما نفس السجل، وتُرَدّ بحركة خارجة عادية. يبقى inventory_stock_balances «أعمى للملكية» (الحقيقة الفيزيائية) فلا تتغيّر منطقيات الـ15 موديولًا. يتراجع الدفتر المنفصل ليصبح مذكرة مالية فقط، وعلَم is_consignment يتقاعد كآلية فصل.

✅ الجاهز (نبني عليه)

  • مسار واحد (StockService) لكل الحركات — نخيط اللوط والمالك في مكان واحد.
  • حلقة استهلاك «الأقدم أولًا» موجودة.
  • التقاط التشغيلات عند الاستلام (مرحلة ٢).
  • الغلاف التجاري للتصنيع للغير كامل: عقود التوريد، supply_source على BOM، الاستلاف/التسوية بقيودها، فاتورة رسوم التصنيع.

🔨 المطلوب بناؤه

  • سجل inventory_lot_balances بِبُعدَي اللوط + المالك يُخصم دائمًا.
  • سجل استهلاك اللوطات (للإلغاء الدقيق + تزامن الدفتر).
  • صرف FEFO ضمن نطاق مالك واحد + منتقٍ يدوي.
  • مستندات أمانة (استلام CRN / رد CRT) + جرد لكل مالك + دُرج «مستحق الإرجاع» + استبعاد التقييم.

🔗 يكمّل هذا الملف تحليلَ الأمانة الأسبق: inventory-consignment-stock-analysis.html (2026-07-08). القرار هنا يتجاوز توصيته «مخزن لكل عميل بلا عمود مالك» — لأن وضع المالك على جدول اللوط الجديد (لا على stock_balances) يتفادى جراحة الـ15 موديولًا تمامًا.

٢ ما طلبه المالك — طلبان في نموذج واحد

الطلب أ — رؤية وصرف اللوطات

«كل لوط في المخزن يبان لوحده علشان أعرف أصرف منه لوحده… أصرف من اللوط أو الأقدم يخرج الأول ويتخصم من اللوطات، علشان أعرف المتبقي والناقص لكل لوط.»

الطلب ب — بضاعة الأمانة / التصنيع للغير 🤝

«أشتري أو أستلم بضاعة من العملاء على سبيل الأمانة، موجودة في مخزني كلوطات لكنها طرف عميل معيّن — المفروض تظهر معايا وأقدر أجردها، وأتسلّم منها وأشتغل منها على سبيل السلف وأرجّعها تاني — خاصة في التصنيع للغير حيث العميل يوفّر البضاعة.»

🧩
لماذا هما طلب واحد

الطلب (ب) هو الطلب (أ) مضافًا إليه بُعد المالك. «كل لوط باين لوحده» + «طرف عميل معيّن» = لوط له (تشغيلة·صلاحية·مالك). فبدل بناء نظامين، نبني نموذج لوط واحدًا ببُعدين متعامدين: اللوط والمالك. كل شاشة تجيب عن سؤالين معًا: «إيه الموجود فيزيائيًّا على الرف؟» و«إيه اللي أملكه فعلًا؟» — والرقم الافتراضي دائمًا ملكنا، والفيزيائي بجانبه لا بداخله.

٣ الوضع الحالي — بُعد اللوط (بالأدلة)

مؤكَّد بقراءة /home/moonui2/moon-erp-be (بحثان مستقلان متطابقان).

٣.١ مسار واحد يحكم كل الحركات

كل تغيير في الرصيد يمرّ عبر دالتين في StockService.php: increaseStock() (ينشئ دائمًا طبقة تكلفة + حركة، ويمرّر التشغيلة/الصلاحية للحركة فقط) وdecreaseStock() (يستهلك أقدم الطبقات في وضع FIFO فقط؛ بلا أي بُعد تشغيلة — الصرف يفقد هوية اللوط). مكسب: نضيف اللوط والمالك في مكان واحد فيرثه كل مسار.

٣.٢ طبقات التكلفة قريبة لكنها ليست سجل لوطات

٣.٣ أين يوجد بُعد اللوط اليوم

inventory_receipt_item_batches (ثابت، تفصيل ما استُلم بلا رصيد متبقٍ) · product_serials (حيّ لكل وحدة) · نَسَب الحركات (التشغيلة الأولى فقط) · inventory_stock_balances (كمية مجمّعة بلا أي بُعد لوط). النقطة العمياء: التحويل بين المخازن يدمّر هوية اللوط.

٤ الوضع الحالي — الأمانة / التصنيع للغير 🤝

نظام موجود (وُصف في الكود بـ«MFG Phase-C») لكنه v1 بمشاكل بنيوية موثّقة.

🔀
سيلو مزدوج يتسرّب

استلام بضاعة العميل (CreateConsignmentReceipt) يكتب في ثلاثة أماكن: الدفتر (consignment_material_ledgers) + لوط (MfgBatch بحالة «حجر») + مخزون حقيقي عبر StockService::increaseStock بالقيمة المعلنة. فبضاعة العميل مخزون حقيقي — لكنها لا تُميَّز عن بضاعتك على الشاشات.

٤.١ المشاكل الأربع (فجوة مقابل طلبك)

طلبكمدعوم اليوم؟الفجوة (بالدليل)
تظهر كلوطات في المخزنجزئي/مضلِّلمخزون حقيقي لكن لا يُميَّز عن بضاعتك؛ لا حقل مالك على اللوط؛ لوط الأمانة بحالة «حجر» يبدو غير مُفرَج عنه.
تُجرَدفيزيائيًّا نعم، لكن خطأتُعدّ كبضاعتك بلا فصل ملكية، وتُقيَّم داخل مخزونك — استبعاد is_consignment وُعِد به في هجرة ولم يُبنَ أبدًا ⇒ تضخيم قيمة مخزونك.
تُستهلك في الإنتاجفيزيائيًّا نعم، الدفتر مكسورالاستهلاك يخصم المخزون لكن لا يخصم دفتر الأمانة أبدًا (recordIssue بلا مستدعٍ) ⇒ balance_quantity يبالغ إلى الأبد. ولوط الأمانة (حجر، بلا أمر إنتاج) لا يُختار FEFO أبدًا.
تُرَدّ للعميللا مسارالمسار الخارج الوحيد هو تسوية استلاف (رد لسداد التزام)، لا «رد فائض العميل». لا يوجد إجراء رد أمانة مقابل لإجراء الاستلام.

٤.٢ ما هو سليم ويبقى فوق النموذج الجديد

الغلاف التجاري متين: supply_source على مكوّنات BOM (مصنع/عميل/مقسوم) + own_qty/customer_qty؛ وسم الملكية على سطور الإصدار؛ قيود الاستلاف (DR WIP / CR Materials Due to Customer بالقيمة المعلنة) والتسوية (شراء/إحلال)؛ عقد التصنيع للغير + دفعة مقدمة + فاتورة رسوم + استرداد مواد المصنع. كلها تجلس فوق نموذج «اللوط المملوك» دون تغيير يُذكر.

📊
الحدّ المحاسبي اليوم

الحدّ مطبَّق في طبقة القيود (الاستلام بلا قيد؛ الإصدار يتخطّى قيمة مادة العميل من WIP) لكنه غير مطبَّق في طبقة تقييم المخزون — فبضاعة العميل تُقيَّم وتُمزَج في متوسط تكلفة المخزن. القيد سليم، لكن سجل المخزون يبالغ في قيمة ما تملكه. هذا بالضبط ما تشعر به.

٥ القرار المعماري الموحّد

⚖️
القرار ١ — سجل لوطات مملوكة واحد

جدول inventory_lot_balances بحبيبة (منتج·متغيّر·مخزن·تشغيلة·صلاحية·مالك) + علَم on_book. يُخصم عند كل صرف مستقلًّا عن طريقة التكلفة. هو الحقيقة الكمية لكل لوط ولكل مالك. الدفتر consignment_material_ledgers يتراجع إلى مذكرة مالية (قيم معلنة، استلاف، تسويات) تُطابَق ضد مجاميع اللوطات — بعمود «فرق دفتر-فعلي» كإنذار مبكر.

القرار ٢ — stock_balances يبقى أعمى للملكية

لا نضيف المالك على stock_balances (كان اعتراض تحليل ٨ يوليو: جراحة ١٥ موديولًا). المالك على جدول اللوط الجديد فقط. stock_balances = الحقيقة الفيزيائية (كل الملّاك). القيمة الدفترية = SUM(remaining WHERE owner=0) مشتقّة.

القرار ٣ — owner_partner_id NOT NULL، ٠=الشركة

لا nullable (فخّ فهرس الفريد في MySQL). الثابت: SUM(كل اللوطات، كل الملّاك) == stock_balances.quantity (فيزيائي)، وon_book يفصل ما يدخل التقييم.

القرار ٤ — الأمانة = لوط on_book=false

استلام الأمانة يُنشئ لوط مالكه العميل وon_book=false ⇒ يظهر، يُجرَد، يُستهلك، يُرَدّ — ومُستبعَد من كل تقارير قيمة الشركة. يُصلح تسريب التقييم بنيويًّا.

القرار ٥ — الدفتر يتزامن في نفس نقطة الخصم

لأن الاستهلاك واللوط والدفتر يمرّون عبر decreaseStock، نكتب recordIssue هناك ⇒ ينتهي الانحراف (يُغلق الكود الميت) وتصير الحقيقة واحدة.

٦ نموذج البيانات — اللوط × المالك

-- رصيد لوط واحد لكل (تشغيلة·صلاحية·منتج·متغيّر·مخزن·مالك). يُخصم دائمًا.
Schema::create('inventory_lot_balances', function (Blueprint $table) {
    $table->id();
    $table->foreignId('company_id')->constrained()->cascadeOnDelete();
    $table->foreignId('product_id')->constrained('products');
    $table->foreignId('product_variant_id')->nullable()->constrained('product_variants')->nullOnDelete();
    $table->foreignId('warehouse_id')->constrained('warehouses');
    ── بُعد المالك (الجديد) ──────────────────────────────────
    $table->unsignedBigInteger('owner_partner_id')->default(0);  -- 0 = الشركة (ملكنا)؛ غير ذلك = عميل
    $table->boolean('on_book')->default(true);                 -- false = أمانة (خارج تقييم الشركة)
    $table->decimal('declared_unit_cost', 15, 3)->default(0);    -- للأمانة: قيمة معلنة/مرجعية فقط
    ── بُعد اللوط ────────────────────────────────────────────
    $table->string('batch_number', 100)->nullable();
    $table->date('production_date')->nullable();
    $table->date('expiry_date')->nullable();               -- null → يرتّب بتاريخ الاستلام
    $table->decimal('original_quantity', 15, 3);
    $table->decimal('remaining_quantity', 15, 3);        -- ← الرصيد الحيّ لكل لوط/مالك
    $table->decimal('unit_cost', 15, 3)->default(0);       -- تكلفة حقيقية للوط المملوك (on_book)
    $table->foreignId('receipt_item_id')->nullable()->constrained('inventory_receipt_items')->nullOnDelete();
    $table->date('received_date');
    $table->boolean('is_estimated')->default(false);      -- من الترحيل التقديري (~)
    $table->timestamps();
    -- الفريد يشمل المالك؛ owner_partner_id غير قابل للـnull ليعمل الفهرس بأمان
    $table->unique(['company_id','product_id','product_variant_id','warehouse_id',
                   'owner_partner_id','batch_number','expiry_date'], 'lot_owner_uq');
    $table->index(['product_id','warehouse_id','owner_partner_id','remaining_quantity']);
    $table->index(['company_id','expiry_date']);
});
🔒
ثابتان

فيزيائي: SUM(remaining, كل الملّاك) == stock_balances.quantity (يبقى تذييل التطابق في الواجهة صادقًا). دفتري: التقييم والتكلفة يستهلكان SUM(remaining WHERE owner_partner_id=0) فقط. صف «غير مخصّص» القديم دائمًا ملكنا (رصيد ما قبل التتبّع بالتعريف بضاعة شركة).

-- ما استهلكه كل صرف — للإلغاء الدقيق ولتزامن دفتر الأمانة.
Schema::create('inventory_issue_lot_allocations', function (Blueprint $table) {
    $table->id();  $table->foreignId('company_id')->constrained()->cascadeOnDelete();
    $table->string('reference_type');  $table->unsignedBigInteger('reference_id');
    $table->unsignedBigInteger('reference_line_id')->nullable();
    $table->foreignId('lot_balance_id')->constrained('inventory_lot_balances');
    $table->unsignedBigInteger('owner_partner_id')->default(0);  -- يرث مالك اللوط المستهلَك
    $table->decimal('quantity', 15, 3);  $table->decimal('unit_cost', 15, 3)->default(0);
    $table->boolean('is_borrow')->default(false);     -- استلاف من أمانة العميل لأمر الشركة
    $table->boolean('expired_override')->default(false);
    $table->timestamps();  $table->index(['reference_type','reference_id']);
});

٧ الصرف — FEFO ضمن نطاق مالك واحد

🚧
قانون

FEFO لا يعبر حدود المالك أبدًا. التخصيص يجري ضمن لوطات مالك واحد. «نطاق المالك» مُدخَل للتخصيص تمامًا كالمخزن — ويُعرض كترويسة سياق مقفولة لا فلترًا يمكن توسيعه بالخطأ.

function allocateFefo(product, variant, warehouse, owner, needed):
    lots = lot_balances
        .where(product, variant, warehouse, owner_partner_id = owner)  ← نطاق المالك
        .where(remaining_quantity > 0)
        .where(expiry not expired OR policy allows)   -- التلقائي لا يلمس منتهيًا أبدًا
        .orderByRaw('expiry_date IS NULL, expiry_date ASC, received_date ASC, id ASC')
    ... يأخذ من الأقدم انتهاءً حتى تُغطّى الكمية؛ ناقص ⇒ SHORT (يمنع الترحيل) ...

٨ الأمانة — استلام · صرف · استلاف · رد 🤝

٨.١ استلام أمانة (CRN) ورد أمانة (CRT) — مستندان لا يُخلَطان

يُعاد استخدام إطاري الاستلام/التسليم مع تمييز خماسي مكرّر يستحيل معه الخلط: نوع مستند مستقل + سلسلة أرقام (CRN-…/CRT-… لا GRN-…) + ترويسة بنفسجية + حقل «المالك (عميل)» لا «مورّد» + عمود «القيمة المعلنة (للحصر فقط)». الاستلام يلتقط التشغيلة/الصلاحية (هذا ما يمنح بضاعة العميل لوطات) ⇒ يُنشئ لوطات موسومة بالمالك + يطبع بطاقات لوط تحمل اسم العميل (وقاية الجرد). بلا قيود محاسبية (يُقيَّد في مذكرة العميل فقط). الرد (CRT) يخصم لوطات العميل عبر حوار التخصيص مقفولًا على مالكه، ويُطبع كإذن تسليم بخانة توقيع العميل — الورقة إثبات انتهاء الأمانة.

٨.٢ الاستهلاك في التصنيع للغير + الاستلاف («يشتغل منها على سبيل السلف»)

لو سطر BOM موسوم «مادة عميل» ⇒ نطاق الإصدار مقفول على عميل العقد. لو نقصت لوطاته: عرض صريح «استخدام من مخزوننا» (تحميل على العميل حسب العقد). والعكس (أمر شركة ناقص ومتاح أمانة عميل) ⇒ مراسم استلاف (RecordBorrow): يعرض لوطات العميل + القيمة المعلنة + جملة «سيُسجَّل التزام تجاه العميل بقيمة X — تسدّده بالشراء أو بالإرجاع»، ويَسِم صفوف التخصيص is_borrow=true.

🔔
دُرج «مستحق الإرجاع»

الاستلاف دَين قائم فيأخذ سطحًا دائمًا: شارة بنفسجية «مستحق الإرجاع (N)» على لوحة القيادة وشريط الأدوات ⇐ قائمة الاستلافات (عميل·منتج·كمية·قيمة معلنة·العمر) بزرّين: [إرجاع] (يرد مادة مكافئة من مخزونك ويولّد إذن CRT ويُقفل الالتزام) و[شراء تسوية] (فوترة شراء للعميل). الصفوف المتقادمة تصير برتقالية — مضاد «محدش بيرجّع أبدًا».

٨.٣ التسويات المحاسبية (تبقى كما هي فوق النموذج)

الاستلاف: DR WIP / CR Materials Due to Customer بالمعلنة. التسوية «شراء»: فاتورة شراء باسم العميل (بلا مخزن على السطر فلا GRN ثانٍ) + قيد تصفية. التسوية «إحلال»: خصم من مخزونك + DR Materials Due to Customer / CR Inventory. رسوم التصنيع للغير + استرداد مواد المصنع + إغلاق الأمر (أساس WIP = التحويل فقط) — كلها سليمة وتُبقى.

٩ كل مسارات حركة المخزون — تصنيف الأثر

صعب — اختيار لوط سهل — تمرير آلي ملكية خارج النطاق

العمليةالموضع+/−التصنيف
اعتماد إذن استلام / افتتاحيApproveReceipt.php:141+سهل — يكتب لوط ملكنا
اعتماد إذن صرف (القناة الرئيسية + الإنتاج)ApproveIssue.php:195صعب — تخصيص FEFO/يدوي
تسليم/فاتورة البيع + POSConfirmDeliveryNote / PostSalesInvoiceصعب مقفول على ملكنا
التحويل — شحن/استلامShipTransfer / ReceiveTransfer±تمرير اللوط والمالك (يصلح النقطة العمياء)
تسوية / جردApproveAdjustment / FinalizeCount±صعب فروق لكل مالك
استلام أمانة (CRN)CreateConsignmentReceipt+لوط عميل، on_book=false
رد أمانة (CRT) — جديد(إجراء جديد)خصم لوط عميل + مذكرة
استهلاك التصنيع للغيرIssueMaterials (supply_source=customer)صعب نطاق مالك = العميل + recordIssue
الاستلاف / التسويةRecordBorrow / SettleBorrow±تحويل ملكية لوط + قيود
مرتجع بيع / مرتجع شراءPostSalesReturn / PostPurchaseReturn±لوط جديد / إعادة لوط
~٩ مسارات إلغاءCancel*±عكس نفس اللوطات المسجّلة
إعادة التقييم · الحجزRevalueStock · reserve/releaseلا كميةخارج النطاق

١٠ تصميم الواجهات (تصميم Fable)

١٠.١ أربعة قوانين تحكم كل شاشة

  1. حقيقتان دائمًا ظاهرتان لا تندمجان: «الموجود فيزيائيًّا» (يشمل بضاعة العميل) و«ما أملكه». الرقم الافتراضي دائمًا ملكنا، والفيزيائي بجانبه لا بداخله.
  2. لون واحد للملكية فقط: الأحمر/البرتقالي محجوزان للصلاحية؛ الملكية تأخذ البنفسجي (🤝 + اسم العميل). ملكنا = بلا لون. البُعدان متعامدان.
  3. عبور الملكية دائمًا مراسم صريحة: الاستلاف/التسوية/الرد/فرق جرد العميل لا يحدث كأثر جانبي — كلٌّ يفتح خطوة تأكيد تسمّي العميل والالتزام. لا استلاف تلقائي صامت.
  4. FEFO لا يعبر مالكًا: النطاق ترويسة مقفولة لا فلتر.

١٠.٢ توسعة اللوطات — ملّاك مختلطون (تذييل التطابق قلب كل شيء)

▾  غزل قطن 40/1        Main WH     On-hand: 105 +45 🤝    Nearest: 2026-08-20 🤝
   ┌─────────────────────────────────────────────────────────────────────────┐
   │  Lot        Expiry       Received  Issued  On-hand   Value       Status │
   │ ── ملكنا (Own) ──────────────────────────────────────── subtotal 105 ── │
   │  B-2201     2026-09-01       80      20       60     4,800              │
   │  B-2288     2027-02-11       50      13       37     2,960              │
   │  Unassigned (pre-lot) ⓘ      —       —         8       640   [LEGACY]  │
   │ ── 🤝 شركة النور (أمانة) ─────────────────────────── subtotal 30 ── │
   │  B-7010     2026-08-20     40      10       30  معلنة 2,100ⓘ [NEAR]│
   │ ── 🤝 مصنع الأمل (أمانة) ──────────────────────────── subtotal 15 ── │
   │  B-2201 ⚠ⓘ  2027-03-15      15       0       15  معلنة 900ⓘ          │
   │ ───────────────────────────────────────────────────────────────────────── │
   │  Physical total: 150   ✓ matches balance                             │
   │  ملكنا (on-book): 105 — قيمة 8,400   ·   أمانة (ليست ملكك): 45 — معلنة 3,000 │
   │  Valuation & costing use the 105 only.          Show depleted (3) ▾     │
   └─────────────────────────────────────────────────────────────────────────┘

١٠.٣ عدسة الملكية · الجرد · الإصدار من لوط عميل

العدسة: p-select واحد (الكل فعلي · ملكنا فقط · أمانة فقط · عميل محدّد). أي عدسة غير «الكل» ⇒ شريط بنفسجي دائم «تعرض بضاعة شركة النور — ليست أرصدتك الدفترية» + إعادة تسمية العمود + العدسة في الـURL (بيان أمانة قابل للمشاركة).

الجرد: بضاعة العميل داخل الجرد افتراضيًّا، مجمّعة لكل مالك. توجيه الفروق مختلف ومسمّى: فرق ملكنا ⇒ تسوية مخزون (ربح/خسارة الشركة)؛ عجز العميل ⇒ تسوية أمانة على بيان العميل (لا يمسّ حساب خسائر مخزونك أبدًا)؛ فائض العميل ⇒ بانتظار تأكيده.

┌─ تخصيص لوطات — قماش قطن · PO-341 — تصنيع للغير 🤝 شركة النور ────────┐
│ ┌────────────────────────────────────────────────────────────────┐        │
│ │ 🤝 خامة العميل — الصرف من بضاعة «شركة النور» فقط        [مقفول] │        │
│ └────────────────────────────────────────────────────────────────┘        │
│  Mode: (●) تلقائي — الأقرب انتهاءً أولًا    ( ) يدوي     Required: 70      │
│  Lot (🤝 النور)   Expiry       On-hand   Take    Remaining after           │
│  B-7010          2026-08-20    30    [ 30 ]         0                │
│  B-7150          2026-11-05      55    [ 40 ]        15                │
│  ┌──────────────────────────────────────────────┐                         │
│  │  Allocated 70 / 70   ✓ fully allocated        │                         │
│  └──────────────────────────────────────────────┘                         │
│  ⓘ لوطاتك الخاصة (105) غير معروضة — هذا صرف من ملكية العميل               │
│                                  [ إلغاء ]   [ تأكيد التخصيص ]            │
└────────────────────────────────────────────────────────────────────────────┘

سطر «لوطاتك غير معروضة» هو الفرق بين الثقة وتذكرة دعم. البيع اليدوي يُظهر لوطات الأمانة معطّلة بتلميحة «بضاعة أمانة — لا تُباع؛ لتملّكها اشترِها من العميل أولًا» (مرئية-مقفولة تُعلّم القاعدة).

١٠.٤ مزالق التصميم (١٢) — أبرزها

الفشلالوقاية
اختلاط إجمالي ملكنا/الأمانةخلية On-hand مركّبة + تذييل سطرين + لا إجمالي قيمة كبير + المالك عمود في التصدير
بيع بضاعة العميل كأنها ملكناتخصيص البيع مقفول على ملكنا بالبناء + لوطات الأمانة معطّلة + مستند رد CRT منفصل
مخزون عميل منتهٍ لا يردّه أحدمؤشرات الصلاحية تنفصل لكل مالك بنداء مختلف («أبلغ العميل/أرجِعها» لا «إعدام»)
مادة مستلَفة لا تُرَدّشارة «مستحق الإرجاع (N)» دائمة + تقادم برتقالي
فرق جرد العميل يقع في أرباح الشركةلوحات فروق لكل مالك بوجهات مسمّاة مختلفة (بنيويًّا لا يمسّ حساب الخسارة)
تصادم نفس التشغيلة تحت مالكينكاشف + بطاقات لوط موسومة بالمالك + مساعد تقسيم صريح

١١ الترحيل + حاجز التقييم

١٢ خطة التنفيذ — الملكية مخيوطة في كل مرحلة

الملكية عمود على كل سطح لا موديول منفصل. البوابة production.enable_consignment: مطفأة ⇒ لا واجهة ملكية إطلاقًا (المرحلة ٤ تشحن لعملاء بلا تصنيع للغير بلا مساس).

4.0
جهد: متوسط

السجل (باللوط + المالك) + التغذية + عرض القراءة

جدول inventory_lot_balances بعمود owner_partner_id NOT NULL DEFAULT 0 وon_book من اليوم الأول (إضافة العمود بعد وجود بيانات مكلفة)؛ التغذية لكل تشغيلة عند الاستلام؛ ترحيل لوطات الأمانة الموجودة موسومةً بمالكها؛ Surface 1 (توسعة + مجموعات ملّاك + تذييل سطرين) — تظهر فقط عند وجود مالك ثانٍ (منتج بمالك واحد يبدو كموك المرحلة ٤ الأصلي، صفر ضريبة على ٩٥٪).

4.1
جهد: كبير

التخصيص + نطاق المالك على القناة الرئيسية

خيط اللوط والمالك في decreaseStock؛ FEFO ضمن نطاق مالك؛ جدول التخصيصات؛ Surface 2 بترويسة النطاق المقفولة (تشحن هنا وإن استُخدمت غير-ملكنا لاحقًا)؛ عكس الإلغاء الدقيق؛ حاجز الرصيد السالب لكل لوط.

4.2
جهد: كبير

البيع + التصنيع للغير + الاستلاف

البيع/POS مقفول على ملكنا؛ استهلاك مادة العميل بنطاق مالكه + كتابة recordIssue (يُغلق العيب الحرج)؛ مراسم الاستلاف + دُرج «مستحق الإرجاع»؛ مسارات الإلغاء المقابلة.

4.3
جهد: صغير

إصلاح النقاط العمياء

تمرير اللوط والمالك في التحويل (شحن FEFO → استلام يمرّر نفس اللوط/المالك)؛ نسخ التشغيلة في فاتورة الشراء المباشرة.

4.4
جهد: متوسط

المستندات + التقارير + الجرد + الترحيل

مستندات CRN/CRT؛ عدسة الملكية + عمود المالك على تقرير اللوطات + شريط المنتهي منفصلًا لكل مالك؛ الجرد لكل مالك + توجيه الفروق؛ حاجز التقييم (استبعاد الأمانة)؛ معالج الترحيل التقديري.

4.5
جهد: صغير

الإعدادات + المذكرة المالية

بوابة enable_consignment في الواجهات؛ عتبة تقادم الاستلاف؛ عمود «فرق دفتر-فعلي» على بيان العميل؛ (اختياري) حجز على مستوى اللوط.

🚦
نقطة قرار بعد 4.0

بعد 4.0 تشوف أرقام لوطات حقيقية مفصولة بالمالك على الشاشة وتتحقّق منها ضد الرف قبل أي منطق صرف. لو الأرقام صحّت، نكمل 4.1 بثقة.

١٣ المخاطر والحالات الحدّية

الخطرالوقاية
تضخيم قيمة مخزونك ببضاعة العميل (تسريب اليوم)on_book + كل تقارير القيمة تقرأ ملكنا فقط — إصلاح بنيوي، لا اعتماد على علَم is_consignment
انحراف الدفتر عن المخزون (العيب الحالي)سجل اللوط = الحقيقة الكمية؛ recordIssue يُكتب في نفس نقطة الخصم ⇒ حقيقة واحدة
بيع بضاعة عميل بالخطأتخصيص البيع مقفول على ملكنا بالبناء + لوطات أمانة معطّلة + مستند رد منفصل
فرق جرد العميل في أرباح الشركةوجهات فروق لكل مالك؛ عجز العميل يذهب لبيانه لا لحساب خسائرك (بنيويًّا)
مادة مستلَفة لا تُرَدّ / التزام غير مُقرّدُرج «مستحق الإرجاع» دائم + تقادم + الاستلاف مراسم صريحة تسمّي العميل والقيمة
تصادم نفس التشغيلة تحت مالكين في الجردكاشف + بطاقات موسومة + مساعد تقسيم صريح + (توصية) صناديق/مخزن لكل عميل
انحراف التطابق / الرصيد السالب لكل لوطصف «غير مخصّص» يمتص الفرق؛ التخصيص لا يتجاوز remaining_quantity
المتوسط المرجّح لا يستهلك الطبقاتسجل اللوط مستقل تمامًا عن طريقة التكلفة
التحويل يجرّد اللوط/المالكالمالك يركب تمرير اللوط في 4.3؛ حركة الأمانة تُسجَّل على بيان العميل

١٤ قرارات مطلوبة منك قبل البدء

  1. نطاق البداية: منتجات بالتشغيلة أولًا (التسلسلية تُشتقّ من السيريالات)، والملكية عمود على كل سطح — صح؟
  2. مخزن مشترك أم مخزن لكل عميل: النموذج يدعم الاثنين؛ توصيتي: اسمح بالخلط وأوصِ بصناديق/مخازن مخصّصة في الدليل (كاشف التصادم يُظهر الخطر أيًّا كان).
  3. من يستلف: صلاحية production.consignment.borrow منفصلة (يُنشئ التزامًا قانونيًّا — على الأرجح مستوى مشرف)؟
  4. تسوية عجز العميل الافتراضية: شراء تعويضي أم إقرار مكتوب فقط (يحدّد ما يعرضه الجرد أولًا)؟
  5. صرف المنتهي: منع صرف لوط عميل منتهٍ حتى لأمره هو (بنفس صلاحية التجاوز + خانة موافقة العميل المكتوبة)؟
  6. بيان الأمانة (المطبوع): بلوطاته وصلاحياتها (توصيتي — ما يريده ضبط جودة العميل) أم بإجماليات المنتج فقط؟
  7. البدء: أبدأ 4.0 فورًا بنفس الأسلوب (agents + مراجعة + نشر + دفع على hazemdev2
🚀
توصيتي

ابدأ بـ 4.0 — أصغر خطوة تُثبت البنية وتُريك أرقام لوطات حقيقية مفصولة بالمالك دون لمس أي منطق صرف. الافتراضات: منتجات بالتشغيلة أولًا · FEFO مثبّت ضمن نطاق مالك · منع المنتهي · owner_partner_id ٠=الشركة من اليوم الأول · بضاعة الأمانة on_book=false مُستبعَدة من التقييم. أخبرني بأي تعديل على هذه الافتراضات.

Moon ERP · المرحلة ٤ (أرصدة اللوطات × الملكية + FEFO + الأمانة) · مبني على قراءة فعلية للكود (٥ باحثين مستقلّين) وتصميم Fable · مُعاد هيكلته 2026-07-11 · hazemdev2
مرجع: StockService · ApproveReceipt · ApproveIssue · CreateConsignmentReceipt · ConsignmentMaterialLedger · ConsignmentBorrow · MfgTollContract · inventory_cost_layers · inventory_receipt_item_batches
يكمّل: تحليل بضاعة الأمانة (2026-07-08)