Maqsad va qamrov
Muammo
Restoran dasturlari odatda bitta bo'lakni yechadi: alohida POS, alohida buyurtma ilovasi, alohida ombor jadvali, alohida xodimlar chati. Ularni bir-biriga moslashtirish ishi restoranning o'z zimmasida qoladi — va bu ish odamlar tomonidan, qayta-qayta, vaqt tig'izligida bajariladi.
Asosiy g'oya
Mehmon ko'rgan tajriba va oshxona ko'rgan operatsiya — bitta voqeaning ikki tomoni. Mehmon buyurtma bergani va oshxona uni boshlashi mumkinmi degan savol — bitta fakt, ikki tarafdan qaralgan. Ular bitta tizimda yashasa, moslashtirish ishi butunlay yo'qoladi.
Shuning uchun Sitora modul-modul sotiladigan "to'plam" emas. Bitta buyurtma o'zi bilan o'z to'lov haqiqatini, stol kontekstini, muhokama tredini va ombor oqibatini olib yuradi — chunki restoran ularni bitta narsa sifatida boshdan kechiradi.
Bozor
O'zbekistondagi ko'p filialli restoranlar.
| Parametr | Qiymat |
|---|---|
| Tillar | uz · ru · en — uchtasi ham birinchi darajali |
| Valyuta | UZS |
| Vaqt mintaqasi | Asia/Tashkent (restoran bo'yicha sozlanadi) |
| To'lov provayderlari | Payme · Click · Paynet · Uzum |
| Identifikatsiya | Telegram, Google, telefon OTP, SMS |
Kim uchun
| Auditoriya | Nima kerak |
|---|---|
| Mehmonlar | Filialni topish, haqiqiy menyuni ko'rish, buyurtma berish, nima bo'layotganini bilish |
| Zal va oshxona | Har bir rol uchun bitta aniq navbat; keyingi harakat doim ko'rinib turadi |
| Kassirlar | Ishonib harakat qilsa bo'ladigan to'lov haqiqati va har bir qarorning izohli yozuvi |
| Filial admini | Platformaga kirmasdan bitta filialni boshqarish |
| Egalar | Bir necha filialni bitta joydan, operatsiya ichida yashamasdan ko'rish |
| Kuryerlar | Shartlari ko'rinib turgan ish va saqlab bo'ladigan reyting |
| Sitora xodimlari | Har bir harakat kimga tegishli ekani yozilgan boshqaruv |
Qamrovdan tashqarida (ataylab)
Bular qilinmaydi, va bu — qaror:
- Sitora pul o'tkazmaydi. U restoran qarzini yozadi, lekin hech qachon to'lamaydi (ADR 0044). Ish haqi hisoblanadi — to'lanmaydi.
- Sitora provayder hisobidan pul yechmaydi. Faqat provayder boshlagan qaytarish (refund).
- Robotlar buyurtma statusini yozmaydi (ADR 0008). Ular buyurtmaga bo'ysunadi.
- AI yordamchi o'zi hech narsani o'zgartirmaydi (ADR 0009). Faqat taklif; odam tasdiqlaydi.
- Bo'lgan voqea tahrirlanmaydi. Tuzatish — yangi yozuv (ADR 0014).
- Fiskal operator ulanmagan. Struktura tayyor, real operator yo'q.
Arxitektura
To'qqizta yuza
| # | Yuza | Workspace | Nima |
|---|---|---|---|
| 1 | Backend | backend/ | Django + DRF + Channels. Yagona API, yagona haqiqat |
| 2 | Sitora | mobile/ customer | Mehmon uchun buyurtma ilovasi |
| 3 | Sitora Pro | mobile/ pro | 8 ta rol workspace'i |
| 4 | Sitora Biz | mobile/ biz | Ega uchun biznes boshqaruvi |
| 5 | Sitora Courier | mobile/ courier | Kuryer ilovasi |
| 6 | Console | frontend/ | Sitora xodimlari uchun platforma admini. Passkey auth |
| 7 | Handbook | handbook/ | Ichki bilim mahsuloti |
| 8 | Landing | landing/ | Reklama sayti. Backend'ga bog'liq emas |
| 9 | Docs site | docs-site/ | Ochiq hujjatlar, uz/ru/en (Astro + Starlight) |
Stack
| Qatlam | Texnologiya | Nega |
|---|---|---|
| Backend | Python / Django + DRF | Domen qoidalari bitta joyda |
| Realtime | Django Channels (WebSocket) | Zal, oshxona, chat jonli yangilanadi |
| Baza | PostgreSQL | Yagona haqiqat manbai |
| Kesh | Redis | WebSocket guruhlari, kesh |
| Navbat | PostgreSQL jadvali | ADR 0023 — Celery/RabbitMQ o'rniga bitta substrat |
| API kontrakt | OpenAPI (drf-spectacular) | Mijoz kodi generatsiya qilinadi, qo'lda yozilmaydi |
| Mobil | Expo / React Native, TypeScript | 4 ilova bitta kod bazasidan |
| Web | React + Vite | Console va Handbook — zich, desktop uchun |
| Identifikatsiya | Supabase (faqat tekshirish) | ADR 0029 |
To'rt ilova — bitta kod bazasi (ADR 0011)
mobile/ bitta daraxtdan to'rtta ilovani yig'adi; tanlov APP_VARIANT orqali (customer :8081, pro :8082, biz :8083, courier :8084).
Variant izolyatsiyasi — kosmetik emas. To'rtta mexanizm buni majburlaydi, va har biri real xatodan kelib chiqqan:
start-variant.mjs— yagona kirish nuqtasi. Port band bo'lsa ishga tushmaydi (Expo boshqa portga sirg'alib noto'g'ri ilovani ko'rsatmasligi uchun).- Har variantga alohida Metro kesh ildizi. (Umumiy kesh tufayli Biz dev-serveri bir marta "Sitora Biz" nomi ostida mijoz ilovasini ochib qo'ygan.)
appVariant.tsmanifest bilan env o'zgaruvchini solishtiradi; mos kelmasa dev'da xato tashlaydi.- Metro
*.variant.*importlarini*.<APP_VARIANT>.*fayliga yo'naltiradi.
Arxitektura qoidalari
- Ish oqimi haqiqati — backend'niki. Odam keyin nima qila olishini platforma hisoblaydi, mijoz faqat chizadi. Har obyekt
allowed_actionsro'yxatini olib yuradi. - Filial — operatsion chegara (ADR 0001). Filialga bog'liq har endpoint
X-Filial-IDtalab qiladi. - Identifikatsiya global, huquq kontekstual. Bitta
Userbutun platformada; vakolat filialdagi a'zolik + o'sha yerdagi huquqdan keladi. - Auth tekisliklari aralashmaydi. To'rttasi bor; birining sessiyasi boshqasiga o'tmaydi.
- Xatolik loyihalanadi. Offline, eskirgan, ziddiyatli, kirish yo'qolgan — har bir jonli ekran o'zi qaysi holatda ekanini aytadi.
- Hech qachon ishonchli soxta narsa. Orqasida backend yo'q imkoniyat ochiq "mavjud emas" deb ko'rsatiladi.
- Ekranlar boshqariladi, o'qilmaydi. Xodim ekrani — boshqaruv paneli. Skroll uzunligi — nuqson o'lchovi.
Rollar va huquqlar
Ijara (tenancy) zanjiri
Restaurant → Filial → FilialMembership → FilialRole / RestaurantRole → Permission
| Model | Qoida |
|---|---|
| Restaurant | Biznes. Bitta egasi, bitta tarifi, o'z vaqt mintaqasi va valyutasi |
| Filial | Filial — operatsion chegara. (restaurant, name) unikal |
| FilialMembership | Bitta user ↔ bitta filial. Rol ustuni yo'q — a'zolik kirish fakti, rollar unga osiladi |
| MembershipRole | A'zolik ushlagan bitta rol; filial_role yoki restaurant_role — aniq bittasi (DB constraint) |
| Permission | Haqiqiy huquq tekshiruvi shu yerda |
A'zolik rollarning to'plamini ushlaydi (ADR 0036). Bitta odam bitta filialda Ofitsiant va Kassir bo'la oladi, boshqa filiallarda boshqa rollar, bir nechta restoranda a'zolik. Rollar beriladi va olinadi — rolni "almashtiradigan" operatsiya mavjud emas.
Sakkizta workspace
| App role | Workspace | Nima bilan ishlaydi |
|---|---|---|
| waiter | Zal | Stollar, dining session, stol tasdig'i — filial yetkazib bersa, dispatch ham |
| kitchen | Ticketlar | Tayyorlash navbati va topshirish |
| cashier | To'lov ko'rigi | Kutilayotgan da'volar, muammolar, ko'rilgan tarix |
| manager | Nazorat | E'tibor talab qiladiganlar, insidentlar, zal va fleet holati |
| inventory_manager | Ombor | Zaxira darajalari, tuzatishlar, chegaralar, ogohlantirishlar |
| supply_manager | Ta'minot | Yetkazib beruvchilar, narxlar, xarid, qabul, hisob-fakturalar |
| content_manager | Kontent | Reels yozish, chop etish, izoh moderatsiyasi |
| admin | Filial boshqaruvi | Sozlamalar, xodimlar, override'lar, audit |
Dispatcher roli yo'q (ADR 0049). Yetkazib berish taxtasi — Zal workspace'ining qo'shimcha bo'limlari: taxtani o'qish — buyurtmani o'qish, unda harakat — buyurtmani o'zgartirish, ofitsiant ikkalasini allaqachon ushlaydi. Dispatch uchun hech kimga ortiqcha vakolat kerak emas.
App role — bu workspace tanlagichi. U hech qachon huquq tekshiruvi emas.
"Stock Room Assistant" deb nomlangan rol ombor workspace'ini ochadi — lekin ichidagi har harakat o'sha filialdagi haqiqiy huquqqa tayanadi. Bu qoidani unutish ikki marta imtiyoz oshirishga olib kelgan. Amaliy natija: rolga nom berish unga hech narsa bermaydi; huquqlar alohida beriladi.
To'rtta autentifikatsiya tekisligi
| # | Tekislik | Kredensial | Kim uchun |
|---|---|---|---|
| 1 | Mobil / tenant API | Authorization: Bearer | 4 mobil ilova |
| 2 | Ichki admin | X-Console-Session-ID / X-Handbook-Session-ID | Console, Handbook |
| 3 | Robotics vendor | sit_rk_ kaliti | Robot vendorlari |
| 4 | Realtime WS | 1-tekislik bearer'ini qayta ishlatadi | Jonli ekranlar |
- JWT emas, stateful sessiya (ADR 0002). Kredensial — bazadagi qator; bekor qilish darhol va haqiqiy.
- Sessiya ID — kredensial emas (ADR 0056). 384-bitli bearer yaratiladi, faqat SHA-256'si saqlanadi.
- Console/Handbook — passkey (WebAuthn), apex RP ID orqali (ADR 0005): bitta kredensial ikkala originda.
Console ichki rollari
Sitora xodimlari uchun 8 rol, 37 huquq kodi: support_agent · billing_operator · risk_reviewer · platform_operations_manager · developer_read_only · auditor · knowledge_reader · super_admin. Xavfli operatsiyalar tasdiqlash oqimidan o'tadi (pending → approved/rejected → executed/failed); audit jurnali faqat qo'shiladi.
Funksional talablar
16 kichik tizim, har biri bir xil shaklda: aktorlar → oqim → qoidalar → chegara.
3.1 Buyurtma va zal
Turlari: dine_in · takeout · delivery. Tur kosmetik emas — u holatlar mashinasini qirqadi.
received → cancelled | pending_payment | preparing
pending_payment → cancelled | preparing
preparing → cancelled | out_for_delivery | pickup_ready | ready
ready → served | cancelled
pickup_ready → delivered | cancelled
out_for_delivery → delivered | cancelled
served, delivered, cancelled → (terminal)
Jadval ikki marta toraytiriladi: tur bo'yicha (masalan dine_in hech qachon out_for_deliveryga yetmaydi) va settlement timing bo'yicha (prepay + to'lanmagan = hech qanday tayyorlash holati ochilmaydi).
| ID | Qoida |
|---|---|
| B-1 | Buyurtma — o'zgarmas operatsion birlik; submitted_at yaratilishda bosiladi |
| B-2 | Narxlar server tomonidan joriy menyudan yoziladi. Mijoz yuborgan narx rad etilmaydi — e'tiborsiz qoldiriladi |
| B-3 | status yaratilishda o'qish uchun — aks holda mashina ham, to'lov darvozasi ham chetlab o'tiladi |
| B-4 | settlement_timing hech qachon mijoz yoza olmaydi — o'z timing'ini nomlay olgan mijoz bepul ovqat topgan bo'lardi |
| B-5 | Zalda qo'shimcha buyurtma — yangi buyurtma, tahrirlash emas |
| B-6 | Ko'pi bilan bitta buyurtmachi: customer yoki guest_profile (DB constraint) |
| B-7 | served_quantity yaratilishda nol — xizmat haqiqati faqat xodim tasdig'i bilan |
Filial xizmat rejimlari (accepting_orders, tur bo'yicha yoqish, favqulodda pauza) yaratishni to'sadi; rad etish — 409 va mashina kodi. Sozlama qatori yo'q filial ruxsat beruvchi. Pauza xodim buyurtmalariga ham tegishli — xodim jim chetlab o'ta oladigan pauza pauza emas. Boshqa filial menyusi — 400 (buzuq so'rov); tugagan element — 409 (oddiy poyga, hujum emas).
3.2 Stol xizmati — tab
is_paid ikki savolga javob berardi: to'landimi? (fakt) va to'lovi kafolatlanganmi? (risk hukmi). Darvozaga ikkinchisi kerak — shu sababli boolean o'rniga uch qiymatli enum (ADR 0048):
| Timing | Ma'nosi | Qachon |
|---|---|---|
| prepay | To'lanmaguncha pishirilmaydi | Har doim standart |
| on_delivery | Kuryer naqd oladi | Yetkazib berish + filial COD'ni yoqqan |
| on_departure | Stol hisobiga yoziladi | Faqat zalda + filial tab rejimini yoqqan |
- Dining session — bu tab. Alohida obyekt yo'q; ochiq sessiyadagi to'lanmagan buyurtmalar yig'indisi = qarz.
- Faqat zalda va faqat stolda (DB constraint). Tab — filial sozlamasi, standart o'chiq. Tab limiti bor.
- Qarz bilan sessiya yopish yoziladi, jim o'tmaydi. Hisobdan chiqarish (write-off) hech qachon
is_paidni true qilmaydi — pul kelmadi.
3.3 To'lov va pul
Sitora pulni ushlamaydi. U pulning haqiqatini yozadi.
Ikki qatlam: Transaction (restoran nima olgani; pending → confirmed | rejected) va ProviderPayment (Payme/Click/Paynet/Uzum bilan muomala; 7 holat, paid → refunded yagona qaytish yo'li).
| ID | Qoida |
|---|---|
| P-1 | is_paid uchun yagona yozuv o'rni (ADR 0006) |
| P-2 | Buyurtma qatori — qulf. Parallel to'lovlar SELECT FOR UPDATE bilan seriyalanadi |
| P-3 | Imzolanmagan provayder maydoniga qarab qaror qabul qilinmaydi (Click refund soxtalashtirishi shu tarzda topilgan) |
| P-4 | Kiruvchi summa menyu haqiqatidan hisoblangan jami bilan solishtiriladi |
| P-5 | Kredensiallar muhrlangan; hech qachon to'liq qaytarilmaydi |
| P-6 | Refund — faqat provayder tomonidan. Sitora pul yechmaydi |
| P-7 | Kill switch pulni to'xtata oladi, hech qachon ko'chira olmaydi |
| P-8 | Takroriy callback (replay) zararsiz — idempotentlik majburiy |
Qurilmalar: terminal, smart-POS, fiskal registr, mijoz displeyi — mashina printsiplari, foydalanuvchi emas; tor scope'li o'z kredensiali bilan. Bosh qoida: qurilma pul kelganini xabar qilishi mumkin, lekin hech qachon e'lon qila olmaydi. 12 konformans stsenariysi kontraktni pinlaydi (device_cannot_declare_money_received, duplicate_callback_replay, kill_switch_compliance…).
Solishtirish (reconciliation) har farqni nomlaydi (matched · missing_in_sitora · missing_at_provider · amount_mismatch) va faqat aniq harakat bilan yopiladi. Fiskalizatsiya: struktura tayyor (FiscalJob: queued → submitted → fiscalized | failed), real operator ulanmagan.
3.4 Yetkazib berish va kuryerlar
Kotirovka — yetkazib berish to'lovi o'ta oladigan yagona yo'l. Masofa manbasi haqida halol (provayder yoki zaxira formula). Kotirovka bir marta sarflanadi; manzil — snapshot. Narxlash — faqat masofa bandlari.
Ish (job): 9 holat (dispatching … delivered | failed | cancelled | unfilled). Kuryerlar taklif qiladi, siyosat hal qiladi; ish buyurtma mashinasiga aniq ikki nuqtada tegadi. Taklif muddati rad etishdan oldin yoziladi — kuryer "javob bermaslik" bilan statistikadan qochmasligi uchun.
Kuryer maqomi — uch mustaqil qatlam: platforma maqomi (hujjatlar, yosh, shartlar) · restoran bilan kelishuv · hozirgi holat (smena, heartbeat, faol ish). Har taklifda qayta tekshiriladi, hech qachon keshlanmaydi.
Ishonchlilik hisoblanadi, saqlanmaydi: completion 0.45 · on-time delivery 0.25 · on-time pickup 0.15 · acceptance 0.15, 30 kunlik oynada. Sovuq start — band, yomon ball emas. Bitta restoran ta'siri 0.3 bilan cheklangan, statistik chetlanuvchi restoran chiqariladi. Har bir majburlash raqami Console'dan boshqariladi; avtomatik jazo bo'lsa — apellyatsiya navbati majburiy.
COD ikkinchi pul yo'lini qo'shmaydi: kuryer qaytadi → da'vo → kassir tasdiqlaydi — mavjud Transaction yo'lining o'zi. Daromad hisoblanadi; Sitora kuryerga pul to'lamaydi.
3.5 Menyu va zaxira
StockTransaction — o'zgarmas. Zaxira soni hech qachon "qo'yilmaydi", faqat tranzaksiya qo'shiladi; ko'rinadigan son — hisoblangan ko'rinish. record_transaction() — yagona yozuv yo'li. Qo'lda tuzatish ziddiyatni aniqlaydi: sanoq davomida son o'zgargan bo'lsa, yozuv rad etiladi. stock_mode qaysi ledger sotiladiganlikni hal qilishini e'lon qiladi — menyu zaxirasi sotiladiganlik, ingredient zaxirasi tannarx (ADR 0042): ikki savol, ikki ledger.
3.6 Ingredientlar va ta'minot
Katalog restoranga, zaxira filialga tegishli. Asosiy birliklar g / ml / unit; konversiya e'lon qilinmagan bo'lsa tizim taxmin qilmaydi — rad etadi. Ingredient ledgeri ham o'zgarmas (11 sabab: qabul, retsept kamomadi, ishlab chiqarish, chiqit, ko'chirish…).
- Manfiy zaxira ruxsat etilgan — ataylab. Oshxonani "bazada 0" degan sabab bilan to'xtatib bo'lmaydi; manfiy son — ko'rinadigan muammo, to'xtagan xizmatdan yaxshi.
- Sanash va tuzatish — ikki xil harakat. Ko'chirish har doim juftlik (
transfer_out+transfer_in). - Xarid: PO 8 holatli (
draft → … → received → closed). Sitora taklif qiladi, odam tasdiqlaydi; ko'tarish ≠ tasdiqlash (ikki huquq). Hech narsa yubormaydi, hech narsa to'lamaydi. - Qabulda tannarx o'rtacha vaznli usulda (ADR 0043). Lot va muddat xizmatni hech qachon to'smaydi. Narxni ko'rish — huquq: yo'q bo'lsa
nullqaytadi. - Retsept versiyalanadi, lahzaga qarab hal qilinadi; kamomad oshxona boshlaganda yoziladi. Tannarx chiqmasa sababi yoziladi (
no_recipe…), jim nolga aylanmaydi.
Storekeeper javonni sanaydi va narxni ko'rmaydi; Supply manager sotib oladi va ko'radi. Ikki ish, bitta so'zning ikki varianti emas.
3.7 Smenalar va mehnat xarajati
To'rt yozuv: smena andozasi · rejalashtirilgan smena (a'zolikni nomlaydi) · ishlangan vaqt (hech qachon tahrirlanmaydi) · stavka (odamni nomlaydi).
- Davomat hech qachon rad etmaydi va hech qachon avtorizatsiya emas. Kelgan odam kelgan — smenasiz ham yoziladi.
- Rejalashtirish ogohlantiradi, rad etmaydi (
double_booked,overlong_shift,role_not_held…). Menejer sababini biladi. - Ikki fe'l — taslim qilish va olish — ikkalasi menejer tasdig'i bilan.
- Xarajat ishga ergashadi, kalendarga emas. Sitora ish haqi to'lamaydi (ADR 0044) — payroll chegaradan tashqarida.
3.8 Operatsion xarajatlar
- Doimiy yoki o'zgaruvchan — kiritiladi, taxmin qilinmaydi.
- Ikki sana juftligi, chunki ikki haqiqat bor: qachon to'landi va qaysi davrni qopladi. Kapital xarajat bir vaqtda butun (naqd oqim) va taqsimlangan (foyda) ko'rinadi.
- Takrorlanuvchi andoza taklif qiladi; odam yozadi. Umumiy xarajat o'z taqsimlash qoidasini nomlaydi (
revenue_share·seat_share·equal·none). - Natija: operatsion foyda va zararsizlik nuqtasi (break-even).
3.9 Analitika va hisobotlar
Metrika qatlami — modeli ham, HTTP yuzasi ham yo'q kutubxona: 45 metrika, hammasi bitta natija shaklida. Halollik qoidalari: har raqam qayerdan kelganini e'lon qiladi; zal metrikalari o'z ko'rligini aytadi; tannarx metrikasi nimani narxlay olmaganini aytadi; yalpi / chegirma / tushum — uch har xil raqam; kompozit metrika eng yosh kirishi qadar eski; ikki renderer bir xil raqam chiqarishi golden faylga pinlangan.
Hisobot: 13 bo'lim (10 operatsiya + 3 pul), 4 tasi bepul, qolgani entitlement bilan. Ikki render — Excel workbook va PDF hujjat; generatsiya past ustuvorlikdagi navbat ishi. Console tahlil mavjudligini ko'radi, hech qachon nima yozilganini emas (ADR 0047).
3.10 Muloqot
Ikki o'q: sinf (direct · staff_group · context_thread · incident) va kontekst (stol, sessiya, buyurtma, mijoz, to'lov, insident). Har xabar o'z auditoriyasini olib yuradi (internal_only / customer_visible). Kim ko'rishi — bitta funksiya, to'rt qoida. Tred konteksti hal bo'lgach "settled", 24 soatdan keyin qulflanadi (ADR 0040). Realtime faqat muloqot uchun (ADR 0007). Tred hech qachon ikkinchi buyurtma yo'liga aylanmaydi (ADR 0059).
3.11 Sitora AI yordamchisi
Transport: ish (job), keyin so'rov (poll) — so'rov ichida model kutilmaydi. Vositalar — qat'iy ro'yxat (17 ta: 9 Pro + 8 Biz), model uni kengaytira olmaydi.
Ikki darvoza qoidasi: har vosita (1) chaqiruvchining o'sha filialdagi haqiqiy huquqini va (2) vositaning o'z ruxsat ro'yxatini tekshiradi.
- Model hech narsani o'zgartirmaydi — faqat draft (ADR 0009):
proposed → confirmed | discarded | expired; faqat odam tasdiqlaydi. Draft turi ikkita: zaxira tuzatish, rol o'zgarishi. - Erkin matn hech qachon tashqariga chiqmaydi — redaksiya chegarasi majburiy. Provayder chegarasi gateway'niki; domen kodi provayderni bilmaydi. Byudjet va tezlik chegarasi bor.
3.12 Counter — ilovasiz mehmonlar
Vakolatli xodim mehmon nomidan mijoz yuzasida ishlaydi (ADR 0041). Mehmon profili — hech qachon akkaunt emas: kirish yo'q, parol yo'q. Ishlaydigan filial mehmondan olinadi. X-Acting-For sarlavhasi vakolatni e'lon qiladi va tekshiriladi (400/403/404/409 kodlari bilan). Counter hech qachon pul ko'chirmaydi — buyurtmasi oddiy to'lov yo'lidan o'tadi. Har harakat o'zgarmas jurnalga yoziladi.
3.13 Reels
Qamrov: filial yoki restoran darajasida — hech qachon noaniq emas. Hayot davri — aniq holatlar mashinasi; mijozga ko'rinish — bitta queryset. Reyting tushuntirib beriladigan qilib qurilgan — qora quti emas. Ko'rish hisobi: ikki jadval, ikki ish; ReelViewDay — kunlik haqiqat.
3.14 Console va Handbook
Console: rol → huquq kodi → tasdiqlash. Audit — qurilishi bo'yicha append-only, o'chirish yo'li mavjud emas. Boshqariladigan operatsiya oilalari tasdiqsiz bajarilmaydi. Console pulni to'xtata oladi, hech qachon ko'chira olmaydi. Deploy tekshiruvi bir protsessli konfiguratsiyadan bosh tortadi.
Handbook: klassifikatsiya — asosiy o'q; grant sezgirlik oshgani sayin torayadi; vakolat imkoniyatlar (capabilities) orqali, rollar orqali emas. Eskirish hisoblanadi, da'vo qilinmaydi. Kirish audit qilinadi.
3.15 Robotics
Vendor → filialga aktivatsiya → mashina kredensiali. Robotlar foydalanuvchi emas — (AnonymousUser, credential) juftligi. Robot buyurtma statusini hech qachon yozmaydi (ADR 0008). Bitta buyurtma + bitta oyoq uchun bitta jonli vazifa. Webhook chiqishi ikki marta qo'riqlanadi (SSRF); yetkazish navbatga qo'yiladi. "O'lib qolgan" robot uchun aniq qaytish yo'li bor. Konformans to'plami vendorni tekshiradi.
3.16 Eksport va import
Arxiv shifrlangan (AES-GCM); parol o'qiladigan holda saqlanmaydi. Import eksportdan ataylab torroq: faqat menyu va stollar; validate (aniq oldindan ko'rish) yoki apply; faqat birlashtirish, tabiiy kalit bo'yicha — hech narsa o'chirilmaydi. Eksport yozuvlari — append-only audit; tashqariga chiqadigan yagona identifikator — public_id.
Ma'lumotlar modeli
Backend'da ~200 model bor; quyida yadro — 26 asosiy obyekt.
| Guruh | Modellar | Kalit qoida |
|---|---|---|
| Shaxs | User · UserIdentity · Session | Global odam; provayderga xos login (link_origin tasodifiy loginni ataylab bog'lashdan ajratadi); bearer'ning faqat SHA-256'si saqlanadi |
| Ijara | Restaurant · Filial · FilialMembership · MembershipRole | Filial — operatsion chegara; a'zolikda rol ustuni yo'q, rollar to'plam bo'lib osiladi |
| Buyurtma | Order · OrderItem · OrderItemAddon · DiningSession · DiningSpot · BranchOperationalSettings | O'zgarmas buyurtma; narx yaratilishda muhrlanadi; sessiya = tab |
| Zaxira | MenuItem · StockTransaction · Ingredient · IngredientStockTransaction · Recipe/Version · PurchaseOrder | Ikki o'zgarmas ledger; retsept versiyalanadi; PO'ni odam tasdiqlaydi |
| Pul | Transaction · PaymentProviderConfig · ProviderPayment · PaymentIntent · PaymentDevice | Yozuv va provayder qatlami alohida; qurilma — mashina printsipi |
| Yetkazish / mehnat | CourierProfile · DeliveryJob · ScheduledShift · TimeEntry · WageRate | Kuryer — profil, a'zolik emas (ADR 0015); ishlangan vaqt tahrirlanmaydi |
O'zgarmaslik naqshi
Uchta ledger bitta naqshni ishlatadi va bu ataylab: StockTransaction · IngredientStockTransaction · Transaction. Har biri faqat qo'shiladi, hech qachon tahrirlanmaydi; joriy qiymat yig'indi sifatida hisoblanadi. Tuzatish — kompensatsiya yozuvi (ADR 0014).
Integratsiyalar
| Integratsiya | Nima uchun | Chegara |
|---|---|---|
| Payme · Click · Paynet · Uzum | Onlayn to'lov | Har biri o'z adapteri; kredensiallar filial bo'yicha muhrlangan; imzolanmagan maydonga qarab qaror yo'q |
| Supabase | Faqat identifikatsiya tekshiruvi (ADR 0029) | Backend Supabase sessiyasini ushlamaydi; kimlik faqat sub bo'yicha — user_metadata foydalanuvchi yozadigan maydon, unga ishonilmaydi |
| Telegram Bot | Deep-link va kod orqali kirish | Sessiya ID — chop etiladigan identifikator, kredensial emas |
| Google Sign-In | Tizim akkaunt tanlagichi | Browser emas, webview emas — oddiy token almashinuvi |
| Xarita provayderi | Masofa hisoblash | Yagona gateway; oylik byudjet va throttle; yiqilsa — filial siyosatiga qarab zaxira narx yoki rad etish |
| AI provayderi | Sitora AI | Gateway chegarani egallaydi; erkin matn tashqariga chiqmaydi |
| Robot vendorlari | Ochiq xizmat API | Sertifikatlash → aktivatsiya → kredensial; webhook SSRF'dan qo'riqlangan |
| Fiskal operator | Chek fiskalizatsiyasi | Ulanmagan. Struktura tayyor, real operator yo'q |
Umumiy qoidalar: provayder chegarasi adapter ortida; har chiquvchi so'rovning yozilgan timeout'i bor; callback'lar idempotent; webhook'lar navbatga qo'yiladi; provayder yiqilganda tizim nima bo'lganini aytadi — jim zaxiraga o'tmaydi.
Nofunksional talablar
Tezlik maqsadlari (ADR 0057)
Maqsad Sitora nazorat qiladigan joyda o'lchanadi — server tomonida, telefonda emas. Toshkentdagi yaxshi 4G server maqsadiga 150–250 ms qo'shadi; yomon ulanishda chegara yo'q.
| Tekislik | Nima kiradi | p95 | p99 |
|---|---|---|---|
| Xizmat | Mehmon/xodim kutib turgani: buyurtmalar, menyu, counter, tranzaksiyalar | 400 ms | 1 200 ms |
| Back office | Console, Handbook, Biz tahlillari, eksport | 1 000 ms | 3 000 ms |
| Poll | Kuryer/qurilma/robot pollingi, provayder callback'lari | 250 ms | 800 ms |
Qurilma: sovuq start ≤ 3 s (etalon Android'da); har asosiy fe'lning javobi ≤ ~100 ms — ushlab turilgan, o'chirilgan yoki optimistik.
Miqyos siyosati (ADR 0058)
Poydevor hozir A darajaga quriladi — arxitektura, so'rov samaradorligi, mobil javobgarlik. Qolgani — yetarli darajada; yuqori darajali optimizatsiya trigger otmaguncha sotib olinmaydi (hajm, kechikish, navbat yoshi, tarix o'qishi, qurilma triggerlari). Miqyos protsess roli bo'yicha (web · machine · worker · scheduler), tenant bo'yicha emas (ADR 0021).
Xavfsizlik
| ID | Talab |
|---|---|
| SEC-1 | A'zolik — filialga bog'liq har o'qish uchun pol (ADR 0030); anonim o'qishlar e'lon qilinadi, meros qilib olinmaydi |
| SEC-2 | Auth tekisliklari aralashmaydi; sessiya ko'tarilmaydi |
| SEC-3 | Sessiya tekshiruvi hech qachon keshlanmaydi (ADR 0027) — bekor qilish darhol ishlashi uchun |
| SEC-4 | Console/Handbook — passkey (WebAuthn), apex RP ID, step-up bilan |
| SEC-5 | Kredensiallar muhrlangan; to'liq qaytarilmaydi |
| SEC-6 | Chiquvchi so'rovlar SSRF'dan qo'riqlanadi |
| SEC-7 | Media avtorizatsiya qilinadi: imzolangan redirect yoki oqim; kalit egasini nomlaydi |
| SEC-8 | Audit — append-only |
| SEC-9 | Erkin matn AI provayderiga chiqmaydi |
Ma'lumot, til, kontrakt
- Operatsion ma'lumot saqlash soatiga ega (ADR 0025); tiklash maqsadlari mashq qilinadi yoki yo'q hisoblanadi (ADR 0024).
- Uch til birinchi darajali. Ma'lum cheklov: generatsiya qilingan hisobotlar hozircha ingliz tilida (ADR 0055) va muqova buni ochiq aytadi.
- API ikkita oldingi mobil kontraktni qo'llab-quvvatlaydi (ADR 0026); barcha ro'yxatlar sahifalanadi (100/500, katalog 500/1000); mijoz kodi generatsiya qilinadi (ADR 0010); generatsiya qilingan artefaktlar qayta generatsiya bilan tekshiriladi (ADR 0031).
- Har protsess rolini e'lon qiladi,
/healthz//readyzjavob beradi; so'rov korrelyatsiya ID bilan kuzatiladi; deploy tekshiruvi bir protsessli konfiguratsiyadan bosh tortadi.
Holat: nima tayyor, nima tayyor emas
Bu bo'lim ataylab ochiq. Repozitoriyda uni saqlaydigan alohida fayl bor va u blokerlarni faqat haqiqatda bajarilganda o'chiradi — uzoq turgani uchun emas.
| Yuza | Lokal darvoza | Ochiq bloker |
|---|---|---|
| Console | o'tadi | Staging smoke — real HTTPS'da cross-origin passkey |
| Handbook | o'tadi | Cross-origin passkey staging smoke (Console bilan umumiy) |
| Biz | o'tadi | Staging smoke — onboarding'dan faol filialgacha |
| Pro | o'tadi | Rol bo'yicha doktrina o'tishlari va qolgan launch hardening |
| Customer | o'tadi | Qurilma/do'kon sinovi yo'q; store assets va maxfiylik siyosati |
| Delivery | o'tadi | Kuryer qurilma sinovi — real temirda; fon geolokatsiyasi yo'q |
| Landing | o'tadi | — |
| Birinchi ishga tushish ekrani | lokal | Qurilmada va screen reader bilan sinalmagan |
| Generatsiya qilingan tahlil | testlar | RU/UZ hisobotlar ingliz tilida; raqamlarni hech kim o'qib chiqmagan |
| Docs site | quriladi | Production domen yo'qligi sababli sozlanmagan |
| Operatsion tiklash | mashq qilingan | 2026-08-24: RTO 25 s, RPO ≤ 60 s — lekin lokal stack'da; production infratuzilmasi hali mavjud emas |
| Tezlik maqsadi | artefakt yo'q | Staging load-smoke o'tkazilmagan: maqsad da'vo qilingan, tekshirilmagan |
Bitta jumlada: hech bir yuza "chiqarilgan" (released) emas. Darvozasi qanchalik yashil bo'lmasin, ochiq blokeri bo'lgan har yuza bloklangan holicha qoladi.
Nima haqiqatan ishlaydi
- Backend to'liq: 27 domen app, ~534 endpoint, testlar yashil
- To'rt mobil ilova quriladi va yuklanadi (bundle + signing tekshirilgan; kuryer AAB sinalgan)
- To'liq stack bitta buyruq bilan lokalda:
docker compose up --build— demo restoran bilan urug'langan - Tiklash muolajasi mashq qilingan va takrorlanadigan
Nima yo'q
- Production infratuzilmasi mavjud emas — staging ham, prod ham
- Hech bir yuza real qurilmada, real tarmoqda, real mehmon bilan sinalmagan
- Fiskal operator ulanmagan
- Kuryer ilovasida fon geolokatsiyasi yo'q (faqat ilova ochiq turganda)
- Tezlik maqsadlari o'lchanmagan — faqat e'lon qilingan
Nega bu ochiq yozilgan
Yashil test — yuza ishlashini aytadi, yaxshi ekanini hech qachon aytmaydi. Eng aniq misol repozitoriyda yozilgan: hisobot tizimining barcha testlari o'tgan edi — jumladan ikkala renderer bir xil raqam chiqarishini isbotlaydigani ham — va PDF mijozning kirill alifbosidagi nomini har sahifada qora kvadratchalar qatori qilib chop etayotgan edi. Testlar renderer xabar qilgan raqamlarni solishtirgan; hech kim o'quvchidan nima ko'rayotganini so'ramagan. Nuqson tuzatilgan va endi ratchet bor. Dars qoladi: har bir yozuv nimani hali hech kim ko'rmaganini ham nomlaydi.
Ilova — chuqurroq o'qish uchun
Bu TZ — qisqartma. Har mavzuning to'liq versiyasi repozitoriyda:
| Kerak bo'lsa | Qarang |
|---|---|
| Hujjatlar xaritasi | docs/README.md |
| Mahsulot tavsifi | docs/product/product-overview.md |
| Platforma tuzilishi | docs/reference/platform-map.md |
| Kim nima qila oladi | docs/reference/identity-and-access.md |
| Har domen qanday ishlaydi | docs/reference/domains/ — 19 hujjat |
| Batafsil spetsifikatsiyalar | docs/specs/ — 28 hujjat |
| Qarorlar va sabablari | docs/decisions/ — 59 ADR |
| Doktrinalar | docs/doctrine/ — 10 hujjat |
| Chiqarish holati | docs/operations/release/verification/README.md |
Hujjat vakolat sinflari (ADR 0017)
Repozitoriyda faqat reference sinfi kod hozir nima qilishini da'vo qila oladi — va har da'vo dalil langariga (evidence anchor) ega. Hujjat va kod ziddiyatga tushsa — kod yutadi.
Loyihani ishga tushirish
docker compose up --build # keyin: bash docker/smoke.sh
Backend PostgreSQL va Redis'da, worker va scheduler, Console (:5173/console), Handbook (:5174), landing (:4173), docs (:4321), to'rt mobil ilova web ko'rinishida (:8081–:8084) — demo restoran bilan. Kirish yo'llari: docs/operations/local-stack.md.