Go to file
2026-06-02 13:35:49 +07:00
static/src feat: implement robust note splitting and defensive JSON parsing for POS order lines and customer display 2026-06-02 13:35:49 +07:00
__manifest__.py feat: implement robust note splitting and defensive JSON parsing for POS order lines and customer display 2026-06-02 13:35:49 +07:00
.gitignore feat: implement mobile-responsive portrait mode layout for PoS screens with tab-based navigation 2026-05-26 08:43:33 +07:00
README.md feat: implement portrait mode enhancements including category dropdown and optimized numpad actions 2026-06-02 08:34:24 +07:00

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
Categories Horizontal scrollable chips Compact hierarchical select dropdown
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 (shows only selected line)
Actions (Pay/Send/Checker) Inside left pane action pad Always-visible bottom strip
Navbar Full labels Compact with smaller padding

Category Dropdown

In portrait mode, the category selector is transformed into a compact dropdown list. It lists all active POS categories formatted hierarchically with indentation, making it extremely easy to filter products on small touch screens.

Selected Line Actions (Note & Delete)

The Numpad tab contains actions for modifying the selected orderline:

  • Note: Triggers the standard customer note input dialog.
  • Delete: Instantly removes the selected line from the cart.

Numpad Single Line Focus

To prevent overlaps on 5.8-inch screens:

  • Cart Tab: Shows only the order lines (full height). The numpad is hidden.
  • Numpad Tab: Hides all non-selected lines and hides the order summary block, showing only the selected line and the numpad/actions. If no item is selected, a friendly guide card is displayed.

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:

  1. The basic_receipt option is enabled in POS settings.
  2. The current cashier's role is either waiter or cashier.

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:

  1. The POS is in restaurant mode (module_pos_restaurant = True)
  2. At least one Preparation Category is configured in POS → Kitchen Printers settings
  3. The current order has unsent changes (nbrOfChanges > 0)
  4. The order is not a direct sale / refund

This mirrors Odoo's standard restaurant swapButton logic exactly.


Installation

  1. Copy the pos_ui_optimization folder into your customaddons directory
  2. Restart the Odoo server
  3. Go to Apps → search for POS UI Optimization → Install
  4. 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/
│       │   │   ├── category_selector/
│       │   │   │   ├── category_selector_patch.js # Hierarchical dropdown list
│       │   │   │   └── category_selector_patch.xml
│       │   │   ├── 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