mirror of
https://github.com/bringout/oca-ocb-pos.git
synced 2026-04-23 05:22:06 +02:00
Initial commit: Pos packages
This commit is contained in:
commit
95dfb9edb0
1301 changed files with 264148 additions and 0 deletions
|
|
@ -0,0 +1,136 @@
|
|||
.pos .popups .gift-card-popup {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
text-align: center;
|
||||
margin: 1em;
|
||||
|
||||
.gift-card-container {
|
||||
display: flex;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.gift-card-footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.gift-card-input-amount {
|
||||
border-bottom: 1px solid;
|
||||
background-color: #F0EEEE;
|
||||
box-shadow: none;
|
||||
text-align: right;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.gift-card-input-code {
|
||||
border-bottom: 1px solid;
|
||||
background-color: #F0EEEE;
|
||||
box-shadow: none;
|
||||
text-align: center;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.gift-card-button {
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.gift-card-button-confirm {
|
||||
flex-grow: 1;
|
||||
height: auto !important;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.gift-card-input-container {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.footer .gift-card-footer-button {
|
||||
margin-left: 5px;
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.gift-card-error {
|
||||
width: 100%;
|
||||
background-color: rgba(255, 76, 76, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.pos .order {
|
||||
|
||||
.active-programs {
|
||||
padding-top: 0.5em;
|
||||
font-weight: normal;
|
||||
font-size: 80%;
|
||||
text-align: right;
|
||||
padding: 0 1rem .5rem;
|
||||
|
||||
.title {
|
||||
padding-top: 0.8em;
|
||||
padding-bottom: 0.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.orderline.program-reward {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.summary {
|
||||
.loyalty-points {
|
||||
float: left;
|
||||
padding: 10px;
|
||||
max-width: 216px;
|
||||
text-align: left;
|
||||
color: #6EC89B;
|
||||
background: rgba(110, 200, 155, 0.17);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.loyalty-points-title {
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
.loyalty-points-balance {
|
||||
color: #714B67;
|
||||
}
|
||||
|
||||
.loyalty-points-spent {
|
||||
color: #C86E6E;
|
||||
}
|
||||
|
||||
.loyalty-points-total {
|
||||
border-top: solid 2px;
|
||||
text-align: center;
|
||||
padding-top: 4px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pos-receipt .pos-coupon-rewards {
|
||||
text-align: center;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.pos-coupon-rewards .coupon-container {
|
||||
padding-top: 1em;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
// Seems unused
|
||||
.loyalty .subtitle{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loyalty .title {
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import PosComponent from 'point_of_sale.PosComponent';
|
||||
import ProductScreen from 'point_of_sale.ProductScreen';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
import { useListener } from "@web/core/utils/hooks";
|
||||
|
||||
export class PromoCodeButton extends PosComponent {
|
||||
setup() {
|
||||
super.setup();
|
||||
useListener('click', this.onClick);
|
||||
}
|
||||
|
||||
async onClick() {
|
||||
let { confirmed, payload: code } = await this.showPopup('TextInputPopup', {
|
||||
title: this.env._t('Enter Code'),
|
||||
startingValue: '',
|
||||
placeholder: this.env._t('Gift card or Discount code'),
|
||||
});
|
||||
if (confirmed) {
|
||||
code = code.trim();
|
||||
if (code !== '') {
|
||||
this.env.pos.get_order().activateCode(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PromoCodeButton.template = 'PromoCodeButton';
|
||||
|
||||
ProductScreen.addControlButton({
|
||||
component: PromoCodeButton,
|
||||
condition: function () {
|
||||
return this.env.pos.programs.some(p => ['coupons', 'promotion', 'gift_card', 'promo_code', 'next_order_coupons'].includes(p.program_type));
|
||||
}
|
||||
});
|
||||
|
||||
Registries.Component.add(PromoCodeButton);
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import PosComponent from 'point_of_sale.PosComponent';
|
||||
import ProductScreen from 'point_of_sale.ProductScreen';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
import { useListener } from "@web/core/utils/hooks";
|
||||
|
||||
export class ResetProgramsButton extends PosComponent {
|
||||
setup() {
|
||||
super.setup();
|
||||
useListener('click', this.onClick);
|
||||
}
|
||||
|
||||
async onClick() {
|
||||
this.env.pos.get_order()._resetPrograms();
|
||||
}
|
||||
}
|
||||
|
||||
ResetProgramsButton.template = 'ResetProgramsButton';
|
||||
|
||||
ProductScreen.addControlButton({
|
||||
component: ResetProgramsButton,
|
||||
condition: function () {
|
||||
return this.env.pos.programs.some(p => ['coupons', 'promotion'].includes(p.program_type));
|
||||
}
|
||||
});
|
||||
|
||||
Registries.Component.add(ResetProgramsButton);
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { Gui } from 'point_of_sale.Gui';
|
||||
import PosComponent from 'point_of_sale.PosComponent';
|
||||
import ProductScreen from 'point_of_sale.ProductScreen';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
import { useListener } from "@web/core/utils/hooks";
|
||||
|
||||
export class RewardButton extends PosComponent {
|
||||
setup() {
|
||||
super.setup()
|
||||
useListener('click', this.onClick);
|
||||
}
|
||||
|
||||
/**
|
||||
* If rewards are the same, prioritize the one from freeProductRewards.
|
||||
* Make sure that the reward is claimable first.
|
||||
*/
|
||||
_mergeFreeProductRewards(freeProductRewards, potentialFreeProductRewards) {
|
||||
const result = []
|
||||
for (const reward of potentialFreeProductRewards) {
|
||||
if (!freeProductRewards.find(item => item.reward.id === reward.reward.id)) {
|
||||
result.push(reward);
|
||||
}
|
||||
}
|
||||
return freeProductRewards.concat(result);
|
||||
}
|
||||
|
||||
_getPotentialRewards() {
|
||||
const order = this.env.pos.get_order();
|
||||
// Claimable rewards excluding those from eWallet programs.
|
||||
// eWallet rewards are handled in the eWalletButton.
|
||||
let rewards = [];
|
||||
if (order) {
|
||||
const claimableRewards = order.getClaimableRewards();
|
||||
rewards = claimableRewards.filter(({ reward }) => reward.program_id.program_type !== 'ewallet');
|
||||
}
|
||||
const discountRewards = rewards.filter(({ reward }) => reward.reward_type == 'discount');
|
||||
const freeProductRewards = rewards.filter(({ reward }) => reward.reward_type == 'product');
|
||||
const potentialFreeProductRewards = order.getPotentialFreeProductRewards();
|
||||
return discountRewards.concat(this._mergeFreeProductRewards(freeProductRewards, potentialFreeProductRewards));
|
||||
}
|
||||
|
||||
hasClaimableRewards() {
|
||||
return this._getPotentialRewards().length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the reward on the current order, if multiple products can be claimed opens a popup asking for which one.
|
||||
*
|
||||
* @param {Object} reward
|
||||
* @param {Integer} coupon_id
|
||||
*/
|
||||
async _applyReward(reward, coupon_id, potentialQty) {
|
||||
const order = this.env.pos.get_order();
|
||||
order.disabledRewards.delete(reward.id);
|
||||
|
||||
const args = {};
|
||||
if (reward.reward_type === 'product' && reward.multi_product) {
|
||||
const productsList = reward.reward_product_ids.map((product_id) => ({
|
||||
id: product_id,
|
||||
label: this.env.pos.db.get_product_by_id(product_id).display_name,
|
||||
item: product_id,
|
||||
}));
|
||||
const { confirmed, payload: selectedProduct } = await this.showPopup('SelectionPopup', {
|
||||
title: this.env._t('Please select a product for this reward'),
|
||||
list: productsList,
|
||||
});
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
args['product'] = selectedProduct;
|
||||
}
|
||||
if (
|
||||
(reward.reward_type == 'product' && reward.program_id.applies_on !== 'both') ||
|
||||
(reward.program_id.applies_on == 'both' && potentialQty)
|
||||
) {
|
||||
const product = this.env.pos.db.get_product_by_id(args['product'] || reward.reward_product_ids[0]);
|
||||
this.trigger(
|
||||
'click-product',
|
||||
{ product, quantity: potentialQty }
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
const result = order._applyReward(reward, coupon_id, args);
|
||||
if (result !== true) {
|
||||
// Returned an error
|
||||
Gui.showNotification(result);
|
||||
}
|
||||
order._updateRewards();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
async onClick() {
|
||||
const rewards = this._getPotentialRewards();
|
||||
if (rewards.length === 0) {
|
||||
await this.showPopup('ErrorPopup', {
|
||||
title: this.env._t('No rewards available.'),
|
||||
body: this.env._t('There are no rewards claimable for this customer.')
|
||||
});
|
||||
return false;
|
||||
} else if (rewards.length === 1) {
|
||||
return this._applyReward(rewards[0].reward, rewards[0].coupon_id, rewards[0].potentialQty);
|
||||
} else {
|
||||
const rewardsList = rewards.map((reward) => ({
|
||||
id: reward.reward.id,
|
||||
label: reward.reward.description,
|
||||
item: reward,
|
||||
}));
|
||||
const { confirmed, payload: selectedReward } = await this.showPopup('SelectionPopup', {
|
||||
title: this.env._t('Please select a reward'),
|
||||
list: rewardsList,
|
||||
});
|
||||
if (confirmed) {
|
||||
return this._applyReward(selectedReward.reward, selectedReward.coupon_id, selectedReward.potentialQty);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RewardButton.template = 'RewardButton';
|
||||
|
||||
ProductScreen.addControlButton({
|
||||
component: RewardButton,
|
||||
condition: function() {
|
||||
return this.env.pos.programs.length > 0;
|
||||
}
|
||||
});
|
||||
|
||||
Registries.Component.add(RewardButton);
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import PosComponent from 'point_of_sale.PosComponent';
|
||||
import ProductScreen from 'point_of_sale.ProductScreen';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
|
||||
export class eWalletButton extends PosComponent {
|
||||
_getEWalletRewards(order) {
|
||||
const claimableRewards = order.getClaimableRewards();
|
||||
return claimableRewards.filter((reward_line) => {
|
||||
const coupon = this.env.pos.couponCache[reward_line.coupon_id];
|
||||
return coupon && reward_line.reward.program_id.program_type == 'ewallet' && !coupon.isExpired();
|
||||
});
|
||||
}
|
||||
_getEWalletPrograms() {
|
||||
return this.env.pos.programs.filter((p) => p.program_type == 'ewallet');
|
||||
}
|
||||
async _onClickWalletButton() {
|
||||
const order = this.env.pos.get_order();
|
||||
const eWalletPrograms = this.env.pos.programs.filter((p) => p.program_type == 'ewallet');
|
||||
const orderTotal = order.get_total_with_tax();
|
||||
const eWalletRewards = this._getEWalletRewards(order);
|
||||
if (eWalletRewards.length === 0 && orderTotal >= 0) {
|
||||
this.showPopup('ErrorPopup', {
|
||||
title: this.env._t('No valid eWallet found'),
|
||||
body: this.env._t('You either have not created an eWallet or all your eWallets have expired.'),
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (orderTotal < 0 && eWalletPrograms.length >= 1) {
|
||||
let selectedProgram = null;
|
||||
if (eWalletPrograms.length == 1) {
|
||||
selectedProgram = eWalletPrograms[0];
|
||||
} else {
|
||||
const { confirmed, payload } = await this.showPopup('SelectionPopup', {
|
||||
title: this.env._t('Refund with eWallet'),
|
||||
list: eWalletPrograms.map((program) => ({
|
||||
id: program.id,
|
||||
item: program,
|
||||
label: program.name,
|
||||
})),
|
||||
});
|
||||
if (confirmed) {
|
||||
selectedProgram = payload;
|
||||
}
|
||||
}
|
||||
if (selectedProgram) {
|
||||
const eWalletProduct = this.env.pos.db.get_product_by_id(selectedProgram.trigger_product_ids[0]);
|
||||
order.add_product(eWalletProduct, {
|
||||
price: -orderTotal,
|
||||
merge: false,
|
||||
eWalletGiftCardProgram: selectedProgram,
|
||||
});
|
||||
}
|
||||
} else if (eWalletRewards.length >= 1) {
|
||||
let eWalletReward = null;
|
||||
if (eWalletRewards.length == 1) {
|
||||
eWalletReward = eWalletRewards[0];
|
||||
} else {
|
||||
const { confirmed, payload } = await this.showPopup('SelectionPopup', {
|
||||
title: this.env._t('Use eWallet to pay'),
|
||||
list: eWalletRewards.map(({ reward, coupon_id }) => ({
|
||||
id: reward.id,
|
||||
item: { reward, coupon_id },
|
||||
label: `${reward.description} (${reward.program_id.name})`,
|
||||
})),
|
||||
});
|
||||
if (confirmed) {
|
||||
eWalletReward = payload;
|
||||
}
|
||||
}
|
||||
if (eWalletReward) {
|
||||
const result = order._applyReward(eWalletReward.reward, eWalletReward.coupon_id, {});
|
||||
if (result !== true) {
|
||||
// Returned an error
|
||||
this.showPopup('ErrorPopup', {
|
||||
title: this.env._t('Error'),
|
||||
body: result,
|
||||
});
|
||||
}
|
||||
order._updateRewards();
|
||||
}
|
||||
}
|
||||
}
|
||||
_shouldBeHighlighted(orderTotal, eWalletPrograms, eWalletRewards) {
|
||||
return (orderTotal < 0 && eWalletPrograms.length >= 1) || eWalletRewards.length >= 1;
|
||||
}
|
||||
_getText(orderTotal, eWalletPrograms, eWalletRewards) {
|
||||
if (orderTotal < 0 && eWalletPrograms.length >= 1) {
|
||||
return this.env._t('eWallet Refund');
|
||||
} else if (eWalletRewards.length >= 1) {
|
||||
return this.env._t('eWallet Pay');
|
||||
} else {
|
||||
return this.env._t('eWallet');
|
||||
}
|
||||
}
|
||||
}
|
||||
eWalletButton.template = 'point_of_sale.eWalletButton';
|
||||
|
||||
ProductScreen.addControlButton({
|
||||
component: eWalletButton,
|
||||
condition: function () {
|
||||
return this.env.pos.programs.filter((p) => p.program_type == 'ewallet').length > 0;
|
||||
},
|
||||
});
|
||||
|
||||
Registries.Component.add(eWalletButton);
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,14 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import OrderSummary from 'point_of_sale.OrderSummary';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
|
||||
export const PosLoyaltyOrderSummary = (OrderSummary) =>
|
||||
class PosLoyaltyOrderSummary extends OrderSummary {
|
||||
getLoyaltyPoints() {
|
||||
const order = this.env.pos.get_order();
|
||||
return order.getLoyaltyPoints();
|
||||
}
|
||||
};
|
||||
|
||||
Registries.Component.extend(OrderSummary, PosLoyaltyOrderSummary)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import Orderline from 'point_of_sale.Orderline';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
|
||||
export const PosLoyaltyOrderline = (Orderline) =>
|
||||
class extends Orderline{
|
||||
get addedClasses() {
|
||||
return Object.assign({'program-reward': this.props.line.is_reward_line}, super.addedClasses);
|
||||
}
|
||||
_isGiftCardOrEWalletReward() {
|
||||
const coupon = this.env.pos.couponCache[this.props.line.coupon_id];
|
||||
if (coupon) {
|
||||
const program = this.env.pos.program_by_id[coupon.program_id]
|
||||
return ['ewallet', 'gift_card'].includes(program.program_type) && this.props.line.is_reward_line;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
_getGiftCardOrEWalletBalance() {
|
||||
const coupon = this.env.pos.couponCache[this.props.line.coupon_id];
|
||||
if (coupon) {
|
||||
return this.env.pos.format_currency(coupon.balance);
|
||||
}
|
||||
return this.env.pos.format_currency(0);
|
||||
}
|
||||
};
|
||||
|
||||
Registries.Component.extend(Orderline, PosLoyaltyOrderline);
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
odoo.define('pos_loyalty.PartnerLine', function (require) {
|
||||
'use strict';
|
||||
|
||||
const PartnerLine = require('point_of_sale.PartnerLine');
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
|
||||
const PosLoyaltyPartnerLine = (PartnerLine) =>
|
||||
class extends PartnerLine {
|
||||
_getLoyaltyPointsRepr(loyaltyCard) {
|
||||
const program = this.env.pos.program_by_id[loyaltyCard.program_id];
|
||||
if (program.program_type === 'ewallet') {
|
||||
return `${program.name}: ${this.env.pos.format_currency(loyaltyCard.balance)}`;
|
||||
}
|
||||
const balanceRepr = this.env.pos.format_pr(loyaltyCard.balance, 0.01);
|
||||
if (program.portal_visible) {
|
||||
return `${balanceRepr} ${program.portal_point_name}`;
|
||||
}
|
||||
return _.str.sprintf(this.env._t('%s Points'), balanceRepr);
|
||||
}
|
||||
};
|
||||
|
||||
Registries.Component.extend(PartnerLine, PosLoyaltyPartnerLine);
|
||||
|
||||
return PartnerLine;
|
||||
});
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
odoo.define('pos_loyalty.PartnerListScreen', function (require) {
|
||||
'use strict';
|
||||
|
||||
const PartnerListScreen = require('point_of_sale.PartnerListScreen');
|
||||
const Registries = require('point_of_sale.Registries');
|
||||
|
||||
const PosLoyaltyPartnerListScreen = (PartnerListScreen) =>
|
||||
class extends PartnerListScreen {
|
||||
/**
|
||||
* Needs to be set to true to show the loyalty points in the partner list.
|
||||
* @override
|
||||
*/
|
||||
get isBalanceDisplayed() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Registries.Component.extend(PartnerListScreen, PosLoyaltyPartnerListScreen);
|
||||
|
||||
return PartnerListScreen;
|
||||
});
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import PaymentScreen from 'point_of_sale.PaymentScreen';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
import session from 'web.session';
|
||||
import { PosLoyaltyCard } from '@pos_loyalty/js/Loyalty';
|
||||
|
||||
export const PosLoyaltyPaymentScreen = (PaymentScreen) =>
|
||||
class extends PaymentScreen {
|
||||
//@override
|
||||
async validateOrder(isForceValidate) {
|
||||
const pointChanges = {};
|
||||
const newCodes = [];
|
||||
for (const pe of Object.values(this.currentOrder.couponPointChanges)) {
|
||||
if (pe.coupon_id > 0) {
|
||||
pointChanges[pe.coupon_id] = pe.points;
|
||||
} else if (pe.barcode && !pe.giftCardId) {
|
||||
// New coupon with a specific code, validate that it does not exist
|
||||
newCodes.push(pe.barcode);
|
||||
}
|
||||
}
|
||||
for (const line of this.currentOrder._get_reward_lines()) {
|
||||
if (line.coupon_id < 1) {
|
||||
continue;
|
||||
}
|
||||
if (!pointChanges[line.coupon_id]) {
|
||||
pointChanges[line.coupon_id] = -line.points_cost;
|
||||
} else {
|
||||
pointChanges[line.coupon_id] -= line.points_cost;
|
||||
}
|
||||
}
|
||||
if (!await this._isOrderValid(isForceValidate)) {
|
||||
return;
|
||||
}
|
||||
// No need to do an rpc if no existing coupon is being used.
|
||||
if (!_.isEmpty(pointChanges) || newCodes.length) {
|
||||
try {
|
||||
const {successful, payload} = await this.rpc({
|
||||
model: 'pos.order',
|
||||
method: 'validate_coupon_programs',
|
||||
args: [[], pointChanges, newCodes],
|
||||
kwargs: { context: session.user_context },
|
||||
});
|
||||
// Payload may contain the points of the concerned coupons to be updated in case of error. (So that rewards can be corrected)
|
||||
if (payload && payload.updated_points) {
|
||||
for (const pointChange of Object.entries(payload.updated_points)) {
|
||||
if (this.env.pos.couponCache[pointChange[0]]) {
|
||||
this.env.pos.couponCache[pointChange[0]].balance = pointChange[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (payload && payload.removed_coupons) {
|
||||
for (const couponId of payload.removed_coupons) {
|
||||
if (this.env.pos.couponCache[couponId]) {
|
||||
delete this.env.pos.couponCache[couponId];
|
||||
}
|
||||
}
|
||||
this.currentOrder.codeActivatedCoupons = this.currentOrder.codeActivatedCoupons.filter((coupon) => !payload.removed_coupons.includes(coupon.id));
|
||||
}
|
||||
if (!successful) {
|
||||
this.showPopup('ErrorPopup', {
|
||||
title: this.env._t('Error validating rewards'),
|
||||
body: payload.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
} catch (_e) {
|
||||
// Do nothing with error, while this validation step is nice for error messages
|
||||
// it should not be blocking.
|
||||
}
|
||||
}
|
||||
await super.validateOrder(...arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
async _postPushOrderResolve(order, server_ids) {
|
||||
// Compile data for our function
|
||||
const rewardLines = order._get_reward_lines();
|
||||
const partner = order.get_partner();
|
||||
let couponData = Object.values(order.couponPointChanges).reduce((agg, pe) => {
|
||||
agg[pe.coupon_id] = Object.assign({}, pe, {
|
||||
points: pe.points - order._getPointsCorrection(this.env.pos.program_by_id[pe.program_id]),
|
||||
});
|
||||
const program = this.env.pos.program_by_id[pe.program_id];
|
||||
if (program.is_nominative && partner) {
|
||||
agg[pe.coupon_id].partner_id = partner.id;
|
||||
}
|
||||
if (program.program_type != 'loyalty') {
|
||||
agg[pe.coupon_id].date_to = program.date_to;
|
||||
}
|
||||
return agg;
|
||||
}, {});
|
||||
for (const line of rewardLines) {
|
||||
const reward = this.env.pos.reward_by_id[line.reward_id];
|
||||
if (!couponData[line.coupon_id]) {
|
||||
couponData[line.coupon_id] = {
|
||||
points: 0,
|
||||
program_id: reward.program_id.id,
|
||||
coupon_id: line.coupon_id,
|
||||
barcode: false,
|
||||
}
|
||||
if (reward.program_type != 'loyalty') {
|
||||
couponData[line.coupon_id].date_to = reward.program_id.date_to;
|
||||
}
|
||||
}
|
||||
if (!couponData[line.coupon_id].line_codes) {
|
||||
couponData[line.coupon_id].line_codes = [];
|
||||
}
|
||||
if (!couponData[line.coupon_id].line_codes.includes(line.reward_identifier_code)) {
|
||||
!couponData[line.coupon_id].line_codes.push(line.reward_identifier_code);
|
||||
}
|
||||
couponData[line.coupon_id].points -= line.points_cost;
|
||||
}
|
||||
// We actually do not care about coupons for 'current' programs that did not claim any reward, they will be lost if not validated
|
||||
couponData = Object.fromEntries(Object.entries(couponData).filter(([key, value]) => {
|
||||
const program = this.env.pos.program_by_id[value.program_id];
|
||||
if (program.applies_on === 'current') {
|
||||
return value.line_codes && value.line_codes.length;
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
if (!_.isEmpty(couponData)) {
|
||||
const payload = await this.rpc({
|
||||
model: 'pos.order',
|
||||
method: 'confirm_coupon_programs',
|
||||
args: [server_ids, couponData],
|
||||
kwargs: { context: session.user_context },
|
||||
});
|
||||
if (payload.coupon_updates) {
|
||||
for (const couponUpdate of payload.coupon_updates) {
|
||||
let dbCoupon = this.env.pos.couponCache[couponUpdate.old_id];
|
||||
if (dbCoupon) {
|
||||
dbCoupon.id = couponUpdate.id;
|
||||
dbCoupon.balance = couponUpdate.points;
|
||||
dbCoupon.code = couponUpdate.code;
|
||||
} else {
|
||||
dbCoupon = new PosLoyaltyCard(
|
||||
couponUpdate.code, couponUpdate.id, couponUpdate.program_id, couponUpdate.partner_id, couponUpdate.points);
|
||||
this.env.pos.partnerId2CouponIds[partner.id] = this.env.pos.partnerId2CouponIds[partner.id] || new Set();
|
||||
this.env.pos.partnerId2CouponIds[partner.id].add(couponUpdate.id);
|
||||
}
|
||||
delete this.env.pos.couponCache[couponUpdate.old_id];
|
||||
this.env.pos.couponCache[couponUpdate.id] = dbCoupon;
|
||||
}
|
||||
}
|
||||
// Update the usage count since it is checked based on local data
|
||||
if (payload.program_updates) {
|
||||
for (const programUpdate of payload.program_updates) {
|
||||
const program = this.env.pos.program_by_id[programUpdate.program_id];
|
||||
if (program) {
|
||||
program.total_order_count = programUpdate.usages;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (payload.coupon_report) {
|
||||
for (const report_entry of Object.entries(payload.coupon_report)) {
|
||||
await this.env.legacyActionManager.do_action(report_entry[0], {
|
||||
additional_context: {
|
||||
active_ids: report_entry[1],
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
order.new_coupon_info = payload.new_coupon_info;
|
||||
}
|
||||
return super._postPushOrderResolve(order, server_ids);
|
||||
}
|
||||
};
|
||||
|
||||
Registries.Component.extend(PaymentScreen, PosLoyaltyPaymentScreen);
|
||||
|
|
@ -0,0 +1,250 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import ProductScreen from 'point_of_sale.ProductScreen';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
import { useBarcodeReader } from 'point_of_sale.custom_hooks';
|
||||
|
||||
export const PosLoyaltyProductScreen = (ProductScreen) =>
|
||||
class extends ProductScreen {
|
||||
setup() {
|
||||
super.setup();
|
||||
useBarcodeReader({
|
||||
coupon: this._onCouponScan,
|
||||
});
|
||||
}
|
||||
async _onClickPay() {
|
||||
const order = this.env.pos.get_order();
|
||||
const eWalletLine = order.get_orderlines().find(line => line.getEWalletGiftCardProgramType() === 'ewallet');
|
||||
if (eWalletLine && !order.get_partner()) {
|
||||
const {confirmed} = await this.showPopup('ConfirmPopup', {
|
||||
title: this.env._t('Customer needed'),
|
||||
body: this.env._t('eWallet requires a customer to be selected'),
|
||||
});
|
||||
if (confirmed) {
|
||||
const { confirmed, payload: newPartner } = await this.showTempScreen(
|
||||
'PartnerListScreen',
|
||||
{ partner: null }
|
||||
);
|
||||
if (confirmed) {
|
||||
order.set_partner(newPartner);
|
||||
order.updatePricelist(newPartner);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return super._onClickPay(...arguments);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Sets up the options for the gift card product.
|
||||
* @param {object} program
|
||||
* @param {object} options
|
||||
* @returns {Promise<boolean>} whether to proceed with adding the product or not
|
||||
*/
|
||||
async _setupGiftCardOptions(program, options) {
|
||||
options.quantity = 1;
|
||||
options.merge = false;
|
||||
options.eWalletGiftCardProgram = program;
|
||||
|
||||
// If gift card program setting is 'scan_use', ask for the code.
|
||||
if (this.env.pos.config.gift_card_settings == 'scan_use') {
|
||||
const { confirmed, payload: code } = await this.showPopup('TextInputPopup', {
|
||||
title: this.env._t('Generate a Gift Card'),
|
||||
startingValue: '',
|
||||
placeholder: this.env._t('Enter the gift card code'),
|
||||
});
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
const trimmedCode = code.trim();
|
||||
let nomenclatureRules = this.env.barcode_reader.barcode_parser.nomenclature.rules;
|
||||
if (this.env.barcode_reader.fallbackBarcodeParser) {
|
||||
nomenclatureRules.push(...this.env.barcode_reader.fallbackBarcodeParser.nomenclature.rules);
|
||||
}
|
||||
const couponNomenclatureRules = _.filter(nomenclatureRules, function(rule) {
|
||||
return rule.type == "coupon";
|
||||
});
|
||||
let nomenclatureCodePatterns = [];
|
||||
_.each(_.pluck(couponNomenclatureRules, "pattern"), function(pattern){
|
||||
nomenclatureCodePatterns.push(...pattern.split("|"));
|
||||
});
|
||||
const trimmedCodeValid = _.find(nomenclatureCodePatterns, function(pattern) {
|
||||
return trimmedCode.startsWith(pattern);
|
||||
});
|
||||
if (trimmedCode && trimmedCodeValid) {
|
||||
// check if the code exist in the database
|
||||
// if so, use its balance, otherwise, use the unit price of the gift card product
|
||||
const fetchedGiftCard = await this.rpc({
|
||||
model: 'loyalty.card',
|
||||
method: 'search_read',
|
||||
args: [
|
||||
[['code', '=', trimmedCode], ['program_id', '=', program.id]],
|
||||
['points', 'source_pos_order_id'],
|
||||
],
|
||||
});
|
||||
// There should be maximum one gift card for a given code.
|
||||
const giftCard = fetchedGiftCard[0];
|
||||
if (giftCard && giftCard.source_pos_order_id) {
|
||||
this.showPopup('ErrorPopup', {
|
||||
title: this.env._t('This gift card has already been sold'),
|
||||
body: this.env._t('You cannot sell a gift card that has already been sold.'),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
options.giftBarcode = trimmedCode;
|
||||
if (giftCard) {
|
||||
// Use the balance of the gift card as the price of the orderline.
|
||||
// NOTE: No need to convert the points to price because when opening a session,
|
||||
// the gift card programs are made sure to have 1 point = 1 currency unit.
|
||||
options.price = giftCard.points;
|
||||
options.giftCardId = giftCard.id;
|
||||
}
|
||||
} else {
|
||||
this.showNotification('Please enter a valid gift card code.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async setupEWalletOptions(program, options) {
|
||||
options.quantity = 1;
|
||||
options.merge = false;
|
||||
options.eWalletGiftCardProgram = program;
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* If the product is a potential reward, also apply the reward.
|
||||
* @override
|
||||
*/
|
||||
async _addProduct(product, options) {
|
||||
const linkedProgramIds = this.env.pos.productId2ProgramIds[product.id] || [];
|
||||
const linkedPrograms = linkedProgramIds.map(id => this.env.pos.program_by_id[id]);
|
||||
let selectedProgram = null;
|
||||
if (linkedPrograms.length > 1) {
|
||||
const { confirmed, payload: program } = await this.showPopup('SelectionPopup', {
|
||||
title: this.env._t('Select program'),
|
||||
list: linkedPrograms.map((program) => ({
|
||||
id: program.id,
|
||||
item: program,
|
||||
label: program.name,
|
||||
})),
|
||||
});
|
||||
if (confirmed) {
|
||||
selectedProgram = program;
|
||||
} else {
|
||||
// Do nothing here if the selection is cancelled.
|
||||
return;
|
||||
}
|
||||
} else if (linkedPrograms.length === 1) {
|
||||
selectedProgram = linkedPrograms[0];
|
||||
}
|
||||
if (selectedProgram && selectedProgram.program_type == 'gift_card') {
|
||||
const shouldProceed = await this._setupGiftCardOptions(selectedProgram, options);
|
||||
if (!shouldProceed) {
|
||||
return;
|
||||
}
|
||||
} else if (selectedProgram && selectedProgram.program_type == 'ewallet') {
|
||||
const shouldProceed = await this.setupEWalletOptions(selectedProgram, options);
|
||||
if (!shouldProceed) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const order = this.env.pos.get_order();
|
||||
const potentialRewards = order.getPotentialFreeProductRewards();
|
||||
let rewardsToApply = [];
|
||||
for (const reward of potentialRewards) {
|
||||
for (const reward_product_id of reward.reward.reward_product_ids) {
|
||||
if (reward_product_id == product.id) {
|
||||
rewardsToApply.push(reward);
|
||||
}
|
||||
}
|
||||
}
|
||||
await super._addProduct(product, options);
|
||||
await order._updatePrograms();
|
||||
if (rewardsToApply.length == 1) {
|
||||
const reward = rewardsToApply[0];
|
||||
order._applyReward(reward.reward, reward.coupon_id, { product: product.id });
|
||||
}
|
||||
}
|
||||
|
||||
_onCouponScan(code) {
|
||||
// IMPROVEMENT: Ability to understand if the scanned code is to be paid or to be redeemed.
|
||||
this.currentOrder.activateCode(code.base_code);
|
||||
}
|
||||
|
||||
async _updateSelectedOrderline(event) {
|
||||
const selectedLine = this.currentOrder.get_selected_orderline();
|
||||
if (event.detail.key === '-') {
|
||||
if (selectedLine && selectedLine.eWalletGiftCardProgram) {
|
||||
// Do not allow negative quantity or price in a gift card or ewallet orderline.
|
||||
// Refunding gift card or ewallet is not supported.
|
||||
this.showNotification(this.env._t('You cannot set negative quantity or price to gift card or ewallet.'), 4000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (selectedLine && selectedLine.is_reward_line && !selectedLine.manual_reward &&
|
||||
(event.detail.key === 'Backspace' || event.detail.key === 'Delete')) {
|
||||
const reward = this.env.pos.reward_by_id[selectedLine.reward_id];
|
||||
const { confirmed } = await this.showPopup('ConfirmPopup', {
|
||||
title: this.env._t('Deactivating reward'),
|
||||
body: _.str.sprintf(
|
||||
this.env._t('Are you sure you want to remove %s from this order?\n You will still be able to claim it through the reward button.'),
|
||||
reward.description
|
||||
),
|
||||
cancelText: this.env._t('No'),
|
||||
confirmText: this.env._t('Yes'),
|
||||
});
|
||||
if (confirmed) {
|
||||
event.detail.buffer = null;
|
||||
} else {
|
||||
// Cancel backspace
|
||||
return;
|
||||
}
|
||||
}
|
||||
return super._updateSelectedOrderline(...arguments);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1/ Perform the usual set value operation (super._setValue) if the line being modified
|
||||
* is not a reward line or if it is a reward line, the `val` being set is '' or 'remove' only.
|
||||
*
|
||||
* 2/ Update activated programs and coupons when removing a reward line.
|
||||
*
|
||||
* 3/ Trigger 'update-rewards' if the line being modified is a regular line or
|
||||
* if removing a reward line.
|
||||
*
|
||||
* @override
|
||||
*/
|
||||
_setValue(val) {
|
||||
const selectedLine = this.currentOrder.get_selected_orderline();
|
||||
if (
|
||||
!selectedLine ||
|
||||
!selectedLine.is_reward_line ||
|
||||
(selectedLine.is_reward_line && ['', 'remove'].includes(val))
|
||||
) {
|
||||
super._setValue(val);
|
||||
}
|
||||
if (!selectedLine) return;
|
||||
if (selectedLine.is_reward_line && val === 'remove') {
|
||||
this.currentOrder.disabledRewards.add(selectedLine.reward_id);
|
||||
const coupon = this.env.pos.couponCache[selectedLine.coupon_id];
|
||||
if (coupon && coupon.id > 0 && this.currentOrder.codeActivatedCoupons.find((c) => c.code === coupon.code)) {
|
||||
delete this.env.pos.couponCache[selectedLine.coupon_id];
|
||||
this.currentOrder.codeActivatedCoupons.splice(this.currentOrder.codeActivatedCoupons.findIndex((coupon) => {
|
||||
return coupon.id === selectedLine.coupon_id;
|
||||
}), 1);
|
||||
}
|
||||
}
|
||||
if (!selectedLine.is_reward_line || (selectedLine.is_reward_line && val === 'remove')) {
|
||||
selectedLine.order._updateRewards();
|
||||
}
|
||||
}
|
||||
async _showDecreaseQuantityPopup() {
|
||||
const result = await super._showDecreaseQuantityPopup();
|
||||
if (result){
|
||||
this.env.pos.get_order()._updateRewards();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Registries.Component.extend(ProductScreen, PosLoyaltyProductScreen);
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import TicketScreen from 'point_of_sale.TicketScreen';
|
||||
import Registries from 'point_of_sale.Registries';
|
||||
import NumberBuffer from 'point_of_sale.NumberBuffer';
|
||||
|
||||
/**
|
||||
* Prevent refunding ewallet/gift card lines.
|
||||
*/
|
||||
export const PosLoyaltyTicketScreen = (TicketScreen) =>
|
||||
class PosLoyaltyTicketScreen extends TicketScreen {
|
||||
_onUpdateSelectedOrderline() {
|
||||
const order = this.getSelectedSyncedOrder();
|
||||
if (!order) return NumberBuffer.reset();
|
||||
const selectedOrderlineId = this.getSelectedOrderlineId();
|
||||
const orderline = order.orderlines.find((line) => line.id == selectedOrderlineId);
|
||||
if (orderline && this._isEWalletGiftCard(orderline)) {
|
||||
this._showNotAllowedRefundNotification();
|
||||
return NumberBuffer.reset();
|
||||
}
|
||||
return super._onUpdateSelectedOrderline(...arguments);
|
||||
}
|
||||
_prepareAutoRefundOnOrder(order) {
|
||||
const selectedOrderlineId = this.getSelectedOrderlineId();
|
||||
const orderline = order.orderlines.find((line) => line.id == selectedOrderlineId);
|
||||
if (this._isEWalletGiftCard(orderline)) {
|
||||
this._showNotAllowedRefundNotification();
|
||||
return false;
|
||||
}
|
||||
return super._prepareAutoRefundOnOrder(...arguments);
|
||||
}
|
||||
_showNotAllowedRefundNotification() {
|
||||
this.showNotification(this.env._t("Refunding a top up or reward product for an eWallet or gift card program is not allowed."), 5000);
|
||||
}
|
||||
_isEWalletGiftCard(orderline) {
|
||||
const linkedProgramIds = this.env.pos.productId2ProgramIds[orderline.product.id];
|
||||
if (linkedProgramIds) {
|
||||
return linkedProgramIds.length > 0;
|
||||
}
|
||||
if (orderline.is_reward_line) {
|
||||
const reward = this.env.pos.reward_by_id[orderline.reward_id];
|
||||
const program = reward && reward.program_id;
|
||||
if (program && ['gift_card', 'ewallet'].includes(program.program_type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
Registries.Component.extend(TicketScreen, PosLoyaltyTicketScreen);
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { ErrorPopup } from 'point_of_sale.tour.ErrorPopupTourMethods';
|
||||
import { PosLoyalty } from 'pos_loyalty.tour.PosCouponTourMethods';
|
||||
import { ProductScreen } from 'point_of_sale.tour.ProductScreenTourMethods';
|
||||
import { TicketScreen } from 'point_of_sale.tour.TicketScreenTourMethods';
|
||||
import { Chrome } from 'point_of_sale.tour.ChromeTourMethods';
|
||||
import { PartnerListScreen } from 'point_of_sale.tour.PartnerListScreenTourMethods';
|
||||
import { getSteps, startSteps } from 'point_of_sale.tour.utils';
|
||||
import Tour from 'web_tour.tour';
|
||||
|
||||
//#region EWalletProgramTour1
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// Topup 50$ for partner_aaa
|
||||
ProductScreen.do.clickDisplayedProduct('Top-up eWallet');
|
||||
PosLoyalty.check.orderTotalIs('50.00');
|
||||
ProductScreen.do.clickPayButton(false);
|
||||
// If there's no partner, we asked to redirect to the partner list screen.
|
||||
Chrome.do.confirmPopup();
|
||||
PartnerListScreen.check.isShown();
|
||||
PartnerListScreen.do.clickPartner('AAAAAAA');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Topup 10$ for partner_bbb
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('BBBBBBB');
|
||||
ProductScreen.exec.addOrderline('Top-up eWallet', '1', '10');
|
||||
PosLoyalty.check.orderTotalIs('10.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('EWalletProgramTour1', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region EWalletProgramTour2
|
||||
|
||||
const getEWalletText = (suffix) => 'eWallet' + (suffix !== '' ? ` ${suffix}` : '');
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '2', '6', '12.00');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: false });
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAAAAAA');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: true, text: getEWalletText('Pay') });
|
||||
PosLoyalty.do.clickEWalletButton(getEWalletText('Pay'));
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Consume partner_bbb's full eWallet.
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('BBBBBBB');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: false });
|
||||
ProductScreen.exec.addOrderline('Desk Pad', '6', '6', '36.00');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: true, text: getEWalletText('Pay') });
|
||||
PosLoyalty.do.clickEWalletButton(getEWalletText('Pay'));
|
||||
PosLoyalty.check.orderTotalIs('26.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Switching partners should work.
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('BBBBBBB');
|
||||
ProductScreen.exec.addOrderline('Desk Pad', '2', '19', '38.00');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: false });
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAAAAAA');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: true, text: getEWalletText('Pay') });
|
||||
PosLoyalty.do.clickEWalletButton(getEWalletText('Pay'));
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('BBBBBBB');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: false });
|
||||
PosLoyalty.check.orderTotalIs('38.00');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAAAAAA');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: true, text: getEWalletText('Pay') });
|
||||
PosLoyalty.do.clickEWalletButton(getEWalletText('Pay'));
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Refund with eWallet.
|
||||
// - Make an order to refund.
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('BBBBBBB');
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '1', '20', '20.00');
|
||||
PosLoyalty.check.orderTotalIs('20.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
// - Refund order.
|
||||
ProductScreen.do.clickRefund();
|
||||
TicketScreen.check.filterIs('Paid');
|
||||
TicketScreen.do.selectOrder('-0004');
|
||||
TicketScreen.check.partnerIs('BBBBBBB');
|
||||
TicketScreen.do.confirmRefund();
|
||||
ProductScreen.check.isShown();
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: true, text: getEWalletText('Refund') });
|
||||
PosLoyalty.do.clickEWalletButton(getEWalletText('Refund'));
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('EWalletProgramTour2', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region ExpiredEWalletProgramTour
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAAA');
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '2', '6', '12.00');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: false });
|
||||
PosLoyalty.do.clickEWalletButton();
|
||||
ErrorPopup.check.isShown();
|
||||
ErrorPopup.do.clickConfirm();
|
||||
|
||||
Tour.register('ExpiredEWalletProgramTour', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
//#endregion
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer("partner_a");
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: false });
|
||||
ProductScreen.exec.addOrderline("product_a", "1");
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: true, text: getEWalletText("Pay") });
|
||||
PosLoyalty.do.clickEWalletButton(getEWalletText("Pay"));
|
||||
PosLoyalty.check.pointsAwardedAre("100"),
|
||||
PosLoyalty.exec.finalizeOrder("Cash", "90");
|
||||
Tour.register("PosLoyaltyPointsEwallet", { test: true, url: "/pos/web" }, getSteps());
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { PosLoyalty } from 'pos_loyalty.tour.PosCouponTourMethods';
|
||||
import { ProductScreen } from 'point_of_sale.tour.ProductScreenTourMethods';
|
||||
import { TextInputPopup } from 'point_of_sale.tour.TextInputPopupTourMethods';
|
||||
import { getSteps, startSteps } from 'point_of_sale.tour.utils';
|
||||
import Tour from 'web_tour.tour';
|
||||
|
||||
//#region GiftCardProgramCreateSetTour1
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickDisplayedProduct('Gift Card');
|
||||
PosLoyalty.check.orderTotalIs('50.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
Tour.register('GiftCardProgramCreateSetTour1', { test: true, url: '/pos/web' }, getSteps());
|
||||
//#endregion
|
||||
|
||||
//#region GiftCardProgramCreateSetTour2
|
||||
startSteps();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
PosLoyalty.do.enterCode('044123456');
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
Tour.register('GiftCardProgramCreateSetTour2', { test: true, url: '/pos/web' }, getSteps());
|
||||
//#endregion
|
||||
|
||||
//#region GiftCardProgramScanUseTour
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
// Pay the 5$ gift card.
|
||||
ProductScreen.do.clickDisplayedProduct('Gift Card');
|
||||
TextInputPopup.check.isShown();
|
||||
TextInputPopup.do.inputText('044123456');
|
||||
TextInputPopup.do.clickConfirm();
|
||||
PosLoyalty.check.orderTotalIs('5.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
// Partially use the gift card. (4$)
|
||||
ProductScreen.exec.addOrderline('Desk Pad', '2', '2', '4.0');
|
||||
PosLoyalty.do.enterCode('044123456');
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
// Use the remaining of the gift card. (5$ - 4$ = 1$)
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '6', '6', '36.0');
|
||||
PosLoyalty.do.enterCode('044123456');
|
||||
PosLoyalty.check.orderTotalIs('35.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
Tour.register('GiftCardProgramScanUseTour', { test: true, url: '/pos/web' }, getSteps());
|
||||
//#endregion
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickDisplayedProduct('Gift Card');
|
||||
TextInputPopup.check.isShown();
|
||||
TextInputPopup.do.inputText('044123456');
|
||||
TextInputPopup.do.clickConfirm();
|
||||
PosLoyalty.check.orderTotalIs('50.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer("partner_a");
|
||||
ProductScreen.exec.addOrderline("product_a", "1");
|
||||
PosLoyalty.do.enterCode("044123456");
|
||||
PosLoyalty.check.orderTotalIs("50.00");
|
||||
PosLoyalty.check.pointsAwardedAre("100"),
|
||||
PosLoyalty.exec.finalizeOrder("Cash", "50");
|
||||
Tour.register("PosLoyaltyPointsGiftcard", { test: true, url: "/pos/web" }, getSteps());
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickDisplayedProduct('Gift Card');
|
||||
TextInputPopup.check.isShown();
|
||||
TextInputPopup.do.inputText('044123456');
|
||||
TextInputPopup.do.clickConfirm();
|
||||
PosLoyalty.check.orderTotalIs('50.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
ProductScreen.do.clickDisplayedProduct("Test Product A");
|
||||
PosLoyalty.do.enterCode("044123456");
|
||||
PosLoyalty.check.orderTotalIs("50.00");
|
||||
ProductScreen.check.checkTaxAmount("-6.52");
|
||||
Tour.register("PosLoyaltyGiftCardTaxes", { test: true }, getSteps());
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickDisplayedProduct('Gift Card');
|
||||
TextInputPopup.check.isShown();
|
||||
TextInputPopup.do.inputText('044123456');
|
||||
TextInputPopup.do.clickConfirm();
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
ProductScreen.do.pressNumpad("Price 5");
|
||||
PosLoyalty.check.orderTotalIs('5.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
Tour.register("PosLoyaltyGiftCardNoPoints", { test: true }, getSteps());
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { PosLoyalty } from 'pos_loyalty.tour.PosCouponTourMethods';
|
||||
import { ProductScreen } from 'point_of_sale.tour.ProductScreenTourMethods';
|
||||
import { SelectionPopup } from 'point_of_sale.tour.SelectionPopupTourMethods';
|
||||
import { getSteps, startSteps } from 'point_of_sale.tour.utils';
|
||||
import Tour from 'web_tour.tour';
|
||||
|
||||
const getEWalletText = (suffix) => 'eWallet' + (suffix !== '' ? ` ${suffix}` : '');
|
||||
|
||||
startSteps();
|
||||
// One card for gift_card_1.
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickDisplayedProduct('Gift Card');
|
||||
SelectionPopup.check.hasSelectionItem('gift_card_1');
|
||||
SelectionPopup.check.hasSelectionItem('gift_card_2');
|
||||
SelectionPopup.do.clickItem('gift_card_1');
|
||||
ProductScreen.do.pressNumpad('Price');
|
||||
ProductScreen.do.pressNumpad('1 0');
|
||||
PosLoyalty.check.orderTotalIs('10.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
// One card for gift_card_1.
|
||||
ProductScreen.do.clickDisplayedProduct('Gift Card');
|
||||
SelectionPopup.do.clickItem('gift_card_2');
|
||||
ProductScreen.do.pressNumpad('Price');
|
||||
ProductScreen.do.pressNumpad('2 0');
|
||||
PosLoyalty.check.orderTotalIs('20.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
// Top up ewallet_1 for AAAAAAA.
|
||||
ProductScreen.do.clickDisplayedProduct('Top-up eWallet');
|
||||
SelectionPopup.check.hasSelectionItem('ewallet_1');
|
||||
SelectionPopup.check.hasSelectionItem('ewallet_2');
|
||||
SelectionPopup.do.clickItem('ewallet_1');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAAAAAA');
|
||||
ProductScreen.do.pressNumpad('Price');
|
||||
ProductScreen.do.pressNumpad('3 0');
|
||||
PosLoyalty.check.orderTotalIs('30.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
// Top up ewallet_2 for AAAAAAA.
|
||||
ProductScreen.do.clickDisplayedProduct('Top-up eWallet');
|
||||
SelectionPopup.do.clickItem('ewallet_2');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAAAAAA');
|
||||
ProductScreen.do.pressNumpad('Price');
|
||||
ProductScreen.do.pressNumpad('4 0');
|
||||
PosLoyalty.check.orderTotalIs('40.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
// Top up ewallet_1 for BBBBBBB.
|
||||
ProductScreen.do.clickDisplayedProduct('Top-up eWallet');
|
||||
SelectionPopup.do.clickItem('ewallet_1');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('BBBBBBB');
|
||||
PosLoyalty.check.orderTotalIs('50.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
// Consume 12$ from ewallet_1 of AAAAAAA.
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '2', '6', '12.00');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: false });
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAAAAAA');
|
||||
PosLoyalty.check.eWalletButtonState({ highlighted: true, text: getEWalletText('Pay') });
|
||||
PosLoyalty.do.clickEWalletButton(getEWalletText('Pay'));
|
||||
SelectionPopup.check.hasSelectionItem('ewallet_1');
|
||||
SelectionPopup.check.hasSelectionItem('ewallet_2');
|
||||
SelectionPopup.do.clickItem('ewallet_1');
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('MultipleGiftWalletProgramsTour', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { PosLoyalty } from 'pos_loyalty.tour.PosCouponTourMethods';
|
||||
import { ProductScreen } from 'point_of_sale.tour.ProductScreenTourMethods';
|
||||
import { getSteps, startSteps } from 'point_of_sale.tour.utils';
|
||||
import Tour from 'web_tour.tour';
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// Order1: Generates 2 points.
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '2');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner AAA');
|
||||
PosLoyalty.check.orderTotalIs('6.40');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Order2: Consumes points to get free product.
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner AAA');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '1.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '2.00');
|
||||
// At this point, Test Partner AAA has 4 points.
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '3.00');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '-3.20', '1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.check.orderTotalIs('6.40');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Order3: Generate 4 points.
|
||||
// - Initially gets free product, but was removed automatically by changing the
|
||||
// number of items to zero.
|
||||
// - It's impossible to checked here if the free product reward is really removed
|
||||
// so we check in the backend the number of orders that consumed the reward.
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '4');
|
||||
PosLoyalty.check.orderTotalIs('12.80');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner AAA');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '-3.20', '1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.do.pressNumpad('Backspace');
|
||||
// At this point, the reward line should have been automatically removed
|
||||
// because there is not enough points to purchase it. Unfortunately, we
|
||||
// can't check that here.
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '1.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '2.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '3.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '4.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
|
||||
PosLoyalty.check.orderTotalIs('12.80');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyLoyaltyProgram1', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// Order1: Immediately set the customer to Test Partner AAA which has 4 points.
|
||||
// - He has enough points to purchase a free product but since there is still
|
||||
// no product in the order, reward button should not yet be highlighted.
|
||||
// - Furthermore, clicking the reward product should not add it as reward product.
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner AAA');
|
||||
// No item in the order, so reward button is off.
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '-3.20', '1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.check.orderTotalIs('3.20');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Order2: Generate 4 points for Test Partner CCC.
|
||||
// - Reference: Order2_CCC
|
||||
// - But set Test Partner BBB first as the customer.
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner BBB');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '1.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '2.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '3.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '4.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner CCC');
|
||||
PosLoyalty.check.customerIs('Test Partner CCC');
|
||||
PosLoyalty.check.orderTotalIs('12.80');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Order3: Generate 3 points for Test Partner BBB.
|
||||
// - Reference: Order3_BBB
|
||||
// - But set Test Partner CCC first as the customer.
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner CCC');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '3');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner BBB');
|
||||
PosLoyalty.check.customerIs('Test Partner BBB');
|
||||
PosLoyalty.check.orderTotalIs('9.60');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Order4: Should not have reward because the customer will be removed.
|
||||
// - Reference: Order4_no_reward
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
ProductScreen.check.selectedOrderlineHas('Whiteboard Pen', '1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner CCC');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '-3.20', '1.00');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
// This deselects the customer.
|
||||
PosLoyalty.do.unselectPartner();
|
||||
PosLoyalty.check.customerIs('Customer');
|
||||
PosLoyalty.check.orderTotalIs('6.40');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyLoyaltyProgram2', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// Generates 10.2 points and use points to get the reward product with zero sale price
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '2');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner AAA');
|
||||
|
||||
// At this point, the free_product program is triggered.
|
||||
// The reward button should be highlighted.
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '0.0', '1.00');
|
||||
|
||||
PosLoyalty.check.orderTotalIs('10.2');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyLoyaltyProgram3', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAA Partner');
|
||||
ProductScreen.exec.addOrderline('Test Product 1', '1.00', '100');
|
||||
ProductScreen.check.totalAmountIs('80.00');
|
||||
|
||||
Tour.register('PosLoyaltyPromotion', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// Generates 10.2 points and use points to get the reward product with zero sale price
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '3');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyNextOrderCouponExpirationDate', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('Test Partner');
|
||||
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '1');
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '1');
|
||||
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
|
||||
PosLoyalty.check.orderTotalIs('5.10');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyDontGrantPointsForRewardOrderLines', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { PosLoyalty } from 'pos_loyalty.tour.PosCouponTourMethods';
|
||||
import { ProductScreen } from 'point_of_sale.tour.ProductScreenTourMethods';
|
||||
import { SelectionPopup } from 'point_of_sale.tour.SelectionPopupTourMethods';
|
||||
import { getSteps, startSteps } from 'point_of_sale.tour.utils';
|
||||
import Tour from 'web_tour.tour';
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '2');
|
||||
|
||||
// At this point, the free_product program is triggered.
|
||||
// The reward button should be highlighted.
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
// Since the reward button is highlighted, clicking the reward product should be added as reward.
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
ProductScreen.check.selectedOrderlineHas('Desk Organizer', '3.00');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Desk Organizer', '-5.10', '1.00');
|
||||
// In the succeeding 2 clicks on the product, it is considered as a regular product.
|
||||
// In the third click, the product will be added as reward.
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
ProductScreen.check.selectedOrderlineHas('Desk Organizer', '6.00');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Desk Organizer', '-10.20', '2.00');
|
||||
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.check.orderTotalIs('25.50');
|
||||
// Finalize order that consumed a reward.
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
ProductScreen.check.selectedOrderlineHas('Desk Organizer', '1.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
ProductScreen.check.selectedOrderlineHas('Desk Organizer', '2.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Desk Organizer', '-5.10', '1.00');
|
||||
ProductScreen.do.pressNumpad('Backspace');
|
||||
ProductScreen.check.selectedOrderlineHas('Desk Organizer', '0.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
ProductScreen.check.selectedOrderlineHas('Desk Organizer', '1.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Organizer');
|
||||
ProductScreen.check.selectedOrderlineHas('Desk Organizer', '2.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
// Finalize order but without the reward.
|
||||
// This step is important. When syncing the order, no reward should be synced.
|
||||
PosLoyalty.check.orderTotalIs('10.20');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
|
||||
ProductScreen.exec.addOrderline('Magnetic Board', '2');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.do.clickDisplayedProduct('Magnetic Board');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '-3.20', '1.00');
|
||||
ProductScreen.do.clickOrderline('Magnetic Board', '3.00');
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', '3.00');
|
||||
ProductScreen.do.pressNumpad('6');
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', '6.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '-6.40', '2.00');
|
||||
// Finalize order that consumed a reward.
|
||||
PosLoyalty.check.orderTotalIs('11.88');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
ProductScreen.exec.addOrderline('Magnetic Board', '6');
|
||||
ProductScreen.do.clickDisplayedProduct('Whiteboard Pen');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '-3.20', '1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
|
||||
ProductScreen.do.clickOrderline('Magnetic Board', '6.00');
|
||||
ProductScreen.do.pressNumpad('Backspace');
|
||||
// At this point, the reward should have been removed.
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', '0.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Magnetic Board');
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', '1.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Magnetic Board');
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', '2.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Magnetic Board');
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', '3.00');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '-3.20', '1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
|
||||
PosLoyalty.check.orderTotalIs('5.94');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Promotion: 2 items of shelves, get desk_pad/monitor_stand free
|
||||
// This is the 5th order.
|
||||
ProductScreen.do.clickDisplayedProduct('Wall Shelf Unit');
|
||||
ProductScreen.check.selectedOrderlineHas('Wall Shelf Unit', '1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.do.clickDisplayedProduct('Small Shelf');
|
||||
ProductScreen.check.selectedOrderlineHas('Small Shelf', '1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
// Click reward product. Should be automatically added as reward.
|
||||
ProductScreen.do.clickDisplayedProduct('Desk Pad');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.check.hasRewardLine('Free Product', '-1.98', '1.00');
|
||||
// Remove the reward line. The next steps will check if cashier
|
||||
// can select from the different reward products.
|
||||
ProductScreen.do.pressNumpad('Backspace');
|
||||
ProductScreen.do.pressNumpad('Backspace');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
SelectionPopup.check.hasSelectionItem('Monitor Stand');
|
||||
SelectionPopup.check.hasSelectionItem('Desk Pad');
|
||||
SelectionPopup.do.clickItem('Desk Pad');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.check.hasRewardLine('Free Product', '-1.98', '1.00');
|
||||
ProductScreen.do.pressNumpad('Backspace');
|
||||
ProductScreen.do.pressNumpad('Backspace');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.claimReward('Monitor Stand');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.check.selectedOrderlineHas('Monitor Stand', '1.00', '3.19');
|
||||
PosLoyalty.check.hasRewardLine('Free Product', '-3.19', '1.00');
|
||||
PosLoyalty.check.orderTotalIs('4.81');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyFreeProductTour', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAA Partner');
|
||||
ProductScreen.exec.addOrderline('Test Product A', '1');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Test Product A', '-11.50', '1.00');
|
||||
|
||||
Tour.register('PosLoyaltyFreeProductTour2', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Test Product A');
|
||||
ProductScreen.check.selectedOrderlineHas('Test Product A', '1.00', '40.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Test Product B');
|
||||
ProductScreen.check.selectedOrderlineHas('Test Product B', '1.00', '40.00');
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
SelectionPopup.do.clickItem("$ 10 per order on specific products");
|
||||
PosLoyalty.check.hasRewardLine('$ 10 per order on specific products', '-10.00', '1.00');
|
||||
PosLoyalty.check.orderTotalIs('70.00');
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
SelectionPopup.do.clickItem("$ 10 per order on specific products");
|
||||
PosLoyalty.check.orderTotalIs('60.00');
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
SelectionPopup.do.clickItem("$ 30 per order on specific products");
|
||||
PosLoyalty.check.hasRewardLine('$ 30 per order on specific products', '-30.00', '1.00');
|
||||
PosLoyalty.check.orderTotalIs('30.00');
|
||||
|
||||
Tour.register('PosLoyaltySpecificDiscountTour', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Test Product A');
|
||||
ProductScreen.do.clickDisplayedProduct('Test Product C');
|
||||
PosLoyalty.check.orderTotalIs('130.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
PosLoyalty.check.orderTotalIs('130.00');
|
||||
|
||||
Tour.register('PosLoyaltySpecificDiscountWithFreeProductTour', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
ProductScreen.check.selectedOrderlineHas('Product A', '1.00', '15.00');
|
||||
PosLoyalty.check.orderTotalIs('15.00');
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Product B');
|
||||
ProductScreen.check.selectedOrderlineHas('Product B', '1.00', '50.00');
|
||||
PosLoyalty.check.orderTotalIs('40.00');
|
||||
|
||||
Tour.register('PosLoyaltySpecificDiscountWithRewardProductDomainTour', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
ProductScreen.check.selectedOrderlineHas('Product A', '1.00', '15.00');
|
||||
PosLoyalty.check.orderTotalIs('15.00');
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Product B');
|
||||
ProductScreen.check.selectedOrderlineHas('Product B', '1.00', '50.00');
|
||||
PosLoyalty.check.orderTotalIs('40.00');
|
||||
|
||||
Tour.register('PosLoyaltySpecificDiscountCategoryTour', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
|
||||
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
SelectionPopup.do.clickItem("product_a");
|
||||
PosLoyalty.check.hasRewardLine("Free Product", "-2", "1.00");
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
|
||||
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
SelectionPopup.do.clickItem("product_b");
|
||||
PosLoyalty.check.hasRewardLine("Free Product", "-5", "1.00");
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
|
||||
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
SelectionPopup.do.clickItem("product_b");
|
||||
PosLoyalty.check.hasRewardLine("Free Product", "-10", "2.00");
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
|
||||
Tour.register("PosLoyaltyRewardProductTag", { test: true, url: "/pos/web" }, getSteps());
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
PosLoyalty.do.enterCode('563412');
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-1.50');
|
||||
|
||||
Tour.register("test_loyalty_on_order_with_fixed_tax", { test: true, url: "/pos/web" }, getSteps());
|
||||
|
|
@ -0,0 +1,435 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { PosLoyalty } from 'pos_loyalty.tour.PosCouponTourMethods';
|
||||
import { ProductScreen } from 'point_of_sale.tour.ProductScreenTourMethods';
|
||||
import { getSteps, startSteps } from 'point_of_sale.tour.utils';
|
||||
import Tour from 'web_tour.tour';
|
||||
|
||||
// --- PoS Loyalty Tour Basic Part 1 ---
|
||||
// Generate coupons for PosLoyaltyTour2.
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// basic order
|
||||
// just accept the automatically applied promo program
|
||||
// applied programs:
|
||||
// - on cheapest product
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '5');
|
||||
PosLoyalty.check.hasRewardLine('90% on the cheapest product', '-2.88');
|
||||
PosLoyalty.do.selectRewardLine('on the cheapest product');
|
||||
PosLoyalty.check.orderTotalIs('13.12');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// remove the reward from auto promo program
|
||||
// no applied programs
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '6');
|
||||
PosLoyalty.check.hasRewardLine('on the cheapest product', '-2.88');
|
||||
PosLoyalty.check.orderTotalIs('16.32');
|
||||
PosLoyalty.exec.removeRewardLine('90% on the cheapest product');
|
||||
PosLoyalty.check.orderTotalIs('19.2');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// order with coupon code from coupon program
|
||||
// applied programs:
|
||||
// - coupon program
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '9');
|
||||
PosLoyalty.check.hasRewardLine('on the cheapest product', '-4.59');
|
||||
PosLoyalty.exec.removeRewardLine('90% on the cheapest product');
|
||||
PosLoyalty.check.orderTotalIs('45.90');
|
||||
PosLoyalty.do.enterCode('invalid_code');
|
||||
PosLoyalty.do.enterCode('1234');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Desk Organizer', '-15.30');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Use coupon but eventually remove the reward
|
||||
// applied programs:
|
||||
// - on cheapest product
|
||||
ProductScreen.exec.addOrderline('Letter Tray', '4');
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '9');
|
||||
PosLoyalty.check.hasRewardLine('90% on the cheapest product', '-4.75');
|
||||
PosLoyalty.check.orderTotalIs('62.27');
|
||||
PosLoyalty.do.enterCode('5678');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Desk Organizer', '-15.30');
|
||||
PosLoyalty.check.orderTotalIs('46.97');
|
||||
PosLoyalty.exec.removeRewardLine('Free Product');
|
||||
PosLoyalty.check.orderTotalIs('62.27');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// specific product discount
|
||||
// applied programs:
|
||||
// - on cheapest product
|
||||
// - on specific products
|
||||
ProductScreen.exec.addOrderline('Magnetic Board', '10') // 1.98
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '3') // 5.1
|
||||
ProductScreen.exec.addOrderline('Letter Tray', '4') // 4.8 tax 10%
|
||||
PosLoyalty.check.hasRewardLine('90% on the cheapest product', '-1.78')
|
||||
PosLoyalty.check.orderTotalIs('54.44')
|
||||
PosLoyalty.do.enterCode('promocode')
|
||||
PosLoyalty.check.hasRewardLine('50% on specific products', '-16.66') // 17.55 - 1.78*0.5
|
||||
PosLoyalty.check.orderTotalIs('37.78')
|
||||
PosLoyalty.exec.finalizeOrder('Cash')
|
||||
|
||||
Tour.register('PosLoyaltyTour1', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
// --- PoS Loyalty Tour Basic Part 2 ---
|
||||
// Using the coupons generated from PosLoyaltyTour1.
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// Test that global discount and cheapest product discounts can be accumulated.
|
||||
// Applied programs:
|
||||
// - global discount
|
||||
// - on cheapest discount
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '10'); // 5.1
|
||||
PosLoyalty.check.hasRewardLine('on the cheapest product', '-4.59');
|
||||
ProductScreen.exec.addOrderline('Letter Tray', '4'); // 4.8 tax 10%
|
||||
PosLoyalty.check.hasRewardLine('on the cheapest product', '-4.75');
|
||||
PosLoyalty.do.enterCode('123456');
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-5.10');
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-1.64');
|
||||
PosLoyalty.check.orderTotalIs('60.63'); //SUBTOTAL
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Scanning coupon twice.
|
||||
// Also apply global discount on top of free product to check if the
|
||||
// calculated discount is correct.
|
||||
// Applied programs:
|
||||
// - coupon program (free product)
|
||||
// - global discount
|
||||
// - on cheapest discount
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '11'); // 5.1 per item
|
||||
PosLoyalty.check.hasRewardLine('90% on the cheapest product', '-4.59');
|
||||
PosLoyalty.check.orderTotalIs('51.51');
|
||||
// add global discount and the discount will be replaced
|
||||
PosLoyalty.do.enterCode('345678');
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-5.15');
|
||||
// add free product coupon (for qty=11, free=4)
|
||||
// the discount should change after having free products
|
||||
// it should go back to cheapest discount as it is higher
|
||||
PosLoyalty.do.enterCode('5678');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Desk Organizer', '-20.40');
|
||||
PosLoyalty.check.hasRewardLine('90% on the cheapest product', '-4.59');
|
||||
// set quantity to 18
|
||||
// free qty stays the same since the amount of points on the card only allows for 4 free products
|
||||
ProductScreen.do.pressNumpad('Backspace 8')
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-6.68');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Desk Organizer', '-20.40');
|
||||
// scan the code again and check notification
|
||||
PosLoyalty.do.enterCode('5678');
|
||||
PosLoyalty.check.orderTotalIs('60.13');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Specific products discount (with promocode) and free product (1357)
|
||||
// Applied programs:
|
||||
// - discount on specific products
|
||||
// - free product
|
||||
ProductScreen.exec.addOrderline('Desk Organizer', '6'); // 5.1 per item
|
||||
PosLoyalty.check.hasRewardLine('on the cheapest product', '-4.59');
|
||||
PosLoyalty.exec.removeRewardLine('90% on the cheapest product');
|
||||
PosLoyalty.do.enterCode('promocode');
|
||||
PosLoyalty.check.hasRewardLine('50% on specific products', '-15.30');
|
||||
PosLoyalty.do.enterCode('1357');
|
||||
PosLoyalty.check.hasRewardLine('Free Product - Desk Organizer', '-10.20');
|
||||
PosLoyalty.check.hasRewardLine('50% on specific products', '-10.20');
|
||||
PosLoyalty.check.orderTotalIs('10.20');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Check reset program
|
||||
// Enter two codes and reset the programs.
|
||||
// The codes should be checked afterwards. They should return to new.
|
||||
// Applied programs:
|
||||
// - cheapest product
|
||||
ProductScreen.exec.addOrderline('Monitor Stand', '6'); // 3.19 per item
|
||||
PosLoyalty.do.enterCode('098765');
|
||||
PosLoyalty.check.hasRewardLine('90% on the cheapest product', '-2.87');
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-1.63');
|
||||
PosLoyalty.check.orderTotalIs('14.64');
|
||||
PosLoyalty.exec.removeRewardLine('90% on the cheapest product');
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-1.91');
|
||||
PosLoyalty.check.orderTotalIs('17.23');
|
||||
PosLoyalty.do.resetActivePrograms();
|
||||
PosLoyalty.check.hasRewardLine('90% on the cheapest product', '-2.87');
|
||||
PosLoyalty.check.orderTotalIs('16.27');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyTour2', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
// --- PoS Loyalty Tour Basic Part 3 ---
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Promo Product');
|
||||
PosLoyalty.check.orderTotalIs('34.50');
|
||||
ProductScreen.do.clickDisplayedProduct('Product B');
|
||||
PosLoyalty.check.hasRewardLine('100% on specific products', '25.00');
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
PosLoyalty.check.hasRewardLine('100% on specific products', '15.00');
|
||||
PosLoyalty.check.orderTotalIs('34.50');
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
PosLoyalty.check.hasRewardLine('100% on specific products', '21.82');
|
||||
PosLoyalty.check.hasRewardLine('100% on specific products', '18.18');
|
||||
PosLoyalty.check.orderTotalIs('49.50');
|
||||
|
||||
|
||||
Tour.register('PosLoyaltyTour3', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.exec.addOrderline('Test Product 1', '1');
|
||||
ProductScreen.exec.addOrderline('Test Product 2', '1');
|
||||
ProductScreen.do.clickPricelistButton();
|
||||
ProductScreen.do.selectPriceList('Public Pricelist');
|
||||
PosLoyalty.do.enterCode('abcda');
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
ProductScreen.do.clickPricelistButton();
|
||||
ProductScreen.do.selectPriceList('Test multi-currency');
|
||||
PosLoyalty.check.orderTotalIs('0.00');
|
||||
|
||||
Tour.register('PosLoyaltyTour4', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.exec.addOrderline('Test Product 1', '1.00', '100');
|
||||
PosLoyalty.do.clickDiscountButton();
|
||||
PosLoyalty.do.clickConfirmButton();
|
||||
ProductScreen.check.totalAmountIs('92.00');
|
||||
|
||||
Tour.register('PosLoyaltyTour5', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAA Partner');
|
||||
ProductScreen.do.clickDisplayedProduct('Test Product A');
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
ProductScreen.check.totalAmountIs('139');
|
||||
|
||||
Tour.register('PosLoyaltyTour6', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.exec.addOrderline('Test Product', '1');
|
||||
PosLoyalty.check.orderTotalIs('100');
|
||||
PosLoyalty.do.enterCode('abcda');
|
||||
PosLoyalty.check.orderTotalIs('90');
|
||||
|
||||
Tour.register('PosLoyaltyTour7', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Product B');
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
ProductScreen.check.totalAmountIs('50.00');
|
||||
|
||||
Tour.register('PosLoyaltyTour8', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAA Partner');
|
||||
ProductScreen.do.clickDisplayedProduct('Product B');
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
ProductScreen.check.totalAmountIs('210.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
ProductScreen.check.totalAmountIs('205.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
ProductScreen.check.totalAmountIs('200.00');
|
||||
|
||||
Tour.register('PosLoyaltyTour9', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAA Partner');
|
||||
ProductScreen.do.clickDisplayedProduct('Product Test');
|
||||
ProductScreen.check.totalAmountIs('1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.claimReward('Free Product B');
|
||||
PosLoyalty.check.hasRewardLine('Free Product B', '-1.00');
|
||||
ProductScreen.check.totalAmountIs('1.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
|
||||
Tour.register('PosLoyaltyTour10', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAA Partner');
|
||||
PosLoyalty.check.customerIs('AAA Partner');
|
||||
ProductScreen.exec.addOrderline('Product Test', '3');
|
||||
ProductScreen.check.totalAmountIs('150.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyTour11.1', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('AAA Partner');
|
||||
PosLoyalty.check.customerIs('AAA Partner');
|
||||
ProductScreen.do.clickDisplayedProduct('Product Test');
|
||||
ProductScreen.check.totalAmountIs('50.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
PosLoyalty.do.enterCode('123456');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
PosLoyalty.do.clickRewardButton();
|
||||
PosLoyalty.check.hasRewardLine('Free Product', '-3.00');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(false);
|
||||
ProductScreen.check.totalAmountIs('50.00');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyTour11.2', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
ProductScreen.exec.addOrderline('Free Product A', '2');
|
||||
ProductScreen.do.clickDisplayedProduct('Free Product A');
|
||||
ProductScreen.check.totalAmountIs('2.00');
|
||||
PosLoyalty.check.hasRewardLine('Free Product', '-1.00');
|
||||
|
||||
ProductScreen.exec.addOrderline('Free Product B', '2');
|
||||
ProductScreen.do.clickDisplayedProduct('Free Product B');
|
||||
ProductScreen.check.totalAmountIs('4.00');
|
||||
PosLoyalty.check.hasRewardLine('Free Product', '-2.00');
|
||||
|
||||
ProductScreen.exec.addOrderline('Free Product B', '5');
|
||||
ProductScreen.do.clickDisplayedProduct('Free Product B');
|
||||
ProductScreen.check.totalAmountIs('6.00');
|
||||
PosLoyalty.check.hasRewardLine('Free Product', '-3.00');
|
||||
|
||||
Tour.register('PosLoyaltyTour12', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
ProductScreen.check.selectedOrderlineHas('Product A', '1.00', '20.00');
|
||||
PosLoyalty.check.orderTotalIs('20.00');
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Product B');
|
||||
ProductScreen.check.selectedOrderlineHas('Product B', '1.00', '30.00');
|
||||
PosLoyalty.check.orderTotalIs('50.00');
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Product A');
|
||||
ProductScreen.check.selectedOrderlineHas('Product A', '2.00', '40.00');
|
||||
PosLoyalty.check.orderTotalIs('66.00');
|
||||
|
||||
Tour.register('PosLoyaltyMinAmountAndSpecificProductTour', {test: true, url: '/pos/web'}, getSteps());
|
||||
|
||||
function createOrderCoupon(totalAmount, couponName, couponAmount, loyaltyPoints) {
|
||||
return [
|
||||
ProductScreen.do.confirmOpeningPopup(),
|
||||
ProductScreen.do.clickHomeCategory(),
|
||||
ProductScreen.do.clickPartnerButton(),
|
||||
ProductScreen.do.clickCustomer("partner_a"),
|
||||
ProductScreen.exec.addOrderline("product_a", "1"),
|
||||
ProductScreen.exec.addOrderline("product_b", "1"),
|
||||
PosLoyalty.do.enterCode("promocode"),
|
||||
PosLoyalty.check.hasRewardLine(`${couponName}`, `${couponAmount}`),
|
||||
PosLoyalty.check.orderTotalIs(`${totalAmount}`),
|
||||
PosLoyalty.check.pointsAwardedAre(`${loyaltyPoints}`),
|
||||
PosLoyalty.exec.finalizeOrder("Cash"),
|
||||
];
|
||||
}
|
||||
|
||||
startSteps();
|
||||
createOrderCoupon("135.00", "10% on your order", "-15.00", "135");
|
||||
Tour.register("PosLoyaltyPointsDiscountNoDomainProgramNoDomain", { test: true, url: "/pos/web" }, getSteps());
|
||||
|
||||
startSteps();
|
||||
createOrderCoupon("135.00", "10% on your order", "-15.00", "100");
|
||||
Tour.register("PosLoyaltyPointsDiscountNoDomainProgramDomain", { test: true, url: "/pos/web" }, getSteps());
|
||||
|
||||
startSteps();
|
||||
createOrderCoupon("140.00", "10% on food", "-10.00", "90");
|
||||
Tour.register("PosLoyaltyPointsDiscountWithDomainProgramDomain", { test: true, url: "/pos/web" }, getSteps());
|
||||
|
||||
startSteps();
|
||||
ProductScreen.do.confirmOpeningPopup(),
|
||||
ProductScreen.do.clickHomeCategory(),
|
||||
ProductScreen.do.clickPartnerButton(),
|
||||
ProductScreen.do.clickCustomer("partner_a"),
|
||||
ProductScreen.exec.addOrderline("product_a", "1"),
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-10.00');
|
||||
PosLoyalty.check.orderTotalIs('90'),
|
||||
PosLoyalty.check.pointsAwardedAre("90"),
|
||||
PosLoyalty.exec.finalizeOrder("Cash", "90"),
|
||||
Tour.register("PosLoyaltyPointsGlobalDiscountProgramNoDomain", { test: true, url: "/pos/web" }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer("partner_a");
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Test Product A');
|
||||
PosLoyalty.check.checkNoClaimableRewards();
|
||||
ProductScreen.check.selectedOrderlineHas('Test Product A', '1.00', '100.00');
|
||||
PosLoyalty.exec.finalizeOrder("Cash");
|
||||
|
||||
Tour.register('PosLoyaltyArchivedRewardProductsInactive', {test: true, url: '/pos/web'}, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer("partner_a");
|
||||
|
||||
ProductScreen.do.clickDisplayedProduct('Test Product A');
|
||||
PosLoyalty.check.isRewardButtonHighlighted(true);
|
||||
ProductScreen.check.selectedOrderlineHas('Test Product A', '1.00', '100.00');
|
||||
PosLoyalty.exec.finalizeOrder("Cash");
|
||||
|
||||
Tour.register('PosLoyaltyArchivedRewardProductsActive', {test: true, url: '/pos/web'}, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer("partner_a");
|
||||
|
||||
ProductScreen.exec.addOrderline("Test Product A", "5"),
|
||||
ProductScreen.do.clickDisplayedProduct('Test Product B');
|
||||
PosLoyalty.check.hasRewardLine('10% on your order', '-3.00');
|
||||
PosLoyalty.check.hasRewardLine('10% on Test Product B', '-0.45');
|
||||
PosLoyalty.exec.finalizeOrder("Cash");
|
||||
|
||||
Tour.register('PosLoyalty2DiscountsSpecificGlobal', {test: true, url: '/pos/web'}, getSteps());
|
||||
|
|
@ -0,0 +1,218 @@
|
|||
odoo.define('pos_loyalty.tour.PosCouponTourMethods', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { createTourMethods } = require('point_of_sale.tour.utils');
|
||||
const { Do: ProductScreenDo } = require('point_of_sale.tour.ProductScreenTourMethods');
|
||||
const { Do: PaymentScreenDo, Check: PaymentScreenCheck } = require('point_of_sale.tour.PaymentScreenTourMethods');
|
||||
const { Do: ReceiptScreenDo } = require('point_of_sale.tour.ReceiptScreenTourMethods');
|
||||
const { Do: ChromeDo } = require('point_of_sale.tour.ChromeTourMethods');
|
||||
|
||||
const ProductScreen = { do: new ProductScreenDo() };
|
||||
const PaymentScreen = { do: new PaymentScreenDo(), check: new PaymentScreenCheck() };
|
||||
const ReceiptScreen = { do: new ReceiptScreenDo() };
|
||||
const Chrome = { do: new ChromeDo() };
|
||||
|
||||
class Do {
|
||||
selectRewardLine(rewardName) {
|
||||
return [
|
||||
{
|
||||
content: 'select reward line',
|
||||
trigger: `.orderline.program-reward .product-name:contains("${rewardName}")`,
|
||||
},
|
||||
{
|
||||
content: 'check reward line if selected',
|
||||
trigger: `.orderline.selected.program-reward .product-name:contains("${rewardName}")`,
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
];
|
||||
}
|
||||
enterCode(code) {
|
||||
const steps = [
|
||||
{
|
||||
content: 'open code input dialog',
|
||||
trigger: '.control-button:contains("Enter Code")',
|
||||
},
|
||||
{
|
||||
content: `enter code value: ${code}`,
|
||||
trigger: '.popup-textinput input[type="text"]',
|
||||
run: `text ${code}`,
|
||||
},
|
||||
{
|
||||
content: 'confirm inputted code',
|
||||
trigger: '.popup-textinput .button.confirm',
|
||||
},
|
||||
{
|
||||
content: 'verify popup is closed',
|
||||
trigger: 'body:not(:has(.popup-textinput))',
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
];
|
||||
return steps;
|
||||
}
|
||||
resetActivePrograms() {
|
||||
return [
|
||||
{
|
||||
content: 'open code input dialog',
|
||||
trigger: '.control-button:contains("Reset Programs")',
|
||||
},
|
||||
];
|
||||
}
|
||||
clickRewardButton() {
|
||||
return [
|
||||
{
|
||||
content: 'open reward dialog',
|
||||
trigger: '.control-button:contains("Reward")',
|
||||
},
|
||||
];
|
||||
}
|
||||
clickEWalletButton(text = 'eWallet') {
|
||||
return [{ trigger: `.control-button:contains("${text}")` }];
|
||||
}
|
||||
claimReward(rewardName) {
|
||||
return [
|
||||
{
|
||||
content: 'open reward dialog',
|
||||
trigger: '.control-button:contains("Reward")',
|
||||
},
|
||||
{
|
||||
content: 'select reward',
|
||||
trigger: `.selection-item:contains("${rewardName}")`,
|
||||
}
|
||||
];
|
||||
}
|
||||
unselectPartner() {
|
||||
return [{ trigger: '.unselect-tag' }];
|
||||
}
|
||||
clickDiscountButton() {
|
||||
return [
|
||||
{
|
||||
content: 'click discount button',
|
||||
trigger: '.js_discount',
|
||||
},
|
||||
];
|
||||
}
|
||||
clickConfirmButton() {
|
||||
return [
|
||||
{
|
||||
content: 'click confirm button',
|
||||
trigger: '.button.confirm',
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class Check {
|
||||
hasRewardLine(rewardName, amount, qty) {
|
||||
const steps = [
|
||||
{
|
||||
content: 'check if reward line is there',
|
||||
trigger: `.orderline.program-reward span.product-name:contains("${rewardName}")`,
|
||||
run: function () {},
|
||||
},
|
||||
{
|
||||
content: 'check if the reward price is correct',
|
||||
trigger: `.orderline.program-reward span.price:contains("${amount}")`,
|
||||
run: function () {},
|
||||
},
|
||||
];
|
||||
if (qty) {
|
||||
steps.push({
|
||||
content: 'check if the reward qty is correct',
|
||||
trigger: `.order .orderline.program-reward .product-name:contains("${rewardName}") ~ .info-list em:contains("${qty}")`,
|
||||
run: function () {},
|
||||
});
|
||||
}
|
||||
return steps;
|
||||
}
|
||||
orderTotalIs(total_str) {
|
||||
return [
|
||||
{
|
||||
content: 'order total contains ' + total_str,
|
||||
trigger: '.order .total .value:contains("' + total_str + '")',
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
];
|
||||
}
|
||||
checkNoClaimableRewards() {
|
||||
return [
|
||||
{
|
||||
content: 'check that no reward can be claimed',
|
||||
trigger: ".control-button:contains('Reward'):not(.highlight)",
|
||||
run: function () {}, // it's a check
|
||||
}
|
||||
]
|
||||
}
|
||||
isRewardButtonHighlighted(isHighlighted) {
|
||||
return [
|
||||
{
|
||||
trigger: isHighlighted
|
||||
? '.control-button.highlight:contains("Reward")'
|
||||
: '.control-button:contains("Reward"):not(:has(.highlight))',
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
];
|
||||
}
|
||||
eWalletButtonState({ highlighted, text = 'eWallet' }) {
|
||||
return [
|
||||
{
|
||||
trigger: highlighted
|
||||
? `.control-button.highlight:contains("${text}")`
|
||||
: `.control-button:contains("${text}"):not(:has(.highlight))`,
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
];
|
||||
}
|
||||
customerIs(name) {
|
||||
return [
|
||||
{
|
||||
trigger: `.actionpad button.set-partner:contains("${name}")`,
|
||||
run: function () {},
|
||||
}
|
||||
]
|
||||
}
|
||||
pointsAwardedAre(points_str) {
|
||||
return [
|
||||
{
|
||||
content: 'loyalty points awarded ' + points_str,
|
||||
trigger: '.loyalty-points-won.value:contains("' + points_str + '")',
|
||||
run: function () {}, // it's a check
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class Execute {
|
||||
constructor() {
|
||||
this.do = new Do();
|
||||
this.check = new Check();
|
||||
}
|
||||
finalizeOrder(paymentMethod, amount) {
|
||||
const actions = [
|
||||
...ProductScreen.do.clickPayButton(),
|
||||
...PaymentScreen.do.clickPaymentMethod(paymentMethod),
|
||||
];
|
||||
if (amount) {
|
||||
actions.push(...PaymentScreen.do.pressNumpad([...amount].join(' ')));
|
||||
} else {
|
||||
actions.push(
|
||||
...PaymentScreen.check.remainingIs('0.0'),
|
||||
...PaymentScreen.check.changeIs('0.0'),
|
||||
)
|
||||
}
|
||||
actions.push(
|
||||
...PaymentScreen.do.clickValidate(),
|
||||
...ReceiptScreen.do.clickNextOrder(),
|
||||
);
|
||||
return actions;
|
||||
}
|
||||
removeRewardLine(name) {
|
||||
return [
|
||||
...this.do.selectRewardLine(name),
|
||||
...ProductScreen.do.pressNumpad('Backspace'),
|
||||
...Chrome.do.confirmPopup(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return createTourMethods('PosLoyalty', Do, Check, Execute);
|
||||
});
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
import { PosLoyalty } from 'pos_loyalty.tour.PosCouponTourMethods';
|
||||
import { ProductScreen } from 'point_of_sale.tour.ProductScreenTourMethods';
|
||||
import { getSteps, startSteps } from 'point_of_sale.tour.utils';
|
||||
import Tour from 'web_tour.tour';
|
||||
|
||||
// First tour should not get any automatic rewards
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// Not valid -> date
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '5');
|
||||
PosLoyalty.check.checkNoClaimableRewards();
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyValidity1', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
||||
// Second tour
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickHomeCategory();
|
||||
|
||||
// Valid
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '5');
|
||||
PosLoyalty.check.hasRewardLine('90% on the cheapest product', '-2.88');
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
// Not valid -> usage
|
||||
ProductScreen.exec.addOrderline('Whiteboard Pen', '5');
|
||||
PosLoyalty.check.checkNoClaimableRewards();
|
||||
PosLoyalty.exec.finalizeOrder('Cash');
|
||||
|
||||
Tour.register('PosLoyaltyValidity2', { test: true, url: '/pos/web' }, getSteps());
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="PromoCodeButton" owl="1">
|
||||
<span class="control-button">
|
||||
<i class="fa fa-barcode"></i>
|
||||
<span> </span>
|
||||
<span>Enter Code</span>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="ResetProgramsButton" owl="1">
|
||||
<span class="control-button">
|
||||
<i class="fa fa-star"></i>
|
||||
<span> </span>
|
||||
<span>Reset Programs</span>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="RewardButton" owl="1">
|
||||
<span class="control-button" t-att-class="hasClaimableRewards() ? 'highlight' : ''">
|
||||
<i class="fa fa-star"></i>
|
||||
<span> </span>
|
||||
<span>Reward</span>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.eWalletButton" owl="1">
|
||||
<t t-set="_order" t-value="env.pos.get_order()" />
|
||||
<t t-set="_orderTotal" t-value="_order.get_total_with_tax()" />
|
||||
<t t-set="_eWalletPrograms" t-value="_getEWalletPrograms()" />
|
||||
<t t-set="_eWalletRewards" t-value="_getEWalletRewards(_order)" />
|
||||
<span class="control-button" t-att-class="_shouldBeHighlighted(_orderTotal, _eWalletPrograms, _eWalletRewards) ? 'highlight' : ''" t-on-click="_onClickWalletButton">
|
||||
<i class="fa fa-credit-card"></i>
|
||||
<span> </span>
|
||||
<span><t t-esc="_getText(_orderTotal, _eWalletPrograms, _eWalletRewards)" /></span>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="pos_coupon.OrderReceipt" t-inherit="point_of_sale.OrderReceipt" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//div[hasclass('pos-receipt')]//div[hasclass('before-footer')]" position="inside">
|
||||
<t t-if='receipt.loyaltyStats'>
|
||||
<t t-foreach="receipt.loyaltyStats" t-as="_loyaltyStat" t-key="_loyaltyStat.couponId">
|
||||
<!-- Show only if portal_visible. -->
|
||||
<div t-if="_loyaltyStat.program.portal_visible and (_loyaltyStat.points.won || _loyaltyStat.points.spent)" class='loyalty'>
|
||||
<span class="pos-receipt-center-align">
|
||||
<div>--------------------------------</div>
|
||||
<br/>
|
||||
<div t-esc='_loyaltyStat.program.name' class="pos-receipt-title" />
|
||||
|
||||
<br />
|
||||
</span>
|
||||
<t t-if='_loyaltyStat.points.won'>
|
||||
<div><t t-esc="_loyaltyStat.points.name"/> Won: <span t-esc='_loyaltyStat.points.won' class="pos-receipt-right-align"/></div>
|
||||
</t>
|
||||
<t t-if='_loyaltyStat.points.spent'>
|
||||
<div><t t-esc="_loyaltyStat.points.name"/> Spent: <span t-esc='_loyaltyStat.points.spent' class="pos-receipt-right-align"/></div>
|
||||
</t>
|
||||
<!-- Don't use points.total, it's wrong in this context (after the order synced). -->
|
||||
<!-- Show balance as it's updated during _postPushOrderResolve. -->
|
||||
<t t-if='_loyaltyStat.points.balance'>
|
||||
<div>Balance <t t-esc="_loyaltyStat.points.name"/>: <span t-esc='_loyaltyStat.points.balance' class="pos-receipt-right-align"/></div>
|
||||
</t>
|
||||
<br />
|
||||
</div>
|
||||
</t>
|
||||
<br/>
|
||||
<div>Customer <span t-esc='receipt.partner.name' class='pos-receipt-right-align'/></div>
|
||||
</t>
|
||||
<t t-if="receipt.new_coupon_info and receipt.new_coupon_info.length !== 0">
|
||||
<div class="pos-coupon-rewards">
|
||||
<div>------------------------</div>
|
||||
<br/>
|
||||
<div>
|
||||
Coupon Codes
|
||||
</div>
|
||||
<t t-foreach="receipt.new_coupon_info" t-as="coupon_info" t-key="coupon_info.code">
|
||||
<div class="coupon-container">
|
||||
<div style="font-size: 110%;">
|
||||
<t t-esc="coupon_info['program_name']"/>
|
||||
</div>
|
||||
<div>
|
||||
<span>Valid until: </span>
|
||||
<t t-if="coupon_info['expiration_date']">
|
||||
<t t-esc="coupon_info['expiration_date']"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
no expiration
|
||||
</t>
|
||||
</div>
|
||||
<div>
|
||||
<img t-att-src="'/report/barcode/Code128/'+coupon_info['code']" style="width:200px;height:50px" alt="Barcode"/>
|
||||
</div>
|
||||
<div>
|
||||
<t t-esc="coupon_info['code']"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="OrderSummary" t-inherit="point_of_sale.OrderSummary" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//div[hasclass('summary')]" position="after">
|
||||
<div class="summary clearfix">
|
||||
<t t-set="_loyaltyStats" t-value="getLoyaltyPoints()"/>
|
||||
<t t-foreach="_loyaltyStats" t-as="_loyaltyStat" t-key="_loyaltyStat.couponId">
|
||||
<t t-if="_loyaltyStat.points.won || _loyaltyStat.points.spent">
|
||||
<div class='loyalty-points'>
|
||||
<div class='loyalty-points-title'>
|
||||
<t t-esc="_loyaltyStat.points.name"/>
|
||||
</div>
|
||||
<t t-if='_loyaltyStat.points.balance'>
|
||||
<div class="loyalty-points-balance">
|
||||
<span class='value'><t t-esc='_loyaltyStat.points.balance'/></span>
|
||||
</div>
|
||||
</t>
|
||||
<div>
|
||||
<t t-if='_loyaltyStat.points.won'>
|
||||
<span class="value loyalty-points-won">+<t t-esc='_loyaltyStat.points.won'/></span>
|
||||
</t>
|
||||
<t t-if='_loyaltyStat.points.spent'>
|
||||
<span class="value loyalty-points-spent">-<t t-esc='_loyaltyStat.points.spent'/></span>
|
||||
</t>
|
||||
</div>
|
||||
<div class='loyalty-points-total'>
|
||||
<span class='value'><t t-esc='_loyaltyStat.points.total'/></span>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<div></div>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="pos_loyalty.Orderline" t-inherit="point_of_sale.Orderline" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//ul[hasclass('info-list')]" position="attributes">
|
||||
<attribute name="t-if">!_isGiftCardOrEWalletReward()</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//ul[hasclass('info-list')]" position="after">
|
||||
<ul t-else="" class="info-list">
|
||||
Current Balance: <span t-esc="_getGiftCardOrEWalletBalance()"/>
|
||||
</ul>
|
||||
</xpath>
|
||||
</t>
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="pos_loyalty.PartnerLine" t-inherit="point_of_sale.PartnerLine" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//td[hasclass('partner-line-balance')]" position="inside">
|
||||
<t t-set="_loyaltyCards" t-value="env.pos.getLoyaltyCards(props.partner)" />
|
||||
<t t-foreach="_loyaltyCards" t-as="_loyaltyCard" t-key="_loyaltyCard.id">
|
||||
<div class="pos-right-align">
|
||||
<t t-esc="_getLoyaltyPointsRepr(_loyaltyCard)"/>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
Loading…
Add table
Add a link
Reference in a new issue