new fix updated

This commit is contained in:
metatroncubeswdev 2026-06-12 20:04:35 -04:00
parent bdea15d7f0
commit c29a74a41b
2 changed files with 96 additions and 135 deletions

View File

@ -1,74 +1,55 @@
/** @odoo-module */
import { SplitBillScreen } from "@pos_restaurant/overrides/components/split_bill_screen/split_bill_screen";
import { patch } from "@web/core/utils/patch";
import { useState } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { usePos } from "@point_of_sale/app/store/pos_hook";
import { Component, useState } from "@odoo/owl";
export class EqualSplitScreen extends Component {
static template = "dine360_restaurant.EqualSplitScreen";
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--;
this.pos = usePos();
this.state = useState({ numPeople: 2 });
}
},
increasePeople() {
if (this.equalSplit.numPeople < 20) {
this.equalSplit.numPeople++;
get order() {
return this.pos.get_order();
}
},
get equalAmountPerPerson() {
const order = this.pos.get_order();
if (!order || this.equalSplit.numPeople < 1) return 0;
return order.getTotalWithTax() / this.equalSplit.numPeople;
},
get formattedTotal() {
const order = this.order;
return this.env.utils.formatCurrency(order ? order.getTotalWithTax() : 0);
}
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);
const order = this.order;
if (!order || this.state.numPeople < 1) return this.env.utils.formatCurrency(0);
return this.env.utils.formatCurrency(order.getTotalWithTax() / this.state.numPeople);
}
},
async _payEqualSplit() {
const order = this.pos.get_order();
decreasePeople() {
if (this.state.numPeople > 2) this.state.numPeople--;
}
increasePeople() {
if (this.state.numPeople < 20) this.state.numPeople++;
}
back() {
this.pos.showScreen("SplitBillScreen");
}
async chargeCurrentPerson() {
const order = this.order;
if (!order) return;
const lines = order.get_orderlines();
if (lines.length === 0) return;
const N = this.equalSplit.numPeople;
const N = this.state.numPeople;
const total = order.getTotalWithTax();
const target = Math.round((total / N) * 100) / 100;
const lines = order.get_orderlines();
const splitlines = {};
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;
@ -79,53 +60,27 @@ patch(SplitBillScreen.prototype, {
const needed = target - accumulated;
if (lineTotal <= needed + 0.005) {
// Take the full line
splitData[line.uid] = line.qty;
splitlines[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;
splitlines[line.uid] = qtyToTake;
accumulated += qtyToTake * perUnit;
}
}
}
// Write into whichever splitlines object the screen uses
this._setSplitlines(splitData);
await super.pay(...arguments);
},
if (typeof this.pos.splitOrder === "function") {
await this.pos.splitOrder(order, splitlines);
}
this.pos.showScreen("PaymentScreen");
}
_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;
}
if (typeof line.get_price_with_tax === "function") return line.get_price_with_tax();
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;
}
},
});
registry.category("pos_screens").add("EqualSplitScreen", EqualSplitScreen);

View File

