هل زر «تحويل عرض السعر لأمر بيع» (وأخواته) مربوط بصلاحية إنشاء المستند الهدف؟ — فحص Opus لكل زر (FE) وكل endpoint (BE). تحليل فقط، بدون كود.
المالك عايز يمنع مستخدم (حازم) من تحويل عرض السعر لأمر بيع عن طريق سحب صلاحية «إنشاء أمر بيع». لكن زر «التحويل» (السهم الأزرق) بيفضل ظاهر رغم سحب الصلاحية. السؤال: هل الزر مربوط بصلاحية؟ وهل فيه صلاحية «إنشاء أمر بيع» أصلًا؟ ونفس الشيء لباقي أزرار التحويل/الإنشاء.
sales.orders.create بالظبط (SalesOrderController.php:33). فلو المستخدم مالوش الصلاحية → الـAPI بيرجّع 403. الثغرة الوحيدة: زر الفرونت مش بيختفي (مفيش *appCan)، فبيدوسه ويجيله رسالة خطأ بدل ما الزر يكون مخفي.| العملية | الـendpoint / الميثود | الصلاحية المفروضة |
|---|---|---|
| عرض سعر → أمر بيع | SalesOrderController::convertFromQuotation :33 | sales.orders.create ✓ |
| أمر بيع → فاتورة | SalesInvoiceController::createFromOrder :41 | sales.invoices.create ✓ |
| أمر بيع → إذن تسليم | SalesDeliveryNoteController::createFromOrder :28 | sales.delivery_notes.create ✓ |
| أمر شراء → إذن استلام (GRN) | PurchaseGrnController::store :46 | purchases.grns.create ✓ |
| أمر شراء → فاتورة شراء | PurchaseBillController::createFromOrder :43 | purchases.bills.create ✓ |
| GRN → فاتورة شراء | PurchaseBillController::createFromGrn :43 | purchases.bills.create ✓ |
| طلب شراء → أمر شراء | PurchaseOrderController::convertFromRequest :57 | purchases.requests.convert (صلاحية تحويل مخصّصة — مش orders.create) |
| الزر | المكان | مربوط بـ*appCan؟ |
|---|---|---|
| عرض سعر → أمر بيع (السهم الأزرق) — حالتك | quotations.component.html:141 | ❌ مكشوف (المفروض sales.orders.create) |
| أمر بيع → إذن تسليم | sales/orders…html:138 | ❌ مكشوف |
| أمر بيع → فاتورة | sales/orders…html:148 | ❌ مكشوف |
| أمر شراء → GRN | purchases/orders…html:145 | ❌ مكشوف |
| أمر شراء → فاتورة | purchases/orders…html:158 | ❌ مكشوف |
| GRN → فاتورة | grns.component.html:82 | ❌ مكشوف |
| طلب شراء → أمر شراء | requests…html:103 | ✓ مربوط (purchases.requests.convert) |
sales.orders.create من حازم:
*appCan="'<target>.create'" على ٦ أزرار:
quotations.html:141 → sales.orders.create ·
sales/orders.html:138 → sales.delivery_notes.create ·
sales/orders.html:148 → sales.invoices.create ·
purchases/orders.html:145 → purchases.grns.create ·
purchases/orders.html:158 → purchases.bills.create ·
grns.html:82 → purchases.bills.create.ملاحظة: الأزرار markup لكل شاشة (مفيش مكوّن تحويل مشترك)، فالإصلاح per-button — بس الآلية المشتركة هي توجيه *appCan نفسه.
purchases.requests.convert (مش orders.create) — متّسق فرونت+باك. قرار المالك: نسيبها كده ولا نربطها بـorders.create كمان؟SalesOrderService.createDelivery بيبعت لـcreate-delivery بينما الراوت create-delivery-note — تباين اسم يستاهل فحص منفصل. (ب) PurchaseOrderService.createGrn بيبعت لـendpoint مالوش راوت (كود ميت؛ الإنشاء الفعلي عبر POST /purchases/grns).*appCan="'<target>.create'" على كل زر (فرونت فقط). صغير ومباشر، بناء أخضر، اختبار يدوي بدور بدون sales.orders.create.purchases.orders.create بدل/إضافةً لـpurchases.requests.convert.create-delivery + الكود الميت createGrn — إصلاحات نظافة منفصلة.| القرار | الخيارات | التوصية |
|---|---|---|
| نطاق الإصلاح | (أ) الـ٦ أزرار [موصى] · (ب) بس تحويل-لأمر (حالتك) | (أ) — نفس الفجوة في الستة، نقفلها كلها مرة واحدة. |
| تحويل طلب الشراء | (أ) سيبها requests.convert · (ب) اربطها بـorders.create كمان | (أ) — متّسقة أصلًا؛ (ب) لو عايز نفس صلاحية إنشاء الأمر تتحكّم. |
مثال — صف عرض سعر «مقبول» لمستخدم مالوش sales.orders.create:
التطبيق: *appCan="'sales.orders.create'" على زر التحويل. لمّا تسحب الصلاحية من دور حازم → الزر يختفي (والباك أصلًا بيرفض). نفس النمط للـ٦ أزرار.
تحليل قراءة-فقط · فحص Opus لـ BE+FE بمراجع دقيقة · لم يُعدَّل أي كود. بانتظار موافقة المالك قبل أي تنفيذ.