[IMP] point_of_sale: cashbox opening popup.

Move the cashbox opening control from the left panel of the product screen widget to a popup that is raised at the opening of the session if its state is: opening_control.

task-id: 2321973
This commit is contained in:
Robin Heinz
2020-10-16 08:49:14 +00:00
committed by Pierre Masereel
parent 9d6f107b1c
commit 396918d638
5 changed files with 164 additions and 83 deletions
+43 -13
View File
@@ -3413,19 +3413,6 @@ td {
cursor: pointer;
}
.cashbox-input {
margin: auto;
line-height: 74px;
font-size: 16px;
border: solid 1px rgb(202, 202, 202);
border-top-width: 0px;
cursor: pointer;
padding-left: 30px;
padding-right: 30px;
flex-grow: 1;
flex-basis: 100%;
}
.currencyCashBox {
font-size: 30px;
}
@@ -3541,3 +3528,46 @@ td {
overflow: visible;
}
}
.pos .cashbox-button {
height: 54px;
width: 54px;
font-weight: bold;
vertical-align: middle;
color: #555555;
border-radius: 0;
border: none;
border-right: 1px solid;
border-bottom: 1px solid;
border-color: #bfbfbf;
transition: all 150ms linear;
}
.pos .cashbox-input {
line-height: 74px;
border: solid 1px rgb(202, 202, 202);
border-top-width: 0px;
cursor: pointer;
background: white;
display: flex;
justify-content: space-between;
}
.cashbox-input .input-title {
margin-left: 10px;
margin-right: 10px;
font-weight: bold;
font-size: 19px;
}
.cashbox-input .input-amount {
margin-left: 10px;
margin-right: 10px;
padding-right: 8px;
}
.cashbox-notes {
font-style: italic;
font-weight: 350;
width: 95%;
}
@@ -1,42 +1,71 @@
odoo.define('point_of_sale.CashBoxOpening', function(require) {
odoo.define('point_of_sale.CashOpeningPopup', function(require) {
'use strict';
const { useState, useRef} = owl.hooks;
const { useListener } = require('web.custom_hooks');
const NumberBuffer = require('point_of_sale.NumberBuffer');
const PosComponent = require('point_of_sale.PosComponent');
const AbstractAwaitablePopup = require('point_of_sale.AbstractAwaitablePopup');
const Registries = require('point_of_sale.Registries');
const { Gui } = require('point_of_sale.Gui');
class CashBoxOpening extends PosComponent {
class CashOpeningPopup extends AbstractAwaitablePopup {
constructor() {
super(...arguments);
this.changes = {};
this.defaultValue = this.env.pos.bank_statement.balance_start || 0;
this.symbol = this.env.pos.currency.symbol;
}
captureChange(event) {
this.changes[event.target.name] = event.target.value;
this.cashBoxValue = this.env.pos.bank_statement.balance_start || 0;;
this.currency = this.env.pos.currency;
this.state = useState({
notes: "",
});
useListener('numpad-click-input', this._updateCashAmount);
useListener('update-cash', this._updateCashAmount);
this.inputRef = useRef('input');
NumberBuffer.use({
nonKeyboardInputEvent: 'numpad-click-input',
triggerAtInput: 'update-cash',
useWithBarcode: false,
});
}
startSession() {
let cashOpening = this.changes.cashBoxValue? this.changes.cashBoxValue: this.defaultValue;
if(isNaN(cashOpening)) {
Gui.showPopup('ErrorPopup',{
'title': 'Wrong value',
'body': 'Please insert a correct value.',
});
if(!parseFloat(this.cashBoxValue))
return;
}
this.env.pos.bank_statement.balance_start = cashOpening;
this.env.pos.bank_statement.balance_start = parseFloat(this.cashBoxValue);
this.env.pos.pos_session.state = 'opened';
this.props.cashControl.cashControl = false;
this.rpc({
model: 'pos.session',
model: 'pos.session',
method: 'set_cashbox_pos',
args: [this.env.pos.pos_session.id, cashOpening, this.changes.notes],
args: [this.env.pos.pos_session.id, parseFloat(this.cashBoxValue), this.state.notes],
});
this.trigger('close-popup');
}
sendInput(value) {
this.trigger('numpad-click-input', { value });
}
async _updateCashAmount(event) {
let value = event.detail.value ? event.detail.value : event.detail.key
if(value !== "Backspace") {
if(this.cashBoxValue === 0) {
this.cashBoxValue = value !== "."? value: this.cashBoxValue + value;
} else {
this.cashBoxValue += value;
}
} else {
if(this.cashBoxValue.length > 1) {
this.cashBoxValue = this.cashBoxValue.substring(0, this.cashBoxValue.length -1)
} else {
this.cashBoxValue = 0;
}
}
this.render();
}
}
CashBoxOpening.template = 'CashBoxOpening';
Registries.Component.add(CashBoxOpening);
CashOpeningPopup.template = 'CashOpeningPopup';
Registries.Component.add(CashOpeningPopup);
return CashBoxOpening;
return CashOpeningPopup;
});
@@ -7,6 +7,7 @@ odoo.define('point_of_sale.ProductScreen', function(require) {
const { useListener } = require('web.custom_hooks');
const Registries = require('point_of_sale.Registries');
const { onChangeOrder, useBarcodeReader } = require('point_of_sale.custom_hooks');
const { Gui } = require('point_of_sale.Gui');
const { useState } = owl.hooks;
class ProductScreen extends ControlButtonsMixin(PosComponent) {
@@ -32,11 +33,13 @@ odoo.define('point_of_sale.ProductScreen', function(require) {
triggerAtInput: 'update-selected-orderline',
useWithBarcode: true,
});
let status = this.showCashBoxOpening()
this.state = useState({ cashControl: status, numpadMode: 'quantity' });
this.state = useState({ numpadMode: 'quantity' });
this.mobile_pane = this.props.mobile_pane || 'right';
}
mounted() {
if(this.env.pos.config.cash_control && this.env.pos.pos_session.state == 'opening_control') {
Gui.showPopup('CashOpeningPopup');
}
this.env.pos.on('change:selectedClient', this.render, this);
}
willUnmount() {
@@ -56,11 +59,6 @@ odoo.define('point_of_sale.ProductScreen', function(require) {
get currentOrder() {
return this.env.pos.get_order();
}
showCashBoxOpening() {
if(this.env.pos.config.cash_control && this.env.pos.pos_session.state == 'opening_control')
return true;
return false;
}
async _clickProduct(event) {
if (!this.currentOrder) {
this.env.pos.add_new_order();
@@ -1,27 +1,56 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="CashBoxOpening" owl="1">
<div style="margin-top: -20px;">
<br/>
<h1>
<span>
Pos closed.
</span><br/>
<span>
Set a cash opening
</span>
</h1>
<h1>Opening amount:</h1>
<input name="cashBoxValue" class="cashbox-input" t-on-change="captureChange" t-att-value="defaultValue"/>
<span class="currencyCashBox" t-esc="symbol"/>
<h1>Notes:</h1>
<textarea name="notes" style="width: 51%" t-on-change="captureChange"/><br/><br/>
<span class="control-button" t-on-click="startSession()">Open</span>
<t t-name="CashOpeningPopup" owl="1">
<div role="dialog" class="modal-dialog">
<div class="popup popup-confirm">
<header class="title drag-handle">
Start Cash Drawer
</header>
<main class="body">
<div class="cashbox-input">
<span class="input-title">
Starting Cash
</span>
<span class="input-amount">
<span t-if="currency.position === 'before'">
<t t-esc="currency.symbol"/><span> </span>
</span>
<t t-esc="cashBoxValue"/>
<span t-if="currency.position === 'after'">
<span> </span><t t-esc="currency.symbol"/>
</span>
</span>
</div><br/>
<textarea style="line-height: 20px;" rows="3"
placeholder="Notes" class="cashbox-input cashbox-notes"
t-model="state.notes" t-ref="input"/><br/><br/>
<div>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('1')">1</button>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('2')">2</button>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('3')">3</button>
<br/>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('4')">4</button>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('5')">5</button>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('6')">6</button>
<br />
<button class="input-button number-char cashbox-button" t-on-click="sendInput('7')">7</button>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('8')">8</button>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('9')">9</button>
<br/>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('.')">.</button>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('0')">0</button>
<button class="input-button number-char cashbox-button" t-on-click="sendInput('Backspace')">
<img style="pointer-events: none;" src="/point_of_sale/static/src/img/backspace.png"
width="24" height="21" alt="Backspace" />
</button>
</div><br/>
</main>
<footer class="footer">
<button style="height: 50px; margin: 22px 22px 22px 0px" t-model="state.notes" class="button cashbox-button" t-on-click="startSession()">Start Drawer</button>
</footer>
</div>
</div>
</t>
@@ -5,29 +5,24 @@
<div class="product-screen screen" t-att-class="{ oe_hidden: !props.isShown }">
<div class="screen-full-width">
<div class="leftpane" t-if="!env.isMobile || mobile_pane === 'left'">
<t t-if="state.cashControl">
<CashBoxOpening cashControl="state"/>
</t>
<t t-else="">
<OrderWidget/>
<div class="pads">
<div class="control-buttons">
<t t-foreach="controlButtons" t-as="cb" t-key="cb.name">
<t t-component="cb.component" t-key="cb.name" />
</t>
</div>
<div class="subpads">
<ActionpadWidget client="client"/>
<NumpadWidget activeMode="state.numpadMode" />
</div>
<OrderWidget/>
<div class="pads">
<div class="control-buttons">
<t t-foreach="controlButtons" t-as="cb" t-key="cb.name">
<t t-component="cb.component" t-key="cb.name" />
</t>
</div>
<t t-if="env.isMobile">
<MobileOrderWidget pane="mobile_pane" t-on-switchpane="switchPane"/>
</t>
<div class="subpads">
<ActionpadWidget client="client"/>
<NumpadWidget activeMode="state.numpadMode" />
</div>
</div>
<t t-if="env.isMobile">
<MobileOrderWidget pane="mobile_pane" t-on-switchpane="switchPane"/>
</t>
</div>
<div class="rightpane" t-if="!env.isMobile || mobile_pane === 'right'">
<ProductsWidget t-if="!state.cashControl"/>
<ProductsWidget/>
<t t-if="env.isMobile">
<MobileOrderWidget pane="mobile_pane" t-on-switchpane="switchPane"/>
</t>