mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-27 02:32:00 +02:00
19.0 vanilla
This commit is contained in:
parent
79f83631d5
commit
73afc09215
6267 changed files with 1534193 additions and 1130106 deletions
|
|
@ -1,84 +0,0 @@
|
|||
odoo.define('pos_sale.tour.ProductScreenTourMethods', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { createTourMethods } = require('point_of_sale.tour.utils');
|
||||
const { Do, Check, Execute } = require('point_of_sale.tour.ProductScreenTourMethods');
|
||||
|
||||
class DoExt extends Do {
|
||||
clickQuotationButton() {
|
||||
return [
|
||||
{
|
||||
content: 'click quotation button',
|
||||
trigger: '.o_sale_order_button',
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
selectFirstOrder() {
|
||||
return [
|
||||
{
|
||||
content: `select order`,
|
||||
trigger: `.order-row .col.name:first`,
|
||||
},
|
||||
{
|
||||
content: `click on select the order`,
|
||||
trigger: `.selection-item:contains('Settle the order')`,
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
selectNthOrder(n) {
|
||||
return [
|
||||
{
|
||||
content: `select order`,
|
||||
trigger: `.order-list .order-row:nth-child(${n})`,
|
||||
},
|
||||
{
|
||||
content: `click on select the order`,
|
||||
trigger: `.selection-item:contains('Settle the order')`,
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
downPaymentFirstOrder() {
|
||||
return [
|
||||
{
|
||||
content: `select order`,
|
||||
trigger: `.order-row .col.name:first`,
|
||||
},
|
||||
{
|
||||
content: `click on select the order`,
|
||||
trigger: `.selection-item:contains('Apply a down payment')`,
|
||||
},
|
||||
{
|
||||
content: `click on +10 button`,
|
||||
trigger: `.mode-button.add:contains('+10')`,
|
||||
},
|
||||
{
|
||||
content: `click on ok button`,
|
||||
trigger: `.button.confirm`,
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class CheckExt extends Check{
|
||||
checkCustomerNotes(note) {
|
||||
return [
|
||||
{
|
||||
content: `check customer notes`,
|
||||
trigger: `.orderline-note:contains(${note})`,
|
||||
}
|
||||
];
|
||||
}
|
||||
checkOrdersListEmpty() {
|
||||
return [
|
||||
{
|
||||
content: 'Check that the orders list is empty',
|
||||
trigger: '.order-list:not(:has(.order-row))',
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
return createTourMethods('ProductScreen', DoExt, CheckExt, Execute);
|
||||
});
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
odoo.define('pos_sale.tour.ReceiptScreenTourMethods', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { createTourMethods } = require('point_of_sale.tour.utils');
|
||||
const { Do, Check, Execute } = require('point_of_sale.tour.ReceiptScreenTourMethods');
|
||||
|
||||
class CheckExt extends Check{
|
||||
checkCustomerNotes(note) {
|
||||
return [
|
||||
{
|
||||
content: `check customer notes`,
|
||||
trigger: `.pos-receipt-customer-note:contains(${note})`,
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return createTourMethods('ReceiptScreen', Do, CheckExt, Execute);
|
||||
});
|
||||
|
|
@ -0,0 +1,662 @@
|
|||
import * as Chrome from "@point_of_sale/../tests/pos/tours/utils/chrome_util";
|
||||
import * as PaymentScreen from "@point_of_sale/../tests/pos/tours/utils/payment_screen_util";
|
||||
import * as ReceiptScreen from "@point_of_sale/../tests/pos/tours/utils/receipt_screen_util";
|
||||
import * as ProductScreen from "@point_of_sale/../tests/pos/tours/utils/product_screen_util";
|
||||
import * as TicketScreen from "@point_of_sale/../tests/pos/tours/utils/ticket_screen_util";
|
||||
import * as PosSale from "@pos_sale/../tests/tours/utils/pos_sale_utils";
|
||||
import * as Dialog from "@point_of_sale/../tests/generic_helpers/dialog_util";
|
||||
import * as Order from "@point_of_sale/../tests/generic_helpers/order_widget_util";
|
||||
import * as Utils from "@point_of_sale/../tests/generic_helpers/utils";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrder", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Pizza Chicken", 9),
|
||||
ProductScreen.clickNumpad("Qty", "2"), // Change the quantity of the product to 2
|
||||
ProductScreen.selectedOrderlineHas("Pizza Chicken", 2),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
Chrome.clickOrders(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrderIncompatiblePartner", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
// The second item in the list is the first sale.order.
|
||||
PosSale.settleNthOrder(2),
|
||||
ProductScreen.selectedOrderlineHas("product1", 1),
|
||||
ProductScreen.totalAmountIs("10.00"),
|
||||
|
||||
// The first item in the list is the second sale.order.
|
||||
// Selecting the 2nd sale.order should use a new order,
|
||||
// therefore, the total amount will change.
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("product2", 1),
|
||||
ProductScreen.totalAmountIs("11.00"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrder2", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.clickOrderline("Product A", "1"),
|
||||
ProductScreen.selectedOrderlineHas("Product A", "1"),
|
||||
ProductScreen.clickOrderline("Product B", "1"),
|
||||
ProductScreen.clickNumpad("Qty", "0"),
|
||||
ProductScreen.selectedOrderlineHas("Product B", "0"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank", true, { remaining: "0.0" }),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosRefundDownpayment", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.downPaymentFirstOrder("+10"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Cash"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
...ProductScreen.clickRefund(),
|
||||
// Filter should be automatically 'Paid'.
|
||||
TicketScreen.filterIs("Paid"),
|
||||
TicketScreen.selectOrder("001"),
|
||||
Order.hasLine({
|
||||
productName: "Down Payment",
|
||||
withClass: ".selected",
|
||||
quantity: "1",
|
||||
}),
|
||||
ProductScreen.clickNumpad("1"),
|
||||
TicketScreen.confirmRefund(),
|
||||
PaymentScreen.isShown(),
|
||||
PaymentScreen.clickPaymentMethod("Cash"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrderRealTime", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.totalAmountIs(40),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrder3", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Product A", "1"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank", true, { remaining: "0.0" }),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrderNotGroupable", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.totalAmountIs(28.98), // 3.5 * 8 * 1.15 * 90%
|
||||
ProductScreen.selectedOrderlineHas("Product A", "0.5"),
|
||||
ProductScreen.checkOrderlinesNumber(4),
|
||||
ProductScreen.selectedOrderlineHas("Product A", "0.5", "4.14"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_import_lot_groupable_and_non_groupable", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1, { loadSN: true }),
|
||||
PosSale.selectedOrderLinesHasLots("Groupable Product", []),
|
||||
ProductScreen.checkOrderlinesNumber(5),
|
||||
ProductScreen.totalAmountIs(60),
|
||||
ProductScreen.selectedOrderlineHas("Groupable Product", "1", "10"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrderWithNote", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
Order.hasLine({
|
||||
customerNote: "Customer note 2--Customer note 3",
|
||||
}),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
// Check in the receipt
|
||||
Order.hasLine({
|
||||
customerNote: "Customer note 2--Customer note 3",
|
||||
}),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleAndInvoiceOrder", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
Order.hasLine({}),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickInvoiceButton(),
|
||||
PaymentScreen.clickValidate(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleAndInvoiceOrder2", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
PosSale.settleNthOrder(1),
|
||||
Order.hasLine({}),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickInvoiceButton(),
|
||||
PaymentScreen.clickValidate(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosOrderDoesNotRemainInList", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
PosSale.checkOrdersListEmpty(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleDraftOrder", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Test service product", "1", "50.00"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleCustomPrice", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Product A", "1", "100"),
|
||||
ProductScreen.clickPartnerButton(),
|
||||
ProductScreen.clickCustomer("A Test Partner AAA"),
|
||||
ProductScreen.selectedOrderlineHas("Product A", "1", "100"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PoSSaleOrderWithDownpayment", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Down Payment (POS)"),
|
||||
ProductScreen.totalAmountIs(980.0),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_settle_so_with_non_pos_groupable_uom", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Pomme de Terre", "0.5", "5.00"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PoSDownPaymentLinesPerTax", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.downPaymentFirstOrder("+20"),
|
||||
Order.hasLine({
|
||||
productName: "Down Payment",
|
||||
quantity: "1",
|
||||
price: "2.20",
|
||||
}),
|
||||
Order.hasLine({
|
||||
productName: "Down Payment",
|
||||
quantity: "1",
|
||||
price: "1.00",
|
||||
}),
|
||||
Order.hasLine({
|
||||
productName: "Down Payment",
|
||||
quantity: "1",
|
||||
price: "3.00",
|
||||
}),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickInvoiceButton(),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PoSApplyDownpayment", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.downPaymentFirstOrder("+10"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PoSApplyDownpaymentInvoice", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.downPaymentFirstOrder("+10"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickInvoiceButton(),
|
||||
PaymentScreen.clickValidate(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PoSApplyDownpaymentInvoice2", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
PosSale.downPaymentFirstOrder("+10"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickInvoiceButton(),
|
||||
PaymentScreen.clickValidate(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosShipLaterNoDefault", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.isShown(),
|
||||
Utils.negateStep(PaymentScreen.shippingLaterHighlighted()),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSaleTeam", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
ProductScreen.clickDisplayedProduct("Test Product"),
|
||||
ProductScreen.totalAmountIs("100.00"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosOrdersListDifferentCurrency", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
ProductScreen.clickControlButton("Quotation/Order"),
|
||||
{
|
||||
content: "Check that no orders are displayed",
|
||||
trigger: '.o_nocontent_help p:contains("No record found")',
|
||||
},
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PoSDownPaymentAmount", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.downPaymentFirstOrder("+20"),
|
||||
Order.hasLine({
|
||||
productName: "Down Payment",
|
||||
quantity: "1",
|
||||
price: "20.0",
|
||||
}),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Cash"),
|
||||
PaymentScreen.clickValidate(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrder4", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Product A", "1"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.remainingIs("0.0"),
|
||||
PaymentScreen.clickShipLaterButton(),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrderShipLater", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(2),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickShipLaterButton(),
|
||||
PaymentScreen.shippingLaterHighlighted(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.remainingIs("0.0"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickShipLaterButton(),
|
||||
PaymentScreen.shippingLaterHighlighted(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.remainingIs("0.0"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSettleOrder5", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Product A", 1),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PosSaleWarning", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
ProductScreen.clickPartnerButton(),
|
||||
ProductScreen.clickCustomer("A Test Customer 2"),
|
||||
{
|
||||
content: "Check warning popup are displayed",
|
||||
trigger:
|
||||
'.modal-dialog:has(.modal-header:contains("Warning for A Test Customer 2")):has(.modal-body:contains("Cannot afford our services"))',
|
||||
},
|
||||
{
|
||||
trigger: ".modal-footer button",
|
||||
run: "click",
|
||||
},
|
||||
ProductScreen.customerIsSelected("A Test Customer 2"),
|
||||
ProductScreen.clickDisplayedProduct("Letter Tray", true, "1"),
|
||||
ProductScreen.selectedOrderlineHas("Letter Tray", "1"),
|
||||
ProductScreen.clickPartnerButton(),
|
||||
ProductScreen.clickCustomer("A Test Customer 1"),
|
||||
{
|
||||
content: "Check warning popup are displayed",
|
||||
trigger:
|
||||
'.modal-dialog:has(.modal-header:contains("Warning for A Test Customer 1")):has(.modal-body:contains("Highly infectious disease"))',
|
||||
},
|
||||
{
|
||||
trigger: ".modal-footer button",
|
||||
run: "click",
|
||||
},
|
||||
ProductScreen.customerIsSelected("A Test Customer 1"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.remainingIs("0.0"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("PoSSettleQuotation", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("POSSalePaymentScreenInvoiceOrder", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
ProductScreen.addOrderline("Product Test", "1"),
|
||||
ProductScreen.clickPartnerButton(),
|
||||
ProductScreen.clickCustomer("AAA - Test Partner invoice"),
|
||||
ProductScreen.clickPayButton(),
|
||||
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickInvoiceButton(),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.receiptIsThere(),
|
||||
Chrome.waitRequest(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_settle_order_with_lot", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1, { loadSN: true }),
|
||||
PosSale.selectedOrderLinesHasLots("Product A", ["1001", "1002"]),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_down_payment_displayed", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.downPaymentFirstOrder("+10"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
PosSale.settleNthOrder(1),
|
||||
Order.hasLine({
|
||||
productName: "Down Payment",
|
||||
quantity: "1.0",
|
||||
price: "-1.15",
|
||||
}),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_sale_order_fp_different_from_partner_one", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleSaleOrderByPrice("20.00"),
|
||||
ProductScreen.checkTaxAmount("10.00"),
|
||||
ProductScreen.checkFiscalPosition("Partner FP"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.receiptIsThere(),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
PosSale.settleSaleOrderByPrice("10.00"),
|
||||
ProductScreen.checkTaxAmount("0.00"),
|
||||
ProductScreen.checkFiscalPosition("Sale Order FP"),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.receiptIsThere(),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_quantity_updated_settle", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.clickNumpad("2"),
|
||||
Order.hasLine({ productName: "Product A", quantity: "2.0" }),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
PosSale.settleNthOrder(1),
|
||||
Order.hasLine({
|
||||
productName: "Product A",
|
||||
quantity: "3.0",
|
||||
price: "34.50",
|
||||
}),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_multiple_lots_sale_order_1", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1),
|
||||
Order.hasLine({ productName: "Product", quantity: "6.0" }),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_multiple_lots_sale_order_2", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
PosSale.settleNthOrder(1, { loadSN: false }),
|
||||
Order.hasLine({ productName: "Product", quantity: "6.0" }),
|
||||
{
|
||||
content: "Check that the line-lot-icon has text-danger class",
|
||||
trigger: `.order-container .orderline:has(.product-name:contains("Product")) .line-lot-icon.text-danger`,
|
||||
},
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_multiple_lots_sale_order_3", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
PosSale.settleNthOrder(1, { loadSN: true }),
|
||||
PosSale.selectedOrderLinesHasLots("Product", ["1002"]),
|
||||
Utils.negateStep(...PosSale.selectedOrderLinesHasLots("Product", ["1001"])),
|
||||
ProductScreen.selectedOrderlineHas("Product", "2.00"),
|
||||
ProductScreen.clickOrderline("Product", "4"),
|
||||
PosSale.selectedOrderLinesHasLots("Product", ["1001"]),
|
||||
ProductScreen.selectedOrderlineHas("Product", "4.00"),
|
||||
Utils.negateStep(...PosSale.selectedOrderLinesHasLots("Product", ["1002"])),
|
||||
ProductScreen.clickPayButton(),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.clickValidate(),
|
||||
ReceiptScreen.isShown(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_selected_partner_quotation_loading", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
ProductScreen.clickPartnerButton(),
|
||||
ProductScreen.clickCustomer("A Test Partner 1"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Product A", "1.00"),
|
||||
Chrome.createFloatingOrder(),
|
||||
ProductScreen.clickPartnerButton(),
|
||||
ProductScreen.clickCustomer("A Test Partner 2"),
|
||||
PosSale.settleNthOrder(1),
|
||||
ProductScreen.selectedOrderlineHas("Product B", "2.00"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_ecommerce_paid_order_is_hidden_in_pos", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
ProductScreen.clickPartnerButton(),
|
||||
ProductScreen.clickCustomer("A Test Partner 1"),
|
||||
PosSale.checkOrdersListEmpty(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_ecommerce_unpaid_order_is_shown_in_pos", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
ProductScreen.clickPartnerButton(),
|
||||
ProductScreen.clickCustomer("A Test Partner 1"),
|
||||
PosSale.checkOrdersListNotEmpty(),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry.category("web_tour.tours").add("test_settle_groupable_lot_total_amount", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
PosSale.settleNthOrder(1, { loadSN: true }),
|
||||
Order.hasTotal("12.00"),
|
||||
].flat(),
|
||||
});
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
odoo.define('pos_sale.tour', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { Chrome } = require('point_of_sale.tour.ChromeTourMethods');
|
||||
const { PaymentScreen } = require('point_of_sale.tour.PaymentScreenTourMethods');
|
||||
const { ProductScreen } = require('pos_sale.tour.ProductScreenTourMethods');
|
||||
const { ReceiptScreen } = require('pos_sale.tour.ReceiptScreenTourMethods');
|
||||
const { TicketScreen } = require('point_of_sale.tour.TicketScreenTourMethods');
|
||||
const { getSteps, startSteps } = require('point_of_sale.tour.utils');
|
||||
const Tour = require('web_tour.tour');
|
||||
|
||||
// signal to start generating steps
|
||||
// when finished, steps can be taken from getSteps
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.check.selectedOrderlineHas('Pizza Chicken', 9);
|
||||
ProductScreen.do.pressNumpad('Qty 2'); // Change the quantity of the product to 2
|
||||
ProductScreen.check.selectedOrderlineHas('Pizza Chicken', 2);
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Bank');
|
||||
PaymentScreen.do.clickValidate();
|
||||
Chrome.do.clickTicketButton();
|
||||
|
||||
Tour.register('PosSettleOrder', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
// The second item in the list is the first sale.order.
|
||||
ProductScreen.do.selectNthOrder(2);
|
||||
ProductScreen.check.selectedOrderlineHas('product1', 1);
|
||||
ProductScreen.check.totalAmountIs("10.00");
|
||||
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
// The first item in the list is the second sale.order.
|
||||
// Selecting the 2nd sale.order should use a new order,
|
||||
// therefore, the total amount will change.
|
||||
ProductScreen.do.selectNthOrder(1);
|
||||
ProductScreen.check.selectedOrderlineHas('product2', 1);
|
||||
ProductScreen.check.totalAmountIs("11.00");
|
||||
|
||||
Tour.register('PosSettleOrderIncompatiblePartner', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.do.clickOrderline('[A001] Product A', '1');
|
||||
ProductScreen.check.selectedOrderlineHas('[A001] Product A', '1.00');
|
||||
ProductScreen.do.clickOrderline('[A002] Product B', '1');
|
||||
ProductScreen.do.pressNumpad('Qty 0');
|
||||
ProductScreen.check.selectedOrderlineHas('[A002] Product B', '0.00');
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Bank');
|
||||
PaymentScreen.check.remainingIs('0.0');
|
||||
PaymentScreen.do.clickValidate();
|
||||
ReceiptScreen.check.isShown();
|
||||
|
||||
Tour.register('PosSettleOrder2', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.do.clickOrderline("Product A", "1");
|
||||
ProductScreen.check.selectedOrderlineHas('Product A', '1.00');
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Bank');
|
||||
PaymentScreen.check.remainingIs('0.0');
|
||||
PaymentScreen.do.clickValidate();
|
||||
ReceiptScreen.check.isShown();
|
||||
|
||||
Tour.register('PosSettleOrder3', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.check.totalAmountIs(40);
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Bank');
|
||||
PaymentScreen.do.clickValidate();
|
||||
Chrome.do.clickTicketButton();
|
||||
|
||||
Tour.register('PosSettleOrderRealTime', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.downPaymentFirstOrder();
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Cash');
|
||||
PaymentScreen.do.clickValidate();
|
||||
ReceiptScreen.do.clickNextOrder();
|
||||
ProductScreen.do.clickRefund();
|
||||
// Filter should be automatically 'Paid'.
|
||||
TicketScreen.check.filterIs('Paid');
|
||||
TicketScreen.do.selectOrder('-0001');
|
||||
TicketScreen.do.clickOrderline('Down Payment');
|
||||
TicketScreen.do.pressNumpad('1');
|
||||
TicketScreen.do.confirmRefund();
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Cash');
|
||||
PaymentScreen.do.clickValidate();
|
||||
ReceiptScreen.do.clickNextOrder();
|
||||
|
||||
Tour.register('PosRefundDownpayment', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.check.totalAmountIs(28.98); // 3.5 * 8 * 1.15 * 90%
|
||||
ProductScreen.do.clickOrderline("Product A", '0.5');
|
||||
ProductScreen.check.checkOrderlinesNumber(4);
|
||||
ProductScreen.check.selectedOrderlineHas('Product A', '0.5', '4.14');
|
||||
|
||||
Tour.register('PosSettleOrderNotGroupable', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.check.checkCustomerNotes("Customer note 2--Customer note 3");
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Bank');
|
||||
PaymentScreen.do.clickValidate();
|
||||
ReceiptScreen.check.checkCustomerNotes("Customer note 2--Customer note 3");
|
||||
ReceiptScreen.do.clickNextOrder();
|
||||
|
||||
Tour.register('PosSettleOrderWithNote', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Bank');
|
||||
PaymentScreen.do.clickValidate();
|
||||
ReceiptScreen.do.clickNextOrder();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.check.checkOrdersListEmpty();
|
||||
|
||||
Tour.register('PosOrderDoesNotRemainInList', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.check.selectedOrderlineHas('product_a', '1', '100');
|
||||
ProductScreen.do.clickPartnerButton();
|
||||
ProductScreen.do.clickCustomer('partner_a');
|
||||
ProductScreen.check.selectedOrderlineHas('product_a', '1', '100');
|
||||
|
||||
Tour.register('PosSettleCustomPrice', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.check.selectedOrderlineHas('Test service product', '1.00', '50.00');
|
||||
|
||||
Tour.register('PosSettleDraftOrder', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.selectFirstOrder();
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickShipLaterButton()
|
||||
PaymentScreen.do.clickPaymentMethod('Bank');
|
||||
PaymentScreen.check.remainingIs('0.0');
|
||||
PaymentScreen.do.clickValidate();
|
||||
ReceiptScreen.check.isShown();
|
||||
|
||||
Tour.register('PosSettleOrderShipLater', { test: true, url: '/pos/ui' }, getSteps());
|
||||
|
||||
startSteps();
|
||||
|
||||
ProductScreen.do.confirmOpeningPopup();
|
||||
ProductScreen.do.clickQuotationButton();
|
||||
ProductScreen.do.downPaymentFirstOrder();
|
||||
ProductScreen.check.selectedOrderlineHas('Down Payment', '1', '10.00');
|
||||
ProductScreen.do.clickPayButton();
|
||||
PaymentScreen.do.clickPaymentMethod('Cash');
|
||||
PaymentScreen.do.clickValidate();
|
||||
ReceiptScreen.do.clickNextOrder();
|
||||
|
||||
Tour.register('PoSDownPaymentAmount', { test: true, url: '/pos/ui' }, getSteps());
|
||||
});
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
import * as Chrome from "@point_of_sale/../tests/pos/tours/utils/chrome_util";
|
||||
import * as Dialog from "@point_of_sale/../tests/generic_helpers/dialog_util";
|
||||
import * as ProductScreen from "@point_of_sale/../tests/pos/tours/utils/product_screen_util";
|
||||
import * as PaymentScreen from "@point_of_sale/../tests/pos/tours/utils/payment_screen_util";
|
||||
import * as ReceiptScreen from "@point_of_sale/../tests/pos/tours/utils/receipt_screen_util";
|
||||
import { escapeRegExp } from "@web/core/utils/strings";
|
||||
import { registry } from "@web/core/registry";
|
||||
|
||||
export function clickDownPaymentNumpad(num) {
|
||||
return {
|
||||
content: `click discount numpad button: ${num}`,
|
||||
trigger: `.o_dialog div.numpad button:contains(/^${escapeRegExp(num)}$/)`,
|
||||
run: "click",
|
||||
};
|
||||
}
|
||||
|
||||
export function addDownPayment(percentage, soNth, downPaymentType) {
|
||||
const steps = [
|
||||
ProductScreen.clickControlButton("Quotation/Order"),
|
||||
{
|
||||
content: "Select the first SO",
|
||||
trigger: `.o_sale_order .o_data_row:nth-child(${soNth}) .o_data_cell:nth-child(1)`,
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
if (downPaymentType === "percent") {
|
||||
steps.push({
|
||||
content: "Select 'Apply a down payment (percentage)'",
|
||||
trigger: ".modal-body button:contains('percentage')",
|
||||
run: "click",
|
||||
});
|
||||
} else {
|
||||
steps.push({
|
||||
content: "Select 'Apply a down payment (fixed amount)'",
|
||||
trigger: ".modal-body button:contains('fixed amount')",
|
||||
run: "click",
|
||||
});
|
||||
}
|
||||
for (const num of percentage.split("")) {
|
||||
steps.push(clickDownPaymentNumpad(num));
|
||||
}
|
||||
steps.push({
|
||||
content: "Select 'Apply'",
|
||||
trigger: ".modal-dialog button.btn-primary:contains('Apply')",
|
||||
run: "click",
|
||||
});
|
||||
return steps;
|
||||
}
|
||||
|
||||
export function payAndInvoice(totalAmount) {
|
||||
return [
|
||||
ProductScreen.clickPayButton(),
|
||||
|
||||
PaymentScreen.totalIs(totalAmount),
|
||||
PaymentScreen.clickPaymentMethod("Bank"),
|
||||
PaymentScreen.remainingIs("0.0"),
|
||||
|
||||
PaymentScreen.clickInvoiceButton(),
|
||||
PaymentScreen.clickValidate(),
|
||||
|
||||
ReceiptScreen.receiptAmountTotalIs(totalAmount),
|
||||
ReceiptScreen.clickNextOrder(),
|
||||
];
|
||||
}
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_in_pos_downpayment_round_per_line_price_excluded", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("0.73"),
|
||||
ProductScreen.checkTaxAmount("0.10"),
|
||||
...payAndInvoice("0.73"),
|
||||
...addDownPayment("0.73", 2, "fixed"),
|
||||
ProductScreen.checkTotalAmount("0.73"),
|
||||
ProductScreen.checkTaxAmount("0.10"),
|
||||
...payAndInvoice("0.73"),
|
||||
...addDownPayment("7", 3, "percent"),
|
||||
ProductScreen.checkTotalAmount("2.56"),
|
||||
ProductScreen.checkTaxAmount("0.33"),
|
||||
...payAndInvoice("2.56"),
|
||||
...addDownPayment("2.56", 4, "fixed"),
|
||||
ProductScreen.checkTotalAmount("2.56"),
|
||||
ProductScreen.checkTaxAmount("0.33"),
|
||||
...payAndInvoice("2.56"),
|
||||
...addDownPayment("18", 5, "percent"),
|
||||
ProductScreen.checkTotalAmount("6.60"),
|
||||
ProductScreen.checkTaxAmount("0.87"),
|
||||
...payAndInvoice("6.60"),
|
||||
...addDownPayment("6.60", 6, "fixed"),
|
||||
ProductScreen.checkTotalAmount("6.60"),
|
||||
ProductScreen.checkTaxAmount("0.87"),
|
||||
...payAndInvoice("6.60"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_in_pos_downpayment_round_globally_price_excluded", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("0.73"),
|
||||
ProductScreen.checkTaxAmount("0.1"),
|
||||
...payAndInvoice("0.73"),
|
||||
...addDownPayment("0.73", 2, "fixed"),
|
||||
ProductScreen.checkTotalAmount("0.73"),
|
||||
ProductScreen.checkTaxAmount("0.1"),
|
||||
...payAndInvoice("0.73"),
|
||||
...addDownPayment("7", 3, "percent"),
|
||||
ProductScreen.checkTotalAmount("2.57"),
|
||||
ProductScreen.checkTaxAmount("0.33"),
|
||||
...payAndInvoice("2.57"),
|
||||
...addDownPayment("2.57", 4, "fixed"),
|
||||
ProductScreen.checkTotalAmount("2.57"),
|
||||
ProductScreen.checkTaxAmount("0.33"),
|
||||
...payAndInvoice("2.57"),
|
||||
...addDownPayment("18", 5, "percent"),
|
||||
ProductScreen.checkTotalAmount("6.60"),
|
||||
ProductScreen.checkTaxAmount("0.87"),
|
||||
...payAndInvoice("6.60"),
|
||||
...addDownPayment("6.60", 6, "fixed"),
|
||||
ProductScreen.checkTotalAmount("6.60"),
|
||||
ProductScreen.checkTaxAmount("0.87"),
|
||||
...payAndInvoice("6.60"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_in_pos_downpayment_round_per_line_price_included", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("0.73"),
|
||||
ProductScreen.checkTaxAmount("0.10"),
|
||||
...payAndInvoice("0.73"),
|
||||
...addDownPayment("0.73", 2, "fixed"),
|
||||
ProductScreen.checkTotalAmount("0.73"),
|
||||
ProductScreen.checkTaxAmount("0.10"),
|
||||
...payAndInvoice("0.73"),
|
||||
...addDownPayment("7", 3, "percent"),
|
||||
ProductScreen.checkTotalAmount("2.56"),
|
||||
ProductScreen.checkTaxAmount("0.33"),
|
||||
...payAndInvoice("2.56"),
|
||||
...addDownPayment("2.56", 4, "fixed"),
|
||||
ProductScreen.checkTotalAmount("2.56"),
|
||||
ProductScreen.checkTaxAmount("0.33"),
|
||||
...payAndInvoice("2.56"),
|
||||
...addDownPayment("18", 5, "percent"),
|
||||
ProductScreen.checkTotalAmount("6.60"),
|
||||
ProductScreen.checkTaxAmount("0.87"),
|
||||
...payAndInvoice("6.60"),
|
||||
...addDownPayment("6.60", 6, "fixed"),
|
||||
ProductScreen.checkTotalAmount("6.60"),
|
||||
ProductScreen.checkTaxAmount("0.87"),
|
||||
...payAndInvoice("6.60"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_in_pos_downpayment_round_globally_price_included", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("0.73"),
|
||||
ProductScreen.checkTaxAmount("0.10"),
|
||||
...payAndInvoice("0.73"),
|
||||
...addDownPayment("0.73", 2, "fixed"),
|
||||
ProductScreen.checkTotalAmount("0.73"),
|
||||
ProductScreen.checkTaxAmount("0.10"),
|
||||
...payAndInvoice("0.73"),
|
||||
...addDownPayment("7", 3, "percent"),
|
||||
ProductScreen.checkTotalAmount("2.57"),
|
||||
ProductScreen.checkTaxAmount("0.33"),
|
||||
...payAndInvoice("2.57"),
|
||||
...addDownPayment("2.57", 4, "fixed"),
|
||||
ProductScreen.checkTotalAmount("2.57"),
|
||||
ProductScreen.checkTaxAmount("0.34"),
|
||||
...payAndInvoice("2.57"),
|
||||
...addDownPayment("18", 5, "percent"),
|
||||
ProductScreen.checkTotalAmount("6.60"),
|
||||
ProductScreen.checkTaxAmount("0.87"),
|
||||
...payAndInvoice("6.60"),
|
||||
...addDownPayment("6.60", 6, "fixed"),
|
||||
ProductScreen.checkTotalAmount("6.60"),
|
||||
ProductScreen.checkTaxAmount("0.87"),
|
||||
...payAndInvoice("6.60"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_br_pos_downpayment_round_per_line_price_excluded", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("1.92"),
|
||||
ProductScreen.checkTaxAmount("0.63"),
|
||||
...payAndInvoice("1.92"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_br_pos_downpayment_round_globally_price_excluded", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("1.92"),
|
||||
ProductScreen.checkTaxAmount("0.63"),
|
||||
...payAndInvoice("1.92"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_br_pos_downpayment_round_per_line_price_included", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("1.92"),
|
||||
ProductScreen.checkTaxAmount("0.63"),
|
||||
...payAndInvoice("1.92"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_br_pos_downpayment_round_globally_price_included", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("1.92"),
|
||||
ProductScreen.checkTaxAmount("0.63"),
|
||||
...payAndInvoice("1.92"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_be_pos_downpayment_round_per_line_price_excluded", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("0.86"),
|
||||
ProductScreen.checkTaxAmount("0.15"),
|
||||
...payAndInvoice("0.86"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_be_pos_downpayment_round_globally_price_excluded", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("0.86"),
|
||||
ProductScreen.checkTaxAmount("0.15"),
|
||||
...payAndInvoice("0.86"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_be_pos_downpayment_round_per_line_price_included", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("0.86"),
|
||||
ProductScreen.checkTaxAmount("0.15"),
|
||||
...payAndInvoice("0.86"),
|
||||
].flat(),
|
||||
});
|
||||
|
||||
registry
|
||||
.category("web_tour.tours")
|
||||
.add("test_taxes_l10n_be_pos_downpayment_round_globally_price_included", {
|
||||
steps: () =>
|
||||
[
|
||||
Chrome.startPoS(),
|
||||
Dialog.confirm("Open Register"),
|
||||
|
||||
...addDownPayment("2", 1, "percent"),
|
||||
ProductScreen.checkTotalAmount("0.86"),
|
||||
ProductScreen.checkTaxAmount("0.15"),
|
||||
...payAndInvoice("0.86"),
|
||||
].flat(),
|
||||
});
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
import * as ProductScreen from "@point_of_sale/../tests/pos/tours/utils/product_screen_util";
|
||||
import * as Dialog from "@point_of_sale/../tests/generic_helpers/dialog_util";
|
||||
import * as Numpad from "@point_of_sale/../tests/generic_helpers/numpad_util";
|
||||
|
||||
export function selectNthOrder(n) {
|
||||
return [
|
||||
...ProductScreen.clickControlButton("Quotation/Order"),
|
||||
{
|
||||
content: `select nth order`,
|
||||
trigger: `.modal:not(.o_inactive_modal) table.o_list_table tbody tr.o_data_row:nth-child(${n}) td`,
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function settleSaleOrderByPrice(price) {
|
||||
return [
|
||||
...ProductScreen.clickControlButton("Quotation/Order"),
|
||||
{
|
||||
content: `select sale order with price ${price}`,
|
||||
trigger: `.modal:not(.o_inactive_modal) table.o_list_table tbody tr.o_data_row td:contains('${price}')`,
|
||||
run: "click",
|
||||
},
|
||||
{
|
||||
content: `Choose to settle the order`,
|
||||
trigger: `.modal:not(.o_inactive_modal) .selection-item:contains('Settle the order')`,
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function settleNthOrder(n, options = {}) {
|
||||
const { loadSN } = options;
|
||||
const step = [
|
||||
...selectNthOrder(n),
|
||||
{
|
||||
content: `Choose to settle the order`,
|
||||
trigger: `.modal:not(.o_inactive_modal) .selection-item:contains('Settle the order')`,
|
||||
run: "click",
|
||||
},
|
||||
];
|
||||
if (loadSN !== undefined) {
|
||||
step.push({
|
||||
content: `Choose to auto link the lot number to the order line`,
|
||||
trigger: `.modal-content:contains('Do you want to load the SN/Lots linked to the Sales Order?') button:contains('${
|
||||
loadSN ? "Ok" : "Cancel"
|
||||
}')`,
|
||||
run: "click",
|
||||
});
|
||||
}
|
||||
step.push({
|
||||
trigger: "body:not(:has(.modal))",
|
||||
});
|
||||
return step;
|
||||
}
|
||||
|
||||
export function downPaymentFirstOrder(amount) {
|
||||
return [
|
||||
...selectNthOrder(1),
|
||||
{
|
||||
content: `click on select the order`,
|
||||
trigger: `.selection-item:contains('Apply a down payment')`,
|
||||
run: "click",
|
||||
},
|
||||
Numpad.click(amount),
|
||||
Dialog.confirm("Apply"),
|
||||
];
|
||||
}
|
||||
|
||||
export function checkOrdersListEmpty() {
|
||||
return [
|
||||
...ProductScreen.clickControlButton("Quotation/Order"),
|
||||
{
|
||||
content: "Check that the orders list is empty",
|
||||
trigger: "p:contains(No record found)",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export function selectedOrderLinesHasLots(productName, lots) {
|
||||
const getSerialStep = (index, serialNumber) => ({
|
||||
content: `check lot${index} is linked`,
|
||||
trigger: `.info-list li:contains(${serialNumber})`,
|
||||
});
|
||||
const lotSteps = lots.reduce((acc, serial, i) => acc.concat(getSerialStep(i, serial)), []);
|
||||
return [...ProductScreen.selectedOrderlineHas(productName), ...lotSteps];
|
||||
}
|
||||
|
||||
export function checkOrdersListNotEmpty() {
|
||||
return [
|
||||
...ProductScreen.clickControlButton("Quotation/Order"),
|
||||
{
|
||||
content: "Check that the orders list is not empty",
|
||||
trigger: ".o_data_row",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import { test, expect } from "@odoo/hoot";
|
||||
import { setupPosEnv } from "@point_of_sale/../tests/unit/utils";
|
||||
import { mountWithCleanup } from "@web/../tests/web_test_helpers";
|
||||
import { Orderline } from "@point_of_sale/app/components/orderline/orderline";
|
||||
import { definePosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
|
||||
definePosModels();
|
||||
|
||||
test("Displays the table with details of the down payment", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = store.addNewOrder();
|
||||
|
||||
const productDownPayment = store.models["product.template"].get(105);
|
||||
const sol1 = store.models["sale.order.line"].get(1);
|
||||
const sol2 = store.models["sale.order.line"].get(2);
|
||||
const line = await store.addLineToOrder(
|
||||
{
|
||||
product_tmpl_id: productDownPayment,
|
||||
sale_order_origin_id: 1,
|
||||
down_payment_details: [
|
||||
{
|
||||
product_name: sol1.display_name,
|
||||
product_uom_qty: sol1.product_uom_qty,
|
||||
price_unit: sol1.price_unit,
|
||||
total: sol1.price_total,
|
||||
},
|
||||
{
|
||||
product_name: sol2.display_name,
|
||||
product_uom_qty: sol2.product_uom_qty,
|
||||
price_unit: sol2.price_unit,
|
||||
total: sol2.price_total,
|
||||
},
|
||||
],
|
||||
qty: 1,
|
||||
},
|
||||
order
|
||||
);
|
||||
|
||||
const comp = await mountWithCleanup(Orderline, { props: { line } });
|
||||
|
||||
const saleOrderInfo = ".orderline .info-list .sale-order-info";
|
||||
const cell = (tr, td) => `${saleOrderInfo} tr:nth-child(${tr}) td:nth-child(${td})`;
|
||||
|
||||
expect(comp.line).toEqual(line);
|
||||
expect(saleOrderInfo).toBeVisible();
|
||||
expect(`${saleOrderInfo} tr`).toHaveCount(2);
|
||||
|
||||
expect(cell(1, 1)).toHaveText("5x");
|
||||
expect(cell(1, 2)).toHaveText("Product 1");
|
||||
expect(cell(1, 4)).toHaveText(`$ 500.00 (tax incl.)`);
|
||||
|
||||
expect(cell(2, 1)).toHaveText("3x");
|
||||
expect(cell(2, 2)).toHaveText("Product 2");
|
||||
expect(cell(2, 4)).toHaveText(`$ 150.00 (tax incl.)`);
|
||||
});
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { PosConfig } from "@point_of_sale/../tests/unit/data/pos_config.data";
|
||||
|
||||
PosConfig._records = PosConfig._records.map((config) => {
|
||||
if (config.id === 1) {
|
||||
return {
|
||||
...config,
|
||||
down_payment_product_id: 105,
|
||||
};
|
||||
}
|
||||
return config;
|
||||
});
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { PosOrderLine } from "@point_of_sale/../tests/unit/data/pos_order_line.data";
|
||||
|
||||
patch(PosOrderLine.prototype, {
|
||||
_load_pos_data_fields() {
|
||||
return [
|
||||
...super._load_pos_data_fields(),
|
||||
"sale_order_origin_id",
|
||||
"sale_order_line_id",
|
||||
"down_payment_details",
|
||||
"settled_order_id",
|
||||
"settled_invoice_id",
|
||||
];
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { PosSession } from "@point_of_sale/../tests/unit/data/pos_session.data";
|
||||
|
||||
patch(PosSession.prototype, {
|
||||
_load_pos_data_models() {
|
||||
return [...super._load_pos_data_models(), "sale.order", "sale.order.line"];
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { ProductProduct } from "@point_of_sale/../tests/unit/data/product_product.data";
|
||||
|
||||
ProductProduct._records = [
|
||||
...ProductProduct._records,
|
||||
{
|
||||
id: 105,
|
||||
product_tmpl_id: 105,
|
||||
lst_price: 0,
|
||||
standard_price: 0,
|
||||
display_name: "Down Payment (POS)",
|
||||
product_tag_ids: [],
|
||||
barcode: false,
|
||||
default_code: false,
|
||||
product_template_attribute_value_ids: [],
|
||||
product_template_variant_value_ids: [],
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { ProductTemplate } from "@point_of_sale/../tests/unit/data/product_template.data";
|
||||
|
||||
patch(ProductTemplate.prototype, {
|
||||
_load_pos_data_fields() {
|
||||
return [...super._load_pos_data_fields(), "sale_line_warn_msg", "invoice_policy"];
|
||||
},
|
||||
});
|
||||
|
||||
ProductTemplate._records = [
|
||||
...ProductTemplate._records,
|
||||
{
|
||||
id: 105,
|
||||
display_name: "Down Payment (POS)",
|
||||
standard_price: 0,
|
||||
categ_id: false,
|
||||
pos_categ_ids: [],
|
||||
taxes_id: [],
|
||||
barcode: false,
|
||||
name: "Down Payment (POS)",
|
||||
list_price: 0,
|
||||
is_favorite: false,
|
||||
default_code: false,
|
||||
to_weight: false,
|
||||
uom_id: 1,
|
||||
description_sale: false,
|
||||
description: false,
|
||||
tracking: "none",
|
||||
type: "service",
|
||||
service_tracking: "no",
|
||||
is_storable: false,
|
||||
write_date: "2025-07-03 17:04:14",
|
||||
color: 0,
|
||||
pos_sequence: 5,
|
||||
available_in_pos: true,
|
||||
attribute_line_ids: [],
|
||||
active: true,
|
||||
image_128: false,
|
||||
sequence: 1,
|
||||
combo_ids: [],
|
||||
product_variant_ids: [7],
|
||||
public_description: false,
|
||||
pos_optional_product_ids: [],
|
||||
product_tag_ids: [],
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { ResPartner as MailResPartner } from "@mail/../tests/mock_server/mock_models/res_partner";
|
||||
|
||||
patch(MailResPartner.prototype, {
|
||||
_load_pos_data_fields() {
|
||||
return [...super._load_pos_data_fields(), "sale_warn_msg"];
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { hootPosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
import { models } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class SaleOrder extends models.ServerModel {
|
||||
_name = "sale.order";
|
||||
|
||||
_load_pos_data_fields() {
|
||||
return [
|
||||
"name",
|
||||
"state",
|
||||
"user_id",
|
||||
"order_line",
|
||||
"partner_id",
|
||||
"pricelist_id",
|
||||
"fiscal_position_id",
|
||||
"amount_total",
|
||||
"amount_untaxed",
|
||||
"amount_unpaid",
|
||||
"picking_ids",
|
||||
"partner_shipping_id",
|
||||
"partner_invoice_id",
|
||||
"date_order",
|
||||
"write_date",
|
||||
];
|
||||
}
|
||||
|
||||
_records = [
|
||||
{
|
||||
id: 1,
|
||||
name: "S00001",
|
||||
state: "sale",
|
||||
order_line: [1, 2],
|
||||
partner_id: 3,
|
||||
pricelist_id: 1,
|
||||
fiscal_position_id: 1,
|
||||
amount_total: 650,
|
||||
amount_untaxed: 500,
|
||||
amount_unpaid: 650,
|
||||
partner_shipping_id: 3,
|
||||
partner_invoice_id: 3,
|
||||
date_order: "2025-07-03 17:04:14",
|
||||
write_date: "2025-07-03 17:04:14",
|
||||
},
|
||||
];
|
||||
|
||||
async load_sale_order_from_pos(id, config_id) {
|
||||
const order = this.env["sale.order"].find((order) => order.id === id);
|
||||
const orderLines = this.env["sale.order.line"].filter((line) =>
|
||||
order.order_line.includes(line.id)
|
||||
);
|
||||
const partner = this.env["res.partner"].find((partner) => partner.id === order.partner_id);
|
||||
const productProducts = this.env["product.product"].filter((product) =>
|
||||
orderLines.map((line) => line.product_id).includes(product.id)
|
||||
);
|
||||
const productTemplates = this.env["product.template"].filter((template) =>
|
||||
productProducts.map((p) => p.product_tmpl_id).includes(template.id)
|
||||
);
|
||||
return {
|
||||
"sale.order": [order],
|
||||
"sale.order.line": orderLines,
|
||||
"res.partner": [partner],
|
||||
"product.product": productProducts,
|
||||
"product.template": productTemplates,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
patch(hootPosModels, [...hootPosModels, SaleOrder]);
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
import { patch } from "@web/core/utils/patch";
|
||||
import { hootPosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
import { models, MockServer } from "@web/../tests/web_test_helpers";
|
||||
|
||||
export class SaleOrderLine extends models.ServerModel {
|
||||
_name = "sale.order.line";
|
||||
|
||||
_load_pos_data_fields() {
|
||||
return [
|
||||
"discount",
|
||||
"display_name",
|
||||
"price_total",
|
||||
"price_unit",
|
||||
"product_id",
|
||||
"product_uom_qty",
|
||||
"qty_delivered",
|
||||
"qty_invoiced",
|
||||
"qty_to_invoice",
|
||||
"display_type",
|
||||
"name",
|
||||
"tax_ids",
|
||||
"is_downpayment",
|
||||
"extra_tax_data",
|
||||
"write_date",
|
||||
"is_repair_line",
|
||||
];
|
||||
}
|
||||
|
||||
_records = [
|
||||
{
|
||||
id: 1,
|
||||
display_name: "Product 1",
|
||||
product_id: 5,
|
||||
product_uom_qty: 5,
|
||||
price_unit: 100,
|
||||
price_total: 500,
|
||||
discount: 0,
|
||||
qty_delivered: 0,
|
||||
qty_invoiced: 0,
|
||||
qty_to_invoice: 5,
|
||||
display_type: false,
|
||||
name: "Product 1",
|
||||
tax_ids: [],
|
||||
is_downpayment: false,
|
||||
extra_tax_data: {},
|
||||
write_date: "2025-07-03 17:04:14",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
display_name: "Product 2",
|
||||
product_id: 6,
|
||||
product_uom_qty: 3,
|
||||
price_unit: 50,
|
||||
price_total: 150,
|
||||
discount: 0,
|
||||
qty_delivered: 0,
|
||||
qty_invoiced: 0,
|
||||
qty_to_invoice: 3,
|
||||
display_type: false,
|
||||
name: "Product 2",
|
||||
tax_ids: [],
|
||||
is_downpayment: false,
|
||||
extra_tax_data: {},
|
||||
write_date: "2025-07-03 17:04:14",
|
||||
},
|
||||
];
|
||||
|
||||
async read_converted(ids) {
|
||||
const model = MockServer.env[this._name];
|
||||
const posFields = model._load_pos_data_fields();
|
||||
const records = model.search_read(
|
||||
[["id", "in", ids]],
|
||||
posFields,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
return records;
|
||||
}
|
||||
}
|
||||
|
||||
patch(hootPosModels, [...hootPosModels, SaleOrderLine]);
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
import { test, expect, describe } from "@odoo/hoot";
|
||||
import { setupPosEnv, getFilledOrder } from "@point_of_sale/../tests/unit/utils";
|
||||
import { definePosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
|
||||
definePosModels();
|
||||
|
||||
describe("saleDetails", () => {
|
||||
test("down payment details as array", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = store.addNewOrder();
|
||||
|
||||
const productDownPayment = store.models["product.template"].get(105);
|
||||
const line = await store.addLineToOrder(
|
||||
{
|
||||
product_tmpl_id: productDownPayment,
|
||||
down_payment_details: [
|
||||
{
|
||||
product_name: "Product 1",
|
||||
product_uom_qty: 2,
|
||||
total: 100,
|
||||
},
|
||||
{
|
||||
product_name: "Product 2",
|
||||
product_uom_qty: 1,
|
||||
total: 50,
|
||||
},
|
||||
],
|
||||
qty: 1,
|
||||
},
|
||||
order
|
||||
);
|
||||
|
||||
const saleDetails = line.saleDetails;
|
||||
expect(saleDetails).toEqual([
|
||||
{
|
||||
product_uom_qty: 2,
|
||||
product_name: "Product 1",
|
||||
total: "$\u00a0100.00",
|
||||
},
|
||||
{
|
||||
product_uom_qty: 1,
|
||||
product_name: "Product 2",
|
||||
total: "$\u00a050.00",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test("down payment details as stringified JSON", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = store.addNewOrder();
|
||||
|
||||
const productDownPayment = store.models["product.template"].get(105);
|
||||
const line = await store.addLineToOrder(
|
||||
{
|
||||
product_tmpl_id: productDownPayment,
|
||||
down_payment_details: JSON.stringify([
|
||||
{
|
||||
product_name: "Product 1",
|
||||
product_uom_qty: 2,
|
||||
total: 100,
|
||||
},
|
||||
{
|
||||
product_name: "Product 2",
|
||||
product_uom_qty: 1,
|
||||
total: 50,
|
||||
},
|
||||
]),
|
||||
qty: 1,
|
||||
},
|
||||
order
|
||||
);
|
||||
|
||||
const saleDetails = line.saleDetails;
|
||||
expect(saleDetails).toEqual([
|
||||
{
|
||||
product_uom_qty: 2,
|
||||
product_name: "Product 1",
|
||||
total: "$\u00a0100.00",
|
||||
},
|
||||
{
|
||||
product_uom_qty: 1,
|
||||
product_name: "Product 2",
|
||||
total: "$\u00a050.00",
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setQuantityFromSOL", () => {
|
||||
test("service product, state != sent/draft → qty_to_invoice", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = await getFilledOrder(store);
|
||||
const line = order.lines[0];
|
||||
line.product_id.type = "service";
|
||||
line.sale_order_origin_id = { state: "sale" }; // not 'sent' or 'draft'
|
||||
|
||||
const saleOrderLine = { qty_to_invoice: 2 };
|
||||
|
||||
await line.setQuantityFromSOL(saleOrderLine);
|
||||
expect(line.qty).toBe(2);
|
||||
});
|
||||
|
||||
test("non-service product → qty = uom_qty - max(delivered, invoiced)", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = await getFilledOrder(store);
|
||||
const line = order.lines[0];
|
||||
line.product_id.type = "consu";
|
||||
|
||||
const saleOrderLine = {
|
||||
product_uom_qty: 8,
|
||||
qty_delivered: 1,
|
||||
qty_invoiced: 2,
|
||||
};
|
||||
|
||||
await line.setQuantityFromSOL(saleOrderLine);
|
||||
expect(line.qty).toBe(6); // 8 - max(1,2)
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
import { test, expect, describe } from "@odoo/hoot";
|
||||
import { setupPosEnv, getFilledOrder } from "@point_of_sale/../tests/unit/utils";
|
||||
import { click, waitFor } from "@odoo/hoot-dom";
|
||||
import { mountWithCleanup } from "@web/../tests/web_test_helpers";
|
||||
import { ProductScreen } from "@point_of_sale/app/screens/product_screen/product_screen";
|
||||
import { Orderline } from "@point_of_sale/app/components/orderline/orderline";
|
||||
import { definePosModels } from "@point_of_sale/../tests/unit/data/generate_model_definitions";
|
||||
|
||||
definePosModels();
|
||||
|
||||
describe("onClickSaleOrder", () => {
|
||||
test("no selection → abort", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = await getFilledOrder(store);
|
||||
await mountWithCleanup(ProductScreen, { props: { orderUuid: order.uuid } });
|
||||
|
||||
const promiseResult = store.onClickSaleOrder(1);
|
||||
const button =
|
||||
".modal-header:has(.modal-title:contains('What do you want to do?')) button[aria-label='Close']";
|
||||
await waitFor(button);
|
||||
await click(button);
|
||||
|
||||
await promiseResult;
|
||||
|
||||
const currentOrder = store.getOrder();
|
||||
expect(currentOrder.id).toBe(order.id);
|
||||
expect(currentOrder.lines.length).toBe(2);
|
||||
|
||||
expect(currentOrder.lines[0].product_id.id).toBe(5);
|
||||
expect(currentOrder.lines[0].qty).toBe(3);
|
||||
|
||||
expect(currentOrder.lines[1].product_id.id).toBe(6);
|
||||
expect(currentOrder.lines[1].qty).toBe(2);
|
||||
});
|
||||
|
||||
test("settle → calls settleSO", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = await getFilledOrder(store);
|
||||
await mountWithCleanup(ProductScreen, { props: { orderUuid: order.uuid } });
|
||||
|
||||
const promiseResult = store.onClickSaleOrder(1);
|
||||
const button = ".modal-body button:contains('Settle the order')";
|
||||
await waitFor(button);
|
||||
await click(button);
|
||||
await promiseResult;
|
||||
|
||||
const currentOrder = store.getOrder();
|
||||
|
||||
expect(currentOrder.id).toBe(order.id);
|
||||
expect(currentOrder.lines.length).toBe(4);
|
||||
|
||||
expect(currentOrder.lines[0].product_id.id).toBe(5);
|
||||
expect(currentOrder.lines[0].qty).toBe(3);
|
||||
expect(currentOrder.lines[0].price_unit).toBe(3);
|
||||
expect(currentOrder.lines[0].prices.total_excluded).toBe(9);
|
||||
|
||||
expect(currentOrder.lines[1].product_id.id).toBe(6);
|
||||
expect(currentOrder.lines[1].qty).toBe(2);
|
||||
expect(currentOrder.lines[1].price_unit).toBe(3);
|
||||
expect(currentOrder.lines[1].prices.total_excluded).toBe(6);
|
||||
|
||||
expect(currentOrder.lines[2].product_id.id).toBe(5);
|
||||
expect(currentOrder.lines[2].qty).toBe(5);
|
||||
expect(currentOrder.lines[2].price_unit).toBe(100);
|
||||
expect(currentOrder.lines[2].prices.total_excluded).toBe(500);
|
||||
|
||||
expect(currentOrder.lines[3].product_id.id).toBe(6);
|
||||
expect(currentOrder.lines[3].qty).toBe(3);
|
||||
expect(currentOrder.lines[3].price_unit).toBe(50);
|
||||
expect(currentOrder.lines[3].prices.total_excluded).toBe(150);
|
||||
});
|
||||
|
||||
test("dpPercentage → calls downPaymentSO", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = await getFilledOrder(store);
|
||||
await mountWithCleanup(ProductScreen, { props: { orderUuid: order.uuid } });
|
||||
|
||||
const promiseResult = store.onClickSaleOrder(1);
|
||||
const buttonDownPaymentPercentage =
|
||||
".modal-body button:contains('Apply a down payment (percentage)')";
|
||||
await waitFor(buttonDownPaymentPercentage);
|
||||
await click(buttonDownPaymentPercentage);
|
||||
await waitFor(".modal-title:contains('Down Payment')");
|
||||
await click(".modal-body .numpad .numpad-button[value='+50']");
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
await click(".modal-footer .btn:contains('Apply')");
|
||||
await promiseResult;
|
||||
|
||||
const currentOrder = store.getOrder();
|
||||
expect(currentOrder.id).toBe(order.id);
|
||||
expect(currentOrder.lines.length).toBe(3);
|
||||
|
||||
expect(currentOrder.lines[0].product_id.id).toBe(5);
|
||||
expect(currentOrder.lines[0].qty).toBe(3);
|
||||
expect(currentOrder.lines[0].price_unit).toBe(3);
|
||||
expect(currentOrder.lines[0].prices.total_excluded).toBe(9);
|
||||
|
||||
expect(currentOrder.lines[1].product_id.id).toBe(6);
|
||||
expect(currentOrder.lines[1].qty).toBe(2);
|
||||
expect(currentOrder.lines[1].price_unit).toBe(3);
|
||||
expect(currentOrder.lines[1].prices.total_excluded).toBe(6);
|
||||
|
||||
expect(currentOrder.lines[2].product_id.id).toBe(105);
|
||||
expect(currentOrder.lines[2].qty).toBe(1);
|
||||
expect(currentOrder.lines[2].price_unit).toBe(325);
|
||||
expect(currentOrder.lines[2].prices.total_excluded).toBe(325);
|
||||
|
||||
const comp = await mountWithCleanup(Orderline, {
|
||||
props: { line: currentOrder.lines[2] },
|
||||
});
|
||||
|
||||
const saleOrderInfo = ".orderline .info-list .sale-order-info";
|
||||
const cell = (tr, td) => `${saleOrderInfo} tr:nth-child(${tr}) td:nth-child(${td})`;
|
||||
|
||||
expect(comp.line).toEqual(currentOrder.lines[2]);
|
||||
expect(`${saleOrderInfo} tr`).toHaveCount(4);
|
||||
|
||||
expect(cell(1, 1)).toHaveText("5x");
|
||||
expect(cell(1, 2)).toHaveText("TEST");
|
||||
expect(cell(1, 4)).toHaveText(`$ 500.00 (tax incl.)`);
|
||||
|
||||
expect(cell(2, 1)).toHaveText("3x");
|
||||
expect(cell(2, 2)).toHaveText("TEST 2");
|
||||
expect(cell(2, 4)).toHaveText(`$ 150.00 (tax incl.)`);
|
||||
});
|
||||
|
||||
test("dpAmount → calls downPaymentSO", async () => {
|
||||
const store = await setupPosEnv();
|
||||
const order = await getFilledOrder(store);
|
||||
await mountWithCleanup(ProductScreen, { props: { orderUuid: order.uuid } });
|
||||
|
||||
const promiseResult = store.onClickSaleOrder(1);
|
||||
const buttonDownPaymentPercentage =
|
||||
".modal-body button:contains('Apply a down payment (fixed amount)')";
|
||||
await waitFor(buttonDownPaymentPercentage);
|
||||
await click(buttonDownPaymentPercentage);
|
||||
await waitFor(".modal-title:contains('Down Payment')");
|
||||
await click(".modal-body .numpad .numpad-button[value='+50']");
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
await click(".modal-footer .btn:contains('Apply')");
|
||||
await promiseResult;
|
||||
|
||||
const currentOrder = store.getOrder();
|
||||
expect(currentOrder.id).toBe(order.id);
|
||||
expect(currentOrder.lines.length).toBe(3);
|
||||
|
||||
expect(currentOrder.lines[0].product_id.id).toBe(5);
|
||||
expect(currentOrder.lines[0].qty).toBe(3);
|
||||
expect(currentOrder.lines[0].price_unit).toBe(3);
|
||||
expect(currentOrder.lines[0].prices.total_excluded).toBe(9);
|
||||
|
||||
expect(currentOrder.lines[1].product_id.id).toBe(6);
|
||||
expect(currentOrder.lines[1].qty).toBe(2);
|
||||
expect(currentOrder.lines[1].price_unit).toBe(3);
|
||||
expect(currentOrder.lines[1].prices.total_excluded).toBe(6);
|
||||
|
||||
expect(currentOrder.lines[2].product_id.id).toBe(105);
|
||||
expect(currentOrder.lines[2].qty).toBe(1);
|
||||
expect(currentOrder.lines[2].price_unit).toBe(50);
|
||||
expect(currentOrder.lines[2].prices.total_excluded).toBe(50);
|
||||
|
||||
const comp = await mountWithCleanup(Orderline, {
|
||||
props: { line: currentOrder.lines[2] },
|
||||
});
|
||||
|
||||
const saleOrderInfo = ".orderline .info-list .sale-order-info";
|
||||
const cell = (tr, td) => `${saleOrderInfo} tr:nth-child(${tr}) td:nth-child(${td})`;
|
||||
|
||||
expect(comp.line).toEqual(currentOrder.lines[2]);
|
||||
expect(`${saleOrderInfo} tr`).toHaveCount(4);
|
||||
|
||||
expect(cell(1, 1)).toHaveText("5x");
|
||||
expect(cell(1, 2)).toHaveText("TEST");
|
||||
expect(cell(1, 4)).toHaveText(`$ 500.00 (tax incl.)`);
|
||||
|
||||
expect(cell(2, 1)).toHaveText("3x");
|
||||
expect(cell(2, 2)).toHaveText("TEST 2");
|
||||
expect(cell(2, 4)).toHaveText(`$ 150.00 (tax incl.)`);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue