[REF] point_of_sale, *pos*: renaming cashier, partner and customer
Multiple refactors - The module pos_hr had two attributes `cashier` and `employee` referencing to the same actual person. The `employee` attribute was removed for the sake of `cashier`. - Refactor of the `useSelectEmployee` which returned functions that where used in two components. Instead, a mixin class was implemented and inherited from both components. - Renaming of the substring `client` and `customer` to `partner` (css included) when it was referencing to the actual `res.partner` object. This way, developers will always know that the object used in the UI is coming from `res.partner`. - Renaming of the substring `client` to `customer`(css included) when it was referencing to a real life person. This avoid having ambiguity since the term `client` can refers to multiple things (hardware, browser, person, ...) closes odoo/odoo#83983 Related: odoo/enterprise#24477 Signed-off-by: Masereel Pierre <pim@odoo.com>
This commit is contained in:
@@ -2,13 +2,13 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="OrderReceipt" t-inherit="point_of_sale.OrderReceipt" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//div[hasclass('orderlines')]" position="before">
|
||||
<t t-if="receipt.client and env.pos.company.country and env.pos.company.country.code == 'IN'">
|
||||
<t t-if="receipt.partner and env.pos.company.country and env.pos.company.country.code == 'IN'">
|
||||
<div class="pos-receipt-center-align">
|
||||
<div><t t-esc="receipt.client.name" /></div>
|
||||
<t t-if="receipt.client.phone">
|
||||
<div><t t-esc="receipt.partner.name" /></div>
|
||||
<t t-if="receipt.partner.phone">
|
||||
<div>
|
||||
<span>Phone: </span>
|
||||
<t t-esc="receipt.client.phone" />
|
||||
<t t-esc="receipt.partner.phone" />
|
||||
</div>
|
||||
</t>
|
||||
<br />
|
||||
|
||||
@@ -229,16 +229,16 @@ td {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pos .clientlist-screen .window,
|
||||
.pos .clientlist-screen .full-content .subwindow{
|
||||
.pos .partnerlist-screen .window,
|
||||
.pos .partnerlist-screen .full-content .subwindow{
|
||||
display: block;
|
||||
}
|
||||
.pos .clientlist-screen .full-content .subwindow-container{
|
||||
.pos .partnerlist-screen .full-content .subwindow-container{
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
.pos .clientlist-screen .full-content .subwindow.collapsed,
|
||||
.pos .clientlist-screen .full-content .subwindow-container.collapsed{
|
||||
.pos .partnerlist-screen .full-content .subwindow.collapsed,
|
||||
.pos .partnerlist-screen .full-content .subwindow-container.collapsed{
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@@ -749,11 +749,11 @@ td {
|
||||
left: 3px;
|
||||
}
|
||||
|
||||
.pos .actionpad .button.set-customer{
|
||||
.pos .actionpad .button.set-partner{
|
||||
padding-left: 40px;
|
||||
padding-right: 40px;
|
||||
}
|
||||
.pos .actionpad .button.set-customer.decentered {
|
||||
.pos .actionpad .button.set-partner.decentered {
|
||||
padding-left: 40px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
@@ -770,11 +770,11 @@ td {
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.pos .actionpad .button.set-customer{
|
||||
.pos .actionpad .button.set-partner{
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
.pos .actionpad .button.set-customer.decentered{
|
||||
.pos .actionpad .button.set-partner.decentered{
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
@@ -1548,7 +1548,7 @@ td {
|
||||
padding-left: 0;
|
||||
flex-grow: 5;
|
||||
}
|
||||
.payment-screen .customer-button {
|
||||
.payment-screen .partner-button {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.payment-screen .payment-buttons .button {
|
||||
@@ -1800,56 +1800,56 @@ td {
|
||||
|
||||
/* e) The Client List Screen */
|
||||
|
||||
.pos .clientlist-screen .full-content{
|
||||
.pos .partnerlist-screen .full-content{
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.pos .clientlist-screen .client-list{
|
||||
.pos .partnerlist-screen .partner-list{
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
.pos .clientlist-screen .client-list th,
|
||||
.pos .clientlist-screen .client-list td {
|
||||
.pos .partnerlist-screen .partner-list th,
|
||||
.pos .partnerlist-screen .partner-list td {
|
||||
padding: 12px 8px;
|
||||
}
|
||||
|
||||
.pos .clientlist-screen .client-list th.client-line-last-column-placeholder,
|
||||
.pos .clientlist-screen .client-list td.client-line-last-column-placeholder {
|
||||
.pos .partnerlist-screen .partner-list th.partner-line-last-column-placeholder,
|
||||
.pos .partnerlist-screen .partner-list td.partner-line-last-column-placeholder {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.pos .clientlist-screen .client-list tr{
|
||||
.pos .partnerlist-screen .partner-list tr{
|
||||
transition: all 150ms linear;
|
||||
background: rgb(230,230,230);
|
||||
}
|
||||
.pos .clientlist-screen .client-list thead > tr,
|
||||
.pos .clientlist-screen .client-list tr:nth-child(even) {
|
||||
.pos .partnerlist-screen .partner-list thead > tr,
|
||||
.pos .partnerlist-screen .partner-list tr:nth-child(even) {
|
||||
background: rgb(247,247,247);
|
||||
}
|
||||
.pos .clientlist-screen .client-list tr.highlight{
|
||||
.pos .partnerlist-screen .partner-list tr.highlight{
|
||||
transition: all 150ms linear;
|
||||
background: rgb(110,200,155) !important;
|
||||
color: white;
|
||||
}
|
||||
.pos .clientlist-screen .client-list tr.lowlight{
|
||||
.pos .partnerlist-screen .partner-list tr.lowlight{
|
||||
transition: all 150ms linear;
|
||||
background: rgb(216, 238, 227);
|
||||
}
|
||||
.pos .clientlist-screen .client-list tr.lowlight:nth-child(even){
|
||||
.pos .partnerlist-screen .partner-list tr.lowlight:nth-child(even){
|
||||
transition: all 150ms linear;
|
||||
background: rgb(227, 246, 237);
|
||||
}
|
||||
.pos .client-line {
|
||||
.pos .partner-line {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
.pos .edit-client-button {
|
||||
.pos .edit-partner-button {
|
||||
margin-top: 6px;
|
||||
color: black;
|
||||
}
|
||||
.pos .clientlist-screen .client-details{
|
||||
.pos .partnerlist-screen .partner-details{
|
||||
padding: 16px;
|
||||
}
|
||||
.pos .clientlist-screen .client-picture{
|
||||
.pos .partnerlist-screen .partner-picture{
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
border-radius: 32px;
|
||||
@@ -1860,7 +1860,7 @@ td {
|
||||
background: white;
|
||||
position: relative;
|
||||
}
|
||||
.pos .clientlist-screen .client-picture > img {
|
||||
.pos .partnerlist-screen .partner-picture > img {
|
||||
position: absolute;
|
||||
top: -9999px;
|
||||
bottom: -9999px;
|
||||
@@ -1869,11 +1869,11 @@ td {
|
||||
max-height: 64px;
|
||||
margin: auto;
|
||||
}
|
||||
.pos .clientlist-screen .client-picture > .fa {
|
||||
.pos .partnerlist-screen .partner-picture > .fa {
|
||||
line-height: 64px;
|
||||
font-size: 32px;
|
||||
}
|
||||
.pos .clientlist-screen .client-picture .image-uploader {
|
||||
.pos .partnerlist-screen .partner-picture .image-uploader {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
@@ -1883,47 +1883,47 @@ td {
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.pos .clientlist-screen .client-name {
|
||||
.pos .partnerlist-screen .partner-name {
|
||||
font-size: 32px;
|
||||
line-height: 64px;
|
||||
margin-bottom:16px;
|
||||
}
|
||||
.pos .clientlist-screen .edit-buttons {
|
||||
.pos .partnerlist-screen .edit-buttons {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 10px;
|
||||
}
|
||||
.pos .clientlist-screen .edit-buttons .button{
|
||||
.pos .partnerlist-screen .edit-buttons .button{
|
||||
display: inline-block;
|
||||
margin-left: 16px;
|
||||
color: rgb(128,128,128);
|
||||
cursor: pointer;
|
||||
font-size: 36px;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-box{
|
||||
.pos .partnerlist-screen .partner-details-box{
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-left{
|
||||
.pos .partnerlist-screen .partner-details-left{
|
||||
width: 50%;
|
||||
float: left;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-right{
|
||||
.pos .partnerlist-screen .partner-details-right{
|
||||
width: 50%;
|
||||
float: right;
|
||||
}
|
||||
.pos .clientlist-screen .client-detail{
|
||||
.pos .partnerlist-screen .partner-detail{
|
||||
line-height: 24px;
|
||||
}
|
||||
.pos .clientlist-screen .client-detail > .label{
|
||||
.pos .partnerlist-screen .partner-detail > .label{
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
width: 75px;
|
||||
text-align: right;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.pos .clientlist-screen .client-details input,
|
||||
.pos .clientlist-screen .client-details select
|
||||
.pos .partnerlist-screen .partner-details input,
|
||||
.pos .partnerlist-screen .partner-details select
|
||||
{
|
||||
padding: 4px;
|
||||
border-radius: 3px;
|
||||
@@ -1936,22 +1936,22 @@ td {
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.pos .clientlist-screen .client-details input.client-name {
|
||||
.pos .partnerlist-screen .partner-details input.partner-name {
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
margin: 18px 6px;
|
||||
width: 340px;
|
||||
}
|
||||
.pos .clientlist-screen .client-detail > .empty{
|
||||
.pos .partnerlist-screen .partner-detail > .empty{
|
||||
opacity: 0.3;
|
||||
}
|
||||
.pos .searchbox-client {
|
||||
.pos .searchbox-partner {
|
||||
padding: 3px 13px;
|
||||
margin-top: 12px;
|
||||
margin-bottom : 12px;
|
||||
}
|
||||
|
||||
.pos .searchbox-client input {
|
||||
.pos .searchbox-partner input {
|
||||
width: 120px;
|
||||
border: 1px solid #cecbcb;
|
||||
padding: 10px 20px;
|
||||
@@ -1962,13 +1962,13 @@ td {
|
||||
font-family: "Lato","Lucida Grande", Helvetica, Verdana, Arial;
|
||||
font-size: 13px;
|
||||
}
|
||||
.pos .searchbox-client input:focus {
|
||||
.pos .searchbox-partner input:focus {
|
||||
outline: none;
|
||||
box-shadow: 0px 0px 0px 2px rgb(153, 153, 255) inset;
|
||||
color: rgb(153, 153, 255);
|
||||
}
|
||||
|
||||
.pos .search-clear-client {
|
||||
.pos .search-clear-partner {
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
width: 30px;
|
||||
@@ -1978,58 +1978,58 @@ td {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.search-clear-client.left {
|
||||
.search-clear-partner.left {
|
||||
left: 11px;
|
||||
color: #808080;
|
||||
}
|
||||
|
||||
.search-clear-client.right {
|
||||
.search-clear-partner.right {
|
||||
left: 145px;
|
||||
color: #808080;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.searchbox-client.top-content-center {
|
||||
.searchbox-partner.top-content-center {
|
||||
display: flex
|
||||
}
|
||||
.pos .searchbox-client input {
|
||||
.pos .searchbox-partner input {
|
||||
width: auto;
|
||||
flex-grow: 1;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-box {
|
||||
.pos .partnerlist-screen .partner-details-box {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-left{
|
||||
.pos .partnerlist-screen .partner-details-left{
|
||||
width: auto;
|
||||
float: none;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.pos .clientlist-screen .client-details-right{
|
||||
.pos .partnerlist-screen .partner-details-right{
|
||||
width: auto;
|
||||
float: none;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.pos .clientlist-screen .client-detail{
|
||||
.pos .partnerlist-screen .partner-detail{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.pos .clientlist-screen .client-details input,
|
||||
.pos .clientlist-screen .client-details select
|
||||
.pos .partnerlist-screen .partner-details input,
|
||||
.pos .partnerlist-screen .partner-details select
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
.pos .clientlist-screen .client-details input.client-name {
|
||||
.pos .partnerlist-screen .partner-details input.partner-name {
|
||||
width: 100%;
|
||||
}
|
||||
.pos .clientlist-screen .client-detail > .label{
|
||||
.pos .partnerlist-screen .partner-detail > .label{
|
||||
width: auto;
|
||||
text-align: left;
|
||||
}
|
||||
.pos .clientlist-screen .client-list td {
|
||||
.pos .partnerlist-screen .partner-list td {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ odoo.define('point_of_sale.Chrome', function(require) {
|
||||
|
||||
// GETTERS //
|
||||
|
||||
get clientScreenButtonIsShown() {
|
||||
get customerFacingDisplayButtonIsShown() {
|
||||
return this.env.pos.config.iface_customer_facing_display;
|
||||
}
|
||||
|
||||
|
||||
+8
-9
@@ -1,4 +1,4 @@
|
||||
odoo.define('point_of_sale.ClientScreenButton', function(require) {
|
||||
odoo.define('point_of_sale.CustomerFacingDisplayButton', function(require) {
|
||||
'use strict';
|
||||
|
||||
const PosComponent = require('point_of_sale.PosComponent');
|
||||
@@ -6,8 +6,7 @@ odoo.define('point_of_sale.ClientScreenButton', function(require) {
|
||||
|
||||
const { useState } = owl;
|
||||
|
||||
// Formerly ClientScreenWidget
|
||||
class ClientScreenButton extends PosComponent {
|
||||
class CustomerFacingDisplayButton extends PosComponent {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.local = this.env.pos.config.iface_customer_facing_display_local && !this.env.pos.config.iface_customer_facing_display_proxy;
|
||||
@@ -19,7 +18,7 @@ odoo.define('point_of_sale.ClientScreenButton', function(require) {
|
||||
success: '',
|
||||
warning: this.env._t('Connected, Not Owned'),
|
||||
failure: this.env._t('Disconnected'),
|
||||
not_found: this.env._t('Client Screen Unsupported. Please upgrade the IoT Box'),
|
||||
not_found: this.env._t('Customer Screen Unsupported. Please upgrade the IoT Box'),
|
||||
}[this.state.status];
|
||||
}
|
||||
onClick() {
|
||||
@@ -39,7 +38,7 @@ odoo.define('point_of_sale.ClientScreenButton', function(require) {
|
||||
async onClickProxy() {
|
||||
try {
|
||||
const renderedHtml = await this.env.pos.render_html_for_customer_facing_display();
|
||||
let ownership = await this.env.proxy.take_ownership_over_client_screen(
|
||||
let ownership = await this.env.proxy.take_ownership_over_customer_screen(
|
||||
renderedHtml
|
||||
);
|
||||
if (typeof ownership === 'string') {
|
||||
@@ -71,7 +70,7 @@ odoo.define('point_of_sale.ClientScreenButton', function(require) {
|
||||
async function loop() {
|
||||
if (self.env.proxy.posbox_supports_display) {
|
||||
try {
|
||||
let ownership = await self.env.proxy.test_ownership_of_client_screen();
|
||||
let ownership = await self.env.proxy.test_ownership_of_customer_screen();
|
||||
if (typeof ownership === 'string') {
|
||||
ownership = JSON.parse(ownership);
|
||||
}
|
||||
@@ -99,9 +98,9 @@ odoo.define('point_of_sale.ClientScreenButton', function(require) {
|
||||
loop();
|
||||
}
|
||||
}
|
||||
ClientScreenButton.template = 'ClientScreenButton';
|
||||
CustomerFacingDisplayButton.template = 'CustomerFacingDisplayButton';
|
||||
|
||||
Registries.Component.add(ClientScreenButton);
|
||||
Registries.Component.add(CustomerFacingDisplayButton);
|
||||
|
||||
return ClientScreenButton;
|
||||
return CustomerFacingDisplayButton;
|
||||
});
|
||||
@@ -18,7 +18,7 @@ odoo.define('point_of_sale.ErrorBarcodePopup', function(require) {
|
||||
title: _lt('Error'),
|
||||
body: '',
|
||||
message:
|
||||
_lt('The Point of Sale could not find any product, client, employee or action associated with the scanned barcode.'),
|
||||
_lt('The Point of Sale could not find any product, customer, employee or action associated with the scanned barcode.'),
|
||||
};
|
||||
|
||||
Registries.Component.add(ErrorBarcodePopup);
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
odoo.define('point_of_sale.ClientLine', function(require) {
|
||||
'use strict';
|
||||
|
||||
const PosComponent = require('point_of_sale.PosComponent');
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
|
||||
class ClientLine extends PosComponent {
|
||||
get highlight() {
|
||||
return this.props.partner !== this.props.selectedClient ? '' : 'highlight';
|
||||
}
|
||||
}
|
||||
ClientLine.template = 'ClientLine';
|
||||
|
||||
Registries.Component.add(ClientLine);
|
||||
|
||||
return ClientLine;
|
||||
});
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
odoo.define('point_of_sale.ClientDetailsEdit', function(require) {
|
||||
odoo.define('point_of_sale.PartnerDetailsEdit', function(require) {
|
||||
'use strict';
|
||||
|
||||
const { _t } = require('web.core');
|
||||
@@ -8,7 +8,7 @@ odoo.define('point_of_sale.ClientDetailsEdit', function(require) {
|
||||
|
||||
const { onMounted, onWillUnmount } = owl;
|
||||
|
||||
class ClientDetailsEdit extends PosComponent {
|
||||
class PartnerDetailsEdit extends PosComponent {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.intFields = ['country_id', 'state_id', 'property_product_pricelist'];
|
||||
@@ -19,11 +19,11 @@ odoo.define('point_of_sale.ClientDetailsEdit', function(require) {
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
this.env.bus.on('save-customer', this, this.saveChanges);
|
||||
this.env.bus.on('save-partner', this, this.saveChanges);
|
||||
});
|
||||
|
||||
onWillUnmount(() => {
|
||||
this.env.bus.off('save-customer', this);
|
||||
this.env.bus.off('save-partner', this);
|
||||
});
|
||||
}
|
||||
get partnerImageUrl() {
|
||||
@@ -125,9 +125,9 @@ odoo.define('point_of_sale.ClientDetailsEdit', function(require) {
|
||||
});
|
||||
}
|
||||
}
|
||||
ClientDetailsEdit.template = 'ClientDetailsEdit';
|
||||
PartnerDetailsEdit.template = 'PartnerDetailsEdit';
|
||||
|
||||
Registries.Component.add(ClientDetailsEdit);
|
||||
Registries.Component.add(PartnerDetailsEdit);
|
||||
|
||||
return ClientDetailsEdit;
|
||||
return PartnerDetailsEdit;
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
odoo.define('point_of_sale.PartnerLine', function(require) {
|
||||
'use strict';
|
||||
|
||||
const PosComponent = require('point_of_sale.PosComponent');
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
|
||||
class PartnerLine extends PosComponent {
|
||||
get highlight() {
|
||||
return this.props.partner !== this.props.selectedPartner ? '' : 'highlight';
|
||||
}
|
||||
}
|
||||
PartnerLine.template = 'PartnerLine';
|
||||
|
||||
Registries.Component.add(PartnerLine);
|
||||
|
||||
return PartnerLine;
|
||||
});
|
||||
+43
-44
@@ -1,4 +1,4 @@
|
||||
odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
odoo.define('point_of_sale.PartnerListScreen', function(require) {
|
||||
'use strict';
|
||||
|
||||
const PosComponent = require('point_of_sale.PosComponent');
|
||||
@@ -11,25 +11,25 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
const { onWillUnmount } = owl;
|
||||
|
||||
/**
|
||||
* Render this screen using `showTempScreen` to select client.
|
||||
* Render this screen using `showTempScreen` to select partner.
|
||||
* When the shown screen is confirmed ('Set Customer' or 'Deselect Customer'
|
||||
* button is clicked), the call to `showTempScreen` resolves to the
|
||||
* selected client. E.g.
|
||||
* selected partner. E.g.
|
||||
*
|
||||
* ```js
|
||||
* const { confirmed, payload: selectedClient } = await showTempScreen('ClientListScreen');
|
||||
* const { confirmed, payload: selectedPartner } = await showTempScreen('PartnerListScreen');
|
||||
* if (confirmed) {
|
||||
* // do something with the selectedClient
|
||||
* // do something with the selectedPartner
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @props client - originally selected client
|
||||
* @props partner - originally selected partner
|
||||
*/
|
||||
class ClientListScreen extends PosComponent {
|
||||
class PartnerListScreen extends PosComponent {
|
||||
setup() {
|
||||
super.setup();
|
||||
useListener('click-save', () => this.env.bus.trigger('save-customer'));
|
||||
useListener('click-edit', () => this.editClient());
|
||||
useListener('click-save', () => this.env.bus.trigger('save-partner'));
|
||||
useListener('click-edit', () => this.editPartner());
|
||||
useListener('save-changes', this.saveChanges);
|
||||
|
||||
// We are not using useState here because the object
|
||||
@@ -39,9 +39,9 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
// is better to be safe.
|
||||
this.state = {
|
||||
query: null,
|
||||
selectedClient: this.props.client,
|
||||
selectedPartner: this.props.partner,
|
||||
detailIsShown: false,
|
||||
isEditMode: false,
|
||||
// isEditMode: false,
|
||||
editModeProps: {
|
||||
partner: {
|
||||
country_id: this.env.pos.company.country_id,
|
||||
@@ -49,8 +49,8 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
}
|
||||
},
|
||||
};
|
||||
this.updateClientList = debounce(this.updateClientList, 70);
|
||||
onWillUnmount(this.updateClientList.cancel);
|
||||
this.updatePartnerList = debounce(this.updatePartnerList, 70);
|
||||
onWillUnmount(this.updatePartnerList.cancel);
|
||||
}
|
||||
// Lifecycle hooks
|
||||
back() {
|
||||
@@ -63,7 +63,7 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
}
|
||||
}
|
||||
confirm() {
|
||||
this.props.resolve({ confirmed: true, payload: this.state.selectedClient });
|
||||
this.props.resolve({ confirmed: true, payload: this.state.selectedPartner });
|
||||
this.trigger('close-temp-screen');
|
||||
}
|
||||
// Getters
|
||||
@@ -72,7 +72,7 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
return this.env.pos.get_order();
|
||||
}
|
||||
|
||||
get clients() {
|
||||
get partners() {
|
||||
let res;
|
||||
if (this.state.query && this.state.query.trim() !== '') {
|
||||
res = this.env.pos.db.search_partner(this.state.query.trim());
|
||||
@@ -82,16 +82,16 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
return res.sort(function (a, b) { return (a.name || '').localeCompare(b.name || '') });
|
||||
}
|
||||
get isNextButtonVisible() {
|
||||
return this.state.selectedClient ? true : false;
|
||||
return this.state.selectedPartner ? true : false;
|
||||
}
|
||||
/**
|
||||
* Returns the text and command of the next button.
|
||||
* The command field is used by the clickNext call.
|
||||
*/
|
||||
get nextButton() {
|
||||
if (!this.props.client) {
|
||||
if (!this.props.partner) {
|
||||
return { command: 'set', text: this.env._t('Set Customer') };
|
||||
} else if (this.props.client && this.props.client === this.state.selectedClient) {
|
||||
} else if (this.props.partner && this.props.partner === this.state.selectedPartner) {
|
||||
return { command: 'deselect', text: this.env._t('Deselect Customer') };
|
||||
} else {
|
||||
return { command: 'set', text: this.env._t('Change Customer') };
|
||||
@@ -102,44 +102,43 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
|
||||
// We declare this event handler as a debounce function in
|
||||
// order to lower its trigger rate.
|
||||
async updateClientList(event) {
|
||||
var newClientList = await this.getNewClient();
|
||||
async updatePartnerList(event) {
|
||||
let newPartnerList = await this.getNewPartners();
|
||||
this.state.query = event.target.value;
|
||||
const clients = this.clients;
|
||||
if (event.code === 'Enter' && clients.length === 1) {
|
||||
this.state.selectedClient = clients[0];
|
||||
const partners = this.partners;
|
||||
if (event.code === 'Enter' && partners.length === 1) {
|
||||
this.state.selectedPartner = partners[0];
|
||||
this.clickNext();
|
||||
} else {
|
||||
this.render(true);
|
||||
}
|
||||
}
|
||||
clickClient(partner) {
|
||||
if (this.state.selectedClient === partner) {
|
||||
this.state.selectedClient = null;
|
||||
clickPartner(partner) {
|
||||
if (this.state.selectedPartner === partner) {
|
||||
this.state.selectedPartner = null;
|
||||
} else {
|
||||
this.state.selectedClient = partner;
|
||||
this.state.selectedPartner = partner;
|
||||
}
|
||||
this.render(true);
|
||||
}
|
||||
editClient() {
|
||||
editPartner() {
|
||||
this.state.editModeProps = {
|
||||
partner: this.state.selectedClient,
|
||||
partner: this.state.selectedPartner,
|
||||
};
|
||||
this.state.detailIsShown = true;
|
||||
this.render(true);
|
||||
}
|
||||
clickNext() {
|
||||
this.state.selectedClient = this.nextButton.command === 'set' ? this.state.selectedClient : null;
|
||||
this.state.selectedPartner = this.nextButton.command === 'set' ? this.state.selectedPartner : null;
|
||||
this.confirm();
|
||||
}
|
||||
activateEditMode(event) {
|
||||
const { isNewClient } = event.detail;
|
||||
this.state.isEditMode = true;
|
||||
activateEditMode(isNewPartner) {
|
||||
// this.state.isEditMode = true;
|
||||
this.state.detailIsShown = true;
|
||||
this.state.isNewClient = isNewClient;
|
||||
if (!isNewClient) {
|
||||
this.state.isNewPartner = isNewPartner;
|
||||
if (!isNewPartner) {
|
||||
this.state.editModeProps = {
|
||||
partner: this.state.selectedClient,
|
||||
partner: this.state.selectedPartner,
|
||||
};
|
||||
}
|
||||
this.render(true);
|
||||
@@ -152,7 +151,7 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
args: [event.detail.processedChanges],
|
||||
});
|
||||
await this.env.pos.load_new_partners();
|
||||
this.state.selectedClient = this.env.pos.db.get_partner_by_id(partnerId);
|
||||
this.state.selectedPartner = this.env.pos.db.get_partner_by_id(partnerId);
|
||||
this.state.detailIsShown = false;
|
||||
this.render(true);
|
||||
} catch (error) {
|
||||
@@ -166,8 +165,8 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
}
|
||||
}
|
||||
}
|
||||
async searchClient() {
|
||||
let result = await this.getNewClient();
|
||||
async searchPartner() {
|
||||
let result = await this.getNewPartners();
|
||||
this.env.pos.db.add_partners(result);
|
||||
if(!result.length) {
|
||||
await this.showPopup('ErrorPopup', {
|
||||
@@ -177,8 +176,8 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
}
|
||||
this.render(true);
|
||||
}
|
||||
async getNewClient() {
|
||||
var domain = [];
|
||||
async getNewPartners() {
|
||||
let domain = [];
|
||||
if(this.state.query) {
|
||||
domain = [["name", "ilike", this.state.query + "%"]];
|
||||
}
|
||||
@@ -203,9 +202,9 @@ odoo.define('point_of_sale.ClientListScreen', function(require) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
ClientListScreen.template = 'ClientListScreen';
|
||||
PartnerListScreen.template = 'PartnerListScreen';
|
||||
|
||||
Registries.Component.add(ClientListScreen);
|
||||
Registries.Component.add(PartnerListScreen);
|
||||
|
||||
return ClientListScreen;
|
||||
return PartnerListScreen;
|
||||
});
|
||||
@@ -43,17 +43,17 @@ odoo.define('point_of_sale.PaymentScreen', function (require) {
|
||||
get selectedPaymentLine() {
|
||||
return this.currentOrder.selected_paymentline;
|
||||
}
|
||||
async selectClient() {
|
||||
async selectPartner() {
|
||||
// IMPROVEMENT: This code snippet is repeated multiple times.
|
||||
// Maybe it's better to create a function for it.
|
||||
const currentClient = this.currentOrder.get_client();
|
||||
const { confirmed, payload: newClient } = await this.showTempScreen(
|
||||
'ClientListScreen',
|
||||
{ client: currentClient }
|
||||
const currentPartner = this.currentOrder.get_partner();
|
||||
const { confirmed, payload: newPartner } = await this.showTempScreen(
|
||||
'PartnerListScreen',
|
||||
{ partner: currentPartner }
|
||||
);
|
||||
if (confirmed) {
|
||||
this.currentOrder.set_client(newClient);
|
||||
this.currentOrder.updatePricelist(newClient);
|
||||
this.currentOrder.set_partner(newPartner);
|
||||
this.currentOrder.updatePricelist(newPartner);
|
||||
}
|
||||
}
|
||||
addNewPaymentLine({ detail: paymentMethod }) {
|
||||
@@ -269,19 +269,19 @@ odoo.define('point_of_sale.PaymentScreen', function (require) {
|
||||
}
|
||||
|
||||
const splitPayments = this.paymentLines.filter(payment => payment.payment_method.split_transactions)
|
||||
if (splitPayments.length && !this.currentOrder.get_client()) {
|
||||
if (splitPayments.length && !this.currentOrder.get_partner()) {
|
||||
const paymentMethod = splitPayments[0].payment_method
|
||||
const { confirmed } = await this.showPopup('ConfirmPopup', {
|
||||
title: this.env._t('Customer Required'),
|
||||
body: _.str.sprintf(this.env._t('Customer is required for %s payment method.'), paymentMethod.name),
|
||||
});
|
||||
if (confirmed) {
|
||||
this.selectClient();
|
||||
this.selectPartner();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((this.currentOrder.is_to_invoice() || this.currentOrder.is_to_ship()) && !this.currentOrder.get_client()) {
|
||||
if ((this.currentOrder.is_to_invoice() || this.currentOrder.is_to_ship()) && !this.currentOrder.get_partner()) {
|
||||
const { confirmed } = await this.showPopup('ConfirmPopup', {
|
||||
title: this.env._t('Please select the Customer'),
|
||||
body: this.env._t(
|
||||
@@ -289,13 +289,13 @@ odoo.define('point_of_sale.PaymentScreen', function (require) {
|
||||
),
|
||||
});
|
||||
if (confirmed) {
|
||||
this.selectClient();
|
||||
this.selectPartner();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
var customer = this.currentOrder.get_client()
|
||||
if (this.currentOrder.is_to_ship() && !(customer.name && customer.street && customer.city && customer.country_id)) {
|
||||
let partner = this.currentOrder.get_partner()
|
||||
if (this.currentOrder.is_to_ship() && !(partner.name && partner.street && partner.city && partner.country_id)) {
|
||||
this.showPopup('ErrorPopup', {
|
||||
title: this.env._t('Incorrect address for shipping'),
|
||||
body: this.env._t('The selected customer needs an address.'),
|
||||
|
||||
@@ -5,13 +5,13 @@ odoo.define('point_of_sale.ActionpadWidget', function(require) {
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
|
||||
/**
|
||||
* @props client
|
||||
* @emits click-customer
|
||||
* @props partner
|
||||
* @emits click-partner
|
||||
* @emits click-pay
|
||||
*/
|
||||
class ActionpadWidget extends PosComponent {
|
||||
get isLongName() {
|
||||
return this.props.client && this.props.client.name.length > 10;
|
||||
return this.props.partner && this.props.partner.name.length > 10;
|
||||
}
|
||||
}
|
||||
ActionpadWidget.template = 'ActionpadWidget';
|
||||
|
||||
+2
-2
@@ -12,8 +12,8 @@ odoo.define('point_of_sale.RefundButton', function (require) {
|
||||
useListener('click', this._onClick);
|
||||
}
|
||||
_onClick() {
|
||||
const customer = this.env.pos.get_order().get_client();
|
||||
const searchDetails = customer ? { fieldName: 'CUSTOMER', searchTerm: customer.name } : {};
|
||||
const partner = this.env.pos.get_order().get_partner();
|
||||
const searchDetails = partner ? { fieldName: 'PARTNER', searchTerm: partner.name } : {};
|
||||
this.trigger('close-popup');
|
||||
this.showScreen('TicketScreen', {
|
||||
ui: { filter: 'SYNCED', searchDetails },
|
||||
|
||||
@@ -18,13 +18,13 @@ odoo.define('point_of_sale.ProductScreen', function(require) {
|
||||
useListener('update-selected-orderline', this._updateSelectedOrderline);
|
||||
useListener('set-numpad-mode', this._setNumpadMode);
|
||||
useListener('click-product', this._clickProduct);
|
||||
useListener('click-customer', this._onClickCustomer);
|
||||
useListener('click-partner', this.onClickPartner);
|
||||
useListener('click-pay', this._onClickPay);
|
||||
useBarcodeReader({
|
||||
product: this._barcodeProductAction,
|
||||
weight: this._barcodeProductAction,
|
||||
price: this._barcodeProductAction,
|
||||
client: this._barcodeClientAction,
|
||||
client: this._barcodePartnerAction,
|
||||
discount: this._barcodeDiscountAction,
|
||||
error: this._barcodeErrorAction,
|
||||
});
|
||||
@@ -53,8 +53,8 @@ odoo.define('point_of_sale.ProductScreen', function(require) {
|
||||
get isScaleAvailable() {
|
||||
return true;
|
||||
}
|
||||
get client() {
|
||||
return this.currentOrder ? this.currentOrder.get_client() : null;
|
||||
get partner() {
|
||||
return this.currentOrder ? this.currentOrder.get_partner() : null;
|
||||
}
|
||||
get currentOrder() {
|
||||
return this.env.pos.get_order();
|
||||
@@ -260,11 +260,11 @@ odoo.define('point_of_sale.ProductScreen', function(require) {
|
||||
}
|
||||
this.currentOrder.add_product(product, options)
|
||||
}
|
||||
_barcodeClientAction(code) {
|
||||
_barcodePartnerAction(code) {
|
||||
const partner = this.env.pos.db.get_partner_by_barcode(code.code);
|
||||
if (partner) {
|
||||
if (this.currentOrder.get_client() !== partner) {
|
||||
this.currentOrder.set_client(partner);
|
||||
if (this.currentOrder.get_partner() !== partner) {
|
||||
this.currentOrder.set_partner(partner);
|
||||
this.currentOrder.set_pricelist(
|
||||
_.findWhere(this.env.pos.pricelists, {
|
||||
id: partner.property_product_pricelist[0],
|
||||
@@ -329,28 +329,28 @@ odoo.define('point_of_sale.ProductScreen', function(require) {
|
||||
}
|
||||
}
|
||||
}
|
||||
async _onClickCustomer() {
|
||||
// IMPROVEMENT: This code snippet is very similar to selectClient of PaymentScreen.
|
||||
const currentClient = this.currentOrder.get_client();
|
||||
if (currentClient && this.currentOrder.getHasRefundLines()) {
|
||||
async onClickPartner() {
|
||||
// IMPROVEMENT: This code snippet is very similar to selectPartner of PaymentScreen.
|
||||
const currentPartner = this.currentOrder.get_partner();
|
||||
if (currentPartner && this.currentOrder.getHasRefundLines()) {
|
||||
this.showPopup('ErrorPopup', {
|
||||
title: this.env._t("Can't change customer"),
|
||||
body: _.str.sprintf(
|
||||
this.env._t(
|
||||
"This order already has refund lines for %s. We can't change the customer associated to it. Create a new order for the new customer."
|
||||
),
|
||||
currentClient.name
|
||||
currentPartner.name
|
||||
),
|
||||
});
|
||||
return;
|
||||
}
|
||||
const { confirmed, payload: newClient } = await this.showTempScreen(
|
||||
'ClientListScreen',
|
||||
{ client: currentClient }
|
||||
const { confirmed, payload: newPartner } = await this.showTempScreen(
|
||||
'PartnerListScreen',
|
||||
{ partner: currentPartner }
|
||||
);
|
||||
if (confirmed) {
|
||||
this.currentOrder.set_client(newClient);
|
||||
this.currentOrder.updatePricelist(newClient);
|
||||
this.currentOrder.set_partner(newPartner);
|
||||
this.currentOrder.updatePricelist(newPartner);
|
||||
}
|
||||
}
|
||||
_onClickPay() {
|
||||
|
||||
@@ -16,9 +16,9 @@ odoo.define('point_of_sale.ReceiptScreen', function (require) {
|
||||
useErrorHandlers();
|
||||
this.orderReceipt = useRef('order-receipt');
|
||||
const order = this.currentOrder;
|
||||
const client = order.get_client();
|
||||
const partner = order.get_partner();
|
||||
this.orderUiState = order.uiState.ReceiptScreen;
|
||||
this.orderUiState.inputEmail = this.orderUiState.inputEmail || (client && client.email) || '';
|
||||
this.orderUiState.inputEmail = this.orderUiState.inputEmail || (partner && partner.email) || '';
|
||||
this.is_email = is_email;
|
||||
|
||||
onMounted(() => {
|
||||
@@ -111,14 +111,14 @@ odoo.define('point_of_sale.ReceiptScreen', function (require) {
|
||||
const receiptString = this.orderReceipt.el.innerHTML;
|
||||
const ticketImage = await printer.htmlToImg(receiptString);
|
||||
const order = this.currentOrder;
|
||||
const client = order.get_client();
|
||||
const partner = order.get_partner();
|
||||
const orderName = order.get_name();
|
||||
const orderClient = { email: this.orderUiState.inputEmail, name: client ? client.name : this.orderUiState.inputEmail };
|
||||
const orderPartner = { email: this.orderUiState.inputEmail, name: partner ? partner.name : this.orderUiState.inputEmail };
|
||||
const order_server_id = this.env.pos.validated_orders_name_server_id_map[orderName];
|
||||
await this.rpc({
|
||||
model: 'pos.order',
|
||||
method: 'action_receipt_to_customer',
|
||||
args: [[order_server_id], orderName, orderClient, ticketImage],
|
||||
args: [[order_server_id], orderName, orderPartner, ticketImage],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -75,24 +75,24 @@ odoo.define('point_of_sale.InvoiceButton', function (require) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Part 1: Handle missing client.
|
||||
// Write to pos.order the selected client.
|
||||
if (!order.get_client()) {
|
||||
// Part 1: Handle missing partner.
|
||||
// Write to pos.order the selected partner.
|
||||
if (!order.get_partner()) {
|
||||
const { confirmed: confirmedPopup } = await this.showPopup('ConfirmPopup', {
|
||||
title: this.env._t('Need customer to invoice'),
|
||||
body: this.env._t('Do you want to open the customer list to select customer?'),
|
||||
});
|
||||
if (!confirmedPopup) return;
|
||||
|
||||
const { confirmed: confirmedTempScreen, payload: newClient } = await this.showTempScreen(
|
||||
'ClientListScreen'
|
||||
const { confirmed: confirmedTempScreen, payload: newPartner } = await this.showTempScreen(
|
||||
'PartnerListScreen'
|
||||
);
|
||||
if (!confirmedTempScreen) return;
|
||||
|
||||
await this.rpc({
|
||||
model: 'pos.order',
|
||||
method: 'write',
|
||||
args: [[orderId], { partner_id: newClient.id }],
|
||||
args: [[orderId], { partner_id: newPartner.id }],
|
||||
kwargs: { context: this.env.session.user_context },
|
||||
});
|
||||
}
|
||||
|
||||
@@ -191,18 +191,18 @@ odoo.define('point_of_sale.TicketScreen', function (require) {
|
||||
this._prepareAutoRefundOnOrder(order);
|
||||
}
|
||||
|
||||
const customer = order.get_client();
|
||||
const partner = order.get_partner();
|
||||
|
||||
// Select the lines from toRefundLines (can come from different orders)
|
||||
// such that:
|
||||
// - the quantity to refund is not zero
|
||||
// - if there is customer in the selected paid order, select the items
|
||||
// - if there is partner in the selected paid order, select the items
|
||||
// with the same orderPartnerId
|
||||
// - it is not yet linked to an active order (no destinationOrderUid)
|
||||
const allToRefundDetails = Object.values(this.env.pos.toRefundLines).filter(
|
||||
({ qty, orderline, destinationOrderUid }) =>
|
||||
!this.env.pos.isProductQtyZero(qty) &&
|
||||
(customer ? orderline.orderPartnerId == customer.id : true) &&
|
||||
(partner ? orderline.orderPartnerId == partner.id : true) &&
|
||||
!destinationOrderUid
|
||||
);
|
||||
if (allToRefundDetails.length == 0) {
|
||||
@@ -212,9 +212,9 @@ odoo.define('point_of_sale.TicketScreen', function (require) {
|
||||
|
||||
// The order that will contain the refund orderlines.
|
||||
// Use the destinationOrder from props if the order to refund has the same
|
||||
// customer as the destinationOrder.
|
||||
// partner as the destinationOrder.
|
||||
const destinationOrder =
|
||||
this.props.destinationOrder && customer === this.props.destinationOrder.get_client()
|
||||
this.props.destinationOrder && partner === this.props.destinationOrder.get_partner()
|
||||
? this.props.destinationOrder
|
||||
: this.env.pos.add_new_order();
|
||||
|
||||
@@ -234,9 +234,9 @@ odoo.define('point_of_sale.TicketScreen', function (require) {
|
||||
refundDetail.destinationOrderUid = destinationOrder.uid;
|
||||
}
|
||||
|
||||
// Set the customer to the destinationOrder.
|
||||
if (customer && !destinationOrder.get_client()) {
|
||||
destinationOrder.set_client(customer);
|
||||
// Set the partner to the destinationOrder.
|
||||
if (partner && !destinationOrder.get_partner()) {
|
||||
destinationOrder.set_partner(partner);
|
||||
}
|
||||
|
||||
this._onCloseScreen();
|
||||
@@ -288,14 +288,14 @@ odoo.define('point_of_sale.TicketScreen', function (require) {
|
||||
getTotal(order) {
|
||||
return this.env.pos.format_currency(order.get_total_with_tax());
|
||||
}
|
||||
getCustomer(order) {
|
||||
return order.get_client_name();
|
||||
getPartner(order) {
|
||||
return order.get_partner_name();
|
||||
}
|
||||
getCardholderName(order) {
|
||||
return order.get_cardholder_name();
|
||||
}
|
||||
getEmployee(order) {
|
||||
return order.employee ? order.employee.name : '';
|
||||
getCashier(order) {
|
||||
return order.cashier ? order.cashier.name : '';
|
||||
}
|
||||
getStatus(order) {
|
||||
if (order.locked) {
|
||||
@@ -348,9 +348,9 @@ odoo.define('point_of_sale.TicketScreen', function (require) {
|
||||
return `${this._state.syncedOrders.currentPage}/${this._getLastPage()}`;
|
||||
}
|
||||
}
|
||||
getSelectedClient() {
|
||||
getSelectedPartner() {
|
||||
const order = this.getSelectedSyncedOrder();
|
||||
return order ? order.get_client() : null;
|
||||
return order ? order.get_partner() : null;
|
||||
}
|
||||
getHasItemsToRefund() {
|
||||
const order = this.getSelectedSyncedOrder();
|
||||
@@ -396,8 +396,8 @@ odoo.define('point_of_sale.TicketScreen', function (require) {
|
||||
if (orderline.id in this.env.pos.toRefundLines) {
|
||||
return this.env.pos.toRefundLines[orderline.id];
|
||||
} else {
|
||||
const customer = orderline.order.get_client();
|
||||
const orderPartnerId = customer ? customer.id : false;
|
||||
const partner = orderline.order.get_partner();
|
||||
const orderPartnerId = partner ? partner.id : false;
|
||||
const newToRefundDetail = {
|
||||
qty: 0,
|
||||
orderline: {
|
||||
@@ -445,8 +445,8 @@ odoo.define('point_of_sale.TicketScreen', function (require) {
|
||||
displayName: this.env._t('Date'),
|
||||
modelField: 'date_order',
|
||||
},
|
||||
CUSTOMER: {
|
||||
repr: (order) => order.get_client_name(),
|
||||
PARTNER: {
|
||||
repr: (order) => order.get_partner_name(),
|
||||
displayName: this.env._t('Customer'),
|
||||
modelField: 'partner_id.display_name',
|
||||
},
|
||||
|
||||
@@ -112,14 +112,6 @@ var ProxyDevice = core.Class.extend(mixins.PropertiesMixin,{
|
||||
this.use_debug_weight = false;
|
||||
|
||||
this.paying = false;
|
||||
this.default_payment_status = {
|
||||
status: 'waiting',
|
||||
message: '',
|
||||
payment_method: undefined,
|
||||
receipt_client: undefined,
|
||||
receipt_shop: undefined,
|
||||
};
|
||||
this.custom_payment_status = this.default_payment_status;
|
||||
|
||||
this.notifications = {};
|
||||
this.bypass_proxy = false;
|
||||
@@ -466,14 +458,14 @@ var ProxyDevice = core.Class.extend(mixins.PropertiesMixin,{
|
||||
* @param {string} html
|
||||
* @returns {Promise}
|
||||
*/
|
||||
take_ownership_over_client_screen: function(html) {
|
||||
take_ownership_over_customer_screen: function(html) {
|
||||
return this.message("take_control", { html: html });
|
||||
},
|
||||
|
||||
/**
|
||||
* @returns {Promise}
|
||||
*/
|
||||
test_ownership_of_client_screen: function() {
|
||||
test_ownership_of_customer_screen: function() {
|
||||
if (this.connection) {
|
||||
return this.message("test_ownership", {});
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ class PosGlobalState extends PosModel {
|
||||
'synch': { status:'connected', pending:0 },
|
||||
'orders': new PosCollection(),
|
||||
'selectedOrder': null,
|
||||
'selectedClient': null,
|
||||
'selectedPartner': null,
|
||||
'selectedCategoryId': null,
|
||||
});
|
||||
}
|
||||
@@ -1135,7 +1135,7 @@ Registries.Model.add(Product);
|
||||
|
||||
var orderline_id = 1;
|
||||
|
||||
// An orderline represent one element of the content of a client's shopping cart.
|
||||
// An orderline represent one element of the content of a customer's shopping cart.
|
||||
// An orderline contains a product, its quantity, its price, discount. etc.
|
||||
// An Order contains zero or more Orderlines.
|
||||
class Orderline extends PosModel {
|
||||
@@ -2109,7 +2109,7 @@ class Payment extends PosModel {
|
||||
}
|
||||
Registries.Model.add(Payment);
|
||||
|
||||
// An order more or less represents the content of a client's shopping cart (the OrderLines)
|
||||
// An order more or less represents the content of a customer's shopping cart (the OrderLines)
|
||||
// plus the associated payment information (the Paymentlines)
|
||||
// there is always an active ('selected') order in the Pos, a new one is created
|
||||
// automaticaly once an order is completed and sent to the server.
|
||||
@@ -2130,11 +2130,11 @@ class Order extends PosModel {
|
||||
this.orderlines = new PosCollection();
|
||||
this.paymentlines = new PosCollection();
|
||||
this.pos_session_id = this.pos.pos_session.id;
|
||||
this.employee = this.pos.get_cashier();
|
||||
this.cashier = this.pos.get_cashier();
|
||||
this.finalized = false; // if true, cannot be modified.
|
||||
this.set_pricelist(this.pos.default_pricelist);
|
||||
|
||||
this.client = null;
|
||||
this.partner = null;
|
||||
|
||||
this.uiState = {
|
||||
ReceiptScreen: {
|
||||
@@ -2177,7 +2177,7 @@ class Order extends PosModel {
|
||||
* @param {object} json JSON representing one PoS order.
|
||||
*/
|
||||
init_from_JSON(json) {
|
||||
var client;
|
||||
let partner;
|
||||
if (json.pos_session_id !== this.pos.pos_session.id) {
|
||||
this.sequence_number = this.pos.pos_session.sequence_number++;
|
||||
} else {
|
||||
@@ -2212,14 +2212,14 @@ class Order extends PosModel {
|
||||
}
|
||||
|
||||
if (json.partner_id) {
|
||||
client = this.pos.db.get_partner_by_id(json.partner_id);
|
||||
if (!client) {
|
||||
partner = this.pos.db.get_partner_by_id(json.partner_id);
|
||||
if (!partner) {
|
||||
console.error('ERROR: trying to load a partner not available in the pos');
|
||||
}
|
||||
} else {
|
||||
client = null;
|
||||
partner = null;
|
||||
}
|
||||
this.set_client(client);
|
||||
this.set_partner(partner);
|
||||
|
||||
this.temporary = false; // FIXME
|
||||
this.to_invoice = false; // FIXME
|
||||
@@ -2272,7 +2272,7 @@ class Order extends PosModel {
|
||||
statement_ids: paymentLines,
|
||||
pos_session_id: this.pos_session_id,
|
||||
pricelist_id: this.pricelist ? this.pricelist.id : false,
|
||||
partner_id: this.get_client() ? this.get_client().id : false,
|
||||
partner_id: this.get_partner() ? this.get_partner().id : false,
|
||||
user_id: this.pos.user.id,
|
||||
uid: this.uid,
|
||||
sequence_number: this.sequence_number,
|
||||
@@ -2307,10 +2307,10 @@ class Order extends PosModel {
|
||||
.map(function (paymentline) {
|
||||
return paymentline.export_for_printing();
|
||||
});
|
||||
var client = this.client;
|
||||
var cashier = this.pos.get_cashier();
|
||||
var company = this.pos.company;
|
||||
var date = new Date();
|
||||
let partner = this.partner;
|
||||
let cashier = this.pos.get_cashier();
|
||||
let company = this.pos.company;
|
||||
let date = new Date();
|
||||
|
||||
function is_html(subreceipt){
|
||||
return subreceipt ? (subreceipt.split('\n')[0].indexOf('<!DOCTYPE QWEB') >= 0) : false;
|
||||
@@ -2344,7 +2344,7 @@ class Order extends PosModel {
|
||||
tax_details: this.get_tax_details(),
|
||||
change: this.locked ? this.amount_return : this.get_change(),
|
||||
name : this.get_name(),
|
||||
client: client ? client : null ,
|
||||
partner: partner ? partner : null ,
|
||||
invoice_id: null, //TODO
|
||||
cashier: cashier ? cashier.name : null,
|
||||
precision: {
|
||||
@@ -2962,18 +2962,18 @@ class Order extends PosModel {
|
||||
is_to_invoice(){
|
||||
return this.to_invoice;
|
||||
}
|
||||
/* ---- Client / Customer --- */
|
||||
// the client related to the current order.
|
||||
set_client(client){
|
||||
/* ---- Partner --- */
|
||||
// the partner related to the current order.
|
||||
set_partner(partner){
|
||||
this.assert_editable();
|
||||
this.client = client;
|
||||
this.partner = partner;
|
||||
}
|
||||
get_client(){
|
||||
return this.client;
|
||||
get_partner(){
|
||||
return this.partner;
|
||||
}
|
||||
get_client_name(){
|
||||
var client = this.client;
|
||||
return client ? client.name : "";
|
||||
get_partner_name(){
|
||||
let partner = this.partner;
|
||||
return partner ? partner.name : "";
|
||||
}
|
||||
get_cardholder_name(){
|
||||
var card_payment_line = this.paymentlines.find(pl => pl.cardholder_name);
|
||||
@@ -3016,27 +3016,27 @@ class Order extends PosModel {
|
||||
paymentlines: this.get_paymentlines(),
|
||||
};
|
||||
}
|
||||
updatePricelist(newClient) {
|
||||
let newClientPricelist, newClientFiscalPosition;
|
||||
updatePricelist(newPartner) {
|
||||
let newPartnerPricelist, newPartnerFiscalPosition;
|
||||
const defaultFiscalPosition = this.pos.fiscal_positions.find(
|
||||
(position) => position.id === this.pos.config.default_fiscal_position_id[0]
|
||||
);
|
||||
if (newClient) {
|
||||
newClientFiscalPosition = newClient.property_account_position_id
|
||||
if (newPartner) {
|
||||
newPartnerFiscalPosition = newPartner.property_account_position_id
|
||||
? this.pos.fiscal_positions.find(
|
||||
(position) => position.id === newClient.property_account_position_id[0]
|
||||
(position) => position.id === newPartner.property_account_position_id[0]
|
||||
)
|
||||
: defaultFiscalPosition;
|
||||
newClientPricelist =
|
||||
newPartnerPricelist =
|
||||
this.pos.pricelists.find(
|
||||
(pricelist) => pricelist.id === newClient.property_product_pricelist[0]
|
||||
(pricelist) => pricelist.id === newPartner.property_product_pricelist[0]
|
||||
) || this.pos.default_pricelist;
|
||||
} else {
|
||||
newClientFiscalPosition = defaultFiscalPosition;
|
||||
newClientPricelist = this.pos.default_pricelist;
|
||||
newPartnerFiscalPosition = defaultFiscalPosition;
|
||||
newPartnerPricelist = this.pos.default_pricelist;
|
||||
}
|
||||
this.set_fiscal_position(newClientFiscalPosition);
|
||||
this.set_pricelist(newClientPricelist);
|
||||
this.set_fiscal_position(newPartnerFiscalPosition);
|
||||
this.set_pricelist(newPartnerPricelist);
|
||||
}
|
||||
/* ---- Ship later --- */
|
||||
set_to_ship(to_ship) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<CashierName />
|
||||
<SaleDetailsButton t-if="env.proxy.printer" />
|
||||
<ProxyStatus t-if="env.pos.config.use_proxy" />
|
||||
<ClientScreenButton t-if="clientScreenButtonIsShown" />
|
||||
<CustomerFacingDisplayButton t-if="customerFacingDisplayButtonIsShown" />
|
||||
<SyncNotification />
|
||||
<HeaderButton />
|
||||
</div>
|
||||
|
||||
+4
-4
@@ -1,17 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="ClientScreenButton" owl="1">
|
||||
<t t-name="CustomerFacingDisplayButton" owl="1">
|
||||
<div class="oe_status" t-on-click="onClick">
|
||||
<span class="message"><t t-esc="message" /></span>
|
||||
<div t-if="state.status === 'warning'" class="js_warning oe_icon oe_orange">
|
||||
<i class="fa fa-fw fa-desktop" role="img" aria-label="Client Screen Warning" title="Client Screen Warning"></i>
|
||||
<i class="fa fa-fw fa-desktop" role="img" aria-label="Customer Screen Warning" title="Customer Screen Warning"></i>
|
||||
</div>
|
||||
<div t-if="state.status === 'failure'" class="js_disconnected oe_icon oe_red">
|
||||
<i class="fa fa-fw fa-desktop" role="img" aria-label="Client Screen Disconnected" title="Client Screen Disconnected"></i>
|
||||
<i class="fa fa-fw fa-desktop" role="img" aria-label="Customer Screen Disconnected" title="Customer Screen Disconnected"></i>
|
||||
</div>
|
||||
<div t-if="state.status === 'success'" class="js_connected oe_icon oe_green">
|
||||
<i class="fa fa-fw fa-desktop" role="img" aria-label="Client Screen Connected" title="Client Screen Connected"></i>
|
||||
<i class="fa fa-fw fa-desktop" role="img" aria-label="Customer Screen Connected" title="Customer Screen Connected"></i>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
+27
-27
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="ClientDetailsEdit" owl="1">
|
||||
<section class="client-details edit">
|
||||
<div class="client-picture">
|
||||
<t t-name="PartnerDetailsEdit" owl="1">
|
||||
<section class="partner-details edit">
|
||||
<div class="partner-picture">
|
||||
<t t-if="partnerImageUrl">
|
||||
<img t-att-src="partnerImageUrl" alt="Partner"
|
||||
style="width: 64px; height: 64px; object-fit: cover;" />
|
||||
@@ -13,31 +13,31 @@
|
||||
</t>
|
||||
<input type="file" class="image-uploader" t-on-change="uploadImage" />
|
||||
</div>
|
||||
<input class="detail client-name" name="name" t-att-value="props.partner.name or ''"
|
||||
<input class="detail partner-name" name="name" t-att-value="props.partner.name or ''"
|
||||
placeholder="Name" t-on-change="captureChange" />
|
||||
<div class="client-details-box clearfix">
|
||||
<div class="client-details-left">
|
||||
<div class="client-detail">
|
||||
<div class="partner-details-box clearfix">
|
||||
<div class="partner-details-left">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Street</span>
|
||||
<input class="detail client-address-street" name="street"
|
||||
<input class="detail" name="street"
|
||||
t-on-change="captureChange" t-att-value="props.partner.street || ''"
|
||||
placeholder="Street" />
|
||||
</div>
|
||||
<div class="client-detail">
|
||||
<div class="partner-detail">
|
||||
<span class="label">City</span>
|
||||
<input class="detail client-address-city" name="city"
|
||||
<input class="detail" name="city"
|
||||
t-on-change="captureChange" t-att-value="props.partner.city || ''"
|
||||
placeholder="City" />
|
||||
</div>
|
||||
<div class="client-detail">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Postcode</span>
|
||||
<input class="detail client-address-zip" name="zip"
|
||||
<input class="detail" name="zip"
|
||||
t-on-change="captureChange" t-att-value="props.partner.zip || ''"
|
||||
placeholder="ZIP" />
|
||||
</div>
|
||||
<div class="client-detail">
|
||||
<div class="partner-detail">
|
||||
<span class="label">State</span>
|
||||
<select class="detail client-address-states needsclick" name="state_id"
|
||||
<select class="detail" name="state_id"
|
||||
t-on-change="captureChange">
|
||||
<option value="">None</option>
|
||||
<t t-foreach="env.pos.states" t-as="state" t-key="state.id">
|
||||
@@ -49,9 +49,9 @@
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
<div class="client-detail">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Country</span>
|
||||
<select class="detail client-address-country needsclick" name="country_id"
|
||||
<select class="detail" name="country_id"
|
||||
t-on-change="captureChange">
|
||||
<option value="">None</option>
|
||||
<t t-foreach="env.pos.countries" t-as="country" t-key="country.id">
|
||||
@@ -63,10 +63,10 @@
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="client-details-right">
|
||||
<div class="client-detail">
|
||||
<div class="partner-details-right">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Language</span>
|
||||
<select class="detail client-lang needsclick" name="lang"
|
||||
<select class="detail" name="lang"
|
||||
t-on-change="captureChange">
|
||||
<t t-foreach="env.pos.langs" t-as="lang" t-key="lang.id">
|
||||
<option t-att-value="lang.code"
|
||||
@@ -76,31 +76,31 @@
|
||||
</t>
|
||||
</select>
|
||||
</div>
|
||||
<div class="client-detail">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Email</span>
|
||||
<input class="detail client-email" name="email" type="email"
|
||||
<input class="detail" name="email" type="email"
|
||||
t-on-change="captureChange"
|
||||
t-att-value="props.partner.email || ''" />
|
||||
</div>
|
||||
<div class="client-detail">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Phone</span>
|
||||
<input class="detail client-phone" name="phone" type="tel"
|
||||
<input class="detail" name="phone" type="tel"
|
||||
t-on-change="captureChange"
|
||||
t-att-value="props.partner.phone || ''" />
|
||||
</div>
|
||||
<div class="client-detail">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Barcode</span>
|
||||
<input class="detail barcode" name="barcode" t-on-change="captureChange"
|
||||
t-att-value="props.partner.barcode || ''" />
|
||||
</div>
|
||||
<div class="client-detail">
|
||||
<div class="partner-detail">
|
||||
<span class="label">Tax ID</span>
|
||||
<input class="detail vat" name="vat" t-on-change="captureChange"
|
||||
t-att-value="props.partner.vat || ''" />
|
||||
</div>
|
||||
<div t-if="env.pos.pricelists.length gt 1" class="client-detail">
|
||||
<div t-if="env.pos.pricelists.length gt 1" class="partner-detail">
|
||||
<span class="label">Pricelist</span>
|
||||
<select class="detail needsclick" name="property_product_pricelist"
|
||||
<select class="detail" name="property_product_pricelist"
|
||||
t-on-change="captureChange">
|
||||
<t t-foreach="env.pos.pricelists" t-as="pricelist"
|
||||
t-key="pricelist.id">
|
||||
+6
-6
@@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="ClientLine" owl="1">
|
||||
<tr t-attf-class="client-line {{highlight}}" t-att-data-id="props.partner.id"
|
||||
t-on-click="() => this.props.onClickClient(props.partner)">
|
||||
<t t-name="PartnerLine" owl="1">
|
||||
<tr t-attf-class="partner-line {{highlight}}" t-att-data-id="props.partner.id"
|
||||
t-on-click="() => this.props.onClickPartner(props.partner)">
|
||||
<td>
|
||||
<t t-esc="props.partner.name or ''" />
|
||||
<span t-if="highlight">
|
||||
<br/><button class="edit-client-button" t-on-click.stop="() => this.trigger('click-edit')">EDIT</button>
|
||||
<br/><button class="edit-partner-button" t-on-click.stop="() => this.trigger('click-edit')">EDIT</button>
|
||||
</span>
|
||||
</td>
|
||||
<td t-if="!env.isMobile">
|
||||
@@ -20,11 +20,11 @@
|
||||
<t t-esc="props.partner.zip or ''" />
|
||||
<span t-if="highlight"><br/></span>
|
||||
</td>
|
||||
<td class="client-line-email">
|
||||
<td class="partner-line-email">
|
||||
<t t-esc="props.partner.email or ''" />
|
||||
<span t-if="highlight"><br/></span>
|
||||
</td>
|
||||
<td class="client-line-last-column-placeholder oe_invisible"></td>
|
||||
<td class="partner-line-last-column-placeholder oe_invisible"></td>
|
||||
</tr>
|
||||
</t>
|
||||
|
||||
+20
-20
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="ClientListScreen" owl="1">
|
||||
<div class="clientlist-screen screen" t-on-activate-edit-mode="activateEditMode">
|
||||
<t t-name="PartnerListScreen" owl="1">
|
||||
<div class="partnerlist-screen screen">
|
||||
<div class="screen-content">
|
||||
<div class="top-content">
|
||||
<div class="button back" t-on-click="back">
|
||||
<i class="fa fa-angle-double-left"/>
|
||||
<t t-if="!env.isMobile"> Discard</t>
|
||||
</div>
|
||||
<div t-if="!state.detailIsShown && !state.selectedClient" class="button new-customer" role="img" aria-label="Add a customer"
|
||||
t-on-click="() => this.trigger('activate-edit-mode', { isNewClient: true })"
|
||||
<div t-if="!state.detailIsShown && !state.selectedClient" class="button" role="img" aria-label="Add a customer"
|
||||
t-on-click="() => this.activateEditMode(true)"
|
||||
title="Add a customer">
|
||||
<i class="fa fa-plus"/>
|
||||
<t t-if="!env.isMobile"> Create</t>
|
||||
@@ -31,51 +31,51 @@
|
||||
<span> Save</span>
|
||||
</t>
|
||||
</div>
|
||||
<div t-if="!state.detailIsShown" class="searchbox-client top-content-center">
|
||||
<input placeholder="Search Customers" size="1" t-on-keyup="updateClientList" />
|
||||
<span class="search-clear-client"></span>
|
||||
<div t-if="!state.detailIsShown" class="searchbox-partner top-content-center">
|
||||
<input placeholder="Search Customers" size="1" t-on-keyup="updatePartnerList" />
|
||||
<span class="search-clear-partner"></span>
|
||||
</div>
|
||||
<div class="button back" t-on-click="searchClient" t-if="!state.detailIsShown">
|
||||
<div class="button back" t-on-click="searchPartner" t-if="!state.detailIsShown">
|
||||
<span class="database-icon">
|
||||
<i class="fa fa-database"/>
|
||||
</span>
|
||||
<t t-if="!env.isMobile">
|
||||
<span class="load-customer-search">
|
||||
<span>
|
||||
Load Customers
|
||||
</span>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
<section class="full-content">
|
||||
<div class="client-window">
|
||||
<div class="partner-window">
|
||||
<section class="subwindow collapsed">
|
||||
<div class="subwindow-container collapsed">
|
||||
<div t-if="state.detailIsShown" class="client-details-contents subwindow-container-fix">
|
||||
<ClientDetailsEdit t-props="state.editModeProps" />
|
||||
<div t-if="state.detailIsShown" class="partner-details-contents subwindow-container-fix">
|
||||
<PartnerDetailsEdit t-props="state.editModeProps" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="subwindow list">
|
||||
<div class="subwindow-container">
|
||||
<div t-if="!state.detailIsShown" class="subwindow-container-fix scrollable-y">
|
||||
<table class="client-list">
|
||||
<table class="partner-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th t-if="!env.isMobile">Address</th>
|
||||
<th t-if="!env.isMobile">Phone</th>
|
||||
<th t-if="env.isMobile">ZIP</th>
|
||||
<th class="client-line-email">Email</th>
|
||||
<th class="client-line-last-column-placeholder oe_invisible"></th>
|
||||
<th class="partner-line-email">Email</th>
|
||||
<th class="partner-line-last-column-placeholder oe_invisible"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="client-list-contents">
|
||||
<t t-foreach="clients" t-as="partner"
|
||||
<tbody class="partner-list-contents">
|
||||
<t t-foreach="partners" t-as="partner"
|
||||
t-key="partner.id">
|
||||
<ClientLine partner="partner"
|
||||
selectedClient="state.selectedClient"
|
||||
<PartnerLine partner="partner"
|
||||
selectedPartner="state.selectedPartner"
|
||||
detailIsShown="state.detailIsShown"
|
||||
onClickClient.bind="clickClient"/>
|
||||
onClickPartner.bind="clickPartner"/>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -54,16 +54,15 @@
|
||||
</section>
|
||||
|
||||
<div class="payment-buttons">
|
||||
<div class="customer-button">
|
||||
<div class="button" t-att-class="{ highlight: currentOrder.get_client() }" t-on-click="selectClient">
|
||||
<i class="fa fa-user" role="img" aria-label="Customer"
|
||||
title="Customer" />
|
||||
<t t-set="_client" t-value="currentOrder.get_client()" />
|
||||
<span class="js_customer_name">
|
||||
<t t-if="_client">
|
||||
<t t-esc="_client.name" />
|
||||
<div class="partner-button">
|
||||
<div class="button" t-att-class="{ highlight: currentOrder.get_partner() }" t-on-click="selectPartner">
|
||||
<i class="fa fa-user" role="img" title="Customer" />
|
||||
<t t-set="partner" t-value="currentOrder.get_partner()" />
|
||||
<span>
|
||||
<t t-if="partner">
|
||||
<t t-esc="partner.name" />
|
||||
</t>
|
||||
<t t-if="!_client">
|
||||
<t t-if="!partner">
|
||||
Customer
|
||||
</t>
|
||||
</span>
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
<t t-name="ActionpadWidget" owl="1">
|
||||
<div class="actionpad">
|
||||
<button class="button set-customer" t-att-class="{'decentered': isLongName}"
|
||||
t-on-click="() => this.trigger('click-customer')">
|
||||
<button class="button set-partner" t-att-class="{'decentered': isLongName}"
|
||||
t-on-click="() => this.trigger('click-partner')">
|
||||
<t t-if="!env.isMobile"><i class="fa fa-user" role="img" aria-label="Customer" title="Customer" /></t>
|
||||
<t t-if="props.client">
|
||||
<t t-esc="props.client.name" />
|
||||
<t t-if="props.partner">
|
||||
<t t-esc="props.partner.name" />
|
||||
</t>
|
||||
<t t-else="">
|
||||
Customer
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</div>
|
||||
<div class="subpads">
|
||||
<t t-set="_actionName">Payment</t>
|
||||
<ActionpadWidget client="client" actionName="_actionName" onSwitchPane.bind="switchPane" />
|
||||
<ActionpadWidget partner="partner" actionName="_actionName" onSwitchPane.bind="switchPane" />
|
||||
<NumpadWidget activeMode="env.pos.numpadMode" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<div class="col wide">Receipt Number</div>
|
||||
<div class="col">Customer</div>
|
||||
<div class="col wide" t-if="showCardholderName()">Cardholder Name</div>
|
||||
<div class="col">Employee</div>
|
||||
<div class="col">Cashier</div>
|
||||
<div class="col end">Total</div>
|
||||
<div class="col narrow">Status</div>
|
||||
<div class="col very-narrow" name="delete"></div>
|
||||
@@ -76,15 +76,15 @@
|
||||
</div>
|
||||
<div class="col">
|
||||
<div t-if="env.isMobile">Customer</div>
|
||||
<div><t t-esc="getCustomer(order)"></t></div>
|
||||
<div><t t-esc="getPartner(order)"></t></div>
|
||||
</div>
|
||||
<div t-if="showCardholderName()" class="col">
|
||||
<div t-if="env.isMobile">Cardholder Name</div>
|
||||
<div><t t-esc="getCardholderName(order)"></t></div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div t-if="env.isMobile">Employee</div>
|
||||
<div><t t-esc="getEmployee(order)"></t></div>
|
||||
<div t-if="env.isMobile">Cashier</div>
|
||||
<div><t t-esc="getCashier(order)"></t></div>
|
||||
</div>
|
||||
<div class="col end">
|
||||
<div t-if="env.isMobile">Total</div>
|
||||
@@ -121,7 +121,7 @@
|
||||
<div class="subpads">
|
||||
<!-- We set so that the term 'Refund' is translated. -->
|
||||
<t t-set="_actionName">Refund</t>
|
||||
<ActionpadWidget client="getSelectedClient()" actionName="_actionName" actionToTrigger="'do-refund'" isActionButtonHighlighted="getHasItemsToRefund()" />
|
||||
<ActionpadWidget partner="getSelectedPartner()" actionName="_actionName" actionToTrigger="'do-refund'" isActionButtonHighlighted="getHasItemsToRefund()" />
|
||||
<NumpadWidget disabledModes="['price', 'discount']" activeMode="_selectedOrderlineId and 'quantity'" disableSign="true" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -92,7 +92,7 @@ odoo.define('point_of_sale.tour.Chrome', function (require) {
|
||||
|
||||
// Invoice an order
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '5', '6');
|
||||
ProductScreen.do.clickCustomerButton();
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Nicole Ford');
|
||||
ProductScreen.do.clickSetCustomer();
|
||||
ProductScreen.do.clickPayButton();
|
||||
|
||||
@@ -4,7 +4,7 @@ odoo.define('point_of_sale.tour.TicketScreen', function (require) {
|
||||
const { ProductScreen } = require('point_of_sale.tour.ProductScreenTourMethods');
|
||||
const { ReceiptScreen } = require('point_of_sale.tour.ReceiptScreenTourMethods');
|
||||
const { PaymentScreen } = require('point_of_sale.tour.PaymentScreenTourMethods');
|
||||
const { ClientListScreen } = require('point_of_sale.tour.ClientListScreenTourMethods');
|
||||
const { PartnerListScreen } = require('point_of_sale.tour.PartnerListScreenTourMethods');
|
||||
const { TicketScreen } = require('point_of_sale.tour.TicketScreenTourMethods');
|
||||
const { ErrorPopup } = require('point_of_sale.tour.ErrorPopupTourMethods');
|
||||
const { Chrome } = require('point_of_sale.tour.ChromeTourMethods');
|
||||
@@ -16,14 +16,14 @@ odoo.define('point_of_sale.tour.TicketScreen', function (require) {
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.exec.addOrderline('Desk Pad', '1', '2');
|
||||
ProductScreen.do.clickCustomerButton();
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Nicole Ford');
|
||||
ProductScreen.do.clickSetCustomer();
|
||||
Chrome.do.clickTicketButton();
|
||||
TicketScreen.check.nthRowContains(2, 'Nicole Ford');
|
||||
TicketScreen.do.clickNewTicket();
|
||||
ProductScreen.exec.addOrderline('Desk Pad', '1', '3');
|
||||
ProductScreen.do.clickCustomerButton();
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Brandon Freeman');
|
||||
ProductScreen.do.clickSetCustomer();
|
||||
ProductScreen.do.clickPayButton();
|
||||
@@ -78,9 +78,9 @@ odoo.define('point_of_sale.tour.TicketScreen', function (require) {
|
||||
TicketScreen.check.orderWidgetIsNotEmpty();
|
||||
TicketScreen.do.clickControlButton('Invoice');
|
||||
Chrome.do.confirmPopup();
|
||||
ClientListScreen.check.isShown();
|
||||
ClientListScreen.exec.setClient('Colleen Diaz');
|
||||
TicketScreen.check.customerIs('Colleen Diaz');
|
||||
PartnerListScreen.check.isShown();
|
||||
PartnerListScreen.exec.setPartner('Colleen Diaz');
|
||||
TicketScreen.check.partnerIs('Colleen Diaz');
|
||||
// Reprint receipt
|
||||
TicketScreen.do.clickControlButton('Print Receipt');
|
||||
ReceiptScreen.check.isShown();
|
||||
@@ -96,7 +96,7 @@ odoo.define('point_of_sale.tour.TicketScreen', function (require) {
|
||||
// Filter should be automatically 'Paid'.
|
||||
TicketScreen.check.filterIs('Paid');
|
||||
TicketScreen.do.selectOrder('-0003');
|
||||
TicketScreen.check.customerIs('Colleen Diaz');
|
||||
TicketScreen.check.partnerIs('Colleen Diaz');
|
||||
TicketScreen.do.clickOrderline('Desk Pad');
|
||||
TicketScreen.do.pressNumpad('3');
|
||||
// Error should show because 2 is more than the number
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
odoo.define('point_of_sale.tour.ClientListScreenTourMethods', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { createTourMethods } = require('point_of_sale.tour.utils');
|
||||
|
||||
class Do {
|
||||
clickClient(name) {
|
||||
return [
|
||||
{
|
||||
content: `click client '${name}' from client list screen`,
|
||||
trigger: `.clientlist-screen .client-list-contents .client-line td:contains("${name}")`,
|
||||
},
|
||||
{
|
||||
content: `check if client '${name}' is highlighted`,
|
||||
trigger: `.clientlist-screen .client-list-contents .client-line.highlight td:contains("${name}")`,
|
||||
run: () => {},
|
||||
},
|
||||
];
|
||||
}
|
||||
clickSet() {
|
||||
return [
|
||||
{
|
||||
content: 'check if set button shown',
|
||||
trigger: '.clientlist-screen .button.next.highlight',
|
||||
run: () => {},
|
||||
},
|
||||
{
|
||||
content: 'click set button',
|
||||
trigger: '.clientlist-screen .button.next.highlight',
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class Check {
|
||||
isShown() {
|
||||
return [
|
||||
{
|
||||
content: 'client list screen is shown',
|
||||
trigger: '.pos-content .clientlist-screen',
|
||||
run: () => {},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class Execute {
|
||||
setClient(name) {
|
||||
const steps = [];
|
||||
steps.push(...this._do.clickClient(name));
|
||||
steps.push(...this._do.clickSet());
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
|
||||
return createTourMethods('ClientListScreen', Do, Check, Execute);
|
||||
});
|
||||
@@ -1,26 +0,0 @@
|
||||
odoo.define('point_of_sale.tour.CompositeTourMethods', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { ProductScreen } = require('point_of_sale.tour.ProductScreenTourMethods');
|
||||
const { ReceiptScreen } = require('point_of_sale.tour.ReceiptScreenTourMethods');
|
||||
const { PaymentScreen } = require('point_of_sale.tour.PaymentScreenTourMethods');
|
||||
const { ClientListScreen } = require('point_of_sale.tour.ClientListScreenTourMethods');
|
||||
|
||||
function makeFullOrder({ orderlist, customer, payment, ntimes = 1 , customerNote}) {
|
||||
for (let i = 0; i < ntimes; i++) {
|
||||
ProductScreen.exec.addMultiOrderlines(...orderlist);
|
||||
if (customer) {
|
||||
ProductScreen.do.clickCustomerButton();
|
||||
ClientListScreen.exec.setClient(customer);
|
||||
}
|
||||
if (customerNote) { // this will add a note to the last selected order line
|
||||
ProductScreen.exec.addCustomerNote(customerNote);
|
||||
}
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.exec.pay(...payment);
|
||||
ReceiptScreen.exec.nextOrder();
|
||||
}
|
||||
}
|
||||
|
||||
return { makeFullOrder };
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
odoo.define('point_of_sale.tour.PartnerListScreenTourMethods', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { createTourMethods } = require('point_of_sale.tour.utils');
|
||||
|
||||
class Do {
|
||||
clickPartner(name) {
|
||||
return [
|
||||
{
|
||||
content: `click partner '${name}' from partner list screen`,
|
||||
trigger: `.partnerlist-screen .partner-list-contents .partner-line td:contains("${name}")`,
|
||||
},
|
||||
{
|
||||
content: `check if partner '${name}' is highlighted`,
|
||||
trigger: `.partnerlist-screen .partner-list-contents .partner-line.highlight td:contains("${name}")`,
|
||||
run: () => {},
|
||||
},
|
||||
];
|
||||
}
|
||||
clickSet() {
|
||||
return [
|
||||
{
|
||||
content: 'check if set button shown',
|
||||
trigger: '.partnerlist-screen .button.next.highlight',
|
||||
run: () => {},
|
||||
},
|
||||
{
|
||||
content: 'click set button',
|
||||
trigger: '.partnerlist-screen .button.next.highlight',
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class Check {
|
||||
isShown() {
|
||||
return [
|
||||
{
|
||||
content: 'partner list screen is shown',
|
||||
trigger: '.pos-content .partnerlist-screen',
|
||||
run: () => {},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class Execute {
|
||||
setPartner(name) {
|
||||
const steps = [];
|
||||
steps.push(...this._do.clickPartner(name));
|
||||
steps.push(...this._do.clickSet());
|
||||
return steps;
|
||||
}
|
||||
}
|
||||
|
||||
return createTourMethods('PartnerListScreen', Do, Check, Execute);
|
||||
});
|
||||
@@ -91,12 +91,12 @@ odoo.define('point_of_sale.tour.ProductScreenTourMethods', function (require) {
|
||||
];
|
||||
}
|
||||
|
||||
clickCustomerButton() {
|
||||
clickPartnerButton() {
|
||||
return [
|
||||
{ content: 'click customer button', trigger: '.actionpad .button.set-customer' },
|
||||
{ content: 'click customer button', trigger: '.actionpad .button.set-partner' },
|
||||
{
|
||||
content: 'customer screen is shown',
|
||||
trigger: '.pos-content .clientlist-screen',
|
||||
content: 'partner screen is shown',
|
||||
trigger: '.pos-content .partnerlist-screen',
|
||||
run: () => {},
|
||||
},
|
||||
];
|
||||
@@ -106,11 +106,11 @@ odoo.define('point_of_sale.tour.ProductScreenTourMethods', function (require) {
|
||||
return [
|
||||
{
|
||||
content: `select customer '${name}'`,
|
||||
trigger: `.clientlist-screen .client-line td:contains("${name}")`,
|
||||
trigger: `.partnerlist-screen .partner-line td:contains("${name}")`,
|
||||
},
|
||||
{
|
||||
content: `client line '${name}' is highlighted`,
|
||||
trigger: `.clientlist-screen .client-line.highlight td:contains("${name}")`,
|
||||
content: `partner line '${name}' is highlighted`,
|
||||
trigger: `.partnerlist-screen .partner-line.highlight td:contains("${name}")`,
|
||||
run: () => {},
|
||||
},
|
||||
];
|
||||
@@ -120,7 +120,7 @@ odoo.define('point_of_sale.tour.ProductScreenTourMethods', function (require) {
|
||||
return [
|
||||
{
|
||||
content: 'click set customer',
|
||||
trigger: '.clientlist-screen .button.next.highlight',
|
||||
trigger: '.partnerlist-screen .button.next.highlight',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -154,10 +154,10 @@ odoo.define('point_of_sale.tour.TicketScreenTourMethods', function (require) {
|
||||
},
|
||||
];
|
||||
}
|
||||
customerIs(name) {
|
||||
partnerIs(name) {
|
||||
return [
|
||||
{
|
||||
trigger: `.ticket-screen .set-customer:contains("${name}")`,
|
||||
trigger: `.ticket-screen .set-partner:contains("${name}")`,
|
||||
run: () => {},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -96,14 +96,14 @@ odoo.define('point_of_sale.tour.pricelist', function (require) {
|
||||
content: "select fixed pricelist",
|
||||
trigger: ".selection-item:contains('Fixed')",
|
||||
}, {
|
||||
content: "open customer list",
|
||||
trigger: "button.set-customer",
|
||||
content: "open partner list",
|
||||
trigger: "button.set-partner",
|
||||
}, {
|
||||
content: "select Deco Addict",
|
||||
trigger: ".client-line:contains('Deco Addict')",
|
||||
trigger: ".partner-line:contains('Deco Addict')",
|
||||
}, {
|
||||
content: "confirm selection",
|
||||
trigger: ".clientlist-screen .next",
|
||||
trigger: ".partnerlist-screen .next",
|
||||
}, {
|
||||
content: "click pricelist button",
|
||||
trigger: ".control-button.o_pricelist_button",
|
||||
@@ -116,13 +116,13 @@ odoo.define('point_of_sale.tour.pricelist', function (require) {
|
||||
trigger: ".button.cancel:visible",
|
||||
}, {
|
||||
content: "open customer list",
|
||||
trigger: "button.set-customer",
|
||||
trigger: "button.set-partner",
|
||||
}, {
|
||||
content: "select Lumber Inc",
|
||||
trigger: ".client-line:contains('Lumber Inc')",
|
||||
trigger: ".partner-line:contains('Lumber Inc')",
|
||||
}, {
|
||||
content: "confirm selection",
|
||||
trigger: ".clientlist-screen .next",
|
||||
trigger: ".partnerlist-screen .next",
|
||||
}, {
|
||||
content: "click pricelist button",
|
||||
trigger: ".control-button.o_pricelist_button",
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Preferences to allow unattended install of R-Kiosk extension
|
||||
// Needed for Odoo IoT Box Client display
|
||||
// Needed for Odoo IoT Box Customer display
|
||||
pref("app.update.checkInstallTime", false);
|
||||
pref("devtools.webide.widget.autoinstall", false);
|
||||
pref("xpinstall.customConfirmationUI", false);
|
||||
|
||||
@@ -374,7 +374,7 @@ odoo.define('pos_coupon.pos', function (require) {
|
||||
const programIdsWithScannedCoupon = Object.values(this.bookedCouponCodes).map(
|
||||
(couponCode) => couponCode.program_id
|
||||
);
|
||||
const customer = this.get_client();
|
||||
const partner = this.get_partner();
|
||||
const { successful, payload } = await rpc.query({
|
||||
model: 'pos.config',
|
||||
method: 'use_coupon_code',
|
||||
@@ -382,7 +382,7 @@ odoo.define('pos_coupon.pos', function (require) {
|
||||
[this.pos.config.id],
|
||||
code,
|
||||
this.creation_date,
|
||||
customer ? customer.id : false,
|
||||
partner ? partner.id : false,
|
||||
programIdsWithScannedCoupon,
|
||||
],
|
||||
kwargs: { context: session.user_context },
|
||||
@@ -777,9 +777,9 @@ odoo.define('pos_coupon.pos', function (require) {
|
||||
};
|
||||
}
|
||||
|
||||
// Check if valid customer
|
||||
const customer = this.get_client();
|
||||
if (program.rule_partners_domain && !program.valid_partner_ids.has(customer ? customer.id : 0)) {
|
||||
// Check if valid partner
|
||||
const partner = this.get_partner();
|
||||
if (program.rule_partners_domain && !program.valid_partner_ids.has(partner ? partner.id : 0)) {
|
||||
return {
|
||||
successful: false,
|
||||
reason: "Current customer can't avail this program.",
|
||||
|
||||
@@ -24,7 +24,7 @@ The actual till still requires one user but an unlimited number of employees can
|
||||
'point_of_sale.assets': [
|
||||
'pos_hr/static/src/css/pos.css',
|
||||
'pos_hr/static/src/js/models.js',
|
||||
'pos_hr/static/src/js/useSelectEmployee.js',
|
||||
'pos_hr/static/src/js/SelectCashierMixin.js',
|
||||
'pos_hr/static/src/js/Chrome.js',
|
||||
'pos_hr/static/src/js/HeaderLockButton.js',
|
||||
'pos_hr/static/src/js/CashierName.js',
|
||||
|
||||
@@ -4,47 +4,14 @@ odoo.define('pos_hr.CashierName', function (require) {
|
||||
|
||||
const CashierName = require('point_of_sale.CashierName');
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
const useSelectEmployee = require('pos_hr.useSelectEmployee');
|
||||
const SelectCashierMixin = require('pos_hr.SelectCashierMixin');
|
||||
const { useBarcodeReader } = require('point_of_sale.custom_hooks');
|
||||
|
||||
const PosHrCashierName = (CashierName) =>
|
||||
class extends CashierName {
|
||||
class extends SelectCashierMixin(CashierName) {
|
||||
setup() {
|
||||
super.setup();
|
||||
const { selectEmployee, askPin } = useSelectEmployee();
|
||||
this.askPin = askPin;
|
||||
this.selectEmployee = selectEmployee;
|
||||
useBarcodeReader({ cashier: this._onCashierScan });
|
||||
}
|
||||
async selectCashier() {
|
||||
if (!this.env.pos.config.module_pos_hr) return;
|
||||
|
||||
const list = this.env.pos.employees
|
||||
.filter((employee) => employee.id !== this.env.pos.get_cashier().id)
|
||||
.map((employee) => {
|
||||
return {
|
||||
id: employee.id,
|
||||
item: employee,
|
||||
label: employee.name,
|
||||
isSelected: false,
|
||||
};
|
||||
});
|
||||
|
||||
const employee = await this.selectEmployee(list);
|
||||
if (employee) {
|
||||
this.env.pos.set_cashier(employee);
|
||||
}
|
||||
}
|
||||
async _onCashierScan(code) {
|
||||
const employee = this.env.pos.employees.find(
|
||||
(emp) => emp.barcode === Sha1.hash(code.code)
|
||||
);
|
||||
|
||||
if (!employee || employee === this.env.pos.get_cashier()) return;
|
||||
|
||||
if (!employee.pin || (await this.askPin(employee))) {
|
||||
this.env.pos.set_cashier(employee);
|
||||
}
|
||||
useBarcodeReader({ cashier: this.barcodeCashierAction });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ odoo.define('pos_hr.chrome', function (require) {
|
||||
if (this.env.pos.config.module_pos_hr) this.showTempScreen('LoginScreen');
|
||||
}
|
||||
get headerButtonIsShown() {
|
||||
return !this.env.pos.config.module_pos_hr || this.env.pos.cashier.role == 'manager' || this.env.pos.get_cashier_user_id() === this.env.pos.user.id;
|
||||
return !this.env.pos.config.module_pos_hr || this.env.pos.get_cashier().role == 'manager' || this.env.pos.get_cashier_user_id() === this.env.pos.user.id;
|
||||
}
|
||||
showCashMoveButton() {
|
||||
return super.showCashMoveButton() && (!this.env.pos.cashier || this.env.pos.cashier.role == 'manager');
|
||||
|
||||
@@ -12,6 +12,7 @@ odoo.define('point_of_sale.HeaderLockButton', function(require) {
|
||||
this.state = useState({ isUnlockIcon: true, title: 'Unlocked' });
|
||||
}
|
||||
async showLoginScreen() {
|
||||
this.env.pos.reset_cashier();
|
||||
await this.showTempScreen('LoginScreen');
|
||||
}
|
||||
onMouseOver(isMouseOver) {
|
||||
|
||||
@@ -4,21 +4,23 @@ odoo.define('pos_hr.LoginScreen', function (require) {
|
||||
|
||||
const PosComponent = require('point_of_sale.PosComponent');
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
const useSelectEmployee = require('pos_hr.useSelectEmployee');
|
||||
const SelectCashierMixin = require('pos_hr.SelectCashierMixin');
|
||||
const { useBarcodeReader } = require('point_of_sale.custom_hooks');
|
||||
|
||||
class LoginScreen extends PosComponent {
|
||||
class LoginScreen extends SelectCashierMixin(PosComponent) {
|
||||
setup() {
|
||||
super.setup();
|
||||
const { selectEmployee, askPin } = useSelectEmployee();
|
||||
this.selectEmployee = selectEmployee;
|
||||
this.askPin = askPin;
|
||||
useBarcodeReader(
|
||||
{
|
||||
cashier: this._barcodeCashierAction,
|
||||
},
|
||||
true
|
||||
);
|
||||
useBarcodeReader({cashier: this.barcodeCashierAction}, true);
|
||||
}
|
||||
async selectCashier() {
|
||||
if (await super.selectCashier()) {
|
||||
this.back();
|
||||
}
|
||||
}
|
||||
async barcodeCashierAction(code) {
|
||||
if (await super.barcodeCashierAction(code)) {
|
||||
this.back();
|
||||
}
|
||||
}
|
||||
back() {
|
||||
this.props.resolve({ confirmed: false, payload: false });
|
||||
@@ -33,38 +35,6 @@ odoo.define('pos_hr.LoginScreen', function (require) {
|
||||
get shopName() {
|
||||
return this.env.pos.config.name;
|
||||
}
|
||||
async selectCashier() {
|
||||
const list = this.env.pos.employees.map((employee) => {
|
||||
return {
|
||||
id: employee.id,
|
||||
item: employee,
|
||||
label: employee.name,
|
||||
isSelected: false,
|
||||
};
|
||||
});
|
||||
|
||||
const employee = await this.selectEmployee(list);
|
||||
if (employee) {
|
||||
this.env.pos.set_cashier(employee);
|
||||
this.back();
|
||||
}
|
||||
}
|
||||
async _barcodeCashierAction(code) {
|
||||
let theEmployee;
|
||||
for (let employee of this.env.pos.employees) {
|
||||
if (employee.barcode === Sha1.hash(code.code)) {
|
||||
theEmployee = employee;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!theEmployee) return;
|
||||
|
||||
if (!theEmployee.pin || (await this.askPin(theEmployee))) {
|
||||
this.env.pos.set_cashier(theEmployee);
|
||||
this.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
LoginScreen.template = 'LoginScreen';
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/* global Sha1 */
|
||||
odoo.define('pos_hr.SelectCashierMixin', function (require) {
|
||||
'use strict';
|
||||
|
||||
const SelectCashierMixin = (PosComponent) => class ComponentWithSelectCashierMixin extends PosComponent {
|
||||
async askPin(employee) {
|
||||
const { confirmed, payload: inputPin } = await this.showPopup('NumberPopup', {
|
||||
isPassword: true,
|
||||
title: this.env._t('Password ?'),
|
||||
startingValue: null,
|
||||
});
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
if (employee.pin === Sha1.hash(inputPin)) {
|
||||
return employee;
|
||||
} else {
|
||||
await this.showPopup('ErrorPopup', {
|
||||
title: this.env._t('Incorrect Password'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a cashier, the returning value will either be an object or nothing (undefined)
|
||||
*/
|
||||
async selectCashier() {
|
||||
if (this.env.pos.config.module_pos_hr) {
|
||||
const employeesList = this.env.pos.employees
|
||||
.filter((employee) => employee.id !== this.env.pos.get_cashier().id)
|
||||
.map((employee) => {
|
||||
return {
|
||||
id: employee.id,
|
||||
item: employee,
|
||||
label: employee.name,
|
||||
isSelected: false,
|
||||
};
|
||||
});
|
||||
let {confirmed, payload: employee} = await this.showPopup('SelectionPopup', {
|
||||
title: this.env._t('Change Cashier'),
|
||||
list: employeesList,
|
||||
});
|
||||
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (employee && employee.pin) {
|
||||
employee = await this.askPin(employee);
|
||||
}
|
||||
if (employee) {
|
||||
this.env.pos.set_cashier(employee);
|
||||
}
|
||||
return employee;
|
||||
}
|
||||
}
|
||||
|
||||
async barcodeCashierAction(code) {
|
||||
const employee = this.env.pos.employees.find(
|
||||
(emp) => emp.barcode === Sha1.hash(code.code)
|
||||
);
|
||||
if (employee && employee !== this.env.pos.get_cashier() && (!employee.pin || (await this.askPin(employee)))) {
|
||||
this.env.pos.set_cashier(employee);
|
||||
}
|
||||
return employee;
|
||||
}
|
||||
}
|
||||
|
||||
return SelectCashierMixin;
|
||||
});
|
||||
@@ -11,7 +11,7 @@ const PosHrPosGlobalState = (PosGlobalState) => class PosHrPosGlobalState extend
|
||||
if (this.config.module_pos_hr) {
|
||||
this.employees = loadedData['hr.employee'];
|
||||
this.employee_by_id = loadedData['employee_by_id'];
|
||||
this.cashier = {name: null, id: null, barcode: null, user_id: null, pin: null};
|
||||
this.reset_cashier();
|
||||
}
|
||||
}
|
||||
async after_load_server_data() {
|
||||
@@ -20,13 +20,16 @@ const PosHrPosGlobalState = (PosGlobalState) => class PosHrPosGlobalState extend
|
||||
this.hasLoggedIn = !this.config.module_pos_hr;
|
||||
}
|
||||
}
|
||||
reset_cashier() {
|
||||
this.cashier = {name: null, id: null, barcode: null, user_id: null, pin: null, role: null};
|
||||
}
|
||||
set_cashier(employee) {
|
||||
this.cashier = employee;
|
||||
const selectedOrder = this.get_order();
|
||||
if (selectedOrder && !selectedOrder.get_orderlines().length) {
|
||||
// Order without lines can be considered to be un-owned by any employee.
|
||||
// We set the employee on that order to the currently set employee.
|
||||
selectedOrder.employee = employee;
|
||||
// We set the cashier on that order to the currently set employee.
|
||||
selectedOrder.cashier = employee;
|
||||
}
|
||||
if (!this.cashierHasPriceControlRights() && this.numpadMode === 'price') {
|
||||
this.numpadMode = 'quantity';
|
||||
@@ -57,19 +60,19 @@ const PosHrOrder = (Order) => class PosHrOrder extends Order {
|
||||
constructor(obj, options) {
|
||||
super(...arguments);
|
||||
if (!options.json && this.pos.config.module_pos_hr) {
|
||||
this.employee = this.pos.get_cashier();
|
||||
this.cashier = this.pos.get_cashier();
|
||||
}
|
||||
}
|
||||
init_from_JSON(json) {
|
||||
super.init_from_JSON(...arguments);
|
||||
if (this.pos.config.module_pos_hr) {
|
||||
this.employee = this.pos.employee_by_id[json.employee_id];
|
||||
this.cashier = this.pos.employee_by_id[json.employee_id];
|
||||
}
|
||||
}
|
||||
export_as_JSON() {
|
||||
const json = super.export_as_JSON(...arguments);
|
||||
if (this.pos.config.module_pos_hr) {
|
||||
json.employee_id = this.employee ? this.employee.id : false;
|
||||
json.employee_id = this.cashier ? this.cashier.id : false;
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/* global Sha1 */
|
||||
odoo.define('pos_hr.useSelectEmployee', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { useComponent } = owl;
|
||||
|
||||
function useSelectEmployee() {
|
||||
const current = useComponent();
|
||||
|
||||
async function askPin(employee) {
|
||||
const { confirmed, payload: inputPin } = await this.showPopup('NumberPopup', {
|
||||
isPassword: true,
|
||||
title: this.env._t('Password ?'),
|
||||
startingValue: null,
|
||||
});
|
||||
|
||||
if (!confirmed) return false;
|
||||
|
||||
if (employee.pin === Sha1.hash(inputPin)) {
|
||||
return employee;
|
||||
} else {
|
||||
await this.showPopup('ErrorPopup', {
|
||||
title: this.env._t('Incorrect Password'),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function selectEmployee(selectionList) {
|
||||
const { confirmed, payload: employee } = await this.showPopup('SelectionPopup', {
|
||||
title: this.env._t('Change Cashier'),
|
||||
list: selectionList,
|
||||
});
|
||||
|
||||
if (!confirmed) return false;
|
||||
|
||||
if (!employee.pin) {
|
||||
return employee;
|
||||
}
|
||||
|
||||
return await askPin.call(current, employee);
|
||||
}
|
||||
return { askPin: askPin.bind(current), selectEmployee: selectEmployee.bind(current) };
|
||||
}
|
||||
|
||||
return useSelectEmployee;
|
||||
});
|
||||
@@ -14,7 +14,7 @@
|
||||
</span>
|
||||
<span class="login-or">or</span>
|
||||
<span class="login-element">
|
||||
<button class="login-button select-employee"
|
||||
<button class="login-button select-cashier"
|
||||
t-on-click="selectCashier">Select Cashier</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ odoo.define('pos_hr.tour.PosHrTourMethods', function (require) {
|
||||
return [
|
||||
{
|
||||
content: 'click login button',
|
||||
trigger: '.login-overlay .login-button.select-employee',
|
||||
trigger: '.login-overlay .login-button.select-cashier',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
+3
-3
@@ -34,9 +34,9 @@ odoo.define('pos_sale.SaleOrderManagementControlPanel', function (require) {
|
||||
useListener('clear-search', this._onClearSearch);
|
||||
useAutofocus();
|
||||
|
||||
let currentClient = this.env.pos.get_order().get_client();
|
||||
if (currentClient) {
|
||||
this.orderManagementContext.searchString = currentClient.name;
|
||||
let currentPartner = this.env.pos.get_order().get_partner();
|
||||
if (currentPartner) {
|
||||
this.orderManagementContext.searchString = currentPartner.name;
|
||||
let domain = this._computeDomain();
|
||||
SaleOrderFetcher.setSearchDomain(domain);
|
||||
}
|
||||
|
||||
@@ -51,9 +51,9 @@ odoo.define('pos_sale.SaleOrderManagementScreen', function (require) {
|
||||
onWillUnmount() {
|
||||
SaleOrderFetcher.off('update', this);
|
||||
}
|
||||
get selectedClient() {
|
||||
get selectedPartner() {
|
||||
const order = this.orderManagementContext.selectedOrder;
|
||||
return order ? order.get_client() : null;
|
||||
return order ? order.get_partner() : null;
|
||||
}
|
||||
get orders() {
|
||||
return SaleOrderFetcher.get();
|
||||
@@ -90,7 +90,7 @@ odoo.define('pos_sale.SaleOrderManagementScreen', function (require) {
|
||||
}
|
||||
catch (error){
|
||||
}
|
||||
currentPOSOrder.set_client(this.env.pos.db.get_partner_by_id(sale_order.partner_id[0]));
|
||||
currentPOSOrder.set_partner(this.env.pos.db.get_partner_by_id(sale_order.partner_id[0]));
|
||||
let orderFiscalPos = sale_order.fiscal_position_id ? this.env.pos.fiscal_positions.find(
|
||||
(position) => position.id === sale_order.fiscal_position_id[0]
|
||||
)
|
||||
|
||||
@@ -26,9 +26,9 @@ odoo.define('pos_sale.SaleOrderRow', function (require) {
|
||||
get date() {
|
||||
return moment(this.order.date_order).format('YYYY-MM-DD hh:mm A');
|
||||
}
|
||||
get customer() {
|
||||
const customer = this.order.partner_id;
|
||||
return customer ? customer[1] : null;
|
||||
get partner() {
|
||||
const partner = this.order.partner_id;
|
||||
return partner ? partner[1] : null;
|
||||
}
|
||||
get total() {
|
||||
return this.env.pos.format_currency(this.order.amount_total);
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
</t>
|
||||
</div>
|
||||
<div class="subpads">
|
||||
<ActionpadWidget client="selectedClient" />
|
||||
<ActionpadWidget partner="selectedPartner" />
|
||||
<NumpadWidget />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
<div t-if="env.isMobile">Date</div>
|
||||
<div><t t-esc="date"/></div>
|
||||
</div>
|
||||
<div class="col customer">
|
||||
<div class="col partner">
|
||||
<div t-if="env.isMobile">Customer</div>
|
||||
<div><t t-esc="customer"/></div>
|
||||
<div><t t-esc="partner"/></div>
|
||||
</div>
|
||||
<div class="col salesman">
|
||||
<div t-if="env.isMobile">Salesman</div>
|
||||
|
||||
Reference in New Issue
Block a user