@ -1,79 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!--
Extends the pos_restaurant SplitBillScreen to add an "Equal Split" panel.
The panel is injected at the top of the screen via xpath on the root div.
Cashier picks the number of people → presses "Charge" → the system
auto-assigns proportional items to the split order and navigates to payment.
-->
<t t-name="dine360_restaurant.EqualSplitPatch"
t-inherit="pos_restaurant.SplitBillScreen"
t-inherit-mode="extension"
owl="1">
<!-- Standalone Equal Split screen — no SplitBillScreen import needed -->
<t t-name="dine360_restaurant.EqualSplitScreen" owl="1">
<div class="equal-split-screen screen d-flex flex-column h-100">
<xpath expr="//div[hasclass('split-bill-screen')]" position="prepend">
<!-- Toggle bar — always visible at the top of the split screen -->
<div class="equal-split-toggle-bar d-flex align-items-center justify-content-between px-3 py-2 border-bottom bg-light">
<span class="fw-semibold text-muted small">
<i class="fa fa-cut me-1"/>By Item
</span>
<button
t-attf-class="btn btn-sm equal-split-toggle-btn {{ equalSplit.active ? 'btn-primary' : 'btn-outline-primary' }}"
t-on-click="toggleEqualSplit">
<i class="fa fa-users me-1"/>
Equal Split
<i t-attf-class="fa ms-1 {{ equalSplit.active ? 'fa-chevron-up' : 'fa-chevron-down' }}"/>
<!-- Header -->
<div class="d-flex align-items-center px-3 py-3 border-bottom bg-light">
<button class="btn btn-secondary me-3" t-on-click="back">
<i class="fa fa-arrow-left me-1"/>Back to Split
</button>
<h4 class="mb-0 fw-bold">
<i class="fa fa-users me-2"/>Equal Split
</h4>
</div>
<!-- Equal Split panel — shown only when toggled on -->
<div t-if="equalSplit.active" class="equal-split-panel d-flex flex-column align-items-center gap-3 p-4 border-bottom bg-white shadow-sm">
<!-- Body -->
<div class="d-flex flex-column align-items-center justify-content-center flex-grow-1 gap-4 p-4">
<!-- Order total reference -->
<div class="text-muted small">
Order Total: <strong t-esc="formattedOrderTotal"/>
<div class="text-muted fs-6">
Order Total: <strong t-esc="formattedTotal"/>
</div>
<!-- People counter -->
<div class="d-flex align-items-center gap-3">
<button
class="btn btn-outline-secondary btn-lg equal-split-counter-btn"
<div class="d-flex align-items-center gap-4">
<button class="btn btn-outline-secondary equal-split-counter-btn"
t-on-click="decreasePeople"
t-att-disabled="equalSplit.numPeople &lt;= 2">
t-att-disabled="state.numPeople &lt;= 2">
<i class="fa fa-minus"/>
</button>
<div class="text-center equal-split-count-display">
<div class="equal-split-count-number fw-bold" t-esc="equalSplit.numPeople"/>
<div class="text-center">
<div class="equal-split-count-number fw-bold" t-esc="state.numPeople"/>
<div class="text-muted small">people</div>
</div>
<button
class="btn btn-outline-secondary btn-lg equal-split-counter-btn"
<button class="btn btn-outline-secondary equal-split-counter-btn"
t-on-click="increasePeople"
t-att-disabled="equalSplit.numPeople >= 20">
t-att-disabled="state.numPeople >= 20">
<i class="fa fa-plus"/>
</button>
</div>
<!-- Per-person amount -->
<div class="equal-split-amount-box text-center p-3 rounded">
<div class="text-muted small mb-1">Each person pays</div>
<div class="equal-split-amount-box text-center p-4 rounded">
<div class="text-muted mb-1 small">Each person pays</div>
<div class="equal-split-amount fw-bold" t-esc="formattedEqualAmount"/>
</div>
<div class="text-muted small text-center">
<!-- Charge button -->
<button class="btn btn-primary btn-lg px-5" t-on-click="chargeCurrentPerson">
<i class="fa fa-credit-card me-2"/>Charge This Person
</button>
<div class="text-muted small text-center" style="max-width: 320px;">
<i class="fa fa-info-circle me-1"/>
Press <strong>Charge</strong> to collect from the first person.
Repeat for each person.
After payment, return to the table and press Split again.
Decrease the count by 1 each time.
</div>
</div>
</div>
</t>
<!-- Inject "Equal Split" button at the top of the standard SplitBillScreen -->
<t t-name="dine360_restaurant.EqualSplitButton"
t-inherit="pos_restaurant.SplitBillScreen"
t-inherit-mode="extension"
owl="1">
<xpath expr="//div[hasclass('split-bill-screen')]" position="prepend">
<div class="equal-split-toggle-bar d-flex align-items-center justify-content-between px-3 py-2 border-bottom">
<span class="fw-semibold text-muted small">
<i class="fa fa-cut me-1"/>Split By Item
</span>
<button class="btn btn-sm btn-primary"
t-on-click="() => pos.showScreen('EqualSplitScreen')">
<i class="fa fa-users me-1"/>Equal Split
</button>
</div>
</xpath>
</t>
</templates>