# Restaurant Stock AI Agent · مخزون المطاعم

`02 · ai-warehouse · MVP`

AI agent لمخزون المطاعم مع two-tier Gemini routing وحد أمان draft→Confirm. الفواتير والتحضيرات والخصومات تبدأ في Telegram؛ WebApp يبقي review وWAC وتأثير dashboard مرئيا.

**النطاق:** Solo · أسبوع واحد  
**الدور:** عمليات مخزون مطاعم بمساعدة AI

**الفيديو:** [YouTube](https://www.youtube.com/watch?v=ReGjrrrQp-w) · [RuTube](https://rutube.ru/video/private/e4fd4d89ce76fa41e2b7545878a85b54/?p=MhviOksLqwnoBjqLD8830A)

## شرح الفيديو

عمليات مخزون مطعم مقسمة بين Telegram (إدخال فوضوي — صور فواتير، دفعات تحضير، خصومات بالنص أو ورقة طلب المطبخ) وWebApp يبقي كل مسودة قابلة للمراجعة قبل أن يتحرك المخزون. الـ agent يقرأ الفواتير، يفكك الأطباق إلى مكونات، يحدّث متوسط التكلفة المرجّح عند التأكيد، ويجيب على أي سؤال حر عن المستودع مع توصيات للطلب التالي.

عمليات مخزون للمطاعم بالذكاء الاصطناعي: الفواتير، التحضير، والهدر تبدأ من تيليجرام، والـ WebApp يخلي كل رقم واضح وقابل للمراجعة.

لوحة التحكم تعرض اليوم، الأسبوع والشهر: الإيرادات، تكلفة الطعام، المشتريات، المسحوبات، وقيمة المخزون، مع رسوم مختصرة ليوم العمل.

المخزون يبرز الأشياء اللي تحتاج انتباه. فيه صنفين مجمدين خلصوا، فيعيد الفريق التوريد ويرسل فاتورة المتجر للبوت.

الـ AI يقرأ الصورة، يطابق الأكل، المشروبات ومستلزمات التشغيل مع تصنيفات المخزون، ويجهز مسودة. راجعها في الـ WebApp، ثم أكدها، فيتحدث المخزون ومتوسط التكلفة المرجّح فوراً.

دفعات التحضير تنحسب أيضاً. لما المطبخ يجهز عجينة بيتزا، صلصة طماطم، برجر باتيز أو دجاج متبل، يقدر الفريق يخبر الـ Agent وش تم تحضيره، أو يضيف الدفعة يدوياً من الـ WebApp. المكونات تطلع من المخزون، والصنف المحضّر يدخل، والتكاليف تبقى مرتبطة من البداية للنهاية.

للمبيعات أو الهدر، أرسل ورقة طلب المطبخ، أو اكتب الوصف بالنص. الـ AI يتعرف على الأطباق، يفككها إلى مكونات، ويجهز المسحوب من المخزون. أكدها، والداشبورد يتحرك من جديد.

وبعدين اسأل الـ Agent أي شيء عن المستودع، مثلاً: كيف كان أداء الشهر؟ يحلل التوريدات السابقة، المسحوبات، الإيرادات، تكلفة الطعام، حركة المخزون، والأصناف الناقصة، ثم يعطي توصيات للطلب الجاي.

تيليجرام يمسك المدخلات الفوضوية. والـ WebApp يمسك المراجعة. والداشبورد يعرض التأثير على الأعمال.

---

## السياق

> النموذج يكتب المسودة. الإنسان يؤكد. والـ dashboard يعرض الأثر.

مخزون المطعم ينحرف عن السجلات أسرع مما يملك المطبخ وقتا لتسجيله. الفواتير تأتي على ورق أو صوت؛ supplies وdish deductions وpre-prepared bases لكل منها حساب مختلف؛ weighted-average cost يبقى صحيحا فقط إذا دخلت كل عملية في الدفاتر وقتها. كلفة إهمال بعض القيود لا تظهر إلا عند اهتزاز المخزون — وحينها يكون الأثر ضاع.

الـ MVP يغلق الحلقة حول هذا bottleneck: Telegram يلتقط عمليات المخزون الفوضوية، WebApp يجعل كل draft قابلا للمراجعة، وdashboard يحول confirmations إلى revenue وgross profit وfood cost وstock value وlow-stock risk وnext-order recommendations.

## حقائق

| | |
|---|---|
| **النطاق** | أسبوع واحد solo |
| **الأسطح** | Telegram bot (Aiogram) + WebApp SPA (React 18) + browser fallback |
| **الدومين** | 100 inventory · 40 menu · 12 prep recipes · 18 tables · تاريخ 30 يوما deterministic |
| **AI** | Gemini 3 Flash workflows · تحليل تشغيلي Pro-style · تتبع $ لكل call |
| **Business** | Revenue · gross profit · food cost · stock value · low-stock risk · next-order list |
| **الحالة** | MVP · Telegram bot + WebApp · multimodal intake live · stock/WAC/dashboard end-to-end |

## المعمارية

### حلقة المشغل · dashboard → Telegram → review → impact

```text
 1  WebApp Dashboard
        │  Today / Week / Month
        │  stock value · revenue · gross profit · purchases
        │  deductions · preparations · movement charts
        ▼
 2  Stock view
        │  category groups · qty · stock value · unit cost
        │  Frozen flags: Green Peas Frozen + Potato Wedges Frozen = out
        ▼
 3  Telegram: Supply photo
        │  📷 Receipt received
        │  👁 Vision pass: reading receipt lines and totals
        │  🧠 Matching products to stock categories
        │  📦 Calculating quantities and weighted costs
        │  ✅ Draft supply ready for review
        ▼
 4  Draft supply result
        │  19 stock items matched · 15 650.24 RSD
        │  actions: Review · Confirm · Cancel
        ▼
 5  WebApp review + Confirm
        │  food · beverages · operating supplies
        │  confirm commits stock_levels + WAC + stock_history
        ▼
 6  Preparations
        │  pizza dough batch: ingredients out, prepared item in
        │  preparation cost cascades through WAC
        ▼
 7  Telegram: Deduction photo
        │  📷 Kitchen slip received
        │  👁 Vision pass: reading dishes and quantities
        │  🧠 Matching dishes to menu recipes
        │  🥘 Expanding dishes into ingredient deductions
        │  ✅ Draft deduction ready for review
        ▼
 8  Draft deduction result
        │  Chicken Shawarma ×3 · Shawarma Plate ×2
        │  confirm writes off ingredients at current WAC
        ▼
 9  Agent monthly analysis
        │  last 30 days · revenue · food cost · supplies
        │  preparations · top deductions · out-of-stock · next order
        ▼
10  Dashboard impact
        │  Telegram handles messy input
        │  WebApp handles review / confirm
        │  Dashboard shows the business effect
```

**Progress جزء من المنتج.** كل AI action يعدل رسالة Telegram واحدة عبر مراحل مرئية: received، vision pass، matching، cost calculation أو recipe expansion، ثم draft ready. المشغل يرى النموذج يعمل بدلا من spinner صامت.

**AI يكتب، Confirm يثبت.** Supply وdeduction وpreparation workflows تعيد drafts structured. Backend يخزنها status=draft؛ stock وWAC وhistory وdashboard totals تتحرك فقط بعد ضغط Confirm.

**Review بين Telegram وWebApp.** نتيجة Telegram تحمل Review وConfirm وCancel. Review يفتح WebApp لفحص الأسطر؛ Confirm يثبت نفس draft عبر backend confirm endpoint.

### Multimodal intake → draft → confirm

```text
 1  User                          text  /  photo  /  voice
        │
 2  Bot  (Aiogram)
        │  base64 encode photo/voice  +  selected workflow
        │  POST /api/agent/message              [X-Telegram-User-Id]
        ▼
 3  Backend.router  (route_message)
        │  dispatch by workflow:
        │     supply | deduction | preparation  →  Flash workflow
        │     agent analysis                    →  monthly operating analysis
        ▼
 4  Flash workflow  (gemini-3-flash, ≤5 iterations)
        │  inject inventory snapshot into system_prompt
        │  call client.generate_content(tools=[...])
        ▼
 5  Gemini  ──►  text  /  function_call
                │
                ▼
              tool_create_supply_draft  (or _deduction_, _preparation_)
                │  parse args, normalize price_type
                ▼
              insert row in supplies / deductions / preparations
              with status = 'draft'
        │
 6  Backend  ──►  AgentMessageResponse(text, actions=[
        │           AgentAction(type=callback, label='Confirm',
        │                       data='confirm_supply:<uuid>'),
        │           AgentAction(type=callback, label='Delete',  ...),
        │         ])
        ▼
 7  Bot  ──►  inline keyboard rendered from actions
        │
 8  User taps Confirm
        │  POST /api/supplies/{id}/confirm
        ▼
 9  Backend
        │  recompute stock_levels  +  WAC
        │  insert stock_history row
        │  snapshot cost_per_unit on lines
        ▼
10  Done  ·  status = 'confirmed'  ·  audit_log written
```

**Two-phase by design.** AI workflow ينشئ draft بلا side effects. Confirm POST منفصل يحدث stock_levels ويكتب stock_history. AI لا يلمس live stock؛ الزر البشري يفعل.

**Backend يملك معنى action.** البوت adapter رقيق لـ Telegram: يرفع media، يعرض progress، يرسم actions القادمة من backend ويمرر callbacks. business meaning يبقى في backend.

**Lanes واضحة للـ MVP.** المشغل يختار Supply أو Deduction أو Preparation أو Agent قبل إرسال الإدخال الفوضوي. هذا يحذف intent classification الخاطئ من مسار المخزون الحرج.

### تخطيط المكونات

```text
   Inputs              docker-compose  (4 services)              External
   ──────              ─────────────────────────────              ────────
   Telegram chat ────► bot  (Aiogram 3.4)                        Gemini API
                            │  POST /api/agent/message            google-genai
                            │  X-Telegram-User-Id                      ▲
                            ▼                                          │
   Telegram WebApp     ┌──────────────────────────────────┐            │
   ─initData──────────►│  backend  (FastAPI · async)      │────────────┘
   browser  ─JWT──────►│  9 routers · 18 tables · 9 mods  │
                       │  GeminiClient + token_usage      │
                       └────┬───────────┬─────────────────┘
                            │           │
                            ▼           ▼
                      postgres 16    receipts_data
                      (asyncpg WAL)  shared volume:
                                     bot writes · backend reads

                            ▲ HTTP /api/*
                            │
                       frontend  (Vite · React 18 SPA · :5173)
                       react-i18next 5 langs × 10 ns
                       @tanstack/react-query
```

**Bot هو HTTP فقط.** البوت يفتح long-poll مع Telegram ويرسل كل event إلى backend. لا DB access مباشر من bot — يبقى stateless عبر restarts.

**الصور عبر FS لا API.** Bot يكتب الصور في receipts_data volume؛ backend يقرأ من نفس path. هذا يتجنب إعادة رفع ملفات كبيرة بين الحاويات.

**Frontend dual-mode.** نفس Vite SPA يعمل داخل Telegram WebApp (initData header) وكتطبيق browser عادي (deep-link JWT). bundle واحد ومسارا auth.

### نواة الدومين · 18 tables في 9 modules

```text
INVENTORY                            SUPPLIES
─────────                            ────────
inventory_items                      suppliers
  · status: active|archived          supplies  (status: draft|confirmed)
       │                               └── supply_lines
       ▼                                     · qty · price_per_unit
  stock_levels                              · expiry_date
    · qty · avg_cost  ◄────── WAC update on confirm
       │
       ▼
  stock_history  (audit log of every movement)


PREPARATIONS                         DEDUCTIONS
────────────                         ──────────
prep_recipes                         deductions  (status: draft|confirmed)
  · default_multiplier                 └── deduction_items
  · portion_size · portion_unit              · type: dish | item
  └── prep_recipe_ingredients               └── deduction_lines
                                                  · cost_per_unit
preparations                                       (snapshot at confirm)
  · multiplier  (e.g. 3× base broth)
  · cost = sum(ingredient × avg_cost) / output_qty   ← cascade WAC


MENU                                 AI · CHAT
────                                 ─────────
menu_items  (with archived flag)     chat_sessions
  └── menu_item_ingredients          chat_messages  (last 40 in context)
                                     user_settings
                                     token_usage
                                       · workflow_type · model
                                       · input/output/thinking_tokens
                                       · cost_usd


AUDIT
─────
audit_logs  ·  receipt_images  (shared FS path with bot)
```

**WAC في stock_levels.avg_cost.** كل supply confirm يعيد حساب المتوسط المرجح. Preparation يحسب كلفة output من avg_cost للمكونات ثم يدمجها في stock_level الناتج بالمعادلة نفسها.

**Cost snapshot عند deduction confirm.** عند confirm deduction، deduction_lines.cost_per_unit = stock.avg_cost في تلك اللحظة. supplies لاحقة بأسعار مختلفة لا تعيد كتابة التاريخ.

**Dual-mode deductions.** deduction_items.type = dish لتوسيع recipe أو item كسطر stock مباشر. deduction واحد يمكن أن يخلط الاثنين.

## قرارات هندسية رئيسية

### 01 · Gemini-3 على مستويين مع workflow lanes صريحة

**القرار.** مستويان من Gemini-3 يعالجان شكلين مختلفين من العمل: Flash الرخيص لتوليد drafts ضيقة، وتحليل Pro-style لأسئلة تشغيلية أوسع فوق تاريخ 30 يوما وmetrics وnext-order list. lane صريحة في MVP عبر أزرار Supply/Deduction/Preparation/Agent، مع حفظ usage/cost لكل call.

**لماذا.** Pro لكل شيء يكلف تقريبا 4× لكل token ويحمل history overhead على كل receipt-photo dispatch. Flash يناسب tool loops الضيقة لكنه لا يكفي لتحليل تشغيلي واسع. الفصل حسب job shape يطابق envelope التكلفة/القيمة.

**الكلفة.** عائلتا prompts للصيانة، وبعض tool declarations مكررة. اختيار lane يكلف زر إضافي في bot؛ auto-router يمكن أن يأتي لاحقا فوق telemetry نفسها.

### 02 · Draft → Confirm على كل عملية تغير الحالة

**القرار.** Supplies وdeductions وpreparations تعمل على مرحلتين: POST أول ينشئ row status=draft بلا side effects، وPOST confirm يقفل stock_levels، يعيد WAC، يكتب stock_history، ويحول status إلى confirmed.

**لماذا.** Agent يغير inventory مباشرة يعني transcription واحد خاطئ يفسد أسابيع من بيانات المخزون. two-phase يجعل كل اقتراح قابل للحذف والفحص والتعديل قبل commit.

**الكلفة.** كل سطح mutating له endpointان. stock totals تتجاهل draft rows. UX يجب أن يوضح أن supply الجديدة ليست live بعد. concurrent confirms تحتاج locks.

### 03 · Review actions من السيرفر، لا business logic في البوت

**القرار.** Backend يصدر AgentAction داخل AgentMessageResponse؛ كل action يحمل type وlabel وdata. Telegram يرسم Review/Confirm/Cancel، وbackend يملك معنى confirm_supply:<uuid>.

**لماذا.** لو امتلك البوت business actions يصبح UI codebase موازيا. إبقاؤه transport adapter يجعل stock flows الجديدة تشحن من backend فقط.

**الكلفة.** Backend يعرف حدود Telegram مثل callback_data ≤64 bytes. الأزرار dispatch فقط؛ editing line quantities يسقط إلى WebApp.

### 04 · Weighted Average Cost مع cascade عبر preparations

**القرار.** كل supply confirm يشغل WAC، preparations تطبق WAC مرتين، وdeduction lines تحفظ cost_per_unit عند confirm فلا يعاد كتابة الماضي.

**لماذا.** FIFO/LIFO يحتاج lot-level tracking لا يطابق مطبخا يستخدم أكياسا مختلطة. WAC يطابق طريقة التفكير في التكلفة، وsnapshots تحمي التقارير التاريخية.

**الكلفة.** WAC يخفي batch variance. preparation يحول deduction إلى سلسلة حسابات؛ debug كلفة خاطئة يعني تتبع السلسلة يدويا.

## التقنيات

| | |
|---|---|
| **Backend** | Python · FastAPI · SQLAlchemy 2.0 Mapped (async) · asyncpg · Alembic · Pydantic v2 |
| **Frontend** | React 18 · Vite · TypeScript · Tailwind · @tanstack/react-query · react-i18next |
| **Bot** | Aiogram 3.4 (long polling) · httpx |
| **AI** | google-genai 1.61 · Gemini 3 Flash + Pro · multimodal (text/photo/voice) · cost matrix |
| **Infra** | PostgreSQL 16 · Docker Compose (4 services · volume مشترك للفواتير) |
| **Scale** | 9 backend modules · 18 tables · 13 pages · 5 لغات × 10 i18n namespaces · 6 currencies · ~50 routes |

## الدروس والحالة

### ما سأحمله للأمام

- تتبع cost لكل call من usage_metadata مع workflow_type — Settings تقسم الإنفاق حسب model وworkflow واليوم. بناؤه قبل أول تشغيل أرخص من إضافته بعد أول فاتورة.
- Draft → Confirm مع cost snapshot — كل output من AI يغير الحالة يبقى reviewable قبل commit. حد الأمان في شكل workflow، لا في دقة النموذج.
- Server-driven review actions — Telegram يعرض progress والنتائج وReview/Confirm/Cancel، بينما backend يملك contract. نفس العقد يعمل في Telegram وأي text channel وWebApp chat pane.
- Design system مضغوط + hot-reload عبر الحاويات الثلاث — UI-STANDARDS.md يثبت receipt-like cards وsquare actions وtype صغير وTelegram CSS vars.

### ما سأغيره

- بدأ المشروع بدون tests — مناسب لسرعة MVP، لكن workflow routing وWAC confirm paths تحتاج pytest fixtures قبل اعتماد مشغلين أكثر.
- HMAC validation لـ Telegram WebApp initData مستورد ولم يستخدم. الثقة اليوم على guarantees من Telegram client؛ إغلاقها إضافة صغيرة.
- init_db() يعمل بجانب Alembic. جيد للـ solo على DB جديدة، لكنه foot-gun عند clone. إما alembic stamp head بعد create_all أو حذف create_all.

MVP · Telegram bot + WebApp · multimodal intake live · supply/preparation/deduction/WAC/dashboard تعمل end-to-end.

---

المصدر: https://ilyadev.xyz/cases/ai-warehouse (HTML) · /cases/ai-warehouse.ar.md (هذا الملف)
السابق: 01 — AI CRM · عقارات → https://ilyadev.xyz/cases/ai-crm.ar.md
التالي: 03 — AI Video Editor · محرر فيديو → https://ilyadev.xyz/cases/ai-video-editor.ar.md
الفهرس: https://ilyadev.xyz/llms-ar.txt — قائمة دراسات الحالة الكاملة
المؤلف: إليا كازانتسيف — https://ilyadev.xyz/index.ar.md
