5.5 KiB
POS UI Optimization
Odoo 19 | Custom Addon
Optimizes the Point of Sale UI for resource-constrained devices and adds a switchable portrait display mode designed for 6-inch touchscreen terminals.
Features
1. Incremental Product Rendering
Prevents low-RAM devices from freezing when the product catalogue is large.
- Only 40 products are rendered on initial load
- More products load automatically as the user scrolls down
- Resets the counter when the search word or category changes
2. Incremental Order Line Rendering
Same approach for the order/cart display.
- Only 20 order lines rendered initially
- Scrolling loads more lines progressively
- Ensures the selected line is always visible (expands count if needed)
3. Hide Invoice Button
Hides the "Invoice" button on the payment stage (Payment Screen) and expands the Customer/Partner button to full width, preventing cashiers from using this button.
4. Portrait Mode (6-inch Display)
A dedicated compact layout for portrait-orientation small screens. Designed for devices like 6-inch Android POS terminals where the standard Odoo two-column layout clutters the screen.
Layout
┌──────────────────────────────────────┐
│ Navbar (compact) │
├──────────────────────────────────────┤
│ │
│ Active tab pane: │
│ Products / Cart / Numpad │
│ │
├──────────────────────────────────────┤
│ TOTAL: Rp X,XX [Checker] [Send] [Pay]│ ← always visible
├──────────────────────────────────────┤
│ [Products] [Cart] [Numpad] │ ← bottom tab bar
└──────────────────────────────────────┘
Key Differences from Standard Mode
| Feature | Standard | Portrait |
|---|---|---|
| Layout | Two-column (order left, products right) | Single pane with bottom tabs |
| Product grid | auto-fill minmax(115px) |
Fixed 2 columns |
| Product images | Full aspect ratio | Capped at 90px height |
| Numpad | Shown inline in left pane | Dedicated "Numpad" tab |
| Actions (Pay/Send/Checker) | Inside left pane action pad | Always-visible bottom strip |
| Navbar | Full labels | Compact with smaller padding |
Table Checker Button
The Checker button is available in the bottom pay strip in portrait mode. It allows waiters or cashiers to quickly print a basic table checker receipt.
The button is visible only when:
- The
basic_receiptoption is enabled in POS settings. - The current cashier's role is either
waiterorcashier.
The button is disabled when the current order is empty.
Auto-Activation
Portrait mode auto-activates when the browser viewport width is < 400 px on first load. A manual override is always available via the burger menu (☰ → Switch to Portrait/Standard Mode). The choice is saved to localStorage.
Send Button Behavior
The Send button appears only when:
- The POS is in restaurant mode (
module_pos_restaurant = True) - At least one Preparation Category is configured in POS → Kitchen Printers settings
- The current order has unsent changes (
nbrOfChanges > 0) - The order is not a direct sale / refund
This mirrors Odoo's standard restaurant swapButton logic exactly.
Installation
- Copy the
pos_ui_optimizationfolder into yourcustomaddonsdirectory - Restart the Odoo server
- Go to Apps → search for POS UI Optimization → Install
- Reload your POS session
Upgrade
./odoo-bin -u pos_ui_optimization -d <your_database>
Compatibility
| Item | Value |
|---|---|
| Odoo version | 19.0 |
| Depends on | point_of_sale |
| Compatible with | pos_restaurant, pos_custom_access, pos_kitchen_printer |
| License | LGPL-3 |
File Structure
pos_ui_optimization/
├── __manifest__.py
├── README.md
├── static/
│ └── src/
│ ├── app/
│ │ ├── components/
│ │ │ ├── navbar/
│ │ │ │ ├── navbar_patch.js # Display Mode toggle in burger menu
│ │ │ │ └── navbar_patch.xml
│ │ │ └── order_display/
│ │ │ ├── order_display_patch.js # Incremental order line rendering
│ │ │ └── order_display_patch.xml
│ │ ├── screens/
│ │ │ ├── payment_screen/
│ │ │ │ └── payment_screen_patch.xml # Hide Invoice button patch
│ │ │ └── product_screen/
│ │ │ ├── portrait_mode_patch.js # Tab state (products/cart/numpad)
│ │ │ ├── portrait_screen.xml # Portrait layout XML patch
│ │ │ ├── product_screen_patch.js # Incremental product rendering
│ │ │ └── product_screen_patch.xml
│ │ └── services/
│ │ └── portrait_mode.js # Auto-detect + localStorage service
│ └── scss/
│ └── portrait.scss # All portrait CSS (scoped to .pos-portrait)
Author
Suherdy Yacob