
Hilton Kitchen
تطبيق عميل / دراسة حالة هندسيةالطلب ليه سكة.والحساب ليه حكاية.
نقطة بيع، تصنيع، مخزون وتحصيل. نظام واحد متصمم على الشغل اللي فريق هيلتون كيتشن بيعمله فعلًا.
جوه الحكاية20 دقيقة


- العلاقة
- تطبيق عميل
- دورنا
- تصميم وهندسة المنتج
- المنصات
- Web + Windows
- لغة التشغيل
- عربي أولًا / دعم إنجليزي
إزاي إحنا في Softworks بنينا نظام تشغيل يجمع البيع والتصنيع والمخزن والتحصيل، من غير ما كل شاشة تحكي حكاية لوحدها.
الطلب في برنامج تشغيل مش مجرد صف فيه اسم وسعر وزرار أخضر. وراه حد بيبيع، وحد بيجهز، وحد بيسلّم، ومخزون بيتحرك، وفلوس ممكن تيجي على دفعات. لو كل جزء فاهم كلمة «خلص» بطريقته، هتلاقي عندك خمس نهايات لنفس الحكاية، وكلهم مقتنعين إن التتر نزل.
في Hilton Kitchen، شغلنا كان إننا نخلي الحكاية واحدة. الطلب، وحركة المخزون، والدفعة، والفاتورة، وشاشة الموظف اللي بعده لازم يتفقوا على اللي حصل. بنينا ده بواجهات عربية للتاتش، وويب للإدارة والتشغيل، وتطبيق Windows للموظفين، وقواعد واضحة لكل حركة.
دي النسخة الخفيفة من دراسة الحالة؛ التفاصيل التقنية فيها جد. الأمثلة الجاية سيناريوهات توضيحية مبنية على الكود وسير العمل، مش حوادث منسوبة للعميل ولا حوارات متخيلة حصلت في المكتب. والأرقام اللي جوه الأمثلة للتوضيح، مش بيانات عملاء. تقدر ترجع لـالنسخة المهنية في أي وقت.
النظام بيتبع حركة الشغل.
البيع، التسليم، والتحصيل. كل واحد له معنى.
الأول نفهم الشغل، وبعدها نختار لون الزرار
بدأنا من سير العمل العربي المرفق بالمشروع، وكملنا مع التعديلات المعتمدة اللي سجلها المستودع. فهمنا إن فيه بيع مباشر من مخزون جاهز، وطلبات توصيل وجملة داخلة تصنيع، وأجهزة لازم نعرف وحداتها الفعلية، وتحصيل ممكن يستمر بعد التسليم.
التخصيص هنا وصل لقلب التشغيل. إمتى المخزون يزيد؟ إمتى يقل؟ مين محتاج يشوف الطابور؟ إيه الورقة اللي تطلع في كل مرحلة؟ وإيه معنى إن الفاتورة لسه عليها باقي؟ الإجابات دي بتحدد شكل قاعدة البيانات قبل ما تحدد شكل الكارت.
إحنا بنحب الواجهة المرتبة، بس ترتيب الألوان لوحده مش هيمنع الجهاز المتباع من الظهور كأنه لسه في المخزن. الترتيب الحقيقي بيبدأ من معنى الحركة، وبعدها بنعمل لها واجهة مفهومة.
نفس الكاونتر. ومسارات مختلفة.
اختار مسار الطلب
- 01
بيع مباشر
منتجات جاهزة أو جهاز محدد برقم مسلسل.
- 02
معاملة واحدة
فحص الرصيد وتسجيل البيع وخصم المخزون وتجهيز المستند.
- 03
مكتمل من المخزون
من غير دخول طابور التصنيع.
المبيعات تقدر تسجل دفعة مقدمة أو أقساط. الكاشير يشترط السداد الكامل.
نفس كلمة «طلب»، بس المشاوير مختلفة
قسمنا التنفيذ لمسارين واضحين. طلبات POS والأجهزة بتبيع مخزون جاهز؛ إنشاء البيع بيفحص الرصيد، ويسجل الخروج، ويكمل الطلب، ويجهز مستنده. طلبات التوصيل والجملة بتدخل تصنيع، وبعدها تجهيز، وبعدها جاهز، وبعدها تسليم لشخص مسمى.
المصنعين بيشوفوا نفس طابور الفرع. ماعملناش محرك توزيع مصانع من عندنا، لأن المطلوب كان مشاركة الطابور. والتسليم للعميل أو السائق هو نهاية المسار الحالي؛ مفيش رحلة سائق ومتابعة خريطة مستخبية في آخر الصفحة.
المراحل العامة فضلت محددة: MANUFACTURING، وPACKAGING، وREADY، وCOMPLETED. اسم الحالة التقني يفضل ثابت، والواجهة تقدم الوصف المناسب. كده كل شاشة بتتكلم على نفس المرحلة، حتى لو طريقة عرضها مختلفة.
البيعة لازم تتسجّل كاملة.
خدمات Fastify بتفحص الإجراءات باستخدام Zod. الطلب والمخزون والدفعات والمستندات يتسجلوا سوا حسب العملية.
إجراء محدد ← معاملة قاعدة بيانات ← إشعار بعد الحفظ ← تحديث الشاشات
التِك ستاك: كل أداة ليها شغلانة
استخدمنا TypeScript في مساحة عمل واحدة، مع Next.js وReact للواجهة، وFastify للـAPI، وPostgreSQL مع Prisma للبيانات والمعاملات. Socket.IO بينبّه الشاشات بالتغييرات المؤكدة، وElectron بيشغّل واجهة الموظفين على Windows، ومعاه SQLite للشغل المحلي المستمر.
| الجزء | اختيارات المستودع وقت المراجعة | دوره |
|---|---|---|
| التشغيل | Node.js 24 وpnpm 11.21.0 | تشغيل وبناء منظمين |
| الواجهة | Next.js 16.3.1 وReact 19.2.8 | الويب وواجهة Windows المشتركة |
| اللغة والعقود | TypeScript 6.0.3 وZod 4.3.3 | أشكال بيانات واضحة وفحص الحدود |
| الخدمات والبيانات | Fastify 5.12.0 وPrisma 7.9.1 وPostgreSQL 16 | تنفيذ قواعد التشغيل |
| الحسابات | decimal.js 10.6.0 | فلوس وكميات عشرية محسوبة |
| التحديثات | Socket.IO 4.8.3 | تنبيه بعد تسجيل التغيير |
| Windows | Electron 44.2.0 وSQLite | واجهة محلية وطابور عمل دائم |
| الاختبارات | Vitest وPlaywright وTesting Library | من القاعدة لحد تجربة المتصفح |
الأرقام دي وصف للإصدارات المثبتة وقت المراجعة. اختيار الأداة عندنا مرتبط بمسؤوليتها، مش بمسابقة مين يحط شعارات أكتر في سلايد المعمارية.
المعاملة الواحدة: البيع ماينفعش يرجع بنص طلب
سيناريو توضيحي: الطلب اتكتب، بس حركة المخزون فشلت. أو المخزون نقص، لكن المستند المرتبط بالبيع ماتسجلش. الواجهة ممكن تعرض نجاح، والبيانات تبقى واقفة على رجل واحدة.
الحل إننا حطينا الكتابات المرتبطة بالفعل جوه transaction في PostgreSQL. في البيع المباشر، الطلب وبنوده وحركته الأولية وخصم المخزون وسجلات الدفع المناسبة ومهمة المستند لازم يتفقوا. لو شرط أساسي فشل، العملية ماتسيبش بيع ناقص.
قواعد التشغيل عايشة في خدمات المجال في الخلفية، والواجهة بتطلب فعل مسمى. ده بيخلّي زرار البيع أو التسليم مجرد مدخل للعملية، مش مكان تاني بيعيد اختراع الحسابات. القاعدة هنا بسيطة: طبق الطلب يطلع كامل؛ مش الفاتورة توصل والسندوتش لسه محتار.
آخر قطعة، وكاشيرين: العدد مش بيتقسم بالمجاملة
سيناريو توضيحي: جهازين فاتحين الكتالوج، والاتنين شايفين قطعة واحدة. كل موظف ضافها للسلة قبل ما التاني يخلص. الصورة اللي على الشاشة كانت صحيحة لحظة تحميلها، لكن لحظة البيع محتاجة قرار جديد.
عشان كده فحص المخزون النهائي وخصمه بيحصلوا جوه نفس معاملة البيع، مع قفل المنتجات المطلوبة وإعادة قراءة الرصيد. لو بيع سبق واتأكد، البيع المنافس ماينفعش يتصرف على نفس القطعة كأنها لسه موجودة.
ده بيفرق بين تجربة اختيار سريعة وبين وعد تجاري مؤكد. السلة تقدر تفتح وتتحرك بسلاسة، لكن رسالة النجاح تستنى النتيجة. ولو الكمية مش كفاية، العملية كلها تترفض من غير بقايا طلب. اختبارات النقص والتزامن هنا جزء من معنى البيع، مش إضافات تجميلية.
النت فصل بعد الحفظ: إعادة المحاولة مش طلب جديد
سيناريو توضيحي: السيرفر خلص البيع، لكن الرد ضاع في الطريق. الموظف شايف شاشة مستنية، ومش عارف هل الضغط تاني هيكمل ولا هيكرر. تعطيل الزرار ثانيتين مفيد، بس مش حل لمشكلة حصلت بعد ما الطلب سافر.
كل تعديل عندنا له clientActionId ثابت. لما نفس الفعل يتعاد بنفس هويته ومحتواه، النظام يرجع النتيجة المسجلة. الرد المجهول بيحافظ على نفس المعرف، وإعادة استخدامه بمحتوى مختلف بتتعامل كتعارض.
الفرق ده مهم: إحنا بنعيد طلب معرفة نتيجة الفعل نفسه، مش بنعلن عن بيع جديد كل مرة. كده إعادة الاتصال والردود المتأخرة والضغط المتكرر ليهم مسار مفهوم. رقم الطلب مش ماكينة فشار يطلع واحد جديد مع كل نقرة.
الجهاز اتسلّم ولسه عليه فلوس: حالة واحدة مش هتكفي
سيناريو توضيحي: موظف مبيعات باع جهاز بعربون، والعميل استلمه، والباقي هيتحصل بعدين. لو خلّينا حالة الطلب تمثل الفلوس والبضاعة مع بعض، كلمة «مكتمل» هتبقى غامضة.
فصلنا تقدم التنفيذ عن تقدم التحصيل. بيع الجهاز بيكمل ويخصم وحداته وقت البيع، بينما سجل الدفعات يوضح المدفوع والمتبقي وأي دفعات لاحقة. الكاشير بيحتاج تسوية كاملة وقت البيع، لكن حساب المبيعات المناسب ممكن يبدأ من غير دفع أو بعربون أو بدفعة جزئية.
الدفعة اللاحقة بتحدث المركز المالي، مش بتبيع الجهاز مرة تانية. وخطة الأقساط بتضيف مواعيد واستحقاقات ومتابعة. أما تسجيل InstaPay وVodafone Cash فبيوثق المرجع والبيانات؛ البرنامج مش بوابة بتحوّل الفلوس بنفسها.
معاملة اختبار مصطنعة من مراجعة سابقة، مش حساب عميل حقيقي.
«انا مش فاهم حاجه» تعليق ميم نشره مستخدم، مش حوار متحقق منه من الفيلم. الصورة من «مرجان أحمد مرجان» — 2007، وفيها مصطفى هريدي، حسب صفحة المصدر على الدهليز. إحنا مستخدمينه هنا على ارتباك تصميم الحالات، مش على العميل أو الموظفين.
الكاش والتحويلات: كله تحصيل، بس مش كله درج
سيناريو توضيحي: جزء من عملية الشراء كاش، وجزء تحويل. لو حطينا الإجمالي كله في المتوقع داخل الدرج، هتطلع فروق جرد سببها إن النظام خلط وسائل الدفع.
الدفع الأولي بيدعم أكتر من tender في نفس العملية، مع الاحتفاظ بطريقة ومبلغ ومرجع كل جزء. حساب الوردية بياخد صافي الحركات النقدية المرتبطة بيها. تحصيل المبيعات له جلسة تحصيل مستقلة، فدفعة حصلها مكتب المبيعات ماينفعش تزود عهدة كاشير تاني.
واستخدمنا حسابات عشرية، لأن كسور الكميات والفلوس محتاجة تمثيل منضبط. التصحيح المالي كمان له سجل مستقل؛ مانمسحش السطر القديم ونكتب جديد مكانه. الدرج في آخر اليوم محتاج تفسير بالأرقام، مش محتاج تفاؤل جماعي حوالين الآلة الحاسبة.
موديل واحد، وحدتين: الرقم المسلسل مش زينة
سيناريو توضيحي: عندنا جهازين من نفس الموديل. الاسم والسعر متطابقين، لكن اللي اتباع واحدة بعينها. ولو حصل رجوع لاحقًا، محتاجين نعرف الوحدة المقصودة.
فرقنا بين المنتج في الكتالوج والوحدة الفعلية. المنتج بيجمع الاسم والسعر وخصائص البيع، والوحدات المسلسلة بتحدد الجهاز اللي دخل واللي اتحدد واللي خرج. منطقة الأجهزة منفصلة عن المنتجات العادية، والنظام بيرفض خلط المسارين في طلب واحد.
ده معناه إن عدد الأجهزة مش مجرد خانة نكتب فيها أي رقم. حركة الوحدات لازم تفضل متفقة مع العدد. ملصق المنتج مفيد للتعرف على الصنف، وهوية الوحدة مفيدة لتتبع الجهاز نفسه. شبه موديل العربية ورقم شاسيه العربية: الاتنين مهمين، بس كل واحد بيجاوب سؤال مختلف.
المرتجع حركة جديدة، مش أستيكة للتاريخ
سيناريو توضيحي: جهاز اتباع وبعدها رجع. أو جزء من طلب مكتمل رجع، والجزء التاني فضل مع العميل. تعديل كمية البيع الأصلية هيضيع الفرق بين اللي حصل وقت البيع واللي حصل بعده.
المرتجع عندنا معاملة مستقلة بتشير للبيع الأصلي وبنوده، وبتحدد الكمية أو الوحدات المسلسلة المناسبة. كمان بتسجل مصير المخزون: يرجع متاح، أو يروح لحالة عزل، أو مايرجعش للمخزون. والأثر المالي له اختيار صريح، زي صرف قيمة أو الاحتفاظ برصيد.
أما تقليل بنود طلب توصيل أو جملة قبل التسليم، فله قواعده الخاصة. لو التغيير خلّى التغليف يحتاج مراجعة، الطلب يرجع للتجهيز المناسب من غير احتساب الناتج المصنع مرتين. التاريخ يفضل مقروء، بدل ما كل تعديل يعمل ريمونتاج للفيلم.
الريال تايم ينقل خبر مؤكد
تنبيهات Socket.IO بتطلع بعد نجاح المعاملة. الشاشة اللي وصلها تنبيه بتعيد تحميل الجزء المناسب من الـAPI. ولما الاتصال يرجع، بتجيب لقطة جديدة، لأن طبيعي تكون فاتتها رسائل وهي مفصولة. ومع وجود الاتصال، فيه كمان إعادة قراءة دورية كل خمس ثواني تقريبًا لمراجعة الحالة، فالشاشات مش معتمدة على وصول كل تنبيه وحده.
ده بيخلي طابور المصنع وشاشة المدير وقائمة الجاهز متفقين على المرجع. مش مطلوب من كل متصفح يجمع رسائل من أول اليوم ويستنتج منها الحالة وحده. الحدث يقول إن فيه تغيير، والقراءة تجيب التفاصيل الحالية.
سيناريو توضيحي: تجهيز خلص، وبعده حد فتح شاشة المدير اللي كانت مفصولة. إعادة القراءة بتجيب الحالة المسجلة، حتى لو تنبيه التجهيز ماوصلش في وقته. الريال تايم مفيد عشان التحديث، لكن خبر «تم» لازم يبقى له أصل في البيانات.
// Illustrative transaction model, not production source.
async function completeSale(command: SaleCommand) {
const result = await database.transaction(async (tx) => {
const previous = await tx.actions.claimOrRead(command.actionId);
if (previous.completed) return previous.result;
const stock = await tx.inventory.lockAndRead(command.items);
assertAvailable(stock, command.items);
const order = await tx.orders.createCompleted(command);
await tx.inventory.recordOut(order);
await tx.documents.enqueue(order);
await tx.actions.complete(command.actionId, order);
return order;
});
// Other workspaces refresh only after the commit succeeds.
notifyCommittedChange(result.id);
return result;
}مثال تعليمي مبسّط، مش كود الإنتاج. claimOrRead بتمثل حجزًا ذريًا لهوية الإجراء، مش مجرد فحص ثم كتابة.
كل كمية وراها حكاية.

