Files
meezi/MEEZI_CURSOR_GUIDE.md
T
soroush.asadi 45cd028d1c chore: initial project structure and root configuration
Adds root-level config files: solution (.slnx), NuGet, global.json,
Docker Compose files for all services (API, dashboard, website, finder,
admin), environment example, and developer documentation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-27 21:33:10 +03:30

763 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# راهنمای کامل توسعه Meezi با Cursor
> از صفر تا اولین سفارش واقعی — گام به گام
---
## پیش‌نیازها — قبل از هر چیز نصب کن
```bash
# 1. Node.js 20+
node --version # باید v20 یا بالاتر باشد
# دانلود: https://nodejs.org
# 2. .NET 10 SDK
dotnet --version # باید 8.x باشد
# دانلود: https://dotnet.microsoft.com/download/dotnet/8.0
# 3. Flutter 3.x
flutter --version
# دانلود: https://docs.flutter.dev/get-started/install
# 4. Docker Desktop (برای PostgreSQL و Redis محلی)
docker --version
# دانلود: https://www.docker.com/products/docker-desktop
# 5. pnpm
npm install -g pnpm
# 6. Cursor
# دانلود: https://cursor.com
```
---
## مرحله ۱ — ساختار پروژه را بساز
```bash
# یک پوشه اصلی بساز
mkdir meezi && cd meezi
# Git راه‌اندازی کن
git init
echo "node_modules/\n.next/\nbuild/\n*.user\n.env*\n!.env.example" > .gitignore
```
---
## مرحله ۲ — فایل‌های کلیدی را بریز
### `.cursorrules` — در ریشه پروژه
```
You are building Meezi (میزی) — a Persian-first SaaS POS and community
platform for Iranian cafés in Tehran and Karaj.
CONTEXT: Read MEEZI_PRD.md for full product details before any task.
STACK:
- Backend: ASP.NET Core 10 (C#) in src/Meezi.API
- Web: Next.js 14 TypeScript in web/dashboard
- Mobile: Flutter 3 Dart in mobile/meezi_app
- DB: PostgreSQL + Redis
- ORM: Entity Framework Core 10
PRODUCT:
- Brand: Meezi (میزی) | میزت منتظرته
- Markets: Tehran + Karaj (V1)
- Languages: Farsi (default) + Arabic + English
- Competitor: Sepidz (legacy license, no SaaS)
- Pricing: Free / Pro 1.49M / Business 3.49M / Enterprise
C# RULES:
- Async/await everywhere — never .Result or .Wait()
- EVERY EF query filters by CafeId (multi-tenant)
- Return ApiResponse<T> always: { bool Success, T? Data, ApiError? Error }
- Use record types for DTOs
- FluentValidation for all inputs
- Hangfire for background jobs
- SignalR for real-time KDS
- Never Console.WriteLine — use ILogger<T>
NEXT.JS RULES:
- next-intl for i18n — ALL strings in messages/fa.json, ar.json, en.json
- RTL for fa/ar — LTR for en
- ms-* me-* ps-* pe-* for spacing (never ml mr pl pr)
- TanStack Query v5 for server state
- Zustand for cart and UI state
- date-fns-jalali for ALL dates — never show Gregorian
- Numbers: .toLocaleString('fa-IR')
- Currency: n.toLocaleString('fa-IR') + ' ت'
- shadcn/ui components always
FLUTTER RULES:
- Riverpod 2 for all state
- GoRouter for navigation
- Drift SQLite for offline
- shamsi_date for all dates
- 3 locales: fa (RTL), ar (RTL), en (LTR)
- Feature-first: lib/features/{feature}/
SECURITY:
- Validate CafeId ownership on every protected endpoint
- Rate limit OTP: 5/hour per phone via Redis
- Never log phone, national ID, or payment tokens
- Soft delete only — never hard delete
API FORMAT:
Success: { "success": true, "data": {...} }
Error: { "success": false, "error": { "code": "...", "message": "..." } }
List: { "success": true, "data": [...], "meta": { "total": 0, "page": 1 } }
```
### `docker-compose.yml` — در ریشه پروژه
```yaml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: meezi
POSTGRES_USER: meezi
POSTGRES_PASSWORD: meezi_local_pass
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
```
---
## مرحله ۳ — Backend راه‌اندازی کن
```bash
# پوشه backend
mkdir src && cd src
# پروژه‌های .NET بساز
dotnet new webapi -n Meezi.API --use-controllers
dotnet new classlib -n Meezi.Core
dotnet new classlib -n Meezi.Infrastructure
dotnet new classlib -n Meezi.Shared
# Solution بساز
cd ..
dotnet new sln -n Meezi
dotnet sln add src/Meezi.API
dotnet sln add src/Meezi.Core
dotnet sln add src/Meezi.Infrastructure
dotnet sln add src/Meezi.Shared
# Reference ها
cd src/Meezi.API
dotnet add reference ../Meezi.Core
dotnet add reference ../Meezi.Infrastructure
dotnet add reference ../Meezi.Shared
cd ../Meezi.Infrastructure
dotnet add reference ../Meezi.Core
dotnet add reference ../Meezi.Shared
```
### حالا Cursor را باز کن و این prompt را بده:
```
I'm building Meezi.API — ASP.NET Core 10 Web API for a SaaS POS system.
Read .cursorrules for full context.
Add these NuGet packages to Meezi.API:
- Npgsql.EntityFrameworkCore.PostgreSQL
- Microsoft.EntityFrameworkCore.Design
- FluentValidation + FluentValidation.DependencyInjectionExtensions
- AutoMapper.Extensions.Microsoft.DependencyInjection
- Hangfire.AspNetCore + Hangfire.PostgreSql
- Serilog.AspNetCore + Serilog.Sinks.Console
- StackExchange.Redis
- Microsoft.AspNetCore.Authentication.JwtBearer
- Microsoft.AspNetCore.SignalR
- QuestPDF (for PDF generation)
- EPPlus (for Excel export)
- CsvHelper
Add these to Meezi.Infrastructure:
- Npgsql.EntityFrameworkCore.PostgreSQL
- Microsoft.EntityFrameworkCore.Tools
Then create this folder structure inside Meezi.API:
Controllers/ Services/ Jobs/ Middleware/ Hubs/ Extensions/
And this in Meezi.Core:
Entities/ Enums/ Interfaces/ Constants/
And this in Meezi.Infrastructure:
Data/ Data/Migrations/ Repositories/ ExternalServices/
Create the base ApiResponse<T> record in Meezi.Shared/ApiResponse.cs
Create Program.cs with full middleware pipeline setup.
```
---
## مرحله ۴ — Database Schema
در Cursor بده:
```
Create all EF Core entity classes in Meezi.Core/Entities/ based on this schema:
Cafe: Id(string/cuid), Name, NameAr, NameEn, Slug(unique), Phone,
Address, City, LogoUrl, PlanTier(enum), PlanExpiresAt, IsVerified,
PreferredLanguage, CreatedAt
Branch: Id, CafeId(FK), Name, Address, City
Table: Id, CafeId, BranchId(nullable), Number, Capacity(default 4),
Floor, QrCode(unique), IsActive
Employee: Id, CafeId, Name, Phone, NationalId, Role(enum EmployeeRole),
BaseSalary, PinCode, CreatedAt
MenuCategory: Id, CafeId, Name, NameAr, NameEn, SortOrder, TaxId,
DiscountPercent, IsActive
MenuItem: Id, CafeId, CategoryId(FK), Name, NameAr, NameEn,
Description, Price, ImageUrl, IsAvailable
Order: Id, CafeId, BranchId, TableId, CustomerId, EmployeeId,
OrderType(enum), Status(enum), CouponId, DiscountAmount,
Subtotal, TaxTotal, Total, SnappfoodOrderId, CreatedAt
OrderItem: Id, OrderId(FK), MenuItemId(FK), Quantity, UnitPrice, Notes
Payment: Id, OrderId(FK), Method(enum PaymentMethod), Amount,
Status(enum), Reference
Customer: Id, CafeId, Name, Phone, NationalId, BirthDateJalali,
Group(enum CustomerGroup), LoyaltyPoints, ReferredBy, CreatedAt
Coupon: Id, CafeId, Code, Type(enum CouponType), Value, MinOrderAmount,
MaxDiscount, UsageLimit, UsedCount, TargetGroup,
StartsAt, ExpiresAt, IsActive
Tax: Id, CafeId, Name, Rate, IsDefault, IsRequired, IsCompound
EmployeeSalary: Id, EmployeeId(FK), MonthYear(string YYYY-MM),
BaseSalary, OvertimePay, Deductions, NetSalary, IsPaid
Attendance: Id, EmployeeId(FK), Date, ClockIn, ClockOut, Notes
Shift: Id, EmployeeId(FK), DayOfWeek(int), ShiftType(enum: Morning/Evening/Off)
LeaveRequest: Id, EmployeeId(FK), StartDate, EndDate, Reason,
Status(enum: Pending/Approved/Rejected), ReviewedBy
Enums to create in Meezi.Core/Enums/:
PlanTier: Free, Pro, Business, Enterprise
OrderType: DineIn, Takeaway, Delivery
OrderStatus: Pending, Confirmed, Preparing, Ready, Delivered, Cancelled
PaymentMethod: Cash, Card, Credit
EmployeeRole: Owner, Manager, Cashier, Waiter, Chef, Delivery
CustomerGroup: Regular, VIP, New, Employee
CouponType: Percentage, FixedAmount, FreeItem
ShiftType: Morning, Evening, DayOff
Then create AppDbContext in Meezi.Infrastructure/Data/AppDbContext.cs
with all DbSets and proper relationships.
Create the initial EF migration called "InitialCreate".
```
---
## مرحله ۵ — Auth System
```
Build the complete auth system for Meezi:
1. In Meezi.Infrastructure/ExternalServices/KavenegarSmsService.cs:
- HTTP client calling Kavenegar REST API
- Method: SendOtpAsync(string phone, string otp)
- Read API key from IConfiguration
2. In Meezi.API/Services/AuthService.cs:
- SendOtpAsync(string phone):
* Generate 6-digit OTP
* Store in Redis with key "otp:{phone}" TTL 5 minutes
* Store attempt counter "otp:attempts:{phone}" TTL 1 hour
* Block if attempts > 5 (return error RATE_LIMITED)
* Call KavenegarSmsService
- VerifyOtpAsync(string phone, string code, string cafeId):
* Check Redis for code
* If valid: generate JWT with claims { userId, cafeId, role, planTier, lang }
* Delete OTP from Redis
* Return token + refresh token
3. In Meezi.API/Controllers/AuthController.cs:
POST /api/auth/send-otp → body: { phone }
POST /api/auth/verify-otp → body: { phone, code }
POST /api/auth/refresh → body: { refreshToken }
4. In Meezi.API/Middleware/TenantMiddleware.cs:
- Extract cafeId from JWT claims
- Inject ITenantContext into request scope
- Return 401 if cafeId missing on protected routes
5. In Meezi.API/Middleware/PlanLimitMiddleware.cs:
- Read planTier from JWT
- Check against PlanLimits constants
- Return PLAN_LIMIT_REACHED error if exceeded
JWT claims: { sub: userId, cafeId, role, planTier, lang, iat, exp }
Token expiry: 7 days access, 30 days refresh
```
---
## مرحله ۶ — Core POS APIs
```
Build these API endpoints in Meezi.API/Controllers/:
MenuController.cs:
GET /api/cafes/{cafeId}/menu/categories
POST /api/cafes/{cafeId}/menu/categories
PATCH /api/cafes/{cafeId}/menu/categories/{id}
DELETE /api/cafes/{cafeId}/menu/categories/{id}
GET /api/cafes/{cafeId}/menu/items
POST /api/cafes/{cafeId}/menu/items
PATCH /api/cafes/{cafeId}/menu/items/{id}
PATCH /api/cafes/{cafeId}/menu/items/{id}/availability
TablesController.cs:
GET /api/cafes/{cafeId}/tables
POST /api/cafes/{cafeId}/tables → auto-generate QR code URL
GET /api/q/{qrCode} → public, returns cafeSlug + tableId
OrdersController.cs:
GET /api/cafes/{cafeId}/orders → with status filter
POST /api/cafes/{cafeId}/orders → create + check plan limits
PATCH /api/cafes/{cafeId}/orders/{id}/status
POST /api/cafes/{cafeId}/orders/{id}/payments → record payment(s)
GET /api/cafes/{cafeId}/orders/live → SSE or SignalR for KDS
Every controller must:
- Use [Authorize] attribute
- Validate CafeId matches JWT claim
- Use FluentValidation for request body
- Return ApiResponse<T> format
- Use async/await throughout
```
---
## مرحله ۷ — Next.js Dashboard
```bash
# از ریشه پروژه
mkdir web && cd web
npx create-next-app@latest dashboard --typescript --tailwind --app --src-dir
cd dashboard
# پکیج‌های اضافی
pnpm add @tanstack/react-query zustand next-intl date-fns-jalali
pnpm add @hookform/resolvers react-hook-form zod
pnpm add recharts lucide-react
pnpm add -D @types/node
```
### در Cursor:
```
Set up the Next.js 14 dashboard for Meezi with these steps:
1. Configure next-intl for 3 locales: fa (default, RTL), ar (RTL), en (LTR)
- Create messages/fa.json, messages/ar.json, messages/en.json
- Wrap app in [locale] dynamic route
- Set dir="rtl" for fa/ar, dir="ltr" for en
- Load Vazirmatn font for fa/ar, Inter for en
2. Install and configure shadcn/ui:
npx shadcn-ui@latest init
Add components: button, input, card, dialog, table, select,
badge, skeleton, toast, sheet, dropdown-menu
3. Create the app layout at app/[locale]/(dashboard)/layout.tsx:
- Sidebar with icons for: POS, CRM, Coupons, Inventory, HR,
Reports, Reservations, SMS, Taxes, Settings
- Top bar with: cafe name, plan badge, language switcher, user menu
- RTL-aware: sidebar on RIGHT for fa/ar, LEFT for en
4. Create Zustand store at lib/stores/cart.store.ts:
State: { items: CartItem[], couponCode, appliedCoupon, tableId }
Actions: addItem, removeItem, updateQty, applyCoupon, clearCart
5. Create API client at lib/api/client.ts:
- Axios instance with baseURL from env
- JWT interceptor (attach token from localStorage)
- 401 interceptor (redirect to login)
- Response unwrapper (extract .data from ApiResponse<T>)
6. Create the main POS page at app/[locale]/(dashboard)/pos/page.tsx:
- Left panel (60%): category tabs + item grid (3 cols)
- Right panel (40%): order items + coupon + tax + split payment
- All text from fa.json translation keys
- Farsi numbers everywhere
- Toman currency format
```
---
## مرحله ۸ — Flutter App
```bash
# از ریشه پروژه
mkdir mobile && cd mobile
flutter create meezi_app --org ir.meezi --platforms android,ios,windows
cd meezi_app
```
### `pubspec.yaml` — جایگزین کن:
```yaml
name: meezi_app
description: Meezi - میزی - سیستم کافه و رستوران
environment:
sdk: '>=3.3.0 <4.0.0'
flutter: ">=3.19.0"
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# State
flutter_riverpod: ^2.5.1
riverpod_annotation: ^2.3.5
# Navigation
go_router: ^14.2.0
# HTTP
dio: ^5.4.3
retrofit: ^4.3.0
# Local DB (offline)
drift: ^2.18.0
sqlite3_flutter_libs: ^0.5.24
path_provider: ^2.1.3
path: ^1.9.0
# i18n
intl: ^0.19.0
# Shamsi date
shamsi_date: ^1.1.1
# QR
qr_flutter: ^4.1.0
mobile_scanner: ^5.2.3
# Printer
esc_pos_utils_plus: ^2.0.1
bluetooth_print: ^4.4.0
# Notifications
firebase_messaging: ^15.1.0
flutter_local_notifications: ^17.2.3
# Storage
flutter_secure_storage: ^9.2.2
shared_preferences: ^2.3.2
# UI
cached_network_image: ^3.3.1
image_picker: ^1.1.2
shimmer: ^3.0.0
flutter_svg: ^2.0.10+1
# Utils
freezed_annotation: ^2.4.1
json_annotation: ^4.9.0
equatable: ^2.0.5
uuid: ^4.4.2
dev_dependencies:
flutter_test:
sdk: flutter
build_runner: ^2.4.11
freezed: ^2.5.2
json_serializable: ^6.8.0
retrofit_generator: ^8.1.0
riverpod_generator: ^2.4.0
drift_dev: ^2.18.0
```
### در Cursor:
```
Set up the Flutter app structure for Meezi following feature-first architecture.
Create this folder structure in lib/:
app/
router.dart → GoRouter with all routes
providers.dart → Riverpod ProviderScope setup
features/
auth/ → OTP login screen
pos/ → Owner POS tablet view
menu/ → Customer menu browse
cart/ → Cart + checkout
track/ → Order tracking
reserve/ → Table reservation
discover/ → کافه‌یاب discovery
hr/ → Employee clock-in + leave request
profile/ → Customer profile + history
core/
api/
api_client.dart → Dio + Retrofit setup
interceptors.dart → JWT + error interceptors
db/
app_database.dart → Drift database
daos/ → Data access objects
sync/
sync_engine.dart → Offline queue + sync logic
i18n/
app_localizations.dart
utils/
jalali_utils.dart → shamsi_date helpers
currency_utils.dart → Toman formatting
shared/
widgets/
theme/
app_theme.dart → RTL-aware theme
Routes to create in router.dart:
/ → redirect to /discover or /pos based on user role
/login → OTP auth screen
/discover → Café discovery (public)
/cafe/:slug → Café public profile
/cafe/:slug/menu → Menu (reads tableId from QR)
/cafe/:slug/cart → Checkout
/order/:id/track → Delivery tracking
/reserve/:slug → Table reservation
/pos → Owner POS (requires OWNER/MANAGER/CASHIER role)
/profile → Customer profile
Configure localization for fa (RTL), ar (RTL), en (LTR).
Create MaterialApp.router with locale switching support.
```
---
## مرحله ۹ — Docker و اجرای محلی
```bash
# از ریشه پروژه
docker-compose up -d
# PostgreSQL روی port 5432 بالا می‌آید
# Redis روی port 6379
# Migration اجرا کن
cd src/Meezi.API
dotnet ef database update
# Backend اجرا کن
dotnet run
# روی https://localhost:7001 بالا می‌آید
# Dashboard اجرا کن (terminal جدید)
cd web/dashboard
pnpm dev
# روی http://localhost:3000 بالا می‌آید
# Flutter اجرا کن (terminal جدید)
cd mobile/meezi_app
flutter run -d chrome # برای تست وب
flutter run # برای اندروید/شبیه‌ساز
```
---
## مرحله ۱۰ — Prompt های آماده برای هر ماژول
### CRM + جستجو با کد ملی:
```
Build the CRM module:
- GET /api/cafes/{cafeId}/customers?q={search}
Search by name, phone, or nationalId (10-digit)
- POST /api/cafes/{cafeId}/customers
Fields: name, phone, nationalId, birthDateJalali (YYYY/MM/DD), group
- Check FREE plan limit: max 50 customers → return PLAN_LIMIT_REACHED
- Next.js page: /crm with search input, customer cards, add modal
- All in Farsi with RTL layout
```
### HR + حضور و غیاب Flutter:
```
Build the HR attendance feature in Flutter:
- Screen: features/hr/attendance_screen.dart
- Show employee's today shift (Morning 8-16 / Evening 16-00 / DayOff)
- Clock In button: POST /api/employees/{id}/attendance/clock-in
- Clock Out button: POST /api/employees/{id}/attendance/clock-out
- Leave request form: reason + date range in Shamsi calendar
- Works OFFLINE: queue attendance locally, sync when online
- Shamsi date display throughout
- Farsi UI with RTL layout
```
### KDS آشپزخانه realtime:
```
Build the Kitchen Display System:
- SignalR Hub in Meezi.API/Hubs/KdsHub.cs
- Group orders by cafeId
- Broadcast new orders to kitchen screen
- Broadcast status changes
- Next.js page: /kds
- Connect to SignalR hub
- Show live order cards (Pending → Preparing → Ready)
- Color coded: yellow=Pending, blue=Preparing, green=Ready
- Each card: table number, items list, time elapsed
- Click to advance status
- Auto-refresh every 30s as fallback
- All Farsi, RTL layout
```
### گزارش مالی + Excel خروجی:
```
Build the reports API:
GET /api/cafes/{cafeId}/reports/daily?date=1403-10-16
Returns: totalOrders, newCustomers, returningCustomers,
revenue, taxTotal, discountTotal, topItems(5)
GET /api/cafes/{cafeId}/reports/monthly?month=1403-10
Returns: daily breakdown, totalRevenue, totalCosts breakdown
(salary from EmployeeSalary, plus manual cost entries)
netProfit = revenue - costs
GET /api/cafes/{cafeId}/reports/export?month=1403-10&format=excel
Returns: Excel file using EPPlus
Sheets: Sales, Items, Customers, Employees
Next.js page /reports:
- Stats cards: today customers (new vs returning)
- Bar chart (Recharts): 7-day revenue vs cost
- Top items list
- Monthly P&L table
- Export button
All Farsi, RTL, Toman currency, Shamsi dates
```
### پرداخت ZarinPal:
```
Build ZarinPal subscription payment in C#:
1. PaymentService.cs:
- InitiateSubscriptionAsync(cafeId, planTier, months):
* Call ZarinPal /pg/v4/payment/request.json
* Store pending payment record
* Return payment URL
- VerifyPaymentAsync(authority, status):
* Call ZarinPal /pg/v4/payment/verify.json
* On success: update cafe PlanTier + PlanExpiresAt
* Send confirmation SMS via Kavenegar
2. BillingController.cs:
POST /api/billing/subscribe → body: { planTier, months }
→ returns { paymentUrl }
GET /api/billing/verify?Authority=...&Status=OK
→ ZarinPal callback, redirect to dashboard
GET /api/billing/status
→ current plan, expiry, usage stats
3. Hangfire job: SubscriptionRenewalReminderJob
- Run daily
- Find cafes expiring in 3 days
- Send SMS reminder via Kavenegar
```
### Snappfood Integration:
```
Build Snappfood webhook receiver:
POST /api/webhooks/snappfood (no auth, verify with HMAC secret)
- Parse Snappfood order payload
- Map to Meezi Order:
* OrderType = Delivery
* Status = Confirmed (already paid via Snappfood)
* SnappfoodOrderId = external ID
* Items mapped from Snappfood items to MenuItems by name match
- Save order to DB
- Broadcast to KDS via SignalR
- Return 200 OK within 5 seconds
Also:
PATCH /api/cafes/{cafeId}/orders/{id}/status
- When status → Delivered: notify Snappfood API if SnappfoodOrderId exists
```
---
## مرحله ۱۱ — اشتباهات رایج که باید از آن‌ها بپرهیزی
```
❌ نکن:
- Console.WriteLine در C# → از ILogger<T> استفاده کن
- ml-4 یا mr-4 در Next.js → از ms-4 و me-4 استفاده کن
- new Date() برای نمایش تاریخ → از date-fns-jalali استفاده کن
- متن فارسی hardcode در کامپوننت → همه در fa.json باشد
- query بدون .Where(x => x.CafeId == cafeId) → داده tenant دیگر برمی‌گرداند
- setState در Flutter برای business logic → از Riverpod استفاده کن
- .Result یا .Wait() در C# → deadlock می‌دهد
✅ بکن:
- هر mutation در Flutter اول به Drift ذخیره کن، بعد sync کن
- هر endpoint با [Authorize] + validate CafeId شروع کن
- هر string قابل نمایش را در fa.json/ar.json/en.json بریز
- تمام اعداد نمایشی را با .toLocaleString('fa-IR') فرمت کن
- هر job background را در Hangfire بریز، نه await inline
```
---
## مرحله ۱۲ — ترتیب توسعه پیشنهادی (Solo با Cursor)
```
هفته ۱-۲: Backend foundation (auth + schema + tenant middleware)
هفته ۳-۴: POS core (menu + orders + tables + QR + payments)
هفته ۵-۶: Dashboard Next.js (POS screen + KDS + basic reports)
هفته ۷-۸: CRM + Coupons + SMS marketing (Kavenegar)
هفته ۹-۱۰: HR module (shifts + attendance + payroll)
هفته ۱۱-۱۲: Flutter customer app (QR + menu + cart + reservation)
هفته ۱۳-۱۴: Discovery platform (کافه‌یاب) + Reviews
هفته ۱۵-۱۶: ZarinPal billing + Taraz + Snappfood + production deploy
اولین beta: 5 کافه در شمال تهران — هفته ۸
اولین پول: هفته ۱۶
```
---
## چک‌لیست شروع روز اول
```
[ ] Node 20+ نصب است
[ ] .NET 10 SDK نصب است
[ ] Flutter 3.x نصب است
[ ] Docker Desktop در حال اجرا است
[ ] Cursor نصب است و باز است
[ ] پوشه meezi/ ساخته شده
[ ] .cursorrules در ریشه قرار دارد
[ ] MEEZI_PRD.md در ریشه قرار دارد
[ ] docker-compose up -d اجرا شده
[ ] در Cursor: Cmd+L → "Read .cursorrules and MEEZI_PRD.md,
then start Sprint 1: create the .NET solution structure"
```