أسئلة في موديول التوزيع والمخازن والمبيعات والمشتريات
إليك نسخة منقحة ومنسقة بشكل احترافي للمحتوى الذي قدمته، مع الحفاظ على جميع المعلومات المهمة:
هل يمكن منع المستخدم من استلام أو شراء صنف إذا تجاوز الكمية القصوى؟
نعم، يمكن ذلك من خلال إعدادات النظام، وذلك باستخدام مسارات كيان مخصصة أو التحقق بناءً على معايير.
✅ الخيار الأفضل: استخدام مسار الكيان EAPreventQtyMoreThan
- يُستخدم هذا المسار لمنع الحركات (مثل الشراء أو الاستلام) إذا تجاوزت إجمالي كمية الصنف في المستند القيمة المحددة في الحقل
maxQuantity
الموجود داخل بطاقة الصنف.
🟢 استعلام المقارنة:
select {details.item.item.defaultDetailData.maxQuantity}
هذا الاستعلام يُستخدم داخل المسار لمقارنة إجمالي الكمية مع الحد الأقصى المسموح به لكل صنف.
⚠️ تنبيه مهم:
النظام يُجري التحقق على الكمية المحوّلة للوحدة الصغرى (الوحدة الأساسية للصنف).
- مثال: إذا كانت الوحدة الصغرى "جرام"، وتم إدخال الكمية بالكيلو، فالنظام سيحوّل الكمية إلى "جرام" قبل المقارنة.
- لذا يُنصح بربط المسار مع مرحلة ما قبل الحفظ لضمان تحويل الكمية فعليًا للوحدة الصغرى.
🔁 بديل آخر: مسار EAPreventQtyLessThan
إذا كنت بحاجة لمنع إدخال كمية أقل من حد معين، يمكنك استخدام المسار التالي: EAPreventQtyLessThan
⚙️ خيار آخر (أقل دقة): التحقق بناءً على معايير
يمكنك أيضًا تنفيذ التحقق باستخدام معايير مباشرة داخل ملفات التحقق، وذلك بمقارنة كمية السطر مع الحقل maxQuantity
في بطاقة الصنف.
لكن انتبه:
- هذا التحقق يتم لكل سطر على حدة.
- إذا تكرر نفس الصنف في أكثر من سطر، لن يتم تجميع الكمية، مما قد يسمح بتجاوز الحد الأقصى عبر عدة سطور.
✅ لهذا السبب، يُفضل استخدام مسار الكيان EAPreventQtyMoreThan
لأنه يُراعي إجمالي الكمية لكل صنف داخل المستند.
ما هي معالجة الفرق ما بين قيمة مردود المشتريات التي تم استردادها من المورد - وتكلفة الصرف المخزنى الناتج عنها ؟
- يرجى قراءة هذا المقال لمعرفة تفاصيل المشكلة والحلول المتاحة
- يمكنك معرفة المزيد من خلال الفيديو التالي:
هل يمكن ربط صنف بمخزن أو موقع معين، أو بعدة مخازن بحيث يمنع النظام الحركات خارج هذه المخازن؟
نعم، يمكن ذلك من خلال استخدام ملف ItemWarehouseRelation
الخطوات المطلوبة:
- تفعيل الخيار التالي من إعدادات سلسلة التوريد (Supply Chain):
إنشاء ملف "ربط أصناف بمخازن": يحتوي هذا الملف على جدول تفاصيل ينقسم إلى قسمين رئيسيين:
أولاً: تحديد الصنف
يمكن تحديد الأصناف باستخدام واحد أو أكثر من المعايير التالية:
- الصنف نفسه
- أي من التصنيفات العشر الخاصة بالصنف
- قسم الصنف
- أي من الفئات الخمس
ثانياً: تحديد المخزن أو الموقع ونوع الربط
المخزن أو الموقع الذي ترغب في تقييد الحركة معه.
نوع الربط ويشمل:
- السماح بالتعامل: يسمح بتنفيذ الحركات فقط من المخازن المحددة.
- منع التعامل: يمنع تنفيذ الحركات مع المخازن المحددة.
أمثلة عملية:
✅ السماح بالتعامل:
مثال: السماح بالتعامل مع الأصناف التي ينتمي قسمها إلى "خامات" بالصرف والتوريد فقط من مخزن "الخامات".
- أدخل "خامات" في حقل قسم الصنف.
- أدخل "الخامات" في حقل المخزن.
- اختر نوع الربط: السماح بالتعامل.
❌ منع التعامل:
مثال: منع التعامل مع صنف "حمض الكبريتيك" في مخزن "المنتجات التامة".
أنشئ سطرًا جديدًا يحتوي على:
- الصنف: حمض الكبريتيك
- المخزن: المنتجات التامة
- نوع الربط: منع التعامل
تنبيه مهم:
عند تفعيل الخيار التالي في إعدادات Supply CHain:
يجب تحديد علاقة الأصناف بالمخازنفإن النظام لن يسمح بالحفظ أو تنفيذ الحركات إلا إذا كانت هناك علاقة "سماح بالتعامل" محددة مسبقًا بين الصنف والمخزن.
مثال على استعلام لحساب تكلفة توريد المبيعات من تكلفة صرف المبيعات المرتبط بالفاتورة
بشكل افتراضي، يقوم نظام Nama ERP بحساب تكلفة توريد المبيعات تلقائيًا باستخدام متوسط تكلفة الصنف لحظة التوريد. لكن في بعض السيناريوهات، قد ترغب في ربط تكلفة التوريد بشكل مباشر بتكلفة الصنف التي تم صرفها فعليًا في فاتورة المبيعات نفسها.
يمكنك تنفيذ ذلك باستخدام الاستعلام التالي داخل جدول مصادر تكلفة التوريد غير المكلف ضمن إعدادات موديول التوزيع (Supply Chain Configuration):
select top 1 l.unitCost
from SalesReturn sr
inner join CostOutTransLine l on l.invoiceId = sr.fromDoc_id
where l.item_id = {item_id}
and l.revisionId = coalesce({dimensions.specificDimensions.revisionId}, '')
and l.color = coalesce({dimensions.specificDimensions.color}, '')
and l.size = coalesce({dimensions.specificDimensions.size}, '')
and sr.id = {invoiceId}
Tips
لكي يتم تفعيل استخدام هذا الاستعلام في حساب تكلفة التوريد، يجب تفعيل الخيار التالي في إعدادات سلسلة التوريد
تجاهل متوسط التكلفة الحالية للتوريدات الغير مكلفةيقوم هذا الخيار بإجبار النظام على تجاهل متوسط التكلفة الحالي عند وجود مصدر مخصص لحساب التكلفة، مثل الاستعلام الموضح أعلاه.
كيف أحدد سعر معين لتصنيف فاتورة جملة في نقطة البيع أو فاتورة المبيعات بالنظام؟
إذا كنت بحاجة إلى أن تعتمد فاتورة الجملة على سعر مختلف عن السعر الافتراضي في بطاقة الصنف (مثل "أقل سعر")، فيمكنك تنفيذ ذلك من خلال:
استعمال الحقل السعر الافتراضي في قائمة الأسعار
الموجود ضمن إعدادات تصنيف الفاتورة.
هذا الحقل يحدد من أين يستمد النظام السعر المستخدم في السطور، حتى وإن لم تكن تستخدم قائمة أسعار.
خيارات هذا الحقل:
أقل سعر (MinPrice)
أقصى سعر (MaxPrice)
السعر الافتراضي (DefaultPrice) تتيح لك استخدام القيم المقابلة لها داخل قائمة الأسعار أو سطر تعريف الوحدة داخل الصنف.
السعر المخصص (CustomPrice)
رقم 1 (N1) إلى رقم 5 (N5) تتيح لك استخدام القيم المقابلة لها داخل قائمة الأسعار.
مثال تطبيقي:
لو أردت أن يتم تسعير فواتير الجملة بناءً على "أقل سعر"، كل ما عليك فعله هو:
- فتح تصنيف الفاتورة المستخدم في الجملة.
- ضبط الحقل
السعر الافتراضي في قائمة الأسعار
ليكون على القيمة "أقل سعر (MinPrice)". - حفظ التغييرات.
بعد ذلك، أي فاتورة جديدة تتبع هذا التصنيف ستستخدم أقل سعر متاح للصنف بشكل تلقائي في نقطة البيع.
كيف يحدد النظام السعر المستخدم في الفاتورة بناءً على حقل السعر الافتراضي في قائمة الأسعار
؟
يمكنك التحكم في السعر المستخدم داخل فواتير البيع من خلال حقل السعر الافتراضي في قائمة الأسعار
، وهو متاح في عدة أماكن داخل النظام.
أماكن توفر الحقل:
يظهر هذا الحقل في الأماكن التالية (مرتبة حسب أولوية التطبيق):
- العميل (Customer)
- توجيه الفاتورة (Document Term)
- فئة العميل (Customer Category)
- تصنيف العميل (Customer Classy)
- تصنيف الفاتورة (Invoice Classification)
- محدد سعر 1 (Price Classifier 1)
- محدد سعر 2 (Price Classifier 2)
- محدد سعر 3 (Price Classifier 3)
- محدد سعر 4 (Price Classifier 4)
- محدد سعر 5 (Price Classifier 5)
- إعدادات Supply Chain
آلية الاختيار:
يقوم النظام بالبحث عن أول قيمة معرفة لهذا الحقل حسب الترتيب أعلاه. بمعنى آخر، إذا وُجدت قيمة لهذا الحقل في ملف العميل، فسيتم استخدامها مباشرة. أما إذا لم تكن معرفة، فسينتقل النظام تلقائيًا إلى الملف التالي في الترتيب (توجيه الفاتورة، ثم تصنيف العميل... وهكذا) حتى يجد أول قيمة معرفة.
مثال توضيحي:
إذا كنت قد ضبطت الحقل "السعر الافتراضي في قائمة الأسعار" في تصنيف الفاتورة على "أقل سعر"، ولكن لديك أيضًا ضبط مختلف داخل العميل، فسيأخذ النظام القيمة الموجودة في العميل ويتجاهل ما في تصنيف الفاتورة، لأن العميل له أولوية أعلى في الترتيب.
ملخص:
- يمكن تخصيص مصدر السعر لكل نوع من العملاء أو الفواتير حسب موقع الضبط.
- الأولوية تبدأ من ملف العميل وتنتهي بإعدادات Supply Chain.
- يكفي تحديد القيمة في أول موقع ضمن الترتيب ليتم اعتمادها تلقائيًا في التسعير داخل الفاتورة.
❓ كيف يمكن حساب تكلفة فاتورة تحتوي على أصناف مركبة (مثل البكجات) يتم صرف مكوناتها من المخزون وليس الصنف نفسه؟
عند التعامل مع فاتورة تحتوي على أصناف مركبة مثل:
بكج 6 عطور نيش بلاك + نيش جولد + دريمز بالاس + ان ذا موود + هيستورى نوت + نيش ان بزنس
فإن عملية الصرف المخزني لا تتم على الصنف المركب نفسه، بل تتم على مكوناته الفرعية، مثل:
- عطر نيش بلاك
NESH BLACK
- عطر نيش جولد
NESH GOLD
- عطر دريمز بالاس
DREAMS PALACE
- وغيرها...
وبالتالي، لا يظهر الصنف الرئيسي (البكج) في سند الصرف المخزني، بل يتم صرف كل مكون من مكوناته كأصناف مستقلة. لحساب التكلفة الحقيقية لهذه الفاتورة، يجب احتساب تكلفة المكونات المستخدمة في كل صنف مركب، وليس الصنف المركب نفسه.
كيفية الربط بين الصنف المركب ومكوناته؟
يتم ربط كل مكون بالصنف المركب عبر الحقل masterRowId
الموجود في جدول SalesInvoiceLine
:
- السطر الخاص بالصنف المركب (مثل "بكج العطور") يحتوي على
masterRowId = NULL
- أما السطور الخاصة بالمكونات (مثل "NESH BLACK") تحتوي على
masterRowId = <ID الخاص بالسطر الرئيسي>
خطوات حساب التكلفة:
- ابدأ من جدول فواتير المبيعات لتحديد الفاتورة المطلوبة.
- اجلب كل سطر رئيسي في الفاتورة (الذي
masterRowId IS NULL
). - ابحث عن السطور الفرعية المرتبطة به عبر
SalesInvoiceLine.masterRowId
. - ابحث عن سطر الصرف المخزني المقابل لكل مكون أو للسطر الأصلي إن لم توجد مكونات.
- اربط بسجل التكلفة (
CostOutTransLine
) عبرoriginLineId
. - استخدم الدالة
coalesce(sub.id, l.id)
لاختيار المكون إذا وُجد، أو السطر الرئيسي إذا لم يكن له مكونات. - استبعد السطور التي لها
masterRowId
عند التجميع، لأن تكلفة المكونات ستُحتسب بالفعل.
استعلام SQL لحساب تكلفة كل صنف مركب في الفاتورة
SQL Query to Calculate cost of a sales invoice
select
l.itemCode,
l.item_id,
sum(co.totalCost) as cost
from SalesInvoice s
left join SalesInvoiceLine l on l.salesInvoice_id = s.id
left join SalesInvoiceLine sub on sub.masterRowId = l.id
left join StockIssueLine sil on sil.sourceLineId = coalesce(sub.id, l.id)
left join CostOutTransLine co on co.originLineId = sil.id
where s.code = 'Salla2025229014'
and l.masterRowId is null
group by l.itemCode, l.item_id
- ملاحظة إضافية:
لو أردت فقط إجمالي تكلفة الفاتورة بالكامل بدون تفاصيل الأصناف، يمكنك تعديل الاستعلام السابق بهذا الشكل:
SQL Query to Calculate total cost of a sales invoice
select
sum(co.totalCost) as total_invoice_cost
from SalesInvoice s
left join SalesInvoiceLine l on l.salesInvoice_id = s.id
left join SalesInvoiceLine sub on sub.masterRowId = l.id
left join StockIssueLine sil on sil.sourceLineId = coalesce(sub.id, l.id)
left join CostOutTransLine co on co.originLineId = sil.id
where s.code = 'Salla2025229014'
and l.masterRowId is null
كيفية حساب التكلفة المؤقتة للتوريد المخزني من أمر الشراء؟
لحساب التكلفة المؤقتة للتوريد المخزني بناءً على أمر الشراء، يُرجى اتباع الخطوات التالية:
في توجيه التوريد المخزني قم بالتالي:
- تفعيل خِيار تسليم غير مكلف.
- تفعيل خِيار حساب التكلفة المؤقتة من بناءا على (أمر شراء).
في إعدادات الـ Supply Chain قم بالتالي:
- فعّل خيار تجاهل متوسط التكلفة الحالية للتوريدات غير المكلفة
- حدد تكلفة السطر في أول مصدر داخل جريد مصادر التكلفة للتوريد الغير مكلف.