التصنيع خلص، لكن البضاعة لسه ماخرجتش
سيناريو توضيحي: طلب جملة خلص تصنيع، وموظف التجهيز بيطابق الموجود مع المطلوب ويجهز الأكياس والملصقات. اختصار ده في تغيير حالة عام هيخفي الشغل اللي لازم يحصل قبل التسليم.
عملنا للتجهيز مسار واضح للمراجعة والوزن والملصقات والتأكيد. الكمية الفعلية لازم تطابق الكمية المتبقية المطلوبة بالضبط؛ الاختلاف بيترفض، والتغليف اللي اتلغى اعتماده محتاج تأكيد جديد. اكتمال التجهيز بيسجل الناتج المصنع كزيادة مخزون، وبيحرك الطلب لـREADY. خروج البضاعة نفسه يحصل بعدين في التسليم لشخص مسمى، ووقتها يتسجل الخصم ويتقفل مسار التنفيذ.
الفصل ده بيخلّي جاهزية الطلب معلومة مختلفة عن انتقاله من عهدة المخزن. ولو الطابعة مش متاحة، تقدم العملية مش بيتوقف عليها؛ المستند يفضل قابل للمعاينة وإعادة الطباعة. الكرتونة ممكن تكون متقفلة ومستنية، وده لسه مختلف عن إنها ركبت العربية.
كتابة ١٢٫٥: العربي مش مجرد اتجاه الصفحة
سيناريو توضيحي: موظف كتب كمية صحيحة بالعربي، لكن حقل الأرقام رفض الحروف قبل ما React تلحق تشوفها. ولو حاول يعدّل من نص القيمة، المؤشر ممكن ينط ويبوّظ التعديل.
استخدمنا حقل نصي مع inputMode="decimal" لعرض لوحة الأرقام المناسبة، ومعاه تحويل من الأرقام العربية والفارسية والفواصل المدعومة للشكل العشري اللي يفهمه النظام. الكمية المكتملة بتتبعت بشكل منضبط؛ القيمة اللي لسه بتتكتب تفضل قابلة للتعديل، وزر الحفظ يستنى اكتمالها.
اشتغلنا كمان على موضع المؤشر وطرق تركيب النص أثناء الكتابة، وحدود الدقة والخطوة المسموحة. لأن واجهة بتقول «الكمية» بالعربي وبعدين تتخانق مع ١٢٫٥ ناقصها جزء مهم من التعريب. اللغة هنا بتدخل الحسابات من الباب، مش واقفة عند اليافطة.
تصحيح المخزون: الرصيد مش سبورة نمسحها ونكتب
سيناريو توضيحي: الرصيد ظاهر عشرة، والموظف فتح نموذج لتصحيحه. قبل الحفظ، حركة صحيحة غيرته. لو حفظنا الرقم الجديد من غير مقارنة، هنعدّي على التغيير اللي حصل في النص.
خلّينا التصحيح أمر منفصل عن إضافة وصرف المخزون. الطلب بيشيل expectedQuantity اللي الموظف شافها وnewQuantity المطلوبة. السيرفر يقارن الرصيد الحالي بالتوقع تحت نفس القفل، ولو اتغير يطلب تحديث القراءة. لو متفقين، يسجل فرق موجب أو سالب كحركة جديدة.
ولو الرقم مااتغيرش، مفيش حركة شكلية تتضاف. الأجهزة المسلسلة خارج التصحيح العددي العام، لأن رصيدها لازم يطابق وحدات موجودة. وفي الإضافة والصرف، الرد بيحمل الرصيد المؤكد balanceQuantity عشان الشاشة تعرض النتيجة من غير ما تتعامل مع حسابها المحلي كأنه الحقيقة النهائية.
نحفظ الشغل. ونحسم اللي لسه معلّق.
Windows / طابور عمل دائم
- تسجيل عميلمحفوظ محليًا
- إنشاء الطلبمنتظر العميل
- دفعة لاحقةمنتظر الطلب
الأوامر محفوظة في SQLite. الطباعة هنا مؤقتة، وإغلاق الشاشة مش بيمسح الشغل.
رسم توضيحي للتنفيذ. أوامر الأوفلاين الدائمة تخص تطبيق Windows؛ المتصفح بيخزن هيكل الواجهة والملفات الثابتة.الأوفلاين: الشغل محفوظ حتى لو الشاشة اتقفلت
سيناريو توضيحي: موظف سجّل عميل جديد وهو أوفلاين، وبعده طلب للعميل، وبعده دفعة مرتبطة بالطلب. إرسال الدفعة الأول هيسأل السيرفر عن طلب لسه ماوصلش.
تطبيق Windows بيحتفظ بأوامر دائمة والعلاقات اللي بينها. منسق في العملية الرئيسية للتطبيق يتابع الإرسال بعيدًا عن شاشة React المفتوحة. إنشاء العميل يسبق الطلب اللي محتاجه، والطلب يسبق الأوامر المعتمدة عليه. ولو فيه مرفق دفع، يتعالج قبل الحركة المعتمدة عليه.
الشغل المرتبط بنفس الكيان بيتحرك بترتيب مفهوم، والتعارض في كيان مايعطلش كل شغل الترمينال. المستند المحلي يبان مؤقت لحد التأكيد المركزي. النسخة العادية في المتصفح بتحتفظ بمسودات وملفات الواجهة؛ قدرة تنفيذ الأوامر الأوفلاين دي تخص تطبيق الموظفين على Windows.
ترمينالين أوفلاين: محدش بيقرأ أفكار التاني
سيناريو توضيحي: جهازين منفصلين عن الشبكة عندهم نسخة قديمة فيها نفس الجهاز المسلسل متاح. كل واحد يقدر يعرف اللي اتسجل عنده، لكن مش اللي اتسجل عند الجهاز التاني.
في بيع الكاشير، التطبيق بيخصم الكميات المعلقة من تصوره المحلي للمخزون. أما الأجهزة، فبيتعامل مع الوحدات والسيريالات المحفوظة محليًا. بعد رجوع الاتصال، السيرفر يفحص الرصيد والوحدة الفعلية من جديد. لو في تعارض، العملية تدخل مسار تسوية واضح، بدل ما شاشة النجاح تسبق الواقع.
وده حد مهم لقدرة الأوفلاين: حفظ الشغل واسترجاعه حاجة، وحجز عالمي بين أجهزة مفصولة حاجة تانية. بنشرح الفرق لأن الموظف محتاج قرار مفهوم لما الاتصال يرجع. الاستقرار مش إن البرنامج يوعد بكل حاجة؛ الاستقرار إن حالة الانتظار والتعارض والتأكيد يبقوا مفهومين ويحتفظوا بالشغل.
موافقة السيرفر وصلت، بس نسخة المخزون لسه قديمة
سيناريو توضيحي: أمر بيع كاشير POS أوفلاين اتقبل، لكن الترمينال لسه معاه لقطة مخزون أقدم من البيع. لو شلنا الخصم المحلي فورًا، القطعة ممكن تظهر متاحة تاني لحد التحديث.
ربطنا حساب كميات بيع الكاشير برقم مراجعة للمخزون. الأمر المقبول يعرف المراجعة اللي اتسجل فيها، واللقطة تعرف المراجعة اللي بتمثلها. التطبيق يفضل حاسب أثر البيع لحد ما توصل لقطة متماسكة تشمل التغيير. الأجهزة ليها بيانات وحدات محفوظة، مش نفس حلقة حساب كميات POS.
كده ترتيب الحقيقة بيتحدد من نسخة بيانات معروفة، مش من مقارنة ساعات أجهزة ممكن تختلف. تفصيلة صغيرة في الكود، لكن معناها على الشاشة مباشر: الوحدة المتباعة ماترجعش للرف حسابيًا في الفترة اللي بين التأكيد والتحديث. المخزون مش محتاج فلاش باك بعد كل مزامنة.
طابور قديم يقابل إصدار جديد
سيناريو توضيحي له أصل موثق في إصلاح التنفيذ: أمر مخزن محفوظ من نسخة سابقة بيستخدم اسم حقل direction، بينما منفذ الأمر بيتوقع movementType. تحديث الشاشة لوحده مش هيعيد كتابة النوايا اللي اتحفظت عند الموظف.
إصلاحات Windows 0.1.5 شملت توافق حركات المخزن القديمة والجديدة، وإصلاح إعادة إرسال أقساط المبيعات. الفكرة إن التوافق يشمل الأوامر الموجودة فعلًا، مش بس الطلبات اللي هتتولد بعد التحديث.
وثقنا الإصلاحات باعتبارها تغييرات محلية وأدلة تقرير بناء، من غير نسبتها لكوميت أقدم منها. ودي نقطة هندسية مهمة: الـAPI عقد ممتد مع بيانات عند أجهزة، مش مجرد function الطرفين بيغيروها سوا. لازم نفهم النسخة القديمة قبل ما نطلب منها تتكلم باللهجة الجديدة.
التجربة مش بتنتهي عند الشاشة.

كل صفحة ليها قاعدة
31 بند = 15 + 15 + 1. الحد الأقصى 15 بند في الصفحة، وعنوان الفاتورة بيتكرر.
نموذج توضيحي، مش فاتورة حقيقية. تفاصيل الأجهزة لها ملحق منفصل: 8 وحدات في الصفحة.فاتورة 31 بند: الصفحة التالتة ليها حق الظهور
سيناريو توضيحي: فاتورة A4 شكلها ممتاز بست بنود، وبعد ما بقوا 31 بند، الصفوف اتقسمت والعنوان اختفى والإجمالي راح في مكان غريب. المعاينة القصيرة مااختبرتش المشكلة أصلًا.
قسمنا بنود فواتير المبيعات والأجهزة بحد أقصى 15 بند مختلف للصفحة. مثال 31 بند يطلع 15 ثم 15 ثم بند واحد. هوية الفاتورة تتكرر في صفحات الاستكمال، والإجمالي والتوقيعات يطلعوا مرة في النهاية. تفاصيل الوحدات المسلسلة ليها ملحق مستقل، بثماني وحدات للصفحة.
وفيه حدود للطلب نفسه: المسارات الأكبر بتقبل لحد 100 بند، وPOS لحد 20. استمرار الصفحات مش معناه إدخال بلا حدود. كده شكل المستند ناتج عن قاعدة، مش عن مزاج المتصفح وهو بيقلب الورق.
الصورة قديمة وبتوضح التصميم؛ لوحدها ماتثبتش مقاس الورق الفعلي أو اختبار صفحات 15 و16 و31 بند.
واجهة تشوف منها الشغل، مش تدور فيها عليه
الكتالوج الحالي فيه شريط للفئات ومسار الاختيار، وشبكة مستقلة للمنتجات بحد أقصى 16 كارت في الصفحة. البحث العام بيعدّي حدود الفئة، والباركود يختصر طريق الاختيار. كده الكتالوج يقدر يكون كبير من غير ما كل أصنافه تتحول لعناصر مرسومة في نفس اللحظة.
المخزن بيجمع البحث والنتائج والرصيد ونموذج الحركة. والمدير له عرض تاتش بكروت أوضح، وعرض كمبيوتر أكثف لنفس البيانات. العربي هو الأساس، والإنجليزي موجود بنفس منطق العمل.
واهتمينا بالحالات اللي مش بتدخل عادة في صورة البورتفوليو اللامعة: طابور فاضي، بحث من غير نتيجة، قيمة غلط، وحركة مستنية الرد. الموظف لازم يفهم الخطوة الجاية حتى لما مفيش نجاح يحتفل بيه البرنامج.
الطباعة واجهة تانية، بس بتطلع من الطابعة
الإيصال الحراري 80 مم له وظيفة مختلفة عن فاتورة A4، وعن ملصق 55 × 40 مم، وعن بوليصة 100 × 150 مم. توزيع المعلومات ومقاس الخط والباركود والمساحة المتاحة بيتحددوا حسب استخدام المستند.
فصلنا شكل الشاشات عن هندسة الطباعة، عشان تحسين مسافات الواجهة مايغيّرش مقاس الملصق. المعاينة وإعادة الطباعة موجودين، وتطور الدعم شمل محولات الطباعة ومكونات التشغيل المحلي. لكن إرسال مهمة لنظام التشغيل لسه مختلف عن إثبات إن الورقة طلعت فعلًا.
اختبار الطابعة والماسح والخامة وضبط المقاس خطوة مستقلة. صورة الإيصال بتوضح تصميمه، مش نتيجة اختبار ورق. ولو فاتورة شكلها حلو على الشاشة، ده سبب نكمل فحصها؛ مش تصريح إننا خلصنا كل حاجة.
الكوميتات بتحكي تطور القرارات
سجل المشروع بيوضح انتقالات فعلية: تحسين تجربة POS في 2fd5c2f يوم 26 أغسطس 2026، وفصل البيع المباشر عن التصنيع في c98173e يوم 29 أغسطس، وإضافة الأجهزة وتقسيم الفواتير في d31f149 يوم 30 أغسطس.
وفي نفس اليوم، 1868850 وسّع التعامل مع الأجهزة الفعلية ومراجعة التجهيز. يوم 9 سبتمبر، 918ab9a وسّع التشغيل الأوفلاين ودورة حياة الطلب. وبعده cb42e3f يوم 26 سبتمبر، ثم 620511a يوم 29 سبتمبر كآخر أساس محفوظ في Git وقت المراجعة، مع إصلاحات محلية لاحقة.
ده دليل على تطور المنتج، مش كشف ساعات ولا إثبات لحجم الفريق. مانستنتجش من عدد الكوميتات عدد أيام الشغل، ومانقولش إن تاريخ كتابة الكود هو بالضرورة تاريخ وصوله لكل ترمينال.
النتيجة باينة في التفاصيل.
دي حقائق عن نطاق المنتج، مش نسب تحسّن تجارية. نتائج اختبارات التطبيق المذكورة تحت مرتبطة بتقارير سبتمبر.
الاختبارات: نجرّب اليوم اللي كل حاجة فيه مش ماشية
الاختبار المفيد عندنا بيسأل عن النتيجة التجارية: هل البيع الناقص رجع كله؟ هل المحاولة المكررة زودت حركة؟ هل المرتجع حافظ على البيع؟ هل صفحة الفاتورة التالتة ظهرت؟ وهل المبلغ المتبقي اتغير من غير خصم مخزون جديد؟
اختبارات المجال والتكامل بتراجع ده مع قاعدة بيانات حقيقية. اختبارات المكونات بتراجع الإدخال والحالات، وPlaywright بيكمل الرحلة في المتصفح. المراجعة البصرية كمان بتشوف النص الطويل والتاتش والعرض الضيق، لأن نجاح TypeScript مش شهادة إن الزرار ظاهر.
الإصلاح الأخير للمخزن شمل تداخل أزرار الهيدر على الموبايل بعد ما ظهر في المراجعة. اتصلح واتراجع بتصوير وفحص أبعاد. الحالات الصعبة هنا مش شتيمة للكود؛ دي طريقة نعطيه فرصة يغلط عندنا قبل التشغيل.
«كابتن.. هو كله ضرب ضرب مفيش شتيمه» — النص المنشور مع ميم من «الناظر» — 2000، حسب الدهليز. الإفيه هنا عن كثافة سيناريوهات الاختبار؛ بقية التشبيهات في الدراسة كتابة أصلية.
أرقام الاختبارات بتاريخها، مش طبق مشكّل
تقرير Windows يوم 29 سبتمبر سجل 153 اختبار Backend، و514 Frontend، و208 اختبارات Vitest للتطبيق المكتبي، ومعاهم 32 فحص لسياسات بناء حزمة تطبيق ويندوز. تسليم المخزن يوم 30 سبتمبر سجل 517 Frontend و153 Backend، مع مراجعات متصفح مركزة على الموبايل والتابلت والكمبيوتر.
دي نقط مراجعة مختلفة؛ مانجمعهاش ونطلع منها رقم عملاق كأنه تشغيل واحد. ومراجعة المستندات يوم 18 أكتوبر 2026 ما شغّلتش التطبيق ولا أعادت تصويره. استخدمنا الكود والاختبارات والتقارير والصور الموجودة، وكل نوع دليل له حدود واضحة.
كمان مفيش قياس مقدم لزيادة الإيراد أو نسبة تقليل الأخطاء أو سرعة الكاشير. عندنا قدرات وتنفيذ وأدلة اختبار؛ أرقام العائد التجاري محتاجة قياس مستقل. الرسم البياني بيبقى أحلى لما الأرقام اللي فيه حصلت فعلًا.
البناء نجح: كويس، وفاضل نعرف نجح في إيه
آخر تحسينات المخزن ليها تحقق محلي مسجل، لكن تقرير النشر الأقدم مايثبتش نشرها. وملف Windows 0.1.5 ليه أدلة بناء وتعبئة وتحميل، بينما تجربة النسخة المجمعة نفسها وقبول الهاردوير لسه موصوفين كخطوات معلقة في التسليم.
التمييز ده بيخلّي كلمة «جاهز» مفيدة: جاهز من ناحية الكود؟ البناء؟ النشر؟ التشغيل على الجهاز الفعلي؟ كل واحدة ليها اختبارها. ماينفعش لقطة شاشة تعمل شغل الأربع شهادات في نفس الوقت.
«ده أنت متفائل أوي!» — عفاف لشحاتة في «غريب.. في بيتي» — 1982، حسب مرجع الاقتباس. الاقتباس مرجع ثقافي منفصل عن الرسومات الأصلية للدراسة.
الصور جزء من الحكاية، وليها بطاقة تعريف
الباكدج فيه 21 لقطة محفوظة من أغسطس وسبتمبر 2026، مع وصف الحالة والمقاس والسياق. فيه صور من التصميم الأحدث للمخزن وصور أقدم للأدوار والطباعة. اللقطة الفاضية موصوفة كحالة فاضية، والخطأ المقصود كحالة اختبار، عشان الصورة ماتبيعش معنى غير اللي فيها.
كل صور المنتج المختارة عربية وبالوضع الفاتح. الشريط الكحلي جزء من التصميم الفاتح، ومش دليل على وضع داكن. القاهرة هنا سياق الفرع التجريبي والتوقيت التشغيلي، مش عنوان مؤكد للعميل ولا مكان تصوير موثق.
التفاصيل في معرض الصور، والإشارات الثقافية موثّقة بروابط مصادرها؛ الصور السينمائية مش معروضة هنا. تغيير نبرة الدراسة أو لون صفحة نشرها مايغيّرش حقيقة لقطات المنتج اللي جواها.
اللي اتبنى، واللي يهم فريق تشغيل فعلي
النتيجة نظام يقدر يعبّر بوضوح عن جهاز اتسلّم وعليه باقي، وبضاعة اتجهزت ولسه ماخرجتش، ووحدة رجعت بمصير مخزون محدد، وأمر أوفلاين مستني نتيجة مؤكدة. كل حالة ليها معنى وبيانات وإجراء مناسب.
بالنسبالنا في Softworks، جودة البرنامج بتبان في الوصلات دي: بين السلة والمخزن، وبين الدفعة والوردية، وبين تجهيز الطلب وتسليمه، وبين شاشة بتستنى ورد فعلي وصل. الإفيه يخفف الشرح، لكن القاعدة اللي وراه لازم تفضل دقيقة.
لو فريقك بيجمع البيع والتصنيع والمخازن والتحصيل، البداية المفيدة هي سير العمل الحقيقي والورق اللي بيعتمد عليه والاستثناءات اللي بتعطله. من هنا بنبني برنامج يخدم التشغيل، ونعرف نختبره ونشرح اللي أنجزناه فيه بأدلة.
فريق هندسة البرمجيات في Softworks
من جوه المنتج
الشغل الحقيقي. شاشة بشاشة.
21 لقطة محفوظة من أغسطس وسبتمبر 2026: أدوار التشغيل، المخزن، التحصيل والطباعة. كل الصور عربية وبالمظهر الفاتح؛ الأوصاف بتوضح حالة الاختبار وتاريخ التصميم.
صور المنتج الأصلية، ببيانات عرض واختبار.
21 شاشة
Webنظرة المدير من الكمبيوتر
نظرة المدير على الكمبيوتر بتجمع مراحل الطلبات وتنبيهات المخزون وآخر النشاط في شاشة واحدة للفرع التجريبي.
Webشاشة الكاشير بتفصل الكتالوج عن ملخص الطلب
شاشة الكاشير بتفصل الكتالوج عن ملخص الطلب، وبتوضح منطقة المنتجات ومنطقة الأجهزة. ظاهر تنبيه فحص الوردية؛ دي لقطة مساحة العمل مش إثبات بيع مكتمل.
Webاختيار الصنف ورصيده
اختيار الصنف ورصيده الحالي، ومعاه الرصيد المتوقع بعد إضافة المخزون. لقطة من مراجعة محلية للتصميم.
Webشاشة المبيعات
مساحة المبيعات بتجمع نوع الطلب واختيار المنتجات أو الأجهزة والبحث في الكتالوج، ومعاها عهدة التحصيل.
Webلقطة اختبار كاملة لطلب جهاز بعد تحصيل الأقساط
لقطة اختبار كاملة لطلب جهاز بعد تحصيل الأقساط، والمبلغ المتبقي صفر والدفعات المسجلة ظاهرة.
Webعرض المدير على التابلت بيستخدم كروت كبيرة لنفس مراحل التشغيل والطلبات الأخيرة
عرض المدير على التابلت بيستخدم كروت كبيرة لنفس مراحل التشغيل والطلبات الأخيرة. الصورة للصفحة كاملة.



