From d073defbda114edeefc38afbb470d1f431245b08 Mon Sep 17 00:00:00 2001 From: metatroncubeswdev Date: Fri, 12 Jun 2026 19:49:53 -0400 Subject: [PATCH] implemented the equal spilt option --- addons/dine360_restaurant/__manifest__.py | 7 + .../static/src/css/equal_split.css | 51 +++++++ .../static/src/js/equal_split.js | 131 ++++++++++++++++++ .../static/src/xml/equal_split.xml | 79 +++++++++++ 4 files changed, 268 insertions(+) create mode 100644 addons/dine360_restaurant/static/src/css/equal_split.css create mode 100644 addons/dine360_restaurant/static/src/js/equal_split.js create mode 100644 addons/dine360_restaurant/static/src/xml/equal_split.xml diff --git a/addons/dine360_restaurant/__manifest__.py b/addons/dine360_restaurant/__manifest__.py index 46c63c4..8e62186 100644 --- a/addons/dine360_restaurant/__manifest__.py +++ b/addons/dine360_restaurant/__manifest__.py @@ -23,6 +23,13 @@ 'views/res_users_views.xml', 'views/product_template_views.xml', ], + 'assets': { + 'point_of_sale._assets_pos': [ + 'dine360_restaurant/static/src/css/equal_split.css', + 'dine360_restaurant/static/src/js/equal_split.js', + 'dine360_restaurant/static/src/xml/equal_split.xml', + ], + }, 'installable': True, 'application': True, 'license': 'LGPL-3', diff --git a/addons/dine360_restaurant/static/src/css/equal_split.css b/addons/dine360_restaurant/static/src/css/equal_split.css new file mode 100644 index 0000000..86a1d45 --- /dev/null +++ b/addons/dine360_restaurant/static/src/css/equal_split.css @@ -0,0 +1,51 @@ +/* Equal Split Panel — dine360_restaurant */ + +.equal-split-toggle-bar { + min-height: 44px; + background-color: #f8f9fa; +} + +.equal-split-toggle-btn { + min-width: 130px; +} + +.equal-split-panel { + background: #fff; + animation: slideDown 0.18s ease-out; +} + +@keyframes slideDown { + from { opacity: 0; transform: translateY(-6px); } + to { opacity: 1; transform: translateY(0); } +} + +.equal-split-counter-btn { + width: 52px; + height: 52px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.1rem; +} + +.equal-split-count-display { + min-width: 60px; +} + +.equal-split-count-number { + font-size: 2.4rem; + line-height: 1.1; + color: #2c3e50; +} + +.equal-split-amount-box { + background: #e8f4fd; + border: 2px solid #3498db; + min-width: 200px; +} + +.equal-split-amount { + font-size: 2rem; + color: #2980b9; +} diff --git a/addons/dine360_restaurant/static/src/js/equal_split.js b/addons/dine360_restaurant/static/src/js/equal_split.js new file mode 100644 index 0000000..0158d20 --- /dev/null +++ b/addons/dine360_restaurant/static/src/js/equal_split.js @@ -0,0 +1,131 @@ +/** @odoo-module */ + +import { SplitBillScreen } from "@pos_restaurant/app/split_bill_screen/split_bill_screen"; +import { patch } from "@web/core/utils/patch"; +import { useState } from "@odoo/owl"; + +patch(SplitBillScreen.prototype, { + setup() { + super.setup(...arguments); + this.equalSplit = useState({ + active: false, + numPeople: 2, + }); + }, + + toggleEqualSplit() { + this.equalSplit.active = !this.equalSplit.active; + }, + + decreasePeople() { + if (this.equalSplit.numPeople > 2) { + this.equalSplit.numPeople--; + } + }, + + increasePeople() { + if (this.equalSplit.numPeople < 20) { + this.equalSplit.numPeople++; + } + }, + + get equalAmountPerPerson() { + const order = this.pos.get_order(); + if (!order || this.equalSplit.numPeople < 1) return 0; + return order.getTotalWithTax() / this.equalSplit.numPeople; + }, + + get formattedEqualAmount() { + return this.env.utils.formatCurrency(this.equalAmountPerPerson); + }, + + get formattedOrderTotal() { + const order = this.pos.get_order(); + if (!order) return this.env.utils.formatCurrency(0); + return this.env.utils.formatCurrency(order.getTotalWithTax()); + }, + + // Intercept pay() to auto-assign proportional lines when equal split is active + async pay() { + if (this.equalSplit.active) { + await this._payEqualSplit(); + } else { + await super.pay(...arguments); + } + }, + + async _payEqualSplit() { + const order = this.pos.get_order(); + if (!order) return; + + const lines = order.get_orderlines(); + if (lines.length === 0) return; + + const N = this.equalSplit.numPeople; + const total = order.getTotalWithTax(); + const target = Math.round((total / N) * 100) / 100; + + let accumulated = 0; + const splitData = {}; + + // Greedy fill: assign lines until we reach the per-person target amount + for (const line of lines) { + if (accumulated >= target - 0.005) break; + + const lineTotal = this._getLineTotal(line); + const perUnit = line.qty > 0 ? lineTotal / line.qty : 0; + if (perUnit <= 0) continue; + + const needed = target - accumulated; + + if (lineTotal <= needed + 0.005) { + // Take the full line + splitData[line.uid] = line.qty; + accumulated += lineTotal; + } else { + // Take a partial quantity to fill up to target + const qtyToTake = Math.round((needed / perUnit) * 1000) / 1000; + if (qtyToTake > 0.001) { + splitData[line.uid] = qtyToTake; + accumulated += qtyToTake * perUnit; + } + } + } + + // Write into whichever splitlines object the screen uses + this._setSplitlines(splitData); + + await super.pay(...arguments); + }, + + _getLineTotal(line) { + // Try the standard Odoo 17 method, fall back to price * qty + if (typeof line.get_price_with_tax === "function") { + return line.get_price_with_tax(); + } + if (typeof line.getDisplayData === "function") { + const d = line.getDisplayData(); + return d.totalPrice || line.price * line.qty; + } + return (line.price || 0) * (line.qty || 1); + }, + + _setSplitlines(newLines) { + // Odoo 17 may store splitlines on this.splitlines or this.state.splitlines + const target = + this.splitlines !== undefined + ? this.splitlines + : this.state && this.state.splitlines !== undefined + ? this.state.splitlines + : null; + + if (!target) return; + + for (const key of Object.keys(target)) { + delete target[key]; + } + for (const [uid, qty] of Object.entries(newLines)) { + target[uid] = qty; + } + }, +}); diff --git a/addons/dine360_restaurant/static/src/xml/equal_split.xml b/addons/dine360_restaurant/static/src/xml/equal_split.xml new file mode 100644 index 0000000..65ae798 --- /dev/null +++ b/addons/dine360_restaurant/static/src/xml/equal_split.xml @@ -0,0 +1,79 @@ + + + + + + + + + +
+ + By Item + + +
+ + +
+ + +
+ Order Total: +
+ + +
+ + +
+
+
people
+
+ + +
+ + +
+
Each person pays
+
+
+ +
+ + Press Charge to collect from the first person. + Repeat for each person. +
+ +
+ + + + + +