URY is a complete restaurant order management system built as a Frappe/ERPNext custom app.
- Publisher: Tridz Technologies Pvt. Ltd
- Requires: ERPNext (must be installed in the Frappe bench)
- Version: 0.2.1
- License: MIT
The system covers the full restaurant workflow: menu management, table management, order taking (POS), kitchen display (KOT), payments (integrated with ERPNext POS), P&L reporting, and multi-branch support.
POS frontend is located in /pos and has its own AGENTS.MD with detailed documentation.
ury/ ← repo root
├── ury/ ← Frappe app Python package (main backend)
├── pos/ ← React 19 POS frontend (v2, current)
├── URYMosaic/ ← Vue 3 KOT kitchen display app
├── urypos/ ← Vue 3 POS frontend (v1, legacy)
├── DEMO/ ← Demo screenshots / assets
├── requirements.txt ← Python dependencies
├── setup.py ← Python package setup
├── package.json ← Yarn workspace root (manages all JS apps)
└── FEATURES.md / README.md ← Human-readable documentation
The Yarn workspace (package.json) at the root manages three JS sub-projects: pos/, URYMosaic/, and urypos/.
ury/
├── hooks.py ← App registration, doc_events, scheduler, fixtures
├── patches.txt ← Migration patch list
├── setup.py ← Custom field creation (add_custom_fields)
├── uninstall.py ← Cleanup on app removal
├── install.py ← Post-install setup
├── permission.py ← check_app_permission for app screen
│
├── ury_pos/
│ └── api.py ← Primary REST API for POS frontend (722 lines)
│ Whitelisted methods: getRestaurantMenu, getBranch,
│ getModeOfPayment, getPosProfile, getAggregatorItem,
│ createPaymentEntry, getInvoiceForCashier, etc.
│
├── ury/
│ ├── doctype/ ← 35 custom Frappe doctypes (see §4)
│ ├── hooks/ ← Document event handlers
│ │ ├── ury_pos_invoice.py ← before_insert, validate, before_submit, on_cancel
│ │ ├── ury_pos_profile.py ← validate
│ │ ├── ury_sales_invoice.py ← before_insert, on_update
│ │ ├── ury_item.py ← validate
│ │ ├── ury_pos_opening_entry.py ← set_cashier_room, before_save
│ │ └── ury_pos_closing_entry.py ← before_save, validate
│ ├── api/ ← Modular API handlers
│ │ ├── ury_kot_display.py ← KOT list, serve/confirm KOT
│ │ ├── ury_kot_order_number.py ← Daily order number logic
│ │ ├── ury_kot_validation.py ← Scheduled KOT validation (every minute)
│ │ ├── ury_kot_notification.py ← Order delay notifications
│ │ └── ury_menu_course_validation.py ← Course priority validation
│ └── page/
│ └── websocket_print/ ← Real-time print via websocket
│
├── www/ ← Web page Python context providers
│ ├── pos.py ← Boot context for /pos page
│ └── *.html ← Build output entry points (generated by Vite build)
│
├── public/ ← Static assets served by Frappe
│ ├── js/ ← Client-side JS injected via hooks.py
│ │ ├── quick_entry.js ← POS quick entry customisation
│ │ ├── pos_print.js ← Standard POS print customisation
│ │ ├── pos_extend.js ← Injected on /point-of-sale page
│ │ ├── restrict_qty_edit_pos.js ← Prevents qty edit in legacy POS
│ │ ├── ury_pos_kot.js ← KOT related JS
│ │ └── sign-message.js / jsrsasign-all-min.js ← QZ Tray signing
│ ├── pos/ ← Built React POS assets (output of `cd pos && yarn build`)
│ ├── URYMosaic/ ← Built KOT display assets
│ └── urypos/ ← Built legacy POS assets
│
├── fixtures/ ← Data fixtures exported via `bench export-fixtures`
│ ├── custom_field.json ← All custom fields definitions
│ ├── role.json ← URY Roles (URY Admin, URY Cashier…)
│ ├── property_setter.json ← Field label overrides
│ ├── custom_html_block.json
│ └── client_script.json
│
├── templates/
│ └── pages/ ← Jinja web page templates (currently minimal)
│
└── patches/
└── v2_0/
└── default_permissions.py ← Post-migration permission setup
| Doctype | Purpose |
|---|---|
URY Order |
Core order document. Created/updated by POS. Linked to POS Invoice on payment. |
URY Order Item |
Line items for URY Order. |
URY KOT |
Kitchen Order Ticket generated when an order is placed/modified. |
URY KOT Items |
Line items for a KOT. |
URY Menu |
Menu definition linked to a Restaurant and Price List. |
URY Menu Item |
Individual item in a menu with rate and image. |
URY Menu Course |
Course grouping (starter, main, dessert) with serve priority. |
URY Restaurant |
Restaurant master record. |
URY Table |
Table in a restaurant room. |
URY Room |
Section/room within a restaurant. |
URY Printer Settings |
Thermal printer configuration (IP, port, format). |
URY User |
Waiter/cashier assignment to a branch. |
Aggregator Settings |
Delivery platform (Zomato, Swiggy) configuration. |
Item Add On |
Modifier/add-on for a menu item. |
POS Item Variants |
Size/variant options for a menu item. |
URY Daily P and L |
Daily P&L report. |
URY Cost of Goods |
COGS tracking doctype. |
Sub POS Closing |
POS closing record per cashier. |
Custom fields added to standard ERPNext doctypes (via setup.py + fixtures/custom_field.json):
POS Invoice/Sales Invoice:order_type,waiter,no_of_pax,cashier,restaurant,branch,restaurant_table,invoice_printed,cancel_reason,custom_comments,custom_ury_order_numberPOS Profile:restaurant,branch,printer_settings,qz_print,qz_host,enable_discount,enable_multiple_cashier,reset_order_number_dailyPOS Opening Entry:restaurant,branch,custom_room,custom_roomsBranch:user(URY User table),custom_aggregatorsCustomer:mobile_numberPrice List:restaurant_menu
| DocType | Event | Handler |
|---|---|---|
POS Invoice |
before_insert |
Set arrived_time, validate restaurant/branch |
POS Invoice |
validate |
Validate order fields |
POS Invoice |
after_insert |
Set daily order number |
POS Invoice |
before_submit |
Final validation before submit |
POS Invoice |
on_cancel / on_trash |
Cleanup KOTs |
POS Profile |
validate |
Validate printer/restaurant setup |
Sales Invoice |
before_insert, on_update |
Copy restaurant fields from linked POS Invoice |
Item |
validate |
Validate menu item configuration |
POS Opening Entry |
validate |
Set cashier room assignment |
POS Opening Entry |
before_save |
Validation before save |
POS Opening Entry |
before_insert |
Set last invoice reference |
POS Closing Entry |
before_save, validate |
Closing validation |
Scheduler: ury.ury.api.ury_kot_validation.kotValidationThread runs every minute to validate KOT state.
- URY orders ultimately create POS Invoices (and Sales Invoices on consolidation) in ERPNext.
- Payment is processed via
make_invoicewhich calls ERPNext's POS payment flow. - Price Lists, Customers, Payment Modes, and Tax Templates are all standard ERPNext objects.
/pos— React POS v2 (seepos/AGENTS.MD)/urypos— Vue POS v1 (legacy,urypos/)/URYMosaic/<production_unit>— Vue KOT display (seeURYMosaic/AGENTS.MD)
All frontends are served as Frappe web pages. Route rules in hooks.py (website_route_rules) handle SPA routing:
{"from_route": "/pos/<path:app_path>", "to_route": "pos"},
{"from_route": "/URYMosaic/<path:app_path>", "to_route": "URYMosaic"},- KOT updates are broadcast via Frappe's Socket.io to the
URYMosaickitchen display. - Channel format:
kot_update_{branch}_{production_unit}
- Thermal printing uses QZ Tray (desktop app). The POS sends signed print jobs.
- Signing keys:
public/js/sign-message.js+jsrsasign-all-min.js - QZ host is configured per POS Profile (
qz_hostfield).
| App | Source | Build output | URL |
|---|---|---|---|
| POS v2 (React) | pos/src/ |
ury/public/pos/ |
/pos |
| KOT display (Vue) | URYMosaic/src/ |
ury/public/URYMosaic/ |
/URYMosaic/<unit> |
| POS v1 (Vue, legacy) | urypos/src/ |
ury/public/urypos/ |
/urypos |
Build commands (from repo root):
cd pos && yarn build # builds React POS
cd URYMosaic && yarn build # builds KOT display
cd urypos && yarn build # builds legacy POSOr from root: yarn build (if configured in root package.json).
After building, run bench build --app ury to copy assets to the Frappe public directory.
To modify POS UI behaviour or translations:
→ Work in pos/. Read pos/AGENTS.MD first.
To modify KOT display logic:
→ Work in URYMosaic/. Read URYMosaic/AGENTS.MD first.
To add or modify a Frappe API endpoint:
→ Edit ury/ury_pos/api.py (main POS API) or ury/ury/api/<module>.py.
→ Decorate with @frappe.whitelist(). No router config needed.
To add a new doctype:
→ Use bench new-doctype or create JSON in ury/ury/doctype/<name>/.
→ Export fixtures after changes: bench export-fixtures --app ury.
To add a custom field to a standard doctype:
→ Add via Frappe desk, then export with bench export-fixtures --app ury.
→ OR add programmatically in ury/setup.py add_custom_fields().
To add a migration patch:
→ Create file in ury/patches/v<major>_<minor>/.
→ Add path to ury/patches.txt under [post_model_sync].
To change document event behaviour:
→ Edit the relevant file in ury/ury/hooks/.
→ Hook registration is in hooks.py doc_events.
Never:
- Modify
ury/public/pos/,ury/public/URYMosaic/, orury/public/urypos/directly — these are build output, not source. - Edit
fixtures/custom_field.jsondirectly — export from Frappe desk instead. - Add business logic to
www/pos.py— it should only return boot context data.