قد تكسر أخطاء منطق القسائم إجماليات الدفع. تعلّم قواعد التكديس، الاستثناءات، وأنماط قابلة للاختبار لمنع الخصم المزدوج والمجاميع السالبة.

تبدو العروض بسيطة حتى تجربها في سلة دفع حقيقية. السلة تتغير طوال الوقت، لكن كثيرًا ما تُكتب الخصومات كقواعد منفصلة. تلك الفجوة هي المكان الذي تظهر فيه معظم مخاطر منطق القسائم.
الصعب هنا أن قاعدة واحدة جديدة يمكنها تغيير المجاميع في كل مكان. أضف "خصم 10%، لكن ليس على السلع المخفضة"، فعليك حينها تحديد معنى "مخفض"، ومتى يتم التحقق منه، وعلى أي مبلغ يُطبَّق الخصم. إذا تداخل عرض آخر مع نفس العناصر، فالأولوية تُحدث فرقًا، وتغيير الترتيب يغير السعر.
تقوم فرق كثيرة أيضًا بخلط الحساب مع قواعد العمل. حل سريع مثل "تقييد الخصم عند المجموع الفرعي" يُنسخ في ثلاثة أماكن، وسرعان ما تحصل على إجابات مختلفة حسب مكان احتساب الإجمالي (صفحة السلة، الدفع، الفاتورة، البريد الإلكتروني).
اللحظات عالية المخاطر هي عندما يعيد نظامك حساب الأسعار:
مثال صغير: يضيف متسوق حزمة، ثم يطبق رمز "20$ خصم عند 100$"، ثم يزيل عنصرًا. إذا ظلّت الشيفرة "تتذكّر" المجموع الفرعي القديم، فقد تمنح 20$ خصمًا لعربة بقيمة 85$، أو حتى تُظهِر سطر عنصر بسعر سالب.
في نهاية هذا المنشور، ستتمكن من منع أكثر فشل العروض شيوعًا: الخصم المزدوج، اختلاف المجاميع بين الشاشات، المجاميع السالبة، تطبيق الخصومات على عناصر مستبعدة، واستردادات لا تطابق ما دفعه العميل أصلاً.
تبدأ معظم مشاكل منطق القسائم بجملة ناقصة واحدة: أي الخصومات مسموح أن تُطبَّق معًا، وبأي ترتيب. إذا لم تستطع شرح قواعد التكديس بلغة بسيطة، سيتصرف نظام السلة في مرحلة ما بشكل مفاجئ.
عرّف التكديس ببيانات نعم أو لا بسيطة. على سبيل المثال: "قسيمة يدوية واحدة لكل طلب. يمكن أن تستمر العروض التلقائية في التطبيق ما لم تذكر القسيمة أنها تمنعها." هذه السطر الواحد يمنع تركيبات عشوائية تؤدي إلى خصم مزدوج.
فصل خصومات مستوى العنصر عن خصومات مستوى الطلب مبكرًا. قواعد مستوى العنصر تغيّر سعر منتجات محددة (مثل خصم 20% على الأحذية). قواعد مستوى الطلب تغيّر الإجمالي (مثل 10$ خصم على السلة). الخلط بينهما بدون هيكل يسبب تباين المجاميع بين صفحات المنتج، السلة، والدفع.
قرر معنى "أفضل صفقة" قبل البرمجة. تختار فرق كثيرة "أقصى توفير"، لكن ذلك قد يكسر حد الأسعار الدنيا. قد تحتاج أيضًا لقواعد مثل "لا تُخَفّض أبداً تحت التكلفة" أو "لا تجعل الشحن سالبًا". اختر قاعدة فائزة واحدة واضحة حتى لا يخمن المحرك.
ترتيب أولوية بسيط يجعل التعارضات متوقعة:
مثال: السلة بها عرض تلقائي 10% على جميع العناصر، بالإضافة إلى قسيمة بقيمة 15$ على الطلبات فوق 100$. إذا قالت الأولوية أن التلقائي أولًا، يمكنك بوضوح الإجابة: هل يستخدم شرط 100$ المجموع الفرعي قبل الخصم أم بعده؟ اكتب الإجابة، ثم التزم بها في كل مكان.
بمجرد كتابة هذه الخيارات، تصبح قواعد تكديس القسائم قواعد قابلة للاختبار، وليست سلوكًا مخفيًا. هذه أسرع طريقة لتجنب مشاكل منطق القسائم لاحقًا.
تبدأ كثير من مشاكل منطق القسائم عندما تعيش الخصومات كفروع if-else متفرقة عبر كود الدفع. نهج أكثر أمانًا هو التعامل مع كل عرض كمجموعة بيانات ذات نوع وصلة وحدود واضحة. حينئذٍ تصبح حسابات السلة مقيّمًا صغيرًا ومتوقعًا.
ابدأ بتسمية نوع الخصم، وليس فكرة التسويق. معظم العروض تتناسب مع أشكال قليلة: نسبة مئوية خصم، مبلغ ثابت خصم، عنصر مجاني (اشترِ X واحصل على Y)، وشحن مجاني. عندما يمكنك التعبير عن العرض باستخدام أحد هذه الأنواع، تتجنب حالات خاصة يصعب اختبارها.
بعد ذلك، اجعل النطاق صريحًا. نفس الخصم النسبي يتصرف بشكل مختلف حسب ما يستهدفه. عرّف ما إذا كان ينطبق على الطلب كله، فئة، منتج، سطر واحد، أو الشحن. إذا كان النطاق غير واضح، ستخصم عن المجموع الفرعي الخطأ أو تكرر الخصم.
سجّل القيود كحقول، وليس كتعليقات في الكود. القيود الشائعة: الحد الأدنى للإنفاق، الطلب الأول فقط، ونطاق التواريخ. سجّل أيضًا كيفية التعامل مع الأسعار المخفضة: التكديس، التطبيق على السعر الأصلي، أم استثناء العناصر المخفضة.
مخطط قاعدة مضغوط قد يشمل:
أخيرًا، أضف قواعد أرضية للأسعار يجب أن يحترمها المحرك دائمًا: لا تنخفض المجاميع تحت الصفر أبدًا، وإذا احتاج عملك لذلك، لا تنخفض الأسعار تحت التكلفة أو تحت حد سعر مُعَرَّف. إذا بنيت هذا، تمنع المجاميع السالبة وحالات "ندفع للعميل" المحرجة.
إذا جربت نموذجًا أوليًا لمحرك خصومات في Koder.ai، حافظ على ظهور هذه الحقول في وضع التخطيط حتى يبقى المُقيّم بسيطًا وقابلًا للاختبار مع إضافة عروض إضافية.
تبدأ معظم مشاكل منطق القسائم عندما تختلط فحوص الأهلية والحسابات معًا. نمط أكثر أمانًا هو ذو مرحلتين: أولًا قرر ما يمكن أن ينطبق، ثم احسب المبالغ. هذا الفصل يجعل القواعد مقروءة ويسهّل منع الحالات السيئة (مثل المجاميع السالبة).
استخدم نفس الترتيب في كل مرة، حتى لو وصلت العروض بترتيب مختلف من واجهة المستخدم أو API. الحتمية مهمة لأنها تحوّل سؤال "لماذا تغيّرت سلة التسوق هذه؟" إلى سؤال يمكنك الإجابة عليه.
تدفق بسيط يعمل جيدًا:
عند تطبيق العروض، لا تخزن مجرد "إجمالي الخصم" واحد. احتفظ بتفصيل لكل سطر وللطلب حتى يمكنك مطابقة المجاميع وشرحها.
سجّل على الأقل:
مثال: سلة بها عنصران، واحد منهما مُخفض بالفعل. المرحلة الأولى تحدد أن القسيمة مؤهلة للعنصر ذو السعر الكامل فقط. المرحلة الثانية تطبق 10% على ذلك السطر، تترك السطر المخفض كما هو، ثم تعيد حساب مجاميع الطلب من تفصيل الأسطر حتى لا تكرر الخصم بطريق الخطأ.
تبدأ معظم مشاكل منطق القسائم عندما تُخفى الاستثناءات داخل فروع حالات خاصة مثل "إذا كان الرمز X، تخطَّ Y." يعمل ذلك لعرض واحد، ثم ينكسر عندما يأتي العرض التالي.
نمط أكثر أمانًا: احتفظ بتدفق تقييم واحد، واجعل الاستثناءات مجموعة من الفحوص التي يمكن أن ترفض مجموعة العروض قبل أن تحسب أي أموال. بهذه الطريقة، لا تُطبّق الخصومات جزئيًا أبدًا.
بدلاً من ترميز السلوكيات، أعطِ كل عرض ملف "توافق" صغير وصريح. على سبيل المثال: نوع العرض (قسيمة مقابل عرض تلقائي)، النطاق (عناصر، شحن، طلب)، وقواعد الدمج.
ادعم كلا:
المهم أن يسأل المحرك نفس الأسئلة لكل عرض، ثم يقرّر إن كانت المجموعة صالحة.
العروض التلقائية تُطبَّق غالبًا أولًا، ثم يدخل القسيمة وتُلغى بصمت. قرر مسبقًا ما الذي يجب أن يحدث:
اختر خيارًا لكل عرض واكوده كفحص، لا كمسار حساب بديل.
طريقة عملية لتفادي المفاجآت هي التحقق من التماثل. إذا كان المقصود أن "WELCOME10 لا يمكن أن يتكدس مع FREESHIP" وأن ذلك متبادل، اكوده بحيث يحجب كلا الاتجاهين. إذا لم يكن متبادلًا، اجعل ذلك مقصودًا ومرئيًا في البيانات.
مثال: هناك عرض تلقائي 15% على الموقع. يدخل العميل قسيمة 20% مخصّصة للعناصر ذات السعر الكامل فقط. يجب أن ترفض فحوصك العناصر المخفضة للقسيمة قبل حساب المجاميع، بدلاً من خصمها ثم محاولة تصحيح الأرقام لاحقًا.
إذا بنيت قواعد الخصم في منصة مثل Koder.ai، اجعل هذه الفحوص طبقة منفصلة قابلة للاختبار حتى تغيّر القواعد دون إعادة كتابة الحسابات.
معظم نزاعات القسائم ليست حول قيمة الخصم الرئيسية. تحدث عندما يُحتسب نفس السلة بطريقتين مختلفتين قليلًا، ثم يرى العميل رقمًا في السلة وآخرًا في الدفع.
ابدأ بتثبيت ترتيب العمليات. قرّر ودوّن ما إذا كانت خصومات مستوى العنصر تحدث قبل خصومات مستوى الطلب، وأين يقع الشحن. قاعدة شائعة: خصومات العنصر أولًا، ثم خصم الطلب على المجموع المتبقي، ثم خصومات الشحن أخيرًا. أيًا كان اختيارك، استخدم نفس التسلسل حرفيًا في كل مكان تعرض فيه إجماليًا.
الضريبة هي الفخ التالي. إذا كانت الأسعار شاملة الضريبة، يخفض الخصم جزء الضريبة أيضًا. إذا كانت الأسعار حصرية الضريبة، تُحسب الضريبة بعد الخصومات. خلط هذه النماذج في أجزاء مختلفة من التدفق هو أحد أخطاء منطق القسائم الكلاسيكية لأن حسابين صحيحين قد يختلفان إذا افترض كل منهما أساس ضريبة مختلف.
قضايا التقريب تبدو صغيرة لكنها تُنتج شكاوى دعم كبيرة. قرّر ما إذا كنت تقرّب على مستوى كل سطر (كل SKU بعد الخصم) أو فقط على مستوى الطلب، والتزم بدقة العملة. مع القسائم النسبية، قد ينحرف التقريب على السطر بعدة سنتات مقارنة بتقريب الطلب، خاصة مع عناصر منخفضة الثمن كثيرة.
هذه حالات حافة تستحق المعالجة صراحة:
مثال ملموس: قسيمة 10% على الطلب زائد شحن مجاني للطلبات فوق 50$. إذا طُبِّق الخصم قبل التحقق من الحد، قد ينخفض المجموع بعد الخصم تحت 50$ ويتوقف الشحن عن كونه مجانيًا. اختر تفسيرًا واحدًا، اكوده كقاعدة، واجعله متسقًا في السلة، الدفع، والاستردادات.
تظهر معظم مخاطر منطق القسائم عندما تُقيّم السلة عبر أكثر من مسار واحد. قد يُطبَّق العرض على مستوى سطر العنصر في مكان، ومرة أخرى على مستوى الطلب في مكان آخر، وكلاهما يبدو "صحيحًا" بمعزل عن الآخر.
إليك الأخطاء التي تظهر غالبًا، والسبب الشائع وراء كل منها:
مثال ملموس: سلة فيها عنصران، أحدهما مؤهل والآخر مستبعد. إذا حسب المحرك "المجموع المؤهل" بشكل صحيح لخصم النسبي، لكنه لاحقًا يخصم مبلغًا ثابتًا من إجمالي الطلب الكامل، فالعنصر المستبعد ينال الخصم فعليًا.
النمط الأكثر أمانًا هو حساب كل عرض مقابل "المبلغ المؤهل" الصريح وإرجاع تعديل محدود (لا يقل عن الصفر أبدًا)، بالإضافة لتتبع واضح لما لمسه. إذا ولّدت محرك خصوماتك في أداة مثل Koder.ai، اجعلها تُخرِج التتبع كبيانات بسيطة حتى تتمكن اختباراتك من التأكد من أي الأسطر كانت مؤهلة وأي مجموع فرعي استُخدم.
تظهر معظم مخاطر منطق القسائم لأن الاختبارات تتحقق فقط من الإجمالي النهائي. مجموعة جيدة تتحقق من الأهلية (هل يجب أن يطبق العرض؟) والرياضيات (كم يجب أن يخصم؟)، مع تفصيل قابل للقراءة يمكنك مقارنته بمرور الوقت.
ابدأ باختبارات وحدة تعزل قاعدة واحدة في كل مرة. حافظ على المدخل صغيرًا، ثم وسّعه إلى سيناريوهات سلة كاملة.
بعد الحصول على تغطية، أضف بضعة فحوص "دائمة الصحة". هذه تلتقط الحالات الغريبة التي لم تفكر في كتابتها يدويًا.
تخيّل سلة بها عنصران: قميص بسعر 40$ (مؤهل) وبطاقة هدايا بسعر 30$ (مستبعد). الشحن 7$. العرض: "20% على الملابس، بحد أقصى 15$"، بالإضافة إلى عرض ثانٍ "10$ خصم على الطلبات فوق 50$" لا يمكن التكديس مع الخصومات النسبية.
يجب أن يختبر سيناريوك أي عرض يفوز (الأولوية)، ويؤكد أن البطاقة مستبعدة، ويتحقق من التخصيص الدقيق: 20% من 40$ = 8$، الشحن غير متأثر، والإجمالي النهائي صحيح. احفظ ذلك التفصيل كقطة مرجعية حتى لا تغير عمليات إعادة البناء أيًا من قواعد التطبيق بصمت.
قبل نشر عرض جديد، قم بمرور أخير بقائمة فحص تلتقط الأخطاء التي يلاحظها العملاء فورًا: مجاميع غريبة، رسائل مربكة، واستردادات غير متطابقة. هذه الفحوص أيضًا تساعد على منع معظم مخاطر منطق القسائم لأنها تجبر قواعدك على التصرف بنفس الطريقة في كل سلة.
شغّل هذه الفحوص ضد مجموعة صغيرة من "السلات المعروفة بالصعوبة" (عنصر واحد، عناصر كثيرة، معدلات ضريبية مختلطة، شحن، وخطّ بكميات كبيرة). احفظ هذه السلات حتى تعيد تشغيلها في كل مرة تغيّر فيها كود التسعير.
إذا بنيت قواعدك في مولّد مثل Koder.ai، أضف هذه الحالات كاختبارات مؤتمتة جنبًا إلى جنب مع تعريفات القواعد. الهدف بسيط: أي عرض مستقبلي يجب أن يفشل سريعًا في الاختبارات بدلًا من أن يفشل في سلة عميل.
إليك سلة صغيرة تكشف معظم مخاطر منطق القسائم دون التعقيد المفرط.
افترض هذه القواعد (اكتبها بالضبط هكذا في نظامك):
سلة:
| Line | Price | Notes |
|---|---|---|
| Item A | $60 | full-price, eligible |
| Item B | $40 | full-price, eligible |
| Item C | $30 | sale item, excluded |
| Shipping | $8 | fee |
العروض:
تحقق من حد القسيمة: البضائع المؤهلة قبل الخصومات = 60$ + 40$ = 100$، لذا القسيمة قابلة للتطبيق.
طبق العرض 1 (10% على العناصر المؤهلة): 100$ × 10% = 10$ خصم. يصبح المجموع المؤهل 90$.
طبق العرض 2 (15$ خصم): الحد الأقصى هو 90$، فَيُطبَّق 15$ كاملًا. يصبح المجموع المؤهل الجديد 75$.
الأجماليات:
غير شيء واحد: يزيل العميل العنصر B (40$). تصبح البضائع المؤهلة 60$، لذا تفشل قسيمة 15$ بخصوص شرط الحد الأدنى. يبقى العرض التلقائي 10% فقط: يصبح سعر Item A = 54$، البضائع = 54$ + 30$ = 84$، والإجمالي النهائي = 99.36$. هذا هو نوع "التعديل الصغير" الذي يكسر السلال إذا لم تكن الأهلية والترتيب صريحين.
أسرع طريقة لتجنّب مخاطر منطق القسائم هي معاملة العروض كقواعد منتجات، وليس "قطعة من الرياضيات في صفحة الدفع." قبل النشر، اكتب مواصفة قصيرة يمكن لأي شخص في الفريق قراءتها والموافقة عليها.
ضمّن أربعة أشياء بلغة بسيطة:
بعد الإطلاق، راقب المجاميع كما تراقب الأخطاء. غالبًا ما يبدو خطأ الخصم كطلب صحيح حتى تراه المالية.
أعد إعداد مراقبة تُعلِم عن طلبات بأنماط غير طبيعية، مثل المجاميع القريبة من الصفر، المجاميع السالبة، خصومات أكبر من المجموع الفرعي، أو ارتفاع مفاجئ في عربات "100% خصم". وجه التنبيهات إلى نفس مكان أخطاء الدفع، واحتفظ بدليل قصير لكيفية تعطيل عرض بأمان.
لإضافة عروض جديدة دون تراجعات، استخدم سير عمل قابل للتكرار: حدّث المواصفة أولًا، اكود القاعدة كبيانات (لا كفرع برمجي)، أضف اختبارات لسلة "طبيعية" وعدة حالات حافة، ثم شغّل مجموعة اختبارات الخصم الكاملة قبل الدمج.
إذا أردت تنفيذًا وتجربة أسرع، يمكنك تصميم تدفقات محرك العروض في Koder.ai باستخدام وضع التخطيط، ثم استخدم لقطات الحالة والرجوع أثناء تحسين اختباراتك. يساعدك ذلك على تجربة تغييرات القواعد بسرعة دون فقدان نسخة جيدة معروفة.