diff --git a/addons/point_of_sale/static/src/app/services/data_service.js b/addons/point_of_sale/static/src/app/services/data_service.js
index 7947cec3c960ce..11bdf0d9b04613 100644
--- a/addons/point_of_sale/static/src/app/services/data_service.js
+++ b/addons/point_of_sale/static/src/app/services/data_service.js
@@ -341,7 +341,9 @@ export class PosData {
for (const model of this.opts.cleanupModels) {
const local = localData[model] || [];
if (local.length > 0) {
- local_records_to_filter[model] = local.map((r) => r.id);
+ local_records_to_filter[model] = local
+ .map((r) => r.id)
+ .filter((id) => typeof id === "number");
}
}
diff --git a/addons/point_of_sale/static/src/app/services/pos_store.js b/addons/point_of_sale/static/src/app/services/pos_store.js
index d105a590f67f04..02ff7b4665c479 100644
--- a/addons/point_of_sale/static/src/app/services/pos_store.js
+++ b/addons/point_of_sale/static/src/app/services/pos_store.js
@@ -1417,7 +1417,7 @@ export class PosStore extends WithLazyGetterTrap {
}
}
- postSyncAllOrders(orders) {}
+ async postSyncAllOrders(orders) {}
async syncAllOrders(options = {}) {
if (this.data.network.offline) {
if (options.throw) {
diff --git a/addons/point_of_sale/static/src/app/utils/order_payment_validation.js b/addons/point_of_sale/static/src/app/utils/order_payment_validation.js
index 2709798fe4a795..3d42edc0bde23b 100644
--- a/addons/point_of_sale/static/src/app/utils/order_payment_validation.js
+++ b/addons/point_of_sale/static/src/app/utils/order_payment_validation.js
@@ -248,7 +248,7 @@ export default class OrderPaymentValidation {
const order = this.pos.getOrder();
const currency = this.pos.currency;
for (const payment of order.payment_ids) {
- if (!payment.payment_method_id.is_cash_count) {
+ if (payment.payment_method_id.type !== "cash") {
continue;
}
@@ -334,7 +334,7 @@ export default class OrderPaymentValidation {
Math.abs(this.order.priceIncl - this.order.amountPaid + this.order.appliedRounding) >
0.00001
) {
- if (!this.pos.models["pos.payment.method"].some((pm) => pm.is_cash_count)) {
+ if (!this.pos.models["pos.payment.method"].some((pm) => pm.type === "cash")) {
this.pos.dialog.add(AlertDialog, {
title: _t("Cannot return change without a cash payment method"),
body: _t(
@@ -381,7 +381,7 @@ export default class OrderPaymentValidation {
async _askForCustomerIfRequired() {
const splitPayments = this.order.payment_ids.filter(
- (payment) => payment.payment_method_id.split_transactions
+ (payment) => payment.payment_method_id.type == "pay_later"
);
if (splitPayments.length && !this.order.getPartner()) {
const paymentMethod = splitPayments[0].payment_method_id;
diff --git a/addons/point_of_sale/static/tests/pos/tours/product_screen_tour.js b/addons/point_of_sale/static/tests/pos/tours/product_screen_tour.js
index 868c3e35a51cab..00ccc6d07ae559 100644
--- a/addons/point_of_sale/static/tests/pos/tours/product_screen_tour.js
+++ b/addons/point_of_sale/static/tests/pos/tours/product_screen_tour.js
@@ -1210,7 +1210,7 @@ registry.category("web_tour.tours").add("test_pos_ui_round_globally", {
...["+/-"].map(Numpad.click),
...ProductScreen.selectedOrderlineHasDirect("Test Product 2", "-1.0"),
]),
- ProductScreen.totalAmountIs("7,771.01"),
+ ProductScreen.totalAmountIs("7,771.00"),
ProductScreen.clickPayButton(),
PaymentScreen.clickPaymentMethod("Bank"),
PaymentScreen.clickValidate(),
diff --git a/addons/point_of_sale/static/tests/pos/tours/test_pos_accounting_http.js b/addons/point_of_sale/static/tests/pos/tours/test_pos_accounting_http.js
new file mode 100644
index 00000000000000..560751e29f8f7a
--- /dev/null
+++ b/addons/point_of_sale/static/tests/pos/tours/test_pos_accounting_http.js
@@ -0,0 +1,31 @@
+/* global posmodel */
+
+import * as ProductScreen from "@point_of_sale/../tests/pos/tours/utils/product_screen_util";
+import * as Chrome from "@point_of_sale/../tests/pos/tours/utils/chrome_util";
+import { registry } from "@web/core/registry";
+import { inLeftSide } from "@point_of_sale/../tests/pos/tours/utils/common";
+import * as Numpad from "@point_of_sale/../tests/generic_helpers/numpad_util";
+
+registry.category("web_tour.tours").add("test_baseline_between_frontend_and_backend", {
+ steps: () =>
+ [
+ Chrome.startPoS(),
+ ProductScreen.clickDisplayedProduct("Test Product 1"),
+ ProductScreen.clickDisplayedProduct("Test Product 2"),
+ inLeftSide([
+ ...["+/-"].map(Numpad.click),
+ ...ProductScreen.selectedOrderlineHasDirect("Test Product 2", "-1.0"),
+ ]),
+ ProductScreen.totalAmountIs("7,771.00"),
+ {
+ trigger: "body",
+ content: "Create an order with a product with dynamic price",
+ run: async () => {
+ const data = JSON.stringify(posmodel.getOrder()._computeAllPrices());
+ const result = await posmodel.syncAllOrders({ orders: [posmodel.getOrder()] });
+ const orderId = result[0].id;
+ await posmodel.data.call("pos.order", "get_frontend_data", [[orderId], data]);
+ },
+ },
+ ].flat(),
+});
diff --git a/addons/point_of_sale/static/tests/pos/tours/utils/partner_list_util.js b/addons/point_of_sale/static/tests/pos/tours/utils/partner_list_util.js
index daeb772d8a828e..bdfcf07216dca0 100644
--- a/addons/point_of_sale/static/tests/pos/tours/utils/partner_list_util.js
+++ b/addons/point_of_sale/static/tests/pos/tours/utils/partner_list_util.js
@@ -62,7 +62,6 @@ export function settleCustomerAccount(
orderPrefix,
orderSuffix = "",
checkYear = false,
- orderSettlement = false,
availability = true
) {
const steps = [
@@ -71,10 +70,9 @@ export function settleCustomerAccount(
},
clickPartnerOptions(`${partner}`),
];
- const buttonText = orderSettlement ? "Settle orders" : "Settle invoices";
steps.push(
...[
- clickDropDownItemText(buttonText),
+ clickDropDownItemText("Settle invoices"),
clickSettleOrderName(orderPrefix, orderSuffix, checkYear, availability),
]
);
diff --git a/addons/point_of_sale/static/tests/unit/accounting/old_tour.test.js b/addons/point_of_sale/static/tests/unit/accounting/old_tour.test.js
index 2cbf517606f0f0..ff87049f987f23 100644
--- a/addons/point_of_sale/static/tests/unit/accounting/old_tour.test.js
+++ b/addons/point_of_sale/static/tests/unit/accounting/old_tour.test.js
@@ -18,8 +18,8 @@ test("[Old Tour] pos_basic_order_01_multi_payment_and_change", async () => {
product1.product_variant_ids[0].lst_price = 5.1;
product1.taxes_id = [];
- const cashPm = store.models["pos.payment.method"].find((pm) => pm.is_cash_count);
- const cardPm = store.models["pos.payment.method"].find((pm) => !pm.is_cash_count);
+ const cashPm = store.models["pos.payment.method"].find((pm) => pm.type === "cash");
+ const cardPm = store.models["pos.payment.method"].find((pm) => pm.type === "bank");
const order = store.addNewOrder();
order.pricelist_id = false;
diff --git a/addons/point_of_sale/static/tests/unit/accounting/utils.js b/addons/point_of_sale/static/tests/unit/accounting/utils.js
index 0e95252b41b017..146f8ec9203c04 100644
--- a/addons/point_of_sale/static/tests/unit/accounting/utils.js
+++ b/addons/point_of_sale/static/tests/unit/accounting/utils.js
@@ -44,8 +44,8 @@ export const prepareRoundingVals = (store, roundingAmount, roundingMethod, onlyC
const config = store.config;
const product1 = store.models["product.template"].get(15);
const product2 = store.models["product.template"].get(16);
- const cashPm = store.models["pos.payment.method"].find((pm) => pm.is_cash_count);
- const cardPm = store.models["pos.payment.method"].find((pm) => !pm.is_cash_count);
+ const cashPm = store.models["pos.payment.method"].find((pm) => pm.type === "cash");
+ const cardPm = store.models["pos.payment.method"].find((pm) => pm.type === "bank");
// Changes prices to have a non rounded change
product1.list_price = 15.73;
diff --git a/addons/point_of_sale/static/tests/unit/data/pos_config.data.js b/addons/point_of_sale/static/tests/unit/data/pos_config.data.js
index 8230ccb2bd03ca..be5e0e0b9ab27c 100644
--- a/addons/point_of_sale/static/tests/unit/data/pos_config.data.js
+++ b/addons/point_of_sale/static/tests/unit/data/pos_config.data.js
@@ -64,7 +64,6 @@ export class PosConfig extends models.ServerModel {
use_order_printer: true,
is_installed_account_accountant: true,
journal_id: 1,
- invoice_journal_id: 1,
currency_id: 1,
iface_big_scrollbars: false,
iface_print_auto: false,
@@ -86,7 +85,6 @@ export class PosConfig extends models.ServerModel {
current_session_id: 1,
current_session_state: "opening_control",
number_of_rescue_session: 0,
- last_session_closing_cash: 0.0,
last_session_closing_date: false,
pos_session_username: "Administrator",
pos_session_state: "opening_control",
diff --git a/addons/point_of_sale/static/tests/unit/data/pos_payment_method.data.js b/addons/point_of_sale/static/tests/unit/data/pos_payment_method.data.js
index 997f78ad4d6d28..d6fc45dd3dabf5 100644
--- a/addons/point_of_sale/static/tests/unit/data/pos_payment_method.data.js
+++ b/addons/point_of_sale/static/tests/unit/data/pos_payment_method.data.js
@@ -7,9 +7,7 @@ export class PosPaymentMethod extends models.ServerModel {
return [
"id",
"name",
- "is_cash_count",
"payment_provider",
- "split_transactions",
"type",
"image",
"sequence",
@@ -22,9 +20,7 @@ export class PosPaymentMethod extends models.ServerModel {
{
id: 2,
name: "Card",
- is_cash_count: false,
payment_provider: false,
- split_transactions: false,
type: "bank",
image: false,
sequence: 1,
@@ -34,9 +30,7 @@ export class PosPaymentMethod extends models.ServerModel {
{
id: 3,
name: "Customer Account",
- is_cash_count: false,
payment_provider: false,
- split_transactions: true,
type: "pay_later",
image: false,
sequence: 2,
@@ -46,9 +40,7 @@ export class PosPaymentMethod extends models.ServerModel {
{
id: 1,
name: "Cash",
- is_cash_count: true,
payment_provider: false,
- split_transactions: false,
type: "cash",
image: false,
sequence: 0,
diff --git a/addons/point_of_sale/static/tests/unit/data/pos_session.data.js b/addons/point_of_sale/static/tests/unit/data/pos_session.data.js
index 00842706a748e5..3406ce206a6997 100644
--- a/addons/point_of_sale/static/tests/unit/data/pos_session.data.js
+++ b/addons/point_of_sale/static/tests/unit/data/pos_session.data.js
@@ -58,7 +58,6 @@ export class PosSession extends models.ServerModel {
"stop_at",
"payment_method_ids",
"state",
- "cash_register_balance_start",
"access_token",
];
}
@@ -167,7 +166,6 @@ export class PosSession extends models.ServerModel {
stop_at: false,
payment_method_ids: [2, 1],
state: "opening_control",
- cash_register_balance_start: 0.0,
access_token: "e09c4843-c913-463a-959d-b9e235881201",
},
];
diff --git a/addons/point_of_sale/static/tests/unit/models/pos_payment.test.js b/addons/point_of_sale/static/tests/unit/models/pos_payment.test.js
index 9b87b66de19a8a..2d8d56ab887003 100644
--- a/addons/point_of_sale/static/tests/unit/models/pos_payment.test.js
+++ b/addons/point_of_sale/static/tests/unit/models/pos_payment.test.js
@@ -168,17 +168,16 @@ test("canBeAdjusted", async () => {
const paymentline = createPaymentLine(store, order, card);
// no payment interface + is cash
- card.is_cash_count = true;
+ card.type = "cash";
card.payment_method_type = "none";
expect(paymentline.canBeAdjusted()).toBe(false);
// no payment interface + is bank qr code
- card.is_cash_count = false;
+ card.type = "bank";
card.payment_method_type = "bank_qr_code";
expect(paymentline.canBeAdjusted()).toBe(false);
// no payment interface + is not cash or bank qr code
- card.is_cash_count = false;
card.payment_method_type = "none";
expect(paymentline.canBeAdjusted()).toBe(true);
diff --git a/addons/point_of_sale/static/tests/unit/services/pos_service.test.js b/addons/point_of_sale/static/tests/unit/services/pos_service.test.js
index 6ae59585ace20b..151fab394b6e54 100644
--- a/addons/point_of_sale/static/tests/unit/services/pos_service.test.js
+++ b/addons/point_of_sale/static/tests/unit/services/pos_service.test.js
@@ -534,7 +534,7 @@ describe("pos_store.js", () => {
test("getPaymentMethodFmtAmount", async () => {
const store = await setupPosEnv();
const order = await getFilledOrder(store);
- const cashPm = store.models["pos.payment.method"].find((pm) => pm.is_cash_count);
+ const cashPm = store.models["pos.payment.method"].find((pm) => pm.type === "cash");
// Case 1: No rounding enabled
expect(store.getPaymentMethodFmtAmount(cashPm, order)).toBeEmpty();
diff --git a/addons/point_of_sale/tests/__init__.py b/addons/point_of_sale/tests/__init__.py
index fabf3c98820a57..255ebd0e92d7be 100644
--- a/addons/point_of_sale/tests/__init__.py
+++ b/addons/point_of_sale/tests/__init__.py
@@ -10,17 +10,15 @@
from . import test_pos_invoice_consolidation
from . import test_pos_cash_rounding
from . import test_pos_setup
-from . import test_pos_simple_orders
-from . import test_pos_simple_invoiced_orders
from . import test_pos_basic_config
from . import test_pos_products_with_tax
from . import test_pos_margin
-from . import test_pos_multiple_receivable_accounts
from . import test_pos_other_currency_config
-from . import test_pos_with_fiscal_position
from . import test_report_pos_order
from . import test_report_session
from . import test_res_config_settings
from . import test_pos_product_variants
from . import test_generic_localization
from . import test_order_receipt
+from . import test_pos_accounting
+from . import test_pos_accounting_http
diff --git a/addons/point_of_sale/tests/common.py b/addons/point_of_sale/tests/common.py
index 0b5907cf7a4a87..f44031946ffe02 100644
--- a/addons/point_of_sale/tests/common.py
+++ b/addons/point_of_sale/tests/common.py
@@ -59,7 +59,6 @@ def create_pos_configs(self):
self.pos_config_usd = self.env['pos.config'].create({
'name': 'PoS Config USD',
'journal_id': self.company_data['default_journal_sale'].id,
- 'invoice_journal_id': self.company_data['default_journal_sale'].id,
'payment_method_ids': [
(4, self.credit_payment_method.id),
(4, self.bank_payment_method.id),
@@ -118,18 +117,20 @@ def create_account_cash_rounding(self):
def create_payment_methods(self):
self.cash_payment_method = self.env['pos.payment.method'].create({
'name': 'Cash',
+ 'type': 'cash',
'receivable_account_id': self.company_data['default_account_receivable'].id,
'journal_id': self.company_data['default_journal_cash'].id,
})
self.bank_payment_method = self.env['pos.payment.method'].create({
'name': 'Bank',
+ 'type': 'bank',
'journal_id': self.company_data['default_journal_bank'].id,
'receivable_account_id': self.company_data['default_account_receivable'].id,
})
self.credit_payment_method = self.env['pos.payment.method'].create({
'name': 'Credit',
'receivable_account_id': self.company_data['default_account_receivable'].id,
- 'split_transactions': True,
+ 'type': 'pay_later',
})
def create_pos_categories(self):
@@ -307,7 +308,7 @@ def create_backend_pos_order(self, data):
'amount_tax': 0,
'amount_return': 0,
'date_order': fields.Datetime.to_string(fields.Datetime.now()),
- 'company_id': self.env.company.id,
+ 'company_id': pos_config.company_id.id,
'session_id': pos_config.current_session_id.id,
'lines': [
Command.create({
@@ -409,7 +410,7 @@ def setUpClass(cls):
})
# Set Point of Sale configurations
# basic_config
- # - derived from 'point_of_sale.pos_config_main' with added invoice_journal_id and credit payment method.
+ # - derived from 'point_of_sale.pos_config_main' with added journal_id and credit payment method.
# other_currency_config
# - pos.config set to have currency different from company currency.
cls.basic_config = cls._create_basic_config()
@@ -448,7 +449,7 @@ def setUpClass(cls):
def _create_basic_config(cls):
config = cls.env['pos.config'].create({
'name': 'PoS Shop Test',
- 'invoice_journal_id': cls.invoice_journal.id,
+ 'journal_id': cls.invoice_journal.id,
'available_pricelist_ids': cls.currency_pricelist.ids,
'pricelist_id': cls.currency_pricelist.id,
})
@@ -459,32 +460,24 @@ def _create_basic_config(cls):
else:
cls.cash_pm1 = cls.env['pos.payment.method'].create({
'name': 'Cash',
+ 'type': 'cash',
'journal_id': cls.company_data['default_journal_cash'].id,
'receivable_account_id': cls.pos_receivable_cash.id,
'company_id': cls.env.company.id,
})
cls.bank_pm1 = cls.env['pos.payment.method'].create({
'name': 'Bank',
+ 'type': 'bank',
'journal_id': cls.company_data['default_journal_bank'].id,
'receivable_account_id': cls.pos_receivable_bank.id,
'outstanding_account_id': cls.outstanding_bank.id,
'company_id': cls.env.company.id,
})
- cls.cash_split_pm1 = cls.cash_pm1.copy(default={
- 'name': 'Split (Cash) PM',
- 'split_transactions': True,
- 'journal_id': cls.env['account.journal'].create({
- 'name': "Cash",
- 'code': "CSH %s" % config.id,
- 'type': 'cash',
- }).id
- })
cls.bank_split_pm1 = cls.bank_pm1.copy(default={
'name': 'Split (Bank) PM',
- 'split_transactions': True,
})
- cls.pay_later_pm = cls.env['pos.payment.method'].create({'name': 'Pay Later', 'split_transactions': True})
- config.write({'payment_method_ids': [(4, cls.cash_split_pm1.id), (4, cls.bank_split_pm1.id), (4, cls.cash_pm1.id), (4, cls.bank_pm1.id), (4, cls.pay_later_pm.id)]})
+ cls.pay_later_pm = cls.env['pos.payment.method'].create({'name': 'Pay Later', 'type': 'pay_later'})
+ config.write({'payment_method_ids': [(4, cls.bank_split_pm1.id), (4, cls.cash_pm1.id), (4, cls.bank_pm1.id), (4, cls.pay_later_pm.id)]})
return config
@classmethod
@@ -503,14 +496,6 @@ def _create_other_currency_config(cls):
'sequence': 10,
'currency_id': cls.other_currency.id
})
- other_invoice_journal = cls.env['account.journal'].create({
- 'name': 'Customer Invoice Other',
- 'type': 'sale',
- 'company_id': cls.company.id,
- 'code': 'INVO',
- 'sequence': 11,
- 'currency_id': cls.other_currency.id
- })
other_sales_journal = cls.env['account.journal'].create({
'name':'PoS Sale Other',
'type': 'sale',
@@ -533,11 +518,13 @@ def _create_other_currency_config(cls):
})
cls.cash_pm2 = cls.env['pos.payment.method'].create({
'name': 'Cash Other',
+ 'type': 'cash',
'journal_id': other_cash_journal.id,
'receivable_account_id': cls.pos_receivable_cash.id,
})
cls.bank_pm2 = cls.env['pos.payment.method'].create({
'name': 'Bank Other',
+ 'type': 'bank',
'journal_id': other_bank_journal.id,
'receivable_account_id': cls.pos_receivable_bank.id,
'outstanding_account_id': cls.outstanding_bank.id,
@@ -545,7 +532,6 @@ def _create_other_currency_config(cls):
config = cls.env['pos.config'].create({
'name': 'Shop Other',
- 'invoice_journal_id': other_invoice_journal.id,
'journal_id': other_sales_journal.id,
'use_pricelist': True,
'available_pricelist_ids': other_pricelist.ids,
@@ -712,19 +698,19 @@ def create_order_line(product, quantity, **kwargs):
tax_ids.compute_all(price_unit_after_discount, self.currency, quantity)
if tax_ids
else {
- 'total_excluded': price_unit * quantity,
- 'total_included': price_unit * quantity,
+ 'total_excluded': price_unit_after_discount * quantity,
+ 'total_included': price_unit_after_discount * quantity,
}
)
return (0, 0, {
'id': randint(1, 1000000),
'price_unit': price_unit,
'product_id': product.id,
- 'price_subtotal': tax_values['total_excluded'],
- 'price_subtotal_incl': tax_values['total_included'],
+ 'price_subtotal': abs(tax_values['total_excluded']), # Must never be negative, qty is used to determine the sign of the amounts
+ 'price_subtotal_incl': abs(tax_values['total_included']), # Must never be negative, qty is used to determine the sign of the amounts
'qty': quantity,
'tax_ids': [(6, 0, tax_ids.ids)],
- **kwargs
+ **kwargs,
})
def create_payment(payment_method, amount):
@@ -743,9 +729,17 @@ def create_payment(payment_method, amount):
]
# 2. generate the payments
- total_amount_incl = sum(line[2]['price_subtotal_incl'] for line in order_lines)
+ total_amount_incl = 0
+ total_amount_base = 0
+ for line in order_lines:
+ line_sign = 1 if line[2]['qty'] >= 0 else -1
+ line_price = line[2]['price_subtotal_incl'] * line_sign
+ base_price = line[2]['price_subtotal'] * line_sign
+
+ total_amount_incl += line_price
+ total_amount_base += base_price
if payments is None:
- default_cash_pm = self.config.payment_method_ids.filtered(lambda pm: pm.is_cash_count and not pm.split_transactions)[:1]
+ default_cash_pm = self.config.payment_method_ids.filtered(lambda pm: pm.type == 'cash')[:1]
if not default_cash_pm:
raise Exception('There should be a cash payment method set in the pos.config.')
payments = [create_payment(default_cash_pm, total_amount_incl)]
@@ -756,7 +750,6 @@ def create_payment(payment_method, amount):
]
# 3. complete the fields of the order_data
- total_amount_base = sum(line[2]['price_subtotal'] for line in order_lines)
return {
'amount_paid': sum(payment[2]['amount'] for payment in payments),
'amount_return': 0,
@@ -827,10 +820,9 @@ def _run_test(self, args):
_logger.info('DONE: Call of before_closing_cb.')
self._check_invoice_journal_entries(pos_session, orders_map, expected_values=args['journal_entries_before_closing'])
_logger.info('DONE: Checks for journal entries before closing the session.')
- cash_payment_method = pos_session.payment_method_ids.filtered('is_cash_count')[:1]
+ cash_payment_method = pos_session.payment_method_ids.filtered(lambda pm: pm.type == 'cash')[:1]
total_cash_payment = sum(pos_session.mapped('order_ids.payment_ids').filtered(lambda payment: payment.payment_method_id.id == cash_payment_method.id).mapped('amount'))
- pos_session.post_closing_cash_details(total_cash_payment)
- pos_session.close_session_from_ui()
+ pos_session.close_session_from_ui({cash_payment_method.id: total_cash_payment})
after_closing_cb = args.get('after_closing_cb')
if after_closing_cb:
after_closing_cb()
@@ -859,7 +851,7 @@ def _check_invoice_journal_entries(self, pos_session, orders_map, expected_value
for uid in orders_map:
order = orders_map[uid]
- if not order.is_invoiced:
+ if not order.is_singly_invoiced:
continue
invoice = order.account_move
# allow not checking the invoice since pos is not creating the invoices
@@ -890,23 +882,16 @@ def _check_session_journal_entries(self, pos_session, expected_values):
currency_rounding = pos_session.currency_id.rounding
# check expected session journal entry
- self._assert_account_move(pos_session.move_id, expected_values['session_journal_entry'])
+ self._assert_account_move(pos_session.sales_move_id, expected_values['session_journal_entry'])
_logger.info("DONE: Check of the session's account move.")
# check expected cash journal entries
- for statement_line in pos_session.statement_line_ids:
+ for statement_line in pos_session.bank_statement_line_ids:
def statement_line_predicate(args):
return tools.float_is_zero(statement_line.amount - args[0], precision_rounding=currency_rounding)
self._find_then_assert_values(statement_line.move_id, expected_values['cash_statement'], statement_line_predicate)
_logger.info("DONE: Check of cash statement lines.")
- # check expected bank payments
- for bank_payment in pos_session.bank_payment_ids:
- def bank_payment_predicate(args):
- return tools.float_is_zero(bank_payment.amount - args[0], precision_rounding=currency_rounding)
- self._find_then_assert_values(bank_payment.move_id, expected_values['bank_payments'], bank_payment_predicate)
- _logger.info("DONE: Check of bank account payments.")
-
def _find_then_assert_values(self, account_move, source_of_expected_vals, predicate):
expected_move_vals = next(move_vals for args, move_vals in source_of_expected_vals if predicate(args))
self._assert_account_move(account_move, expected_move_vals)
diff --git a/addons/point_of_sale/tests/test_backend.py b/addons/point_of_sale/tests/test_backend.py
index 435c08bbf2e19e..6a78984344c11f 100644
--- a/addons/point_of_sale/tests/test_backend.py
+++ b/addons/point_of_sale/tests/test_backend.py
@@ -10,7 +10,7 @@
class TestBackend(TestPoSCommon):
def test_onchange_payment_provider(self):
- pm = self.env['pos.payment.method'].create({'name': 'Test PM'})
+ pm = self.env['pos.payment.method'].create({'name': 'Test PM', 'type': 'bank'})
with patch.object(PosPaymentMethod, '_get_terminal_provider_selection', return_value=[('terminal_1', 'Terminal 1'), ('terminal_2', 'Terminal 2')]), \
patch.object(PosPaymentMethod, '_get_external_qr_provider_selection', return_value=[('qr_1', 'QR Code 1'), ('qr_2', 'QR Code 2')]), \
patch.object(PosPaymentMethod, '_get_cash_machine_selection', return_value=[('cash_1', 'Cash Machine 1'), ('cash_2', 'Cash Machine 2')]):
@@ -65,7 +65,7 @@ def test_onchange_payment_provider(self):
self.assertEqual(pm.payment_method_type, 'cash_machine')
def test_onchange_payment_method_type(self):
- pm = self.env['pos.payment.method'].create({'name': 'Test PM'})
+ pm = self.env['pos.payment.method'].create({'name': 'Test PM', 'type': 'bank'})
with patch.object(PosPaymentMethod, '_get_terminal_provider_selection', return_value=[('terminal_1', 'Terminal 1'), ('terminal_2', 'Terminal 2')]), \
patch.object(PosPaymentMethod, '_get_external_qr_provider_selection', return_value=[('qr_1', 'QR Code 1'), ('qr_2', 'QR Code 2')]), \
patch.object(PosPaymentMethod, '_get_cash_machine_selection', return_value=[('cash_1', 'Cash Machine 1'), ('cash_2', 'Cash Machine 2')]):
diff --git a/addons/point_of_sale/tests/test_frontend.py b/addons/point_of_sale/tests/test_frontend.py
index cc358fa025a4fe..089a4539e0964a 100644
--- a/addons/point_of_sale/tests/test_frontend.py
+++ b/addons/point_of_sale/tests/test_frontend.py
@@ -56,8 +56,13 @@ def with_new_session(self, config=None, user=None):
config.with_user(user).open_ui()
session = config.current_session_id
yield session
- session.post_closing_cash_details(0)
- session.close_session_from_ui()
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ cash_pm = self.main_pos_config._get_cash_payment_method()
+ session.close_session_from_ui({
+ cash_pm.id: expected_cashbox_amount,
+ })
@classmethod
def setUpClass(cls):
@@ -115,6 +120,7 @@ def setUpClass(cls):
cls.bank_payment_method = env['pos.payment.method'].create({
'name': 'Bank',
+ 'type': 'bank',
'journal_id': cls.bank_journal.id,
'outstanding_account_id': cls.inbound_payment_method_line.payment_account_id.id,
})
@@ -579,8 +585,8 @@ def setUpClass(cls):
'tax_regime_selection': True,
'fiscal_position_ids': FP_POS_2M,
'journal_id': test_sale_journal.id,
- 'invoice_journal_id': test_sale_journal.id,
'payment_method_ids': [(0, 0, { 'name': 'Cash',
+ 'type': 'cash',
'journal_id': cash_journal.id,
'receivable_account_id': cls.account_receivable.id,
})],
@@ -776,67 +782,12 @@ def test_product_information_screen_admin(self):
self.main_pos_config.with_user(self.pos_admin).open_ui()
self.start_tour("/pos/ui/%d" % self.main_pos_config.id, 'CheckProductInformation', login="pos_admin")
- def test_fixed_tax_negative_qty(self):
- """ Assert the negative amount of a negative-quantity orderline
- with zero-amount product with fixed tax.
- """
-
- # setup the zero-amount product
- tax_received_account = self.env['account.account'].create({
- 'name': 'TAX_BASE',
- 'code': 'TBASE',
- 'account_type': 'asset_current',
- })
- fixed_tax = self.env['account.tax'].create({
- 'name': 'fixed amount tax',
- 'amount_type': 'fixed',
- 'amount': 1,
- 'invoice_repartition_line_ids': [
- (0, 0, {'repartition_type': 'base'}),
- (0, 0, {
- 'repartition_type': 'tax',
- 'account_id': tax_received_account.id,
- }),
- ],
- 'price_include_override': 'tax_excluded',
- })
- zero_amount_product = self.env['product.product'].create({
- 'name': 'Zero Amount Product',
- 'available_in_pos': True,
- 'list_price': 0,
- 'taxes_id': [(6, 0, [fixed_tax.id])],
- 'categ_id': self.env.ref('product.product_category_services').id,
- })
-
- # Make an order with the zero-amount product from the frontend.
- # We need to do this because of the fix in the "compute_all" port.
- self.main_pos_config.write({'iface_tax_included': 'total'})
- self.main_pos_config.with_user(self.pos_user).open_ui()
- self.start_tour("/pos/ui/%d" % self.main_pos_config.id, 'FixedTaxNegativeQty', login="pos_user")
- pos_session = self.main_pos_config.current_session_id
-
- # Close the session and check the session journal entry.
- pos_session.action_pos_session_validate()
-
- lines = pos_session.move_id.line_ids.sorted('balance')
-
- # order in the tour is paid using the bank payment method.
- bank_pm = self.main_pos_config.payment_method_ids.filtered(lambda pm: pm.name == 'Bank')
-
- self.assertEqual(lines[0].account_id, bank_pm.receivable_account_id or self.env.company.account_default_pos_receivable_account_id)
- self.assertAlmostEqual(lines[0].balance, -1)
- self.assertEqual(lines[1].account_id, self.env.company.income_account_id)
- self.assertAlmostEqual(lines[1].balance, 0)
- self.assertEqual(lines[2].account_id, tax_received_account)
- self.assertAlmostEqual(lines[2].balance, 1)
-
def test_change_without_cash_method(self):
#create bank payment method
bank_pm = self.env['pos.payment.method'].create({
'name': 'Bank',
'receivable_account_id': self.env.company.account_default_pos_receivable_account_id.id,
- 'is_cash_count': False,
- 'split_transactions': False,
+ 'type': 'bank',
'company_id': self.env.company.id,
})
self.main_pos_config.write({'payment_method_ids': [(6, 0, bank_pm.ids)]})
@@ -891,26 +842,6 @@ def test_rounding_down(self):
self.env["pos.order"].search([('state', '=', 'draft')]).write({'state': 'cancel'})
self.start_tour("/pos/ui/%d" % self.main_pos_config.id, 'PaymentScreenTotalDueWithOverPayment', login="pos_user")
- def test_pos_closing_cash_details(self):
- """Test cash difference *loss* at closing.
- """
- self.main_pos_config.open_ui()
- current_session = self.main_pos_config.current_session_id
- current_session.post_closing_cash_details(0)
- current_session.close_session_from_ui()
- self.main_pos_config.with_user(self.pos_user).open_ui()
- self.start_tour("/pos/ui/%d" % self.main_pos_config.id, 'CashClosingDetails', login="pos_user")
- self.assertEqual(self.main_pos_config.last_session_closing_cash, 50.0)
- cash_diff_line = self.env['account.bank.statement.line'].search([
- ('payment_ref', 'ilike', 'Cash difference observed during the counting (Loss)')
- ])
- self.assertAlmostEqual(cash_diff_line.amount, -1.00)
-
- def test_cash_payments_should_reflect_on_next_opening(self):
- self.main_pos_config.with_user(self.pos_user).open_ui()
- self.start_tour("/pos/ui/%d" % self.main_pos_config.id, 'OrderPaidInCash', login="pos_user")
- self.assertEqual(self.main_pos_config.last_session_closing_cash, 25.0)
-
def test_pos_session_statistics_display(self):
"""Test that POS session statistics are properly displayed in the UI."""
# For testing `opening_cash` and `paid_orders` in dashboard
@@ -1776,11 +1707,14 @@ def test_refund_multiple_products_amounts_compliance(self):
refund_order = current_session.order_ids.filtered(lambda order: order.is_refund)
self.assertEqual(refund_order.lines[0].price_subtotal, 2 * test_product.list_price)
- total_cash_payment = sum(current_session.mapped('order_ids.payment_ids').filtered(
- lambda payment: payment.payment_method_id.type == 'cash').mapped('amount')
- )
- current_session.post_closing_cash_details(total_cash_payment)
- current_session.close_session_from_ui()
+ closing_data = current_session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ cash_pm = self.main_pos_config._get_cash_payment_method()
+ current_session.close_session_from_ui({
+ cash_pm.id: expected_cashbox_amount,
+ })
+
self.assertEqual(current_session.state, 'closed')
report_refund_order, report_order = self.env['report.pos.order'].sudo().search([('order_id', 'in', current_session.order_ids.ids)])
self.assertEqual(report_order.margin, 20.0)
@@ -2200,10 +2134,10 @@ def test_pricelist_multi_items_different_qty_thresholds(self):
def test_tracking_number_closing_session(self):
self.main_pos_config.with_user(self.pos_user).open_ui()
- self.start_tour(f"/pos/ui/{self.main_pos_config.id}", 'test_tracking_number_closing_session', login="pos_user")
+ self.start_tour(f"/pos/ui/{self.main_pos_config.id}", 'test_tracking_number_closing_session', login="accountman")
# Change should be given in cash
- cash_payment_method = self.main_pos_config.payment_method_ids.filtered(lambda p: p.is_cash_count)
+ cash_payment_method = self.main_pos_config.payment_method_ids.filtered(lambda p: p.type == 'cash')
last_order = self.main_pos_config.current_session_id.order_ids[-1]
self.assertRecordValues(last_order.payment_ids.sorted(), [
{'amount': -18.02, 'payment_method_id': cash_payment_method.id, 'is_change': True},
@@ -2218,7 +2152,7 @@ def test_tracking_number_closing_session(self):
def test_reload_page_before_payment_with_customer_account(self):
self.customer_account_payment_method = self.env['pos.payment.method'].create({
'name': 'Customer Account',
- 'split_transactions': True,
+ 'type': 'pay_later',
})
self.main_pos_config.write({'payment_method_ids': [(6, 0, self.customer_account_payment_method.ids)]})
self.main_pos_config.with_user(self.pos_user).open_ui()
@@ -2242,8 +2176,8 @@ def test_cash_in_out(self):
self.main_pos_config.with_user(self.pos_user).open_ui()
self.start_tour(f"/pos/ui/{self.main_pos_config.id}", 'test_cash_in_out', login="pos_user")
- self.assertEqual(len(self.main_pos_config.current_session_id.statement_line_ids), 1, "There should be one cash in/out statement line")
- self.assertEqual(self.main_pos_config.current_session_id.statement_line_ids[0].amount, -5, "The cash in/out amount should be -5")
+ self.assertEqual(len(self.main_pos_config.current_session_id.bank_statement_line_ids), 1, "There should be one cash in/out statement line")
+ self.assertEqual(self.main_pos_config.current_session_id.bank_statement_line_ids[0].amount, -5, "The cash in/out amount should be -5")
def test_edit_paid_order(self):
self.main_pos_config.with_user(self.pos_user).open_ui()
@@ -2620,19 +2554,17 @@ def test_pos_ui_round_globally(self):
self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'test_pos_ui_round_globally', login="pos_user")
pos_session = self.main_pos_config.current_session_id
- self.assertEqual(pos_session.order_ids[0].payment_ids[0].amount, 7771.01)
+ self.assertEqual(pos_session.order_ids[0].payment_ids[0].amount, 7771.0)
# Close the session and check the session journal entry.
- pos_session.action_pos_session_validate()
+ pos_session.close_session_from_ui()
- lines = pos_session.move_id.line_ids.sorted('balance')
+ lines = pos_session.move_ids.line_ids.sorted('balance')
- self.assertEqual(len(lines), 5, "There should be 5 lines in the session journal entry")
- self.assertAlmostEqual(lines[0].balance, -7051.73)
- self.assertAlmostEqual(lines[1].balance, -1128.28)
- self.assertAlmostEqual(lines[2].balance, 56.41)
- self.assertAlmostEqual(lines[3].balance, 352.59)
- self.assertAlmostEqual(lines[4].balance, 7771.01)
+ self.assertEqual(len(lines), 3, "There should be 3 lines in the session journal entry")
+ self.assertAlmostEqual(lines[0].balance, -6699.14) # Negative line and positive are aggregated
+ self.assertAlmostEqual(lines[1].balance, -1071.86) # Negative line and positive are aggregated
+ self.assertAlmostEqual(lines[2].balance, 7771.0)
def test_ctrl_number_ignored(self):
self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'test_ctrl_number_ignored', login="pos_user")
@@ -3064,38 +2996,46 @@ def test_consistent_refund_process_between_frontend_and_backend(self):
# Fetch orders created in the current POS session
orders = self.env['pos.order'].search([
- ('session_id', '=', self.main_pos_config.current_session_id.id)
+ ('session_id', '=', self.main_pos_config.current_session_id.id),
])
self.assertEqual(len(orders), 2, "Expected two orders: original and refund.")
- original_order = next(o for o in orders if o.amount_total > 0)
- frontend_refund_order = next(o for o in orders if o.amount_total < 0)
+ refunded = orders.filtered(lambda o: o.is_refund)
+ order = orders - refunded
self.assertEqual(
- frontend_refund_order.pricelist_id.id,
- original_order.pricelist_id.id,
- "Refund order pricelist should be the original order's pricelist."
+ refunded.pricelist_id.id,
+ order.pricelist_id.id,
+ "Refund order pricelist should be the original order's pricelist.",
)
# Perform refund on order and retrieve the resulting draft refund order
- refund_action = original_order.refund()
- refund_order = self.env['pos.order'].browse(refund_action['res_id'])
+ refund_action = order.refund()
+ backend_refund_order = self.env['pos.order'].browse(refund_action['res_id'])
# Validate the refund order is in draft and has correct negative total
- self.assertEqual(refund_order.state, 'draft', "Refund order should be in draft state.")
- self.assertEqual(refund_order.amount_total, -4, "Refund order total should be -4.")
+ self.assertEqual(backend_refund_order.state, 'draft', "Refund order should be in draft state.")
# Create a payment for the refund using the configured bank method
payment_context = {
- "active_ids": refund_order.ids,
- "active_id": refund_order.id
+ "active_id": backend_refund_order.id,
}
refund_payment = self.env['pos.make.payment'].with_context(**payment_context).create({
- 'amount': refund_order.amount_total,
+ 'amount': backend_refund_order.amount_total,
'payment_method_id': self.bank_payment_method.id,
})
# Validate and finalize the refund payment
refund_payment.with_context(**payment_context).check()
- self.assertEqual(refund_order.state, 'paid', "Refund order should be marked as paid.")
+ self.assertEqual(backend_refund_order.state, 'paid', "Refund order should be marked as paid.")
+
+ # Lines are always positive even in refunds
+ self.assertTrue(backend_refund_order.lines.price_subtotal > 0)
+ self.assertTrue(refunded.lines.price_subtotal > 0)
+ self.assertTrue(backend_refund_order.lines.price_subtotal_incl > 0)
+ self.assertTrue(refunded.lines.price_subtotal_incl > 0)
+
+ # Refund order total should be negative (qty = -1)
+ self.assertTrue(backend_refund_order.amount_total < 0)
+ self.assertTrue(refunded.amount_total < 0)
def test_paid_order_with_archived_product_loads(self):
""" Test that a paid order with archived products can be loaded in the POS. """
@@ -3681,7 +3621,7 @@ def test_pos_snooze(self):
self.start_pos_tour('test_pos_snooze')
def test_set_opening_note_without_cash_method(self):
- cash_method = self.main_pos_config.payment_method_ids.filtered(lambda pm: pm.is_cash_count)
+ cash_method = self.main_pos_config.payment_method_ids.filtered(lambda pm: pm.type == 'cash')
self.main_pos_config.payment_method_ids -= cash_method
self.main_pos_config.with_user(self.pos_user).open_ui()
current_session = self.main_pos_config.current_session_id
@@ -3899,11 +3839,17 @@ def _close_pos_session(self):
draft_orders = session.order_ids.filtered(lambda o: o.state == 'draft')
if draft_orders:
draft_orders.action_pos_order_cancel()
- session.post_closing_cash_details(0)
- session.close_session_from_ui()
+ cash_pm = self.main_pos_config._get_cash_payment_method()
+ session.close_session_from_ui({
+ cash_pm.id: 0,
+ })
def assert_pos_orders_and_invoices(self, tour, tests_with_orders):
- self._close_pos_session()
+ if self.main_pos_config.current_session_id:
+ cash_pm = self.main_pos_config._get_cash_payment_method()
+ self.main_pos_config.current_session_id.close_session_from_ui({
+ cash_pm.id: 0,
+ })
self.start_pos_tour(tour)
orders = self.env['pos.order'].search([('session_id', '=', self.main_pos_config.current_session_id.id)], limit=len(tests_with_orders))
diff --git a/addons/point_of_sale/tests/test_point_of_sale_flow.py b/addons/point_of_sale/tests/test_point_of_sale_flow.py
index d8dfe01bb1907a..bc26d5a82864cf 100644
--- a/addons/point_of_sale/tests/test_point_of_sale_flow.py
+++ b/addons/point_of_sale/tests/test_point_of_sale_flow.py
@@ -1,13 +1,11 @@
import odoo
-from freezegun import freeze_time
from unittest.mock import patch
from odoo import fields
from odoo.fields import Command
-from odoo.tests import Form
from datetime import datetime, timedelta
from odoo.addons.point_of_sale.tests.common import CommonPosTest
-from odoo.exceptions import ValidationError, UserError
+from odoo.exceptions import ValidationError
@odoo.tests.tagged('post_install', '-at_install')
@@ -54,17 +52,18 @@ def test_order_refund(self):
self.assertAlmostEqual(order.amount_total, order.amount_paid)
self.assertEqual(refund.state, 'paid', "The refund is not marked as paid")
- self.assertTrue(refund.payment_ids.payment_method_id.is_cash_count)
+ self.assertTrue(refund.payment_ids.payment_method_id.type == 'cash')
# refund lines should be positive
self.assertEqual(refund.lines[0].price_subtotal_incl, 10.0)
self.assertEqual(refund.lines[1].price_subtotal_incl, 20.0)
current_session = self.pos_config_usd.current_session_id
- total_cash_payment = sum(current_session.mapped('order_ids.payment_ids').filtered(
- lambda payment: payment.payment_method_id.type == 'cash').mapped('amount')
- )
- current_session.post_closing_cash_details(total_cash_payment)
- current_session.close_session_from_ui()
+ closing_data = current_session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ current_session.close_session_from_ui({
+ self.cash_payment_method.id: expected_cashbox_amount,
+ })
self.assertEqual(current_session.state, 'closed')
def test_refund_multiple_payment_rounding(self):
@@ -101,102 +100,6 @@ def test_refund_multiple_payment_rounding(self):
self.assertEqual(refund.amount_paid, -10.0)
self.assertEqual(refund.state, 'paid')
- def test_order_partial_refund_rounding(self):
- """ This test ensures that the refund amound of a partial order corresponds to
- the price of the item, without rounding. """
- self.account_cash_rounding_down.rounding = 5.0
- self.pos_config_usd.write({
- 'rounding_method': self.account_cash_rounding_down.id,
- 'cash_rounding': True,
- })
-
- self.pos_config_usd.open_ui()
- current_session = self.pos_config_usd.current_session_id
-
- # order total will be 34.5 with 4.5 taxes excluded, with rounding 10 should be paid
- order, _ = self.create_backend_pos_order({
- 'line_data': [
- {'product_id': self.ten_dollars_with_15_excl.product_variant_id.id, 'qty': 3},
- ],
- 'payment_data': [
- {'payment_method_id': self.bank_payment_method.id, 'amount': 34.5},
- ],
- })
-
- self.assertEqual(order._get_rounded_amount(order.amount_total), order.amount_paid)
- refund_action = order.refund()
- refund = self.env['pos.order'].browse(refund_action['res_id'])
-
- with Form(refund) as refund_form:
- with refund_form.lines.edit(0) as line:
- line.qty = 1
- refund = refund_form.save()
-
- self.assertEqual(refund.amount_total, 10.0)
- payment_context = {"active_ids": refund.ids, "active_id": refund.id}
- refund_payment = self.env['pos.make.payment'].with_context(**payment_context).create({
- 'amount': refund.amount_total,
- 'payment_method_id': self.cash_payment_method.id,
- })
- refund_payment.with_context(**payment_context).check()
- self.assertEqual(refund.state, 'paid')
- current_session.action_pos_session_closing_control()
- self.assertEqual(current_session.state, 'closed')
-
- def test_order_partial_refund(self):
- """ The purpose of this test is to make a partial refund of a pos order.
- The amount to refund should depend on the article returned and once the
- payment made, the refund order should be marked as paid."""
- self.pos_config_usd.open_ui()
- current_session = self.pos_config_usd.current_session_id
-
- # order total will be 30 with 3.52 taxes included
- order, _ = self.create_backend_pos_order({
- 'line_data': [
- {'product_id': self.ten_dollars_with_10_incl.product_variant_id.id},
- {'product_id': self.twenty_dollars_with_15_incl.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': self.cash_payment_method.id, 'amount': 10},
- {'payment_method_id': self.bank_payment_method.id, 'amount': 20},
- ]
- })
-
- refund_action = order.refund()
- refund = self.env['pos.order'].browse(refund_action['res_id'])
-
- with Form(refund) as refund_form:
- with refund_form.lines.edit(0) as line:
- line.qty = 0
- refund = refund_form.save()
-
- self.assertEqual(refund.amount_total, -20.0)
-
- payment_context = {"active_ids": refund.ids, "active_id": refund.id}
- refund_payment = self.env['pos.make.payment'].with_context(**payment_context).create({
- 'amount': refund.amount_total,
- 'payment_method_id': self.cash_payment_method.id,
- })
- refund_payment.with_context(**payment_context).check()
-
- self.assertEqual(refund.state, 'paid')
-
- refund_action = order.refund()
- remaining_refund = self.env['pos.order'].browse(refund_action['res_id'])
- self.assertEqual(remaining_refund.amount_total, -10.0)
-
- payment_context = {"active_ids": remaining_refund.ids, "active_id": remaining_refund.id}
- refund_payment = self.env['pos.make.payment'].with_context(**payment_context).create({
- 'amount': remaining_refund.amount_total,
- 'payment_method_id': self.cash_payment_method.id,
- })
- refund_payment.with_context(**payment_context).check()
-
- self.assertEqual(remaining_refund.state, 'paid')
-
- current_session.action_pos_session_closing_control()
- self.assertEqual(current_session.state, 'closed')
-
def test_pos_orders_count(self):
parent_partner = self.env['res.partner'].create({
'name': 'Parent Partner',
@@ -232,59 +135,6 @@ def test_pos_orders_count(self):
self.assertEqual(parent_partner.pos_order_count, 2, "Parent partner should see 2 orders including child’s")
self.assertEqual(child_partner.pos_order_count, 1, "Child partner should see only their own order")
- def test_order_to_payment_currency(self):
- """
- In order to test the Point of Sale in module, I will do a full flow
- from the sale to the payment and invoicing. I will use two products,
- one with price including a 10% tax, the other one with 5% tax
- excluded from the price.
-
- The order will be in a different currency than the company currency.
- """
- self.env.cr.execute(
- "UPDATE res_company SET currency_id = %s WHERE id = %s",
- [self.env.ref('base.USD').id, self.env.company.id])
-
- # Demo data are crappy, clean-up the rates
- self.env['res.currency.rate'].search([]).unlink()
- self.env['res.currency.rate'].create({
- 'name': '2010-01-01',
- 'rate': 2.0,
- 'currency_id': self.env.ref('base.EUR').id,
- })
-
- order, _ = self.create_backend_pos_order({
- 'order_data': {
- 'partner_id': self.partner_mobt.id,
- 'pricelist_id': self.partner_mobt.property_product_pricelist.id,
- },
- 'line_data': [
- {'product_id': self.ten_dollars_no_tax.product_variant_id.id},
- {'product_id': self.twenty_dollars_no_tax.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': self.bank_payment_method.id, 'amount': 10},
- {'payment_method_id': self.bank_payment_method.id},
- ],
- 'pos_config': self.pos_config_eur,
- })
-
- self.assertEqual(order.amount_total, 30)
- self.assertEqual(order.amount_paid, 30)
- self.assertEqual(order.state, 'paid')
- current_session = self.pos_config_eur.current_session_id
- current_session.action_pos_session_validate()
- self.assertTrue(current_session.move_id)
- debit_lines = current_session.move_id.mapped('line_ids.debit')
- credit_lines = current_session.move_id.mapped('line_ids.credit')
- amount_currency_lines = current_session.move_id.mapped('line_ids.amount_currency')
- for a, b in zip(sorted(debit_lines), [0.0, 15.0]):
- self.assertAlmostEqual(a, b)
- for a, b in zip(sorted(credit_lines), [0.0, 15.0]):
- self.assertAlmostEqual(a, b)
- for a, b in zip(sorted(amount_currency_lines), [-30, 30]):
- self.assertAlmostEqual(a, b)
-
def test_order_to_invoice_no_tax(self):
order, _ = self.create_backend_pos_order({
'order_data': {
@@ -328,46 +178,11 @@ def test_order_to_invoice_no_tax(self):
self.pos_config_usd.current_session_id.action_pos_session_closing_control()
- def test_order_with_deleted_tax(self):
- order, _ = self.create_backend_pos_order({
- 'line_data': [
- {'product_id': self.ten_dollars_with_10_excl.product_variant_id.id},
- ],
- })
-
- untax, atax = self.compute_tax(self.ten_dollars_with_10_excl.product_variant_id, 10.0)
- self.ten_dollars_with_10_excl.taxes_id.active = False
- current_session = self.pos_config_usd.current_session_id
- payment = self.env['pos.make.payment'].create({
- 'config_id': self.pos_config_usd.id,
- 'amount': untax + atax,
- 'payment_method_id': self.cash_payment_method.id,
- })
- payment.with_context(active_ids=order.ids, active_id=order.id).check()
- self.assertEqual(order.state, 'paid', "Order should be in paid state.")
-
- total_cash_payment = sum(current_session.mapped('order_ids.payment_ids').filtered(
- lambda payment: payment.payment_method_id.type == 'cash').mapped('amount'))
- current_session.post_closing_cash_details(total_cash_payment)
-
- # close session (should not fail here)
- # We don't call `action_pos_session_closing_control` to force the failed
- # closing which will return the action because the internal rollback call messes
- # with the rollback of the test runner. So instead, we directly call the method
- # that returns the action by specifying the imbalance amount.
- action = current_session._close_session_action(1.0)
- wizard = self.env['pos.close.session.wizard'].browse(action['res_id'])
- wizard.with_context(action['context']).close_session()
-
- diff_line = current_session.move_id.line_ids.filtered(
- lambda line: line.name == 'Difference at closing PoS session')
- self.assertAlmostEqual(diff_line.credit, 1.0, msg="Missing amount of 1.0")
-
def test_pos_order_invoice_payment_term(self):
""" Test that when invoicing a POS order paid with customer account, the partner's payment term is then applied to the invoice. """
self.customer_account_payment_method = self.env['pos.payment.method'].create({
'name': 'Customer Account',
- 'split_transactions': True,
+ 'type': 'pay_later',
})
payment_methods = self.pos_config_usd.payment_method_ids | self.customer_account_payment_method
self.pos_config_usd.write({'payment_method_ids': [Command.set(payment_methods.ids)]})
@@ -436,191 +251,6 @@ def test_order_with_different_payments_and_refund(self):
})
self.assertEqual(order.account_move.amount_residual, 20)
- def test_sale_order_postponed_invoicing(self):
- """
- Test the flow of creating an invoice later, after the POS session
- has been closed and everything has been processed. Process should:
- - Create a new misc entry, that will revert part of the POS
- closing entry.
- - Create the move and associating payment(s) entry, as it would
- do when closing with invoice.
- - Reconcile the receivable lines from the created misc entry
- with the ones from the created payment(s)
- """
- tags = self.setup_tags()
- with freeze_time('2020-01-01'):
- order, _ = self.create_backend_pos_order({
- 'line_data': [
- {'product_id': self.twenty_dollars_with_15_excl.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': self.bank_payment_method.id, 'amount': 23.0},
- ],
- })
- self.pos_config_usd.current_session_id.action_pos_session_closing_control()
-
- # Check the closing entry.
- closing_entry = order.session_move_id
- self.assertRecordValues(closing_entry.line_ids.sorted(), [{
- 'balance': -3.0,
- 'account_id': self.company_data['default_account_tax_sale'].id,
- 'tax_ids': [],
- 'tax_tag_ids': tags[1].ids,
- 'reconciled': False
- }, {
- 'balance': -20.0,
- 'account_id': self.company_data['default_account_revenue'].id,
- 'tax_ids': self.tax_sale_a.ids,
- 'tax_tag_ids': tags[0].ids,
- 'reconciled': False
- }, {
- 'balance': 23.0,
- 'account_id': self.company_data['default_account_receivable'].id,
- 'tax_ids': [],
- 'tax_tag_ids': [],
- 'reconciled': True
- }])
-
- with freeze_time('2020-01-03'):
- order.partner_id = self.partner_adgu.id
- order.action_pos_order_invoice()
-
- # Check the reverse moves, one for the closing entry, one for the statement lines.
- reverse_closing_entries = self.env['account.move'].search([
- ('id', '!=', closing_entry.id),
- ('company_id', '=', self.env.company.id),
- ('statement_line_id', '=', False),
- ('move_type', '=', 'entry'),
- ('state', '=', 'posted'),
- ])
- self.assertRecordValues(reverse_closing_entries[0].line_ids.sorted(), [{
- 'balance': 3.0,
- 'account_id': self.company_data['default_account_tax_sale'].id,
- 'tax_ids': [],
- 'tax_tag_ids': tags[1].ids,
- 'reconciled': False
- }, {
- 'balance': 20.0,
- 'account_id': self.company_data['default_account_revenue'].id,
- 'tax_ids': self.tax_sale_a.ids,
- 'tax_tag_ids': tags[0].ids,
- 'reconciled': False
- }, {
- 'balance': -23.0,
- 'account_id': self.company_data['default_account_receivable'].id,
- 'tax_ids': [],
- 'tax_tag_ids': [],
- 'reconciled': True
- }])
- self.assertRecordValues(reverse_closing_entries[2].line_ids.sorted(), [{
- 'balance': -23.0,
- 'account_id': self.company_data['default_account_receivable'].id,
- 'tax_ids': [],
- 'tax_tag_ids': [],
- 'reconciled': True
- }, {
- 'balance': 23.0,
- 'account_id': self.company_data['default_account_receivable'].id,
- 'tax_ids': [],
- 'tax_tag_ids': [],
- 'reconciled': True
- }])
-
- def test_sale_order_postponed_invoicing_storno(self):
- """
- Test the flow of creating an invoice later, after the POS session
- has been closed and everything has been processed. Process should:
- - Create a new misc entry, that will revert part of the POS
- closing entry.
- - Create the move and associating payment(s) entry, as it would
- do when closing with invoice.
- - Reconcile the receivable lines from the created misc entry
- with the ones from the created payment(s)
- This test is the same as test_sale_order_postponed_invoicing but
- with the storno feature enabled.
- """
- self.env.company.account_storno = True
-
- tags = self.setup_tags()
- with freeze_time('2020-01-01'):
- order, _ = self.create_backend_pos_order({
- 'line_data': [
- {'product_id': self.twenty_dollars_with_15_excl.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': self.bank_payment_method.id, 'amount': 23.0},
- ],
- })
- self.pos_config_usd.current_session_id.action_pos_session_closing_control()
-
- # Check the closing entry.
- closing_entry = order.session_move_id
- self.assertRecordValues(closing_entry.line_ids.sorted(), [{
- 'balance': -3.0,
- 'debit': 0.0,
- 'credit': 3.0,
- 'account_id': self.company_data['default_account_tax_sale'].id,
- 'tax_ids': [],
- 'tax_tag_ids': tags[1].ids,
- 'reconciled': False,
- }, {
- 'balance': -20.0,
- 'debit': 0.0,
- 'credit': 20.0,
- 'account_id': self.company_data['default_account_revenue'].id,
- 'tax_ids': self.tax_sale_a.ids,
- 'tax_tag_ids': tags[0].ids,
- 'reconciled': False,
- }, {
- 'balance': 23.0,
- 'debit': 23.0,
- 'credit': 0.0,
- 'account_id': self.company_data['default_account_receivable'].id,
- 'tax_ids': [],
- 'tax_tag_ids': [],
- 'reconciled': True,
- }])
-
- with freeze_time('2020-01-03'):
- order.partner_id = self.partner_adgu.id
- order.action_pos_order_invoice()
-
- # Check the reverse moves, one for the closing entry, one for the statement lines.
- reverse_closing_entries = self.env['account.move'].search([
- ('id', '!=', closing_entry.id),
- ('company_id', '=', self.env.company.id),
- ('statement_line_id', '=', False),
- ('move_type', '=', 'entry'),
- ('state', '=', 'posted'),
- ])
- self.assertRecordValues(reverse_closing_entries[0].line_ids.sorted(), [{
- 'balance': 3.0,
- 'debit': 0.0,
- 'credit': -3.0,
- 'account_id': self.company_data['default_account_tax_sale'].id,
- 'tax_ids': [],
- 'tax_tag_ids': tags[1].ids,
- 'reconciled': False,
- }, {
- 'balance': 20.0,
- 'debit': 0.0,
- 'credit': -20.0,
- 'account_id': self.company_data['default_account_revenue'].id,
- 'tax_ids': self.tax_sale_a.ids,
- 'tax_tag_ids': tags[0].ids,
- 'reconciled': False,
- }, {
- 'balance': -23.0,
- 'debit': -23.0,
- 'credit': 0.0,
- 'account_id': self.company_data['default_account_receivable'].id,
- 'tax_ids': [],
- 'tax_tag_ids': [],
- 'reconciled': True,
- }])
- self.assertTrue(all(amount >= 0 for amount in reverse_closing_entries[1:].line_ids.mapped('debit') + reverse_closing_entries[1:].line_ids.mapped('credit')),
- "Non-reverse entries should have positive debit or credit amounts.")
-
def test_order_pos_tax_same_as_company(self):
"""
Test that when the default_pos_receivable_account and the partner
@@ -649,32 +279,6 @@ def test_order_pos_tax_same_as_company(self):
self.assertEqual(order.account_move.amount_residual, 0)
- def test_journal_entries_category_without_account(self):
- # Set company's default accounts to false
- self.env.company.income_account_id = False
- self.env.company.expense_account_id = False
- self.twenty_dollars_with_10_incl.write({
- 'property_account_income_id': False,
- 'property_account_expense_id': False,
- })
- account = self.env['account.account'].create({
- 'name': 'Account for category without account',
- 'code': 'X1111',
- })
-
- self.pos_config_usd.journal_id.default_account_id = account.id
- self.create_backend_pos_order({
- 'line_data': [
- {'product_id': self.twenty_dollars_with_10_incl.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': self.cash_payment_method.id, 'amount': 20},
- ],
- })
- current_session = self.pos_config_usd.current_session_id
- current_session.action_pos_session_closing_control()
- self.assertEqual(current_session.move_id.line_ids[0].account_id.id, account.id)
-
def test_order_refund_with_invoice(self):
"""This test make sure that credit notes of pos orders are correctly
linked to the original invoice."""
@@ -696,7 +300,7 @@ def test_order_refund_with_invoice(self):
]
})
- current_session.action_pos_session_closing_control()
+ current_session.close_session_from_ui()
invoices = self.env['account.move'].search([('move_type', '=', 'out_invoice')], order='id desc', limit=1)
credit_notes = self.env['account.move'].search([('move_type', '=', 'out_refund')], order='id desc', limit=1)
self.assertEqual(credit_notes.ref, "Reversal of: "+invoices.name)
@@ -744,44 +348,6 @@ def test_refund_rounding_backend(self):
self.assertEqual(refund.amount_paid, -25.0)
self.assertEqual(current_session.state, 'closed')
- def test_pos_branch_account(self):
- branch = self.env['res.company'].create({
- 'name': 'Sub Company',
- 'parent_id': self.env.company.id,
- 'chart_template': self.env.company.chart_template,
- 'country_id': self.env.company.country_id.id,
- })
- self.env.cr.precommit.run()
- self.env.user.group_ids += self.env.ref('point_of_sale.group_pos_manager')
- bank_payment_method = self.bank_payment_method.copy()
- bank_payment_method.company_id = branch.id
- sub_pos_config = self.env['pos.config'].with_company(branch).create({
- 'name': 'Main',
- 'journal_id': self.company_data['default_journal_sale'].id,
- 'invoice_journal_id': self.company_data['default_journal_sale'].id,
- 'payment_method_ids': [(4, bank_payment_method.id)],
- })
-
- sub_pos_config.open_ui()
- current_session = sub_pos_config.current_session_id
- self.create_backend_pos_order({
- 'order_data': {
- 'partner_id': self.partner_moda.id,
- 'pricelist_id': sub_pos_config.pricelist_id.id,
- },
- 'line_data': [
- {'product_id': self.ten_dollars_with_10_incl.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': bank_payment_method.id},
- ],
- 'pos_config': sub_pos_config,
- })
-
- current_session = sub_pos_config.current_session_id
- sub_pos_config.current_session_id.action_pos_session_closing_control()
- self.assertEqual(current_session.state, 'closed', msg='State of current session should be closed.')
-
def test_pos_branch_payment_method_config(self):
""" This test checks that we don't set a config on a payment
method that have different companies.
@@ -798,7 +364,6 @@ def test_pos_branch_payment_method_config(self):
sub_pos_config = self.env['pos.config'].with_company(branch).create({
'name': 'Main',
'journal_id': self.company_data['default_journal_sale'].id,
- 'invoice_journal_id': self.company_data['default_journal_sale'].id,
})
with self.assertRaises(ValidationError, msg="The points of sale for the payment method Bank must belong to its company."):
@@ -815,24 +380,13 @@ def test_pos_creation_in_branch(self):
"name": "Branch Point of Sale"
})
- def test_state_when_closing_register(self):
- self.create_backend_pos_order({
- 'line_data': [
- {'product_id': self.ten_dollars_with_10_incl.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': self.bank_payment_method.id, 'amount': 10},
- ],
- })
- current_session = self.pos_config_usd.current_session_id
- current_session.action_pos_session_closing_control(bank_payment_method_diffs={self.bank_payment_method.id: 5.00})
- self.assertEqual(current_session.state, 'closed')
-
def test_change_with_card_only(self):
"""Test that the change is not skipped if order was overpaid only with card"""
self.pos_config_usd.open_ui()
pos_session = self.pos_config_usd.current_session_id
- cash_payment_method = pos_session.payment_method_ids.filtered('is_cash_count')[:1]
+ cash_payment_method = pos_session.payment_method_ids.filtered(
+ lambda pm: pm.type == 'cash',
+ )[:1]
product_order = {
'amount_paid': 500,
'amount_return': -50,
@@ -874,12 +428,12 @@ def test_change_with_card_only(self):
order_account_move = pos_order.account_move
self.assertEqual(order_account_move.amount_total, pos_order.amount_total)
- account_moves = self.env['account.move'].search([('pos_payment_ids', 'in', pos_order.payment_ids.ids)])
- self.assertEqual(len(account_moves), 2)
- self.assertRecordValues(account_moves.sorted(), [
- {'amount_total': 50},
- {'amount_total': 500},
- ])
+ payment_term = order_account_move.line_ids.filtered(
+ lambda line: line.display_type == 'payment_term',
+ )
+ payment_amount = payment_term.mapped('amount_currency')
+ self.assertEqual(len(payment_term), 2)
+ self.assertEqual(payment_amount, [500.0, -50.0])
def test_refund_qty_refund_cancel(self):
"""
@@ -1047,114 +601,6 @@ def test_pos_order_partner_bank_id(self):
"Invoice should not use journal bank account when not allowed."
)
- def test_order_invoiced_after_session_closed(self):
- """Test that an order can be invoiced after its session is closed.
- Scenario:
- 1. Create a POS session and two orders:
- - Order A: Not to be invoiced immediately.
- - Order B: To be invoiced immediately.
- 2. Close the POS session.
- 3. Ensure:
- - Both orders have `reversed_move_ids` unset.
- 4. Assign a partner to Order A and invoice it AFTER the session is closed.
- - Confirm that `reversed_move_ids` is set accordingly.
- """
- order_data = {
- 'line_data': [
- {'product_id': self.ten_dollars_with_10_incl.product_variant_id.id},
- {'product_id': self.twenty_dollars_with_10_incl.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': self.bank_payment_method.id, 'amount': 30},
- ],
- }
-
- self.pos_config_usd.open_ui()
- current_session = self.pos_config_usd.current_session_id
-
- order_no_invoice, _ = self.create_backend_pos_order({**order_data, 'to_invoice': False, 'partner_id': False})
- order_invoiced_immediate, _ = self.create_backend_pos_order({**order_data, 'to_invoice': True, 'partner_id': self.partner.id})
-
- total_cash_payment = sum(
- current_session.mapped('order_ids.payment_ids')
- .filtered(lambda p: p.payment_method_id.type == 'cash')
- .mapped('amount')
- )
- current_session.post_closing_cash_details(total_cash_payment)
- current_session.close_session_from_ui()
-
- # Ensure the session is closed
- self.assertEqual(current_session.state, 'closed')
-
- # Initial state: no reversal moves for both orders
- self.assertFalse(order_no_invoice.reversed_move_ids,
- "Order with 'to_invoice' = False should have no reversal moves after session is closed.")
- self.assertFalse(order_invoiced_immediate.reversed_move_ids,
- "Immediate invoiced order should have no reversal moves after session is closed.")
-
- # Now, set a partner and invoice the order after the session is closed
- order_no_invoice.partner_id = self.partner
- order_no_invoice.action_pos_order_invoice()
-
- # Confirm that reversal move(s) are now set
- reversal_moves = self.env['account.move'].search([('reversed_pos_order_id', '=', order_no_invoice.id)])
- self.assertEqual(order_no_invoice.reversed_move_ids, reversal_moves,
- "Reversal move should be set for the order invoiced after the session is closed.")
-
- def test_payment_difference_accounting_items(self):
- """Verify that the amount of the accounting items are correct when closing a session with a payment difference."""
- self.product1 = self.env['product.product'].create({
- 'name': 'Test Product',
- 'lst_price': 100,
- })
- # Make a sale paid by bank
- self.pos_config_usd.open_ui()
- session_id = self.pos_config_usd.current_session_id
- order = self.env['pos.order'].create({
- 'company_id': self.env.company.id,
- 'session_id': session_id.id,
- 'partner_id': False,
- 'lines': [Command.create({
- 'name': 'OL/0001',
- 'product_id': self.product1.id,
- 'price_unit': 100.00,
- 'discount': 0,
- 'qty': 1,
- 'tax_ids': False,
- 'price_subtotal': 100.00,
- 'price_subtotal_incl': 100.00,
- })],
- 'pricelist_id': self.pos_config_usd.pricelist_id.id,
- 'amount_paid': 100.00,
- 'amount_total': 100.00,
- 'amount_tax': 0.0,
- 'amount_return': 0.0,
- 'to_invoice': False,
- })
-
- # Make payment
- payment_context = {"active_ids": order.ids, "active_id": order.id}
- order_payment = self.env['pos.make.payment'].with_context(**payment_context).create({
- 'amount': order.amount_total,
- 'payment_method_id': self.bank_payment_method.id
- })
- order_payment.with_context(**payment_context).check()
-
- session_id.action_pos_session_closing_control(bank_payment_method_diffs={self.bank_payment_method.id: -10.00})
- self.bank_payment_move = session_id._get_related_account_moves().filtered(lambda move: 'Combine Bank' in move.ref)
- self.assertRecordValues(self.bank_payment_move.line_ids.sorted('balance'), [{
- 'balance': -100.0,
- 'account_id': self.bank_payment_method.receivable_account_id.id,
- },
- {
- 'balance': 10.0,
- 'account_id': self.bank_payment_method.journal_id.loss_account_id.id,
- },
- {
- 'balance': 90.0,
- 'account_id': self.bank_payment_move.payment_ids.outstanding_account_id.id,
- }])
-
def test_invoice_rounding_overpaid_backend(self):
rouding_method = self.env['account.cash.rounding'].create({
'name': 'Rounding up',
@@ -1180,9 +626,9 @@ def test_invoice_rounding_overpaid_backend(self):
current_session = self.pos_config_usd.current_session_id
pos_order_data = {
- 'amount_paid': 149.99,
+ 'amount_paid': 150, # Should correspond to the total paid in payment_ids
'amount_tax': 0,
- 'amount_return': 0.01,
+ 'amount_return': 0, # Is computed by sync_from_ui
'amount_total': 149.99,
'date_order': fields.Datetime.to_string(fields.Datetime.now()),
'fiscal_position_id': False,
@@ -1214,9 +660,12 @@ def test_invoice_rounding_overpaid_backend(self):
}
self.env['pos.order'].sync_from_ui([pos_order_data])
- total_cash_payment = sum(current_session.mapped('order_ids.payment_ids').filtered(lambda payment: payment.payment_method_id.type == 'cash').mapped('amount'))
- current_session.post_closing_cash_details(total_cash_payment)
- current_session.close_session_from_ui()
+ closing_data = current_session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ current_session.close_session_from_ui({
+ self.cash_payment_method.id: expected_cashbox_amount,
+ })
pos_order = self.env['pos.order'].search([])
pos_order.action_pos_order_invoice()
@@ -1259,26 +708,6 @@ def test_search_paid_order_ids(self):
self.assertNotIn(paid_order_1.id, order_ids)
self.assertIn(paid_order_2.id, order_ids)
- def test_session_name_gap(self):
- self.pos_config_usd.open_ui()
- session = self.pos_config_usd.current_session_id
- session.set_opening_control(0, None)
- current_session_name = session.name
- session.action_pos_session_closing_control()
-
- self.pos_config_usd.open_ui()
- session = self.pos_config_usd.current_session_id
-
- def _post_cash_details_message_patch(*_args, **_kwargs):
- raise UserError('Test Error')
-
- with patch.object(self.env.registry.models['pos.session'], "_post_cash_details_message", _post_cash_details_message_patch):
- with self.assertRaises(UserError):
- session.set_opening_control(0, None)
-
- session.set_opening_control(0, None)
- self.assertEqual(int(session.name.split('/')[1]), int(current_session_name.split('/')[1]) + 1)
-
def test_open_ui_missing_country(self):
""" Test that a POS can not be opened if it has no country """
self.pos_config_usd.company_id.account_fiscal_country_id = False
@@ -1309,7 +738,7 @@ def test_branch_company_access_cost_currency_id(self):
'name': 'Main',
'company_id': branch.id,
})
- config.payment_method_ids.filtered(lambda pm: pm.is_cash_count).unlink()
+ config.payment_method_ids.filtered(lambda pm: pm.type == 'cash').unlink()
config.open_ui()
current_session = config.current_session_id
@@ -1374,56 +803,6 @@ def test_delete_res_partner_linked_to_pos_order(self):
with self.assertRaises(ValidationError, msg='You cannot delete a customer that has point of sales orders. You can archive it instead.'):
partner.unlink()
- def test_split_payment_linked_to_accounting_partner(self):
- self.bank_payment_method.write({'split_transactions': True})
- self.pos_config_usd.open_ui()
- current_session = self.pos_config_usd.current_session_id
-
- child_partner = self.env['res.partner'].create({
- 'name': 'partner1 child',
- 'parent_id': self.partner.id
- })
- product_order = {
- 'amount_paid': 750,
- 'amount_tax': 0,
- 'amount_return': 0,
- 'amount_total': 750,
- 'date_order': fields.Datetime.to_string(fields.Datetime.now()),
- 'fiscal_position_id': False,
- 'lines': [[0, 0, {
- 'discount': 0,
- 'price_unit': 750.0,
- 'product_id': self.product.id,
- 'price_subtotal': 750.0,
- 'price_subtotal_incl': 750.0,
- 'tax_ids': [[6, False, []]],
- 'qty': 1,
- }]],
- 'name': 'Order 12345-123-1234',
- 'partner_id': child_partner.id,
- 'session_id': current_session.id,
- 'sequence_number': 2,
- 'payment_ids': [[0, 0, {
- 'amount': 750,
- 'name': fields.Datetime.now(),
- 'payment_method_id': self.bank_payment_method.id
- }]],
- 'uuid': '12345-123-1234',
- 'user_id': self.env.uid,
- 'to_invoice': False}
-
- self.env['pos.order'].sync_from_ui([product_order])
- current_session.close_session_from_ui()
- order_balance = current_session.move_id.line_ids.filtered(
- lambda l: l.account_id.account_type == "asset_receivable"
- and l.partner_id == self.partner
- ).balance
- payment_balance = current_session.bank_payment_ids.move_id.line_ids.filtered(
- lambda l: l.account_id.account_type == "asset_receivable"
- and l.partner_id == self.partner
- ).balance
- self.assertEqual(order_balance + payment_balance, 0)
-
def test_draft_orders_products_loading(self):
""" Test that products are correctly loaded when limited product loading is enabled and there are draft orders. """
self.env['ir.config_parameter'].sudo().set_int('point_of_sale.limited_product_count', 1)
@@ -1514,40 +893,9 @@ def test_payment_method_sequence(self):
methods = self.env['pos.payment.method'].browse(pm_ids)[:3]
self.assertEqual(methods.mapped('name'), ['Cash', 'Card', 'Customer Account'])
self.assertEqual(methods.mapped('sequence'), [1, 2, 4])
- new_pm = self.env['pos.payment.method'].create({'name': 'Quick Pay'})
+ new_pm = self.env['pos.payment.method'].create({'name': 'Quick Pay', 'type': 'bank'})
self.assertEqual(new_pm.sequence, 5)
- def test_order_invoiced_customer_account_after_session_closed(self):
- """Test that an order paid via customer account can be invoiced after its session is closed.
- Then make sure that the reversal move is reconciled with the PoS session account move line so that only the invoice remains open.
- """
- order_data = {
- 'line_data': [
- {'product_id': self.twenty_dollars_with_10_incl.product_variant_id.id},
- ],
- 'payment_data': [
- {'payment_method_id': self.credit_payment_method.id, 'amount': 20},
- ],
- 'order_data': {
- 'partner_id': self.partner.id,
- },
- }
-
- self.pos_config_usd.open_ui()
- current_session = self.pos_config_usd.current_session_id
-
- order_no_invoice, _ = self.create_backend_pos_order({**order_data, 'to_invoice': False})
-
- current_session.close_session_from_ui()
- self.assertEqual(current_session.state, 'closed')
-
- order_no_invoice.action_pos_order_invoice()
- customer_account_receivable_entry = current_session.move_id.line_ids.filtered(lambda l: l.partner_id == self.partner)
- reversal_receivable_entry = order_no_invoice.reversed_move_ids.line_ids.filtered(lambda l: l.account_id == self.partner.property_account_receivable_id)
- self.assertTrue(customer_account_receivable_entry.reconciled)
- self.assertTrue(reversal_receivable_entry.reconciled)
- self.assertEqual(customer_account_receivable_entry.reconciled_lines_ids, reversal_receivable_entry)
-
def test_add_two_lines_with_same_uuid_through_sync_from_ui(self):
"""Test that adding two lines with the same UUID doesn't cause issues."""
self.pos_config_usd.open_ui()
@@ -1590,101 +938,3 @@ def test_add_two_lines_with_same_uuid_through_sync_from_ui(self):
}])
self.assertEqual(len(order.lines), 1, "Two lines with the same UUID were created")
self.assertEqual(order.lines[0].qty, 2, "The quantity of the line should have been updated to 2")
-
- def test_manual_refund_negative_qty_invoice_creates_credit_note(self):
- """Invoicing a POS order created with negative qty (manual refund, no Refund action)
- must create a credit note (RINV/out_refund), not a customer invoice (INV)."""
- self.pos_config_usd.open_ui()
-
- # Create an order with negative qty only (no Refund action → is_refund stays False)
- order, _ = self.create_backend_pos_order({
- 'order_data': {
- 'partner_id': self.partner_mobt.id,
- 'pricelist_id': self.pos_config_usd.pricelist_id.id,
- },
- 'line_data': [
- {'product_id': self.ten_dollars_no_tax.product_variant_id.id, 'qty': -1},
- ],
- 'payment_data': [
- {'payment_method_id': self.cash_payment_method.id, 'amount': -10},
- ],
- })
-
- self.assertEqual(order.state, 'paid')
- self.assertLess(order.amount_total, 0, 'Order total should be negative (manual refund).')
- self.assertFalse(order.is_refund, 'Order was not created via Refund action.')
-
- order.action_pos_order_invoice()
-
- self.assertTrue(order.account_move, 'An invoice/credit note should be created.')
- self.assertEqual(
- order.account_move.move_type,
- 'out_refund',
- 'Invoicing a manual refund (negative qty) must create a credit note (RINV), not a customer invoice.',
- )
-
- def test_pos_payment_direction_and_accounts(self):
- """Ensure POS payments create correct inbound/outbound payments and accounts."""
-
- def _do_pos_transaction(amount, split, index):
- self.bank_payment_method.write({'split_transactions': split})
- self.pos_config_usd.open_ui()
- current_session = self.pos_config_usd.current_session_id
- product_order = {
- 'amount_paid': amount,
- 'amount_tax': 0,
- 'amount_return': 0,
- 'amount_total': amount,
- 'date_order': fields.Datetime.to_string(fields.Datetime.now()),
- 'lines': [[0, 0, {
- 'price_unit': 100.0,
- 'product_id': self.product.id,
- 'price_subtotal': amount,
- 'price_subtotal_incl': amount,
- 'qty': 1 if amount > 0 else -1,
- }]],
- 'name': f'Order {index}',
- 'partner_id': self.partner.id,
- 'session_id': current_session.id,
- 'payment_ids': [[0, 0, {
- 'amount': amount,
- 'payment_method_id': self.bank_payment_method.id
- }]],
- 'uuid': f'12345-123-1253{index}',
- 'user_id': self.env.uid,
- 'to_invoice': False
- }
- self.env['pos.order'].sync_from_ui([product_order])
- current_session.close_session_from_ui()
- return current_session
-
- self.bank_payment_method.outstanding_account_id = self.inbound_payment_method_line.payment_account_id.id
- session_ids = [
- _do_pos_transaction(amount, split, idx).id
- for idx, (amount, split) in enumerate([(100, False), (-100, False), (100, True), (-100, True)])
- ]
- self.assertRecordValues(
- self.env['account.payment'].search([('pos_session_id', 'in', session_ids)], order='id'),
- [
- {
- "payment_type": "inbound",
- "outstanding_account_id": self.bank_payment_method.outstanding_account_id.id,
- "destination_account_id": self.bank_payment_method.receivable_account_id.id,
- },
- {
- "payment_type": "outbound",
- "outstanding_account_id": self.bank_payment_method.receivable_account_id.id,
- "destination_account_id": self.bank_payment_method.outstanding_account_id.id,
- },
- {
- "payment_type": "inbound",
- "outstanding_account_id": self.bank_payment_method.outstanding_account_id.id,
- "destination_account_id": self.bank_payment_method.receivable_account_id.id,
- },
- {
- "payment_type": "outbound",
- "outstanding_account_id": self.bank_payment_method.receivable_account_id.id,
- "destination_account_id": self.bank_payment_method.outstanding_account_id.id,
- },
- ],
- )
diff --git a/addons/point_of_sale/tests/test_pos_accounting.py b/addons/point_of_sale/tests/test_pos_accounting.py
new file mode 100644
index 00000000000000..c3fd213ae412e6
--- /dev/null
+++ b/addons/point_of_sale/tests/test_pos_accounting.py
@@ -0,0 +1,1831 @@
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from odoo import Command, fields
+from odoo.exceptions import UserError
+from odoo.tests import Form, freeze_time
+
+from odoo.addons.account.tests.common import AccountTestInvoicingCommon
+
+
+class TestPosAccounting(AccountTestInvoicingCommon):
+
+ @classmethod
+ def _get_main_company(self):
+ return self.company_data['company']
+
+ @classmethod
+ def setUpClass(self):
+ super().setUpClass()
+ self.main_company = self._get_main_company()
+ pos_manager = self.env.ref('point_of_sale.group_pos_manager')
+ self.env.user.group_ids += pos_manager
+
+ # Create journals
+ self.bank_journal = self.env['account.journal'].create({
+ 'name': 'Bank Test',
+ 'type': 'bank',
+ 'company_id': self.main_company.id,
+ 'code': 'BNK',
+ 'sequence': 10,
+ })
+ self.cash_journal = self.env['account.journal'].create({
+ 'name': 'Cash Test',
+ 'type': 'cash',
+ 'company_id': self.main_company.id,
+ 'code': 'CSH',
+ 'sequence': 10,
+ })
+ self.config_sale_journal = self.env['account.journal'].create({
+ 'name': 'PoS Sale',
+ 'type': 'sale',
+ 'code': 'POSS',
+ 'company_id': self.company.id,
+ 'sequence': 12,
+ })
+
+ # Accounts
+ self.bank_outstanding_account = self.copy_account(
+ self.inbound_payment_method_line.payment_account_id,
+ {'name': 'Outstanding Bank'},
+ )
+
+ # Create payment methods
+ self.cash_pm = self.env['pos.payment.method'].create({
+ 'name': 'Cash',
+ 'type': 'cash',
+ 'journal_id': self.cash_journal.id,
+ })
+ self.customer_pm = self.env['pos.payment.method'].create({
+ 'name': 'Customer Account',
+ 'type': 'pay_later',
+ })
+ self.bank_pm = self.env['pos.payment.method'].create({
+ 'name': 'Bank',
+ 'type': 'bank',
+ 'journal_id': self.bank_journal.id,
+ 'outstanding_account_id': self.bank_outstanding_account.id,
+ })
+
+ # Create taxes with different rates
+ self.tax_received_account = self.env['account.account'].create({
+ 'name': 'TAX_BASE',
+ 'code': 'TBASE',
+ 'account_type': 'asset_current',
+ })
+ tax_repartition = [
+ (0, 0, {'repartition_type': 'base'}),
+ (0, 0, {
+ 'repartition_type': 'tax',
+ 'account_id': self.tax_received_account.id,
+ }),
+ ]
+ self.tax_6 = self.env['account.tax'].create({
+ 'name': 'Tax 6%',
+ 'amount_type': 'percent',
+ 'amount': 6,
+ 'invoice_repartition_line_ids': tax_repartition,
+ 'refund_repartition_line_ids': tax_repartition,
+ })
+ self.tax_12 = self.env['account.tax'].create({
+ 'name': 'Tax 12%',
+ 'amount_type': 'percent',
+ 'amount': 12,
+ 'invoice_repartition_line_ids': tax_repartition,
+ 'refund_repartition_line_ids': tax_repartition,
+ })
+ self.tax_21 = self.env['account.tax'].create({
+ 'name': 'Tax 21%',
+ 'amount_type': 'percent',
+ 'amount': 21,
+ 'invoice_repartition_line_ids': tax_repartition,
+ 'refund_repartition_line_ids': tax_repartition,
+ })
+ self.tax_fixed = self.env['account.tax'].create({
+ 'name': 'fixed amount tax',
+ 'amount_type': 'fixed',
+ 'amount': 1,
+ 'price_include_override': 'tax_excluded',
+ 'invoice_repartition_line_ids': tax_repartition,
+ 'refund_repartition_line_ids': tax_repartition,
+ })
+
+ # Create products with different tax configurations
+ self.product_6 = self.env['product.product'].create({
+ 'name': 'Product 6%',
+ 'type': 'consu',
+ 'qty_available': 100,
+ 'is_storable': True,
+ 'list_price': 10,
+ 'taxes_id': [(6, 0, [self.tax_6.id])],
+ 'available_in_pos': True,
+ })
+ self.product_12 = self.env['product.product'].create({
+ 'name': 'Product 12%',
+ 'type': 'consu',
+ 'qty_available': 100,
+ 'is_storable': True,
+ 'list_price': 10,
+ 'taxes_id': [(6, 0, [self.tax_12.id])],
+ 'available_in_pos': True,
+ })
+ self.product_21 = self.env['product.product'].create({
+ 'name': 'Product 21%',
+ 'type': 'consu',
+ 'is_storable': True,
+ 'list_price': 10,
+ 'taxes_id': [(6, 0, [self.tax_21.id])],
+ 'available_in_pos': True,
+ })
+ self.product_6_12 = self.env['product.product'].create({
+ 'name': 'Product 6% + 12%',
+ 'type': 'consu',
+ 'is_storable': True,
+ 'list_price': 10,
+ 'taxes_id': [(6, 0, [self.tax_6.id, self.tax_12.id])],
+ 'available_in_pos': True,
+ })
+ taxes = [self.tax_6.id, self.tax_12.id, self.tax_21.id]
+ self.product_6_12_21 = self.env['product.product'].create({
+ 'name': 'Product 6% + 12% + 21%',
+ 'type': 'consu',
+ 'is_storable': True,
+ 'list_price': 10,
+ 'taxes_id': [(6, 0, taxes)],
+ 'available_in_pos': True,
+ })
+
+ # Create different partners to use customer account
+ self.partner_1 = self.env['res.partner'].create({
+ 'name': 'Partner 1',
+ })
+ self.partner_2 = self.env['res.partner'].create({
+ 'name': 'Partner 2',
+ })
+
+ # Create the main PoS configuration used in the tests
+ revenue = self.company_data['default_account_revenue'].id
+ expense = self.company_data['default_account_expense'].id
+ self.rounding_method = self.env['account.cash.rounding'].create({
+ 'name': 'Rounding up',
+ 'rounding': 0.05,
+ 'rounding_method': 'UP',
+ 'profit_account_id': revenue,
+ 'loss_account_id': expense,
+ })
+ self.pos_config = self.env['pos.config'].create({
+ 'name': 'PoS Config',
+ 'journal_id': self.config_sale_journal.id,
+ 'payment_method_ids': [
+ (4, self.cash_pm.id),
+ (4, self.customer_pm.id),
+ (4, self.bank_pm.id),
+ ],
+ })
+
+ def get_pos_session(self):
+ return self.pos_config.current_session_id
+
+ def open_pos_session(self, opening=0, note=""):
+ self.pos_config.open_ui()
+ session = self.get_pos_session()
+ session.set_opening_control(opening, note)
+ self.assertEqual(session.state, 'opened')
+ return session
+
+ def close_session(self, amount=0, note=""):
+ session = self.get_pos_session()
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ session.close_session_from_ui({self.cash_pm.id: expected_cashbox_amount})
+ self.assertEqual(session.state, 'closed')
+ return session
+
+ def create_pos_order(self, payment_method=[], products=[], extra_data={}):
+ order = {
+ 'amount_total': 0,
+ 'amount_paid': 0,
+ 'amount_tax': 0,
+ 'amount_return': 0,
+ 'state': 'draft',
+ 'date_order': fields.Datetime.to_string(fields.Datetime.now()),
+ 'company_id': self.env.company.id,
+ 'session_id': self.get_pos_session().id,
+ 'lines': [Command.create({
+ 'product_id': product.id,
+ 'price_unit': product.lst_price,
+ 'price_subtotal': product.lst_price,
+ 'tax_ids': [(6, 0, product.taxes_id.ids)],
+ 'price_subtotal_incl': 0,
+ **extra_data,
+ }) for [product, extra_data] in products],
+ 'payment_ids': [
+ Command.create({
+ 'payment_method_id': pm.id,
+ **data,
+ }) for [pm, data] in payment_method
+ ],
+ **extra_data,
+ }
+
+ data = self.env['pos.order'].sync_from_ui([order])
+ order = self.env['pos.order'].browse(data['pos.order'][0]['id'])
+ order._compute_prices()
+ if len(payment_method):
+ order_ctx = order.with_context({'generate_pdf': False})
+ order_ctx._process_saved_order(False)
+ return order
+
+ def test_cash_closing_data_do_not_take_into_account_invoiced_order(self):
+ session = self.open_pos_session()
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+
+ # Payment amount doesn't need to be taken into account for
+ # invoiced orders since the statement line is already generated
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ self.assertEqual(cash_details['amount'], 10.6)
+ self.assertEqual(cash_details['payment_amount'], 0)
+
+ def test_invoiced_order_are_on_partner_receivable_account(self):
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ self.close_session()
+ move = order.account_move
+ self.assertNotEqual(move, session.sales_move_id)
+
+ def test_cash_statement_opening_and_closing_consistency(self):
+ def open_and_close_session_with_cash_amounts(start, end):
+ session = self.open_pos_session(start)
+ session.close_session_from_ui({self.cash_pm.id: end})
+ self.assertEqual(session.state, 'closed')
+ return self.env['account.bank.statement'].browse(
+ session.bank_statement_id.id,
+ )
+
+ # OPEN WITH MORE CLOSE EQUAL
+ # Initial balance is 0
+ # - Opening 10 line +10 balance 10
+ # - Closing 10 line N/A balance 10
+ statement = open_and_close_session_with_cash_amounts(10, 10)
+ self.assertEqual(len(statement.line_ids), 1)
+ self.assertEqual(statement.line_ids.amount, 10)
+ self.assertEqual(statement.balance_end_real, 10)
+
+ # OPEN WITH LESS CLOSE WITH MORE
+ # Initial balance is 10
+ # - Opening 5 line -5 balance 5
+ # - Closing 10 line +5 balance 10
+ statement = open_and_close_session_with_cash_amounts(5, 10)
+ self.assertEqual(len(statement.line_ids), 2)
+ self.assertEqual(statement.line_ids[0].amount, -5)
+ self.assertEqual(statement.line_ids[1].amount, 5)
+ self.assertEqual(statement.balance_end_real, 10)
+
+ # OPEN WITH MORE CLOSE WITH LESS
+ # Initial balance is 10
+ # - Opening 20 line +10 balance 20
+ # - Closing 10 line -10 balance 10
+ statement = open_and_close_session_with_cash_amounts(20, 10)
+ self.assertEqual(len(statement.line_ids), 2)
+ self.assertEqual(statement.line_ids[0].amount, 10)
+ self.assertEqual(statement.line_ids[1].amount, -10)
+ self.assertEqual(statement.balance_end_real, 10)
+
+ # OPEN EQUAL CLOSE EQUAL
+ # Initial balance is 10
+ # - Opening 10 line N/A balance 10
+ # - Closing 10 line N/A balance 10
+ statement = open_and_close_session_with_cash_amounts(10, 10)
+ self.assertEqual(len(statement.line_ids), 0)
+ self.assertEqual(statement.balance_end_real, 10)
+
+ # OPEN EQUAL CLOSE WITH MORE
+ # Initial balance is 10
+ # - Opening 10 line N/A balance 10
+ # - Closing 20 line +10 balance 20
+ statement = open_and_close_session_with_cash_amounts(10, 20)
+ self.assertEqual(len(statement.line_ids), 1)
+ self.assertEqual(statement.line_ids[0].amount, 10)
+ self.assertEqual(statement.balance_end_real, 20)
+
+ # OPEN EQUAL CLOSE WITH LESS
+ # Initial balance is 20
+ # - Opening 20 line N/A balance 20
+ # - Closing 15 line -5 balance 15
+ statement = open_and_close_session_with_cash_amounts(20, 15)
+ self.assertEqual(len(statement.line_ids), 1)
+ self.assertEqual(statement.line_ids[0].amount, -5)
+ self.assertEqual(statement.balance_end_real, 15)
+
+ # OPEN WITH LESS CLOSE EQUAL
+ # Initial balance is 15
+ # - Opening 10 line -5 balance 10
+ # - Closing 10 line N/A balance 10
+ statement = open_and_close_session_with_cash_amounts(10, 10)
+ self.assertEqual(len(statement.line_ids), 1)
+ self.assertEqual(statement.line_ids[0].amount, -5)
+ self.assertEqual(statement.balance_end_real, 10)
+
+ # OPEN WITH LESS CLOSE WITH LESS
+ # Initial balance is 10
+ # - Opening 5 line -5 balance 5
+ # - Closing 3 line -2 balance 3
+ statement = open_and_close_session_with_cash_amounts(5, 3)
+ self.assertEqual(len(statement.line_ids), 2)
+ self.assertEqual(statement.line_ids[0].amount, -5)
+ self.assertEqual(statement.line_ids[1].amount, -2)
+ self.assertEqual(statement.balance_end_real, 3)
+
+ # OPEN WITH MORE CLOSE WITH MORE
+ # Initial balance is 3
+ # - Opening 8 line +5 balance 8
+ # - Closing 12 line +4 balance 12
+ statement = open_and_close_session_with_cash_amounts(8, 12)
+ self.assertEqual(len(statement.line_ids), 2)
+ self.assertEqual(statement.line_ids[0].amount, 5)
+ self.assertEqual(statement.line_ids[1].amount, 4)
+ self.assertEqual(statement.balance_end_real, 12)
+
+ def test_tax_change_blocked_when_open_pos_session(self):
+ """
+ Changing a POS sale tax must be blocked when a POS session
+ is open, this test also check if the tax is correctly marked
+ as used when it's part of a PoS order line
+ """
+ session = self.open_pos_session()
+ tax_pos = self.product_6.taxes_id
+ self.assertFalse(tax_pos.is_used)
+
+ order = self.create_pos_order(
+ products=[[self.product_6, {}]],
+ extra_data={'state': 'draft'},
+ )
+ self.assertEqual(order.lines.tax_ids, self.tax_6) # sanity check to ensure the order line has the correct tax
+ self.assertEqual(order.session_id, session) # sanity check to ensure the order is linked to the current session
+ with self.assertRaises(UserError):
+ self.tax_6.write({
+ 'price_include_override': 'tax_included',
+ })
+
+ tax_pos.invalidate_model(fnames=['is_used'])
+ self.assertTrue(tax_pos.is_used)
+
+ def test_classic_order(self):
+ session = self.open_pos_session()
+ customer_order = self.create_pos_order(
+ payment_method=[[self.customer_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ extra_data={'partner_id': self.partner_1.id},
+ )
+
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+
+ self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+
+ self.close_session()
+ sale_move = session.move_ids
+ cash_statement = self.cash_pm.journal_id.last_statement_id
+ self.assertEqual(cash_statement, session.bank_statement_id) # Cash statement should be the one linked to the session
+ self.assertEqual(len(sale_move.line_ids), 4) # 3 payment_term + 1 product + 1 tax
+ self.assertEqual(sale_move.amount_total, 21.2) # 10 + 6% tax * 2 orders (customer account order is not taken into account)
+ self.assertEqual(sale_move.amount_tax, 1.2) # 6% tax on 30
+ self.assertEqual(len(cash_statement.line_ids), 1) # Only one line in the cash statement since the 3 orders are merged into one statement line
+ self.assertEqual(cash_statement.line_ids.amount, 10.6) # 10 + 6% tax from the cash order
+ self.assertEqual(cash_statement.is_complete, True)
+
+ # Customer account invoice
+ invoice = self.env['account.move'].search([
+ ('move_type', '=', 'out_invoice'),
+ ('partner_id', '=', self.partner_1.id),
+ ])
+ self.assertEqual(invoice.amount_total, 10.6) # 10 + 6% tax from the customer account order
+ self.assertEqual(invoice.amount_tax, 0.6) # 6% tax on 10
+ self.assertEqual(invoice.amount_residual, 10.6) # Not yet paid
+ self.assertEqual(invoice.amount_paid, 0.0) # Not yet paid
+ self.assertEqual(customer_order.to_invoice, True) # Forced to True since the order is paid with a customer account
+
+ def test_cash_statement_line(self):
+ session = self.open_pos_session()
+
+ # Cash payment of 10.6 (10 + 6% tax)
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+
+ # Cash payment of 11.2 (10 + 12% tax)
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 11.2}]],
+ products=[[self.product_12, {}]],
+ )
+
+ # Cash payment of 12.0 (10 + 21% tax)
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 12.1}]],
+ products=[[self.product_21, {}]],
+ )
+
+ self.close_session()
+ cash_statement = self.cash_pm.journal_id.last_statement_id
+ self.assertEqual(cash_statement, session.bank_statement_id) # Cash statement should be the one linked to the session
+ statement_lines = cash_statement.line_ids
+ self.assertEqual(len(statement_lines), 1)
+ self.assertEqual(statement_lines.amount, 33.9) # 10 + 6% tax + 10 + 12% tax + 10 + 21% tax
+
+ def test_closing_entry_by_product(self):
+ self.pos_config.use_closing_entry_by_product = True
+ session = self.open_pos_session()
+
+ # Create a PoS order with 2 products with different taxes
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 21.8}]], # Total amount of the order is 10 + 6% tax + 10 + 12% tax = 21.8
+ products=[[self.product_6, {}], [self.product_12, {}]],
+ extra_data={'partner_id': self.partner_1.id},
+ )
+
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ session.close_session_from_ui({self.cash_pm.id: expected_cashbox_amount})
+ self.assertEqual(session.state, 'closed')
+
+ sale_move = session.move_ids
+ self.assertEqual(len(sale_move.line_ids), 5) # 1 payment_term + 2 product + 2 tax
+ product_lines = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ tax_lines = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'tax',
+ )
+ product1 = product_lines[0]
+ product2 = product_lines[1]
+ self.assertEqual(product1.product_id, self.product_6) # First product line should be for product with 6% tax
+ self.assertEqual(product2.product_id, self.product_12) # Second product line should be for product with 12% tax
+ self.assertEqual(product1.tax_ids.ids, [self.tax_6.id]) # First tax line should be for 6% tax
+ self.assertEqual(product2.tax_ids.ids, [self.tax_12.id]) # Second tax line should be for 12% tax
+ self.assertEqual(tax_lines[0].amount_currency, -0.6) # First tax line should be at 0.6 (6% of 10)
+ self.assertEqual(tax_lines[1].amount_currency, -1.2) # Second tax line should be at 1.2 (12% of 10)
+
+ def test_separate_invoicing_pos_order(self):
+ session = self.open_pos_session()
+
+ # Create a PoS order with 2 payment methods
+ # (customer account + cash)
+ pos_order = self.create_pos_order(
+ payment_method=[
+ [self.customer_pm, {'amount': 5.3}],
+ [self.cash_pm, {'amount': 5.3}],
+ ],
+ products=[[self.product_6, {}]],
+ extra_data={'partner_id': self.partner_1.id},
+ )
+
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ session.close_session_from_ui({self.cash_pm.id: expected_cashbox_amount})
+ self.assertEqual(session.state, 'closed')
+
+ # Check that the invoice is correctly created with the customer
+ # account payment method
+ invoice = self.env['account.move'].search([
+ ('move_type', '=', 'out_invoice'),
+ ('partner_id', '=', self.partner_1.id),
+ ])
+ self.assertEqual(pos_order.account_move, invoice) # Invoice should be linked to the PoS order
+ self.assertEqual(invoice.amount_total, 10.6) # 10 + 6% tax from the customer account order
+ self.assertEqual(invoice.amount_tax, 0.6) # 6% tax on 10
+ self.assertEqual(invoice.amount_residual, 5.3) # Customer account part isn't yet paid, but cash part is paid
+
+ # Check each account.move.line of the invoice to ensure that the
+ # cash payment line is reconciled with the correct invoice line
+ # (in case of multiple tax lines for example)
+ payment_terms = invoice.line_ids.filtered(
+ lambda line: line.display_type == 'payment_term',
+ )
+ cash_payment = payment_terms[0]
+ customer_payment = payment_terms[1]
+ self.assertEqual(cash_payment.amount_currency, 5.3) # Cash part of the payment
+ self.assertEqual(customer_payment.amount_currency, 5.3) # Customer account part of the payment
+ self.assertEqual(cash_payment.reconciled, True) # Cash part
+ self.assertEqual(customer_payment.reconciled, False) # Customer account part
+
+ product_line = invoice.line_ids.filtered(
+ lambda line: line.product_id == self.product_6,
+ )
+ product_taxes = self.product_6.taxes_id.ids
+ self.assertEqual(product_line.tax_ids.ids, product_taxes) # Taxes should be correctly copied on the invoice line
+ self.assertEqual(product_line.amount_currency, -10.0) # Product line should be at 10 (without taxes)
+ self.assertEqual(product_line.credit, 10.0) # Product line should be a credit of 10 (without taxes)
+
+ tax_lines = invoice.line_ids.filtered(
+ lambda line: line.display_type == 'tax',
+ )
+ self.assertEqual(tax_lines.amount_currency, -0.6)
+
+ def test_fixed_tax_negative_qty_should_be_negative(self):
+ service = self.env.ref('product.product_category_services').id
+ zero_amount_product = self.env['product.product'].create({
+ 'name': 'Zero Amount Product',
+ 'available_in_pos': True,
+ 'list_price': 0,
+ 'taxes_id': [(6, 0, [self.tax_fixed.id])],
+ 'categ_id': service,
+ })
+ self.pos_config.write({'iface_tax_included': 'total'})
+
+ # Test with a positive order first
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 1}]],
+ products=[[zero_amount_product, {'qty': 1}]],
+ )
+ session.close_session_from_ui({self.cash_pm.id: 1})
+ self.assertEqual(session.state, 'closed')
+ move = session.move_ids
+ tax_line = move.line_ids.filtered(
+ lambda line: line.display_type == 'tax',
+ )
+ product_line = move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ payment_line = move.line_ids.filtered(
+ lambda line: line.display_type == 'payment_term',
+ )
+ self.assertEqual(order.amount_total, 1) # Total amount should be 1 since it's a fixed tax
+ self.assertEqual(tax_line.credit, 1) # We credit the tax account with 1 since it's a fixed tax on a positive order
+ self.assertEqual(tax_line.debit, 0) # Nothing should be debited
+ self.assertEqual(product_line.debit, 0) # Product line should be at 0 since it's a zero amount product
+ self.assertEqual(product_line.credit, 0) # Product line should be at 0 since it's a zero amount product
+ self.assertEqual(payment_line.credit, 0) # Nothing should be credited since it's a payment
+ self.assertEqual(payment_line.debit, 1) # Total amount (only taxes) should be debited to the payment line since it's a positive order
+
+ # Now test with a negative order
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': -1}]],
+ products=[[zero_amount_product, {'qty': -1}]],
+ extra_data={'is_refund': True},
+ )
+ session.close_session_from_ui({self.cash_pm.id: 0})
+ self.assertEqual(session.state, 'closed')
+ move = session.move_ids
+ tax_line = move.line_ids.filtered(
+ lambda line: line.display_type == 'tax',
+ )
+ product_line = move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ payment_line = move.line_ids.filtered(
+ lambda line: line.display_type == 'payment_term',
+ )
+ self.assertEqual(order.amount_total, -1) # Total amount should be 1 since it's a fixed tax
+ self.assertEqual(tax_line.credit, 0) # Nothing should be credited since it's a refund order
+ self.assertEqual(tax_line.debit, 1) # We debit the tax account with 1 since it's a fixed tax on a refund
+ self.assertEqual(product_line.debit, 0) # Product line should be at 0 since it's a zero amount product
+ self.assertEqual(product_line.credit, 0) # Product line should be at 0 since it's a zero amount product
+ self.assertEqual(payment_line.credit, 1) # Nothing should be credited since it's a payment, but we debit the payment line with 1 since it's a refund
+ self.assertEqual(payment_line.debit, 0) # Total amount (only taxes) should be debited to the payment line since it's a positive order
+
+ def test_user_right_on_statement_line_for_pos_user(self):
+ """Test cash difference *loss* at closing.
+ """
+ session = self.open_pos_session()
+ session.close_session_from_ui({self.cash_pm.id: 0})
+ session = self.open_pos_session()
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ session.close_session_from_ui({self.cash_pm.id: expected_cashbox_amount})
+ self.assertEqual(session.state, 'closed')
+ bank_statement = session.bank_statement_id
+ self.assertEqual(bank_statement.balance_end_real, 10.6) # The order is 10 + 0.60 taxes
+
+ def test_rounding_when_closing_session(self):
+ rounding_method = self.rounding_method
+ rounding_method.rounding_method = 'HALF-UP'
+ self.product_a.write({
+ 'name': 'Product Test',
+ 'list_price': 0.04,
+ 'taxes_id': False,
+ })
+ self.pos_config.write({
+ 'rounding_method': rounding_method.id,
+ 'cash_rounding': True,
+ 'only_round_cash_method': False,
+ })
+
+ def check_difference(session, difference):
+ currency = self.pos_config.currency_id
+ rounded = currency.round(difference)
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ session.close_session_from_ui({self.cash_pm.id: expected_cashbox_amount})
+ self.assertEqual(session.state, 'closed')
+ rounding_lines = session.sales_move_id.line_ids.filtered(
+ lambda line: line.display_type == 'rounding',
+ )
+ if difference > 0:
+ self.assertEqual(rounding_lines.credit, rounded)
+ self.assertEqual(rounding_lines.debit, 0)
+ else:
+ self.assertEqual(rounding_lines.debit, abs(rounded))
+ self.assertEqual(rounding_lines.credit, 0)
+
+ def create_order_and_check(amount, qty=1, pm=self.cash_pm):
+ order = self.create_pos_order(
+ payment_method=[[pm, {'amount': amount}]],
+ products=[[self.product_a, {'qty': qty}]],
+ )
+ rounded = rounding_method.round(order.amount_total)
+ self.assertEqual(order.amount_paid, rounded)
+ self.assertEqual(order.amount_return, 0)
+ return order.amount_difference
+
+ # Only cash check when rounding amount is negative, it should be
+ # debited from the move to be credited on the rounding account
+ self.product_a.list_price = 0.04
+ session = self.open_pos_session()
+ difference = 0
+ difference += create_order_and_check(0.05) # Rounding +0.01 (total is 0.04)
+ difference += create_order_and_check(0.10, 2) # Rounding +0.02 (total is 0.08)
+ difference += create_order_and_check(0.10, 3) # Rounding -0.02 (total is 0.12)
+ check_difference(session, difference) # Difference +0.01
+
+ # Only cash check when rounding amount is positive, it should be
+ # credited from the move to be debited on the rounding account
+ self.product_a.list_price = 0.06
+ session = self.open_pos_session()
+ difference = 0
+ difference += create_order_and_check(0.05) # Rounding -0.01 (total is 0.04)
+ difference += create_order_and_check(0.10, 2) # Rounding -0.02 (total is 0.12)
+ check_difference(session, difference) # Difference -0.03
+
+ # Round bank payment method as well
+ self.product_a.list_price = 0.03
+ session = self.open_pos_session()
+ difference = 0
+ difference += create_order_and_check(0.05, 2, self.bank_pm) # Rounding -0.01 (total is 0.06)
+ difference += create_order_and_check(0.10, 3, self.bank_pm) # Rounding +0.01 (total is 0.09)
+ check_difference(session, difference) # Difference 0.00
+
+ # Try to round with mixed payment methods, both should be taken
+ # into account for the rounding
+ self.product_a.list_price = 0.03
+ session = self.open_pos_session()
+ difference = 0
+ difference += create_order_and_check(0.05, 2, self.bank_pm) # Rounding -0.01 (total is 0.06)
+ difference += create_order_and_check(0.10, 4) # Rounding -0.02 (total is 0.12)
+ check_difference(session, difference) # Difference -0.03
+
+ def test_journal_entries_category_without_account(self):
+ # Set company's default accounts to false
+ self.env.company.income_account_id = False
+ self.env.company.expense_account_id = False
+ self.product_12.write({
+ 'property_account_income_id': False,
+ 'property_account_expense_id': False,
+ })
+ account = self.env['account.account'].create({
+ 'name': 'Account for category without account',
+ 'code': 'X1111',
+ })
+ self.open_pos_session()
+ self.pos_config.journal_id.default_account_id = account.id
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 11.2}]],
+ products=[[self.product_12, {}]],
+ )
+
+ def test_invoice_a_negative_order_should_create_credit_note(self):
+ self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': -10.6}]],
+ products=[[self.product_6, {'qty': -1}]],
+ extra_data={
+ 'is_refund': True,
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ self.assertEqual(order.account_move.move_type, 'out_refund') # Negative order should be flagged as a refund order
+
+ def test_order_with_positive_and_negative_lines(self):
+ self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.0}]], # 10.6 * 2 + -11.2 = = 10.0
+ products=[
+ [self.product_6, {'qty': 2}],
+ [self.product_12, {'qty': -1}],
+ ],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ },
+ )
+ self.close_session()
+ invoice = order._generate_pos_order_invoice()
+ self.assertEqual(order.amount_total, 10.0)
+ self.assertEqual(invoice.amount_total, 10.0) # Total should be 10 since we have 2 lines at 10.6 and one line at -11.2
+ self.assertEqual(invoice.move_type, 'out_invoice') # Invoice should be flagged as a regular invoice
+ self.open_pos_session()
+ refund = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': -10.0}]],
+ products=[
+ [self.product_6, {'qty': -2}],
+ [self.product_12, {'qty': 1}],
+ ],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'is_refund': True,
+ },
+ )
+ self.close_session()
+ refund_invoice = refund._generate_pos_order_invoice()
+ self.assertEqual(refund.amount_total, -10.0)
+ self.assertEqual(refund_invoice.amount_total, 10.0)
+ self.assertEqual(refund_invoice.move_type, 'out_refund') # Refund invoice should be flagged as a refund
+
+ def test_invoice_an_order_from_closed_session(self):
+ self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ extra_data={'partner_id': self.partner_1.id},
+ )
+ refund = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': -10.6}]],
+ products=[[self.product_6, {'qty': -1}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'is_refund': True,
+ 'refunded_order_id': order.id,
+ },
+ )
+ session = self.close_session()
+
+ # Refund the sale order to check if move are correctly created
+ data = order.action_pos_order_invoice()
+ order_move = self.env['account.move'].browse(data['res_id'])
+ data = refund.action_pos_order_invoice()
+ refund_move = self.env['account.move'].browse(data['res_id'])
+
+ session_sales = session.sales_move_id
+ session_refunds = session.refunds_move_id
+ reversal_sale_move = session_sales.reversal_move_ids
+ reversal_refund_move = session_refunds.reversal_move_ids
+
+ # Check that the reversal moves have the exact opposite lines
+ # than the original moves
+ for sline in session_sales.line_ids:
+ rline = reversal_sale_move.line_ids.filtered(
+ lambda line: line.account_id == sline.account_id,
+ )
+ self.assertEqual(sline.debit, rline.credit)
+ self.assertEqual(sline.credit, rline.debit)
+
+ for rline in session_refunds.line_ids:
+ rliner = reversal_refund_move.line_ids.filtered(
+ lambda line: line.account_id == rline.account_id,
+ )
+ self.assertEqual(rline.debit, rliner.credit)
+ self.assertEqual(rline.credit, rliner.debit)
+
+ # Check if the account transfer exists between pos receivable
+ # and the customer receivable for both sale and refund
+ sale_account_transfer = self.env['account.move'].search([
+ ('ref', 'ilike', f"invoice {order_move.name}"),
+ ])
+ refund_account_transfer = self.env['account.move'].search([
+ ('ref', 'ilike', f"invoice {refund_move.name}"),
+ ])
+ defaul_partner = session.config_id.default_partner_id
+ s_receivable = defaul_partner.property_account_receivable_id
+ p_receivable = self.partner_1.property_account_receivable_id
+
+ line_session = sale_account_transfer.line_ids.filtered(
+ lambda line: line.account_id == s_receivable,
+ )
+ line_partner = sale_account_transfer.line_ids.filtered(
+ lambda line: line.account_id == p_receivable,
+ )
+ self.assertEqual(line_session.debit, order.amount_total)
+ self.assertEqual(line_session.credit, 0)
+ self.assertEqual(line_partner.debit, 0)
+ self.assertEqual(line_partner.credit, order.amount_total)
+
+ line_session = refund_account_transfer.line_ids.filtered(
+ lambda line: line.account_id == s_receivable,
+ )
+ line_partner = refund_account_transfer.line_ids.filtered(
+ lambda line: line.account_id == p_receivable,
+ )
+ self.assertEqual(line_session.debit, 0)
+ self.assertEqual(line_session.credit, abs(order.amount_total))
+ self.assertEqual(line_partner.debit, abs(order.amount_total))
+ self.assertEqual(line_partner.credit, 0)
+
+ def test_order_partial_refund_rounding(self):
+ """
+ This test ensures that the refund amount of a partial order
+ corresponds to the price of the item, without rounding.
+ """
+ self.rounding_method.rounding = 5.0
+ self.rounding_method.rounding_method = 'DOWN'
+ self.pos_config.write({
+ 'rounding_method': self.rounding_method.id,
+ 'cash_rounding': True,
+ })
+
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 30}]],
+ products=[[self.product_6, {'qty': 3}]],
+ extra_data={'partner_id': self.partner_1.id},
+ )
+ rounded_amount = order._get_rounded_amount(order.amount_total)
+ self.assertEqual(rounded_amount, order.amount_paid)
+
+ refund_action = order.refund()
+ refund = self.env['pos.order'].browse(refund_action['res_id'])
+ with Form(refund) as refund_form:
+ with refund_form.lines.edit(0) as line:
+ line.qty = -1
+ refund = refund_form.save()
+
+ self.assertEqual(refund.amount_total, -10.6)
+ payment_context = self.env['pos.make.payment'].with_context({
+ "active_ids": refund.ids,
+ "active_id": refund.id,
+ })
+ refund_payment = payment_context.create({
+ 'amount': refund.amount_total,
+ 'payment_method_id': self.cash_pm.id,
+ })
+ refund_payment.check()
+ self.assertEqual(refund.amount_paid, -10)
+
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ session.close_session_from_ui({self.cash_pm.id: expected_cashbox_amount})
+
+ self.assertEqual(refund.state, 'done')
+ self.assertEqual(session.state, 'closed')
+
+ def test_pos_order_sale_and_refund_with_taxes_not_invoiced(self):
+ """
+ It will also check if cash_pm receivable account is correctly
+ updated. Statement line should also be created with the correct
+ amount.
+ """
+ config_partner = self.pos_config.default_partner_id
+ cash_receivable = config_partner.property_account_receivable_id
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 21.8}]], # Total amount of the order is 10 + 6% tax + 10 + 12% tax = 21.8
+ products=[[self.product_6, {}], [self.product_12, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ },
+ )
+ self.assertEqual(self.product_6.qty_available, 99) # Check that the stock of the product is correctly updated when the order is done
+ self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': -21.8}]], # Total amount of the order is 10 + 6% tax + 10 + 12% tax = 21.8
+ products=[
+ [self.product_6, {'qty': -1}],
+ [self.product_12, {'qty': -1}],
+ ],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'is_refund': True,
+ 'refunded_order_id': order.id,
+ },
+ )
+ self.assertEqual(self.product_6.qty_available, 100) # Check that the stock of the product is correctly updated when the order is done
+
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['payment_amount']
+ session.close_session_from_ui({self.cash_pm.id: expected_cashbox_amount})
+ self.assertEqual(session.state, 'closed')
+ sale_move = session.sales_move_id
+ refund_move = session.refunds_move_id
+
+ self.assertEqual(sale_move.move_type, 'out_invoice')
+ self.assertEqual(sale_move.amount_total, 21.8)
+ self.assertEqual(refund_move.move_type, 'out_refund')
+ self.assertEqual(refund_move.amount_total, 21.8)
+
+ sale_product_lines = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ refund_product_lines = refund_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ self.assertEqual(len(sale_product_lines), 2)
+ self.assertEqual(len(refund_product_lines), 2)
+ taxes = [self.tax_6, self.tax_12]
+ zippeeeed = zip(sale_product_lines, refund_product_lines, taxes)
+ for sale_line, refund_line, tax in zippeeeed:
+ self.assertEqual(sale_line.tax_ids, refund_line.tax_ids)
+ self.assertEqual(sale_line.tax_ids.ids, tax.ids)
+ self.assertEqual(sale_line.credit, refund_line.debit)
+
+ cash_move = self.env['account.move.line'].search([
+ ('account_id', '=', cash_receivable.id),
+ ]).mapped('amount_currency')
+ self.assertEqual([-21.8, 21.8, 21.8, -21.8], cash_move) # The config default journal is used because cash_pm doesn't have a journal
+
+ product_line_balance = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ ).mapped('balance')
+ self.assertEqual([-10.0, -10.0], product_line_balance) # Product lines should be at 10 (without taxes)
+
+ tax_line_balance = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'tax',
+ ).mapped('balance')
+ self.assertEqual([-0.6, -1.2], tax_line_balance) # Tax lines should be at 0.6 and 1.2 for the 6
+
+ sale_move = session.move_ids
+ cash_statement = self.cash_pm.journal_id.last_statement_id
+ self.assertEqual(cash_statement, session.bank_statement_id) # Cash statement should be the one linked to the session
+ cash_lines = cash_statement.line_ids.mapped('amount')
+ self.assertEqual([21.8, -21.8], cash_lines) # One by closing entry (refund and sale)
+
+ def test_pos_order_sale_and_refund_with_taxes_invoiced(self):
+ """
+ This test will check if the taxes on refunds and sales are
+ correctly applied when closing the session or when invoicing
+ the order.
+
+ It will also check if cash_pm receivable account is correctly
+ updated. Statement line should also be created with the correct
+ amount.
+ """
+ cash_receivable = self.partner_1.property_account_receivable_id
+ session = self.open_pos_session()
+
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 21.8}]], # Total amount of the order is 10 + 6% tax + 10 + 12% tax = 21.8
+ products=[[self.product_6, {}], [self.product_12, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ self.assertEqual(self.product_6.qty_available, 99) # Check that the stock of the product is correctly updated when the order is done
+ refund = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': -21.8}]], # Total amount of the order is 10 + 6% tax + 10 + 12% tax = 21.8
+ products=[
+ [self.product_6, {'qty': -1}],
+ [self.product_12, {'qty': -1}],
+ ],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'is_refund': True,
+ 'refunded_order_id': order.id,
+ 'to_invoice': True,
+ },
+ )
+ self.assertEqual(self.product_6.qty_available, 100) # Check that the stock of the product is correctly updated when the order is done
+ sale_move = order.account_move
+ refund_move = refund.account_move
+
+ self.assertEqual(sale_move.move_type, 'out_invoice')
+ self.assertEqual(sale_move.amount_total, 21.8)
+ self.assertEqual(refund_move.move_type, 'out_refund')
+ self.assertEqual(refund_move.amount_total, 21.8)
+
+ sale_product_lines = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ refund_product_lines = refund_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ self.assertEqual(len(sale_product_lines), 2)
+ self.assertEqual(len(refund_product_lines), 2)
+ taxes = [self.tax_6, self.tax_12]
+ zippeeeed = zip(sale_product_lines, refund_product_lines, taxes)
+ for sale_line, refund_line, tax in zippeeeed:
+ self.assertEqual(sale_line.tax_ids, refund_line.tax_ids)
+ self.assertEqual(sale_line.tax_ids.ids, tax.ids)
+ self.assertEqual(sale_line.credit, refund_line.debit)
+
+ cash_move = self.env['account.move.line'].search([
+ ('account_id', '=', cash_receivable.id),
+ ]).mapped('amount_currency')
+ self.assertEqual([-21.8, 21.8, 21.8, -21.8], cash_move) # The config default journal is used because cash_pm doesn't have a journal
+
+ product_line_balance = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ ).mapped('balance')
+ self.assertEqual([-10.0, -10.0], product_line_balance) # Product lines should be at 10 (without taxes)
+
+ tax_line_balance = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'tax',
+ ).mapped('balance')
+ self.assertEqual([-0.6, -1.2], tax_line_balance) # Tax lines should be at 0.6 and 1.2 for the 6
+
+ cash_statement = self.cash_pm.journal_id.last_statement_id
+ self.assertEqual(cash_statement, session.bank_statement_id) # Cash statement should be the one linked to the session
+ cash_lines = cash_statement.line_ids.mapped('amount')
+ self.assertEqual([21.8, -21.8], cash_lines) # One by invoice
+
+ def test_invoiced_order_with_discount_sale_and_refund_with_tax(self):
+ """
+ This test will check if the taxes on refunds and sales with
+ discount are correctly applied when closing the session or when
+ invoicing the order.
+
+ It will also check if cash_pm receivable account is correctly
+ updated. Statement line should also be created with the correct
+ amount.
+ """
+ cash_receivable = self.partner_1.property_account_receivable_id
+ self.open_pos_session()
+
+ order = self.create_pos_order(
+ products=[
+ [self.product_6, {'discount': 50}],
+ [self.product_12, {'discount': 50}],
+ ],
+ payment_method=[[self.cash_pm, {'amount': 10.9}]], # Total amount of the order is 5 + 6% tax + 5 + 12% tax = 10.9
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ refund = self.create_pos_order(
+ products=[
+ [self.product_6, {'discount': 50, 'qty': -1}],
+ [self.product_12, {'discount': 50, 'qty': -1}],
+ ],
+ payment_method=[[self.cash_pm, {'amount': -10.9}]], # Total amount of the order is 5 + 6% tax + 5 + 12% tax = 10.9
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'is_refund': True,
+ 'refunded_order_id': order.id,
+ 'to_invoice': True,
+ },
+ )
+ sale_move = order.account_move
+ refund_move = refund.account_move
+
+ refund_product_line = refund_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ sale_product_line = sale_move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ zippeeeed = zip(sale_product_line, refund_product_line)
+ for sale_line, refund_line in zippeeeed:
+ self.assertEqual(sale_line.discount, 50) # Discount should be at 50%
+ self.assertEqual(sale_line.discount, refund_line.discount) # Discount should be the same on sale and refund
+
+ self.assertEqual(sale_move.move_type, 'out_invoice')
+ self.assertEqual(sale_move.amount_total, 10.9)
+ self.assertEqual(refund_move.move_type, 'out_refund')
+ self.assertEqual(refund_move.amount_total, 10.9)
+
+ cash_move = self.env['account.move.line'].search([
+ ('account_id', '=', cash_receivable.id),
+ ]).mapped('amount_currency')
+ self.assertEqual([-10.9, 10.9, 10.9, -10.9], cash_move)
+
+ def test_pos_payment_direction_and_account(self):
+ """
+ Ensure POS payments create correct inbound/outbound payments
+ and accounts. This test will check for invoiced orders and
+ classic global entry of the session.
+ """
+ inbound = self.inbound_payment_method_line.payment_account_id
+ self.bank_pm.outstanding_account_id = inbound.id
+ config_partner = self.pos_config.default_partner_id
+ pos_receivable = config_partner.property_account_receivable_id
+ session = self.env['pos.session']
+
+ def create_session_with_single_order(**kwargs):
+ config = self.pos_config
+ config.open_ui()
+ session = self.get_pos_session()
+ cash_acc = config._get_opening_balance()
+ session.set_opening_control(cash_acc, "")
+ order = self.create_pos_order(**kwargs)
+ self.assertEqual(order.state, 'paid')
+ closing_data = session.get_closing_control_data()
+ cash_details = closing_data['default_cash_details']
+ expected_cashbox_amount = cash_details['amount']
+ session.close_session_from_ui({self.cash_pm.id: expected_cashbox_amount})
+ self.assertEqual(session.state, 'closed')
+ return session
+
+ session |= create_session_with_single_order(
+ payment_method=[[self.bank_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+ session |= create_session_with_single_order(
+ payment_method=[[self.bank_pm, {'amount': -10.6}]],
+ products=[[self.product_6, {'qty': -1}]],
+ extra_data={'is_refund': True},
+ )
+ session |= create_session_with_single_order(
+ payment_method=[[self.cash_pm, {'amount': 11.2}]],
+ products=[[self.product_12, {}]],
+ )
+ session |= create_session_with_single_order(
+ payment_method=[[self.cash_pm, {'amount': -11.2}]],
+ products=[[self.product_12, {'qty': -1}]],
+ extra_data={'is_refund': True},
+ )
+ payments = self.env['account.payment'].search(
+ [('pos_session_id', 'in', session.ids)],
+ order='id',
+ )
+
+ # Check bank payments in global entry
+ expected_out_acc = self.bank_pm.outstanding_account_id
+ destination_account = payments.destination_account_id
+ outstanding_account = payments.outstanding_account_id
+ self.assertEqual(len(payments), 2)
+ self.assertEqual(destination_account, pos_receivable) # Bank payment should be posted on the account defined on the payment method or default config account
+ self.assertEqual(outstanding_account, expected_out_acc)
+ self.assertEqual(payments.pos_payment_method_id, self.bank_pm) # Only bank pm cash payment is managed from statements
+ self.assertEqual(
+ payments.mapped('payment_type'),
+ ['inbound', 'outbound'], # One sale and one refund
+ )
+
+ # Check cash payments
+ lines = session.bank_statement_id.line_ids
+ self.assertEqual(len(lines), 2)
+ self.assertEqual(lines.mapped('amount'), [11.2, -11.2]) # One line for the sale and one for the refund
+ accounts = lines.invoice_line_ids.account_id.ids
+ cash_acc = self.cash_pm.journal_id.default_account_id
+ self.assertEqual(accounts, [cash_acc.id, pos_receivable.id]) # Cash payment should be posted on the cash account of the statement
+
+ # Open session
+ self.pos_config.open_ui()
+ session = self.get_pos_session()
+ cash_acc = self.pos_config._get_opening_balance()
+ session.set_opening_control(cash_acc, "")
+ order1 = self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ refund1 = self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': -10.6}]],
+ products=[[self.product_6, {'qty': -1}]],
+ extra_data={
+ 'is_refund': True,
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ order2 = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 11.2}]],
+ products=[[self.product_12, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ refund2 = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': -11.2}]],
+ products=[[self.product_12, {'qty': -1}]],
+ extra_data={
+ 'is_refund': True,
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+
+ # Check bank payments for invoiced orders
+ expected_out_acc = self.bank_pm.outstanding_account_id
+ destination_account = payments.destination_account_id
+ outstanding_account = payments.outstanding_account_id
+ self.assertEqual(len(payments), 2)
+ self.assertEqual(destination_account, pos_receivable) # Bank payment should be posted on the account defined on the payment method or default config account
+ self.assertEqual(outstanding_account, expected_out_acc)
+ self.assertEqual(payments.pos_payment_method_id, self.bank_pm) # Only bank pm cash payment is managed from statements
+ self.assertEqual(
+ payments.mapped('payment_type'),
+ ['inbound', 'outbound'], # One sale and one refund
+ )
+
+ sale_invoices = order1.account_move + order2.account_move
+ refund_invoices = refund1.account_move + refund2.account_move
+ partner_invoices = self.partner_1.invoice_ids.ids
+ for id in sale_invoices.ids + refund_invoices.ids:
+ self.assertIn(id, partner_invoices)
+
+ def test_invoicing_zero_amount_pos_order(self):
+ session = self.open_pos_session()
+ self.product_6.lst_price = 0
+
+ order = self.create_pos_order(
+ payment_method=[
+ [self.cash_pm, {'amount': 0}],
+ ],
+ products=[[self.product_6, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+
+ session.close_session_from_ui({self.cash_pm.id: 0})
+ self.assertEqual(session.state, 'closed')
+
+ receivable = self.partner_1.property_account_receivable_id
+ line_ids = order.account_move.line_ids
+ self.assertEqual(len(line_ids), 2) # Only one line for the product
+ self.assertEqual(line_ids[0].account_id, receivable) # Line should be posted on the partner receivable
+ self.assertEqual(line_ids[0].display_type, 'payment_term')
+ self.assertEqual(line_ids[0].debit, 0) # Line should be at 0 since it's a zero amount order
+ self.assertEqual(line_ids[0].credit, 0) # Line should be at 0 since it's a zero amount order
+
+ # Check product line
+ self.assertEqual(line_ids[1].display_type, 'product')
+ self.assertEqual(line_ids[1].debit, 0) # Line should be at 0 since it's a zero amount order
+ self.assertEqual(line_ids[1].credit, 0) # Line should be at 0 since it's a zero amount order
+
+ def test_various_orders(self):
+ StatementLine = self.env['account.bank.statement.line']
+ BankPayment = self.env['account.payment']
+ defaut_partner = self.pos_config.default_partner_id
+
+ def create_order_and_check(order_args, values={
+ 'amount_total': 0,
+ 'amount_tax': 0,
+ 'amount_paid': 0,
+ }):
+ receivable = defaut_partner.property_account_receivable_id
+ cash_acc = self.pos_config._get_opening_balance()
+ session = self.open_pos_session(cash_acc)
+ order = self.create_pos_order(**order_args)
+
+ self.assertEqual(order.state, 'paid')
+ self.assertEqual(order.amount_total, values['amount_total'])
+ self.assertEqual(order.amount_tax, values['amount_tax'])
+ self.assertEqual(order.amount_paid, values['amount_paid'])
+ self.assertEqual(order.state, 'paid')
+ self.assertEqual(session.state, 'opened')
+
+ cash_pm = order.payment_ids.filtered(
+ lambda pm: pm.payment_method_id.type == 'cash',
+ )
+ closing_amount = sum(cash_pm.mapped('amount')) + cash_acc
+ session.close_session_from_ui({self.cash_pm.id: closing_amount})
+ move = session.move_ids
+
+ self.assertEqual(session.state, 'closed')
+ self.assertEqual(order.state, 'done')
+
+ if order.is_singly_invoiced and order.account_move:
+ move = order.account_move
+ partner = order.partner_id
+ nb_product = len(order_args['products'])
+ nb_payment = len(order_args['payment_method'])
+ tax_ids = [p[0].taxes_id.ids for p in order_args['products']]
+ flat = [x for xs in tax_ids for x in xs]
+ nb_lines = nb_product + nb_payment + len(flat)
+ self.assertEqual(move.state, 'posted')
+ self.assertEqual(len(move.line_ids), nb_lines)
+ self.assertEqual(move.amount_total, order.amount_total)
+ self.assertEqual(move.amount_tax, order.amount_tax)
+
+ if partner.property_account_receivable_id:
+ receivable = partner.property_account_receivable_id
+
+ payment_term = move.line_ids.filtered(
+ lambda line: line.display_type == 'payment_term',
+ )
+ zipped = zip(order.payment_ids, payment_term)
+ for payment, term in zipped:
+ pm = payment.payment_method_id
+
+ if not order.to_invoice and pm.receivable_account_id:
+ receivable = pm.receivable_account_id
+
+ if pm.type == 'cash':
+ self.assertEqual(term.account_id, receivable)
+ statement = StatementLine.search([
+ ('pos_session_id', '=', order.session_id.id),
+ ])
+ self.assertEqual(len(statement), 1)
+ self.assertEqual(statement.amount, payment.amount)
+ elif pm.type == 'pay_later':
+ session_move = session.sales_move_id
+ self.assertEqual(order.to_invoice, True)
+ self.assertNotEqual(
+ order.account_move,
+ session_move,
+ )
+ acc = self.partner_1.property_account_receivable_id
+ self.assertEqual(term.account_id, acc)
+ elif pm.type == 'bank':
+ payment = BankPayment.search([
+ ('pos_session_id', '=', order.session_id.id),
+ ])
+ self.assertEqual(term.account_id, receivable)
+ self.assertEqual(len(payment), 1)
+ self.assertEqual(payment.amount, term.debit)
+
+ one_product_6_check_values = {
+ 'amount_total': 10.6,
+ 'amount_tax': 0.6,
+ 'amount_paid': 10.6,
+ }
+ create_order_and_check(
+ order_args={
+ 'payment_method': [[self.customer_pm, {'amount': 10.6}]],
+ 'products': [[self.product_6, {}]],
+ 'extra_data': {'partner_id': self.partner_1.id},
+ },
+ values=one_product_6_check_values,
+ )
+ create_order_and_check(
+ order_args={
+ 'payment_method': [[self.bank_pm, {'amount': 10.6}]],
+ 'products': [[self.product_6, {}]],
+ },
+ values=one_product_6_check_values,
+ )
+ create_order_and_check(
+ order_args={
+ 'payment_method': [[self.cash_pm, {'amount': 10.6}]],
+ 'products': [[self.product_6, {}]],
+ },
+ values=one_product_6_check_values,
+ )
+ create_order_and_check(
+ order_args={
+ 'payment_method': [
+ [self.cash_pm, {'amount': 5.3}],
+ [self.bank_pm, {'amount': 5.3}],
+ ],
+ 'products': [[self.product_6, {}]],
+ },
+ values=one_product_6_check_values,
+ )
+ create_order_and_check(
+ order_args={
+ 'payment_method': [
+ [self.bank_pm, {'amount': 2.3}],
+ [self.customer_pm, {'amount': 5.3}],
+ [self.cash_pm, {'amount': 3.0}],
+ ],
+ 'products': [[self.product_6, {}]],
+ 'extra_data': {'partner_id': self.partner_1.id},
+ },
+ values=one_product_6_check_values,
+ )
+ total = 10.6 + 11.2 + 12.1
+ create_order_and_check(
+ order_args={
+ 'payment_method': [[self.bank_pm, {'amount': total}]],
+ 'products': [
+ [self.product_6, {}],
+ [self.product_12, {}],
+ [self.product_21, {}],
+ ],
+ },
+ values={
+ 'amount_total': total,
+ 'amount_paid': total,
+ 'amount_tax': 0.6 + 1.2 + 2.1,
+ },
+ )
+ total = 13.9
+ create_order_and_check(
+ order_args={
+ 'payment_method': [[self.bank_pm, {'amount': total}]],
+ 'products': [
+ [self.product_6_12_21, {}],
+ ],
+ },
+ values={
+ 'amount_total': total,
+ 'amount_paid': total,
+ 'amount_tax': 0.6 + 1.2 + 2.1,
+ },
+ )
+ self.tax_6.price_include_override = 'tax_included'
+ create_order_and_check(
+ order_args={
+ 'payment_method': [[self.bank_pm, {'amount': 10}]],
+ 'products': [[self.product_6, {}]],
+ },
+ values={
+ 'amount_total': 10,
+ 'amount_paid': 10,
+ 'amount_tax': 0.57,
+ },
+ )
+
+ def test_pos_config_with_other_currency_than_company(self):
+ eur = self.env.ref('base.EUR')
+ usd = self.env.ref('base.USD')
+ self.env['res.currency.rate'].search([]).unlink()
+ self.env['res.currency.rate'].create({
+ 'name': '2010-01-01',
+ 'rate': 2.0,
+ 'currency_id': usd.id,
+ })
+
+ self.pos_config.company_id.currency_id = eur
+ self.pos_config.journal_id.currency_id = usd
+ self.pos_config.currency_id = usd
+ self.cash_pm.journal_id.currency_id = usd
+
+ self.assertEqual(self.pos_config.company_id.currency_id, eur)
+ self.assertEqual(self.pos_config.currency_id, usd)
+ self.assertEqual(self.pos_config.journal_id.currency_id, usd)
+ self.assertEqual(self.cash_pm.journal_id.currency_id, usd)
+
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 21.8}]], # Total amount of the order is 10 + 6% tax + 10 + 12% tax = 21.8
+ products=[[self.product_6, {}], [self.product_12, {}]],
+ )
+
+ self.assertEqual(order.amount_total, 21.8)
+ self.assertEqual(order.amount_paid, 21.8)
+ self.assertEqual(order.state, 'paid')
+ self.close_session()
+
+ self.assertTrue(session.move_ids)
+ self.assertEqual(session.move_ids.currency_id, usd)
+
+ total_usd = session.move_ids.amount_total_in_currency_signed
+ total_eur = session.move_ids.amount_total_signed
+ self.assertEqual(total_usd, 21.8)
+ self.assertEqual(total_eur, 10.9) # 21.8 / 2 because of the rate we set on USD
+
+ session = self.open_pos_session()
+ invoiced_order = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 21.8}]], # Total amount of the order is 10 + 6% tax + 10 + 12% tax = 21.8
+ products=[[self.product_6, {}], [self.product_12, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ move = invoiced_order.account_move
+ self.assertEqual(move.currency_id, usd)
+ total_usd = move.amount_total_in_currency_signed
+ total_eur = move.amount_total_signed
+ self.assertEqual(total_usd, 21.8)
+ self.assertEqual(total_eur, 10.9) # 21.8 / 2 because of the rate we set on USD
+
+ def test_accounting_items_when_closing_with_bank_difference(self):
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+ self.assertEqual(order.state, 'paid')
+ session.close_session_from_ui({self.bank_pm.id: 9.6}) # Simulate a bank difference of -1
+ self.assertEqual(session.state, 'closed')
+
+ move = session.correction_move_ids
+ account_names = move.line_ids.mapped('account_id.name')
+ balances = move.line_ids.mapped('balance')
+
+ self.assertEqual(balances, [-1.0, 1.0])
+ self.assertEqual(
+ account_names,
+ ['Accounts Receivable (PoS)', 'Cash Difference Loss'],
+ )
+
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+ self.assertEqual(order.state, 'paid')
+ session.close_session_from_ui({self.bank_pm.id: 11.6}) # Simulate a bank difference of +1
+ self.assertEqual(session.state, 'closed')
+
+ move = session.correction_move_ids
+ account_names = move.line_ids.mapped('account_id.name')
+ balances = move.line_ids.mapped('balance')
+
+ self.assertEqual(balances, [1.0, -1.0])
+ self.assertEqual(
+ account_names,
+ ['Accounts Receivable (PoS)', 'Cash Difference Gain'],
+ )
+
+ def test_pos_order_with_closing_storno(self):
+ with freeze_time('2020-01-01'):
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+ self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': -10.6}]],
+ products=[[self.product_6, {'qty': -1}]],
+ extra_data={
+ 'is_refund': True,
+ 'refunded_order_id': order.id,
+ },
+ )
+ self.close_session()
+ classic_refund = session.refunds_move_id
+ classic_sale = session.sales_move_id
+
+ self.env.company.account_storno = True
+ session = self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ )
+ self.create_pos_order(
+ payment_method=[[self.bank_pm, {'amount': -10.6}]],
+ products=[[self.product_6, {'qty': -1}]],
+ extra_data={
+ 'is_refund': True,
+ 'refunded_order_id': order.id,
+ },
+ )
+ self.close_session()
+ storno_refund = session.refunds_move_id
+ storno_sale = session.sales_move_id
+
+ r_classic_credit = classic_refund.line_ids.mapped('credit')
+ r_classic_debit = classic_refund.line_ids.mapped('debit')
+ r_storno_credit = storno_refund.line_ids.mapped('credit')
+ r_storno_debit = storno_refund.line_ids.mapped('debit')
+
+ self.assertEqual(r_classic_credit, [10.6, 0.0, 0.0])
+ self.assertEqual(r_classic_debit, [0.0, 10.0, 0.6])
+ self.assertEqual(r_storno_credit, [0.0, -10.0, -0.6])
+ self.assertEqual(r_storno_debit, [-10.6, 0.0, 0.0])
+
+ s_classic_credit = classic_sale.line_ids.mapped('credit')
+ s_classic_debit = classic_sale.line_ids.mapped('debit')
+ s_storno_credit = storno_sale.line_ids.mapped('credit')
+ s_storno_debit = storno_sale.line_ids.mapped('debit')
+
+ self.assertEqual(s_classic_credit, s_storno_credit)
+ self.assertEqual(s_classic_debit, s_storno_debit)
+
+ def test_pos_order_session_closing_with_fp(self):
+ """
+ PoS orders can have fiscal positions applied on them. This test
+ will check that when closing a session with orders with fiscal
+ position, the correct taxes are applied and the correct accounts
+ are used for the move lines of the session move.
+
+ Will test to use the tax 21% with a fiscal position that
+ replaces it with the tax 6%.
+
+ Will also test with a product with tax of 12% with no
+ destination tax (0%)
+ """
+ src_account = self.company.income_account_id
+ dest_account = self.env['account.account'].search([
+ ('company_ids', '=', self.company.id),
+ ('account_type', '=', 'income'),
+ ('id', '!=', src_account.id),
+ ], limit=1)
+
+ fp = self.env['account.fiscal.position'].create({
+ 'name': 'Test Fiscal Position',
+ })
+ account_fp = self.env['account.fiscal.position.account'].create({
+ 'position_id': fp.id,
+ 'account_src_id': src_account.id,
+ 'account_dest_id': dest_account.id,
+ })
+ fp.write({
+ 'account_ids': [(6, 0, account_fp.ids)],
+ })
+ self.tax_6.write({
+ 'fiscal_position_ids': [Command.link(fp.id)],
+ 'original_tax_ids': [Command.link(self.tax_21.id)],
+ })
+ self.env['account.tax'].create({
+ 'name': 'Tax 0%',
+ 'amount': 0,
+ 'fiscal_position_ids': [Command.link(fp.id)],
+ 'original_tax_ids': [Command.link(self.tax_12.id)],
+ })
+
+ # So when selling a product with 21% tax, the fiscal position
+ # should replace it with the 6% tax
+ session = self.open_pos_session()
+ order_with_fp = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.6}]], # Fiscal position apply 6% tax instead of 21% tax
+ products=[[self.product_21, {}]],
+ extra_data={
+ 'fiscal_position_id': fp.id,
+ },
+ )
+ self.assertEqual(order_with_fp.amount_total, 10.6)
+ self.assertEqual(order_with_fp.amount_tax, 0.6)
+ self.assertEqual(order_with_fp.amount_paid, 10.6)
+ self.assertEqual(order_with_fp.state, 'paid')
+
+ order_without_fp = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 12.1}]], # No fiscal position, so 21% tax should be applied
+ products=[[self.product_21, {}]],
+ )
+ self.assertEqual(order_without_fp.amount_total, 12.1)
+ self.assertEqual(order_without_fp.amount_tax, 2.1)
+ self.assertEqual(order_without_fp.amount_paid, 12.1)
+ self.assertEqual(order_without_fp.state, 'paid')
+
+ order_with_0_tax = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10}]], # Fiscal position applies 0% tax instead of 12% tax
+ products=[[self.product_12, {}]],
+ extra_data={
+ 'fiscal_position_id': fp.id,
+ },
+ )
+ self.assertEqual(order_with_0_tax.amount_total, 10)
+ self.assertEqual(order_with_0_tax.amount_tax, 0)
+ self.assertEqual(order_with_0_tax.amount_paid, 10)
+ self.assertEqual(order_with_0_tax.state, 'paid')
+ self.close_session()
+ move = session.move_ids
+ product_line = move.line_ids.filtered(
+ lambda line: line.display_type == 'product',
+ )
+ tax_lines = move.line_ids.filtered(
+ lambda line: line.display_type == 'tax',
+ )
+
+ tax_sorted = tax_lines.sorted('balance')
+ self.assertEqual(tax_sorted[0].balance, -2.1)
+ self.assertEqual(tax_sorted[1].balance, -0.6)
+
+ product_line_6 = product_line.filtered(
+ lambda line: self.tax_6 in line.tax_ids,
+ )
+ product_line_21 = product_line.filtered(
+ lambda line: self.tax_21 in line.tax_ids,
+ )
+ product_line_0 = product_line - product_line_6 - product_line_21
+ self.assertEqual(product_line_6.account_id, dest_account) # Product line with tax_6 should be posted on the dest account of the fiscal position
+ self.assertEqual(product_line_21.account_id, src_account) # Product line with tax_21 should be posted on the src account of the fiscal position
+ self.assertEqual(product_line_0.account_id, dest_account)
+
+ def test_pos_order_invoice_with_fp(self):
+ src_account = self.company.income_account_id
+ dest_account = self.env['account.account'].search([
+ ('company_ids', '=', self.company.id),
+ ('account_type', '=', 'income'),
+ ('id', '!=', src_account.id),
+ ], limit=1)
+
+ fp = self.env['account.fiscal.position'].create({
+ 'name': 'Test Fiscal Position',
+ })
+ account_fp = self.env['account.fiscal.position.account'].create({
+ 'position_id': fp.id,
+ 'account_src_id': src_account.id,
+ 'account_dest_id': dest_account.id,
+ })
+ fp.write({
+ 'account_ids': [(6, 0, account_fp.ids)],
+ })
+ self.tax_6.write({
+ 'fiscal_position_ids': [Command.link(fp.id)],
+ 'original_tax_ids': [Command.link(self.tax_21.id)],
+ })
+ self.env['account.tax'].create({
+ 'name': 'Tax 0%',
+ 'amount': 0,
+ 'fiscal_position_ids': [Command.link(fp.id)],
+ 'original_tax_ids': [Command.link(self.tax_12.id)],
+ })
+
+ # So when selling a product with 21% tax, the fiscal position
+ # should replace it with the 6% tax
+ session = self.open_pos_session()
+ order_with_fp = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10.6}]], # Fiscal position apply 6% tax instead of 21% tax
+ products=[[self.product_21, {}]],
+ extra_data={
+ 'fiscal_position_id': fp.id,
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ self.assertEqual(order_with_fp.amount_total, 10.6)
+ self.assertEqual(order_with_fp.amount_tax, 0.6)
+ self.assertEqual(order_with_fp.amount_paid, 10.6)
+ self.assertEqual(order_with_fp.state, 'paid')
+ self.assertEqual(order_with_fp.account_move.state, 'posted')
+ move = order_with_fp.account_move
+ self.assertEqual(move.fiscal_position_id, fp)
+
+ order_without_fp = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 12.1}]], # No fiscal position, so 21% tax should be applied
+ products=[[self.product_21, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ self.assertEqual(order_without_fp.amount_total, 12.1)
+ self.assertEqual(order_without_fp.amount_tax, 2.1)
+ self.assertEqual(order_without_fp.amount_paid, 12.1)
+ self.assertEqual(order_without_fp.state, 'paid')
+ self.assertEqual(order_without_fp.account_move.state, 'posted')
+ move = order_without_fp.account_move
+ self.assertFalse(move.fiscal_position_id)
+
+ order_with_0_tax = self.create_pos_order(
+ payment_method=[[self.cash_pm, {'amount': 10}]], # Fiscal position applies 0% tax instead of 12% tax
+ products=[[self.product_12, {}]],
+ extra_data={
+ 'fiscal_position_id': fp.id,
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ self.assertEqual(order_with_0_tax.amount_total, 10)
+ self.assertEqual(order_with_0_tax.amount_tax, 0)
+ self.assertEqual(order_with_0_tax.amount_paid, 10)
+ self.assertEqual(order_with_0_tax.state, 'paid')
+ self.assertEqual(order_with_0_tax.account_move.state, 'posted')
+ move = order_with_0_tax.account_move
+ self.assertEqual(move.fiscal_position_id, fp)
+ self.close_session()
+ self.assertFalse(session.move_ids)
+
+ def test_pos_order_with_company_branch(self):
+ branch = self.env['res.company'].create({
+ 'name': 'Sub Company',
+ 'parent_id': self.env.company.id,
+ 'chart_template': self.env.company.chart_template,
+ 'country_id': self.env.company.country_id.id,
+ })
+ self.env.cr.precommit.run()
+
+ AccJournal = self.env['account.journal'].with_company(branch)
+ PosPm = self.env['pos.payment.method'].with_company(branch)
+ PosConfig = self.env['pos.config'].with_company(branch)
+
+ cash_journal = AccJournal.create({
+ 'name': 'Cash Test',
+ 'type': 'cash',
+ 'company_id': branch.id,
+ 'code': 'CSH',
+ 'sequence': 10,
+ })
+ cash_pm = PosPm.create({
+ 'name': 'Bank',
+ 'type': 'cash',
+ 'journal_id': cash_journal.id,
+ })
+ self.pos_config = PosConfig.create({
+ 'name': 'Main - Sub Company',
+ 'journal_id': self.company_data['default_journal_sale'].id,
+ 'payment_method_ids': [(4, cash_pm.id)],
+ })
+
+ self.open_pos_session()
+ order = self.create_pos_order(
+ payment_method=[[cash_pm, {'amount': 10.6}]],
+ products=[[self.product_6, {}]],
+ extra_data={
+ 'partner_id': self.partner_1.id,
+ 'to_invoice': True,
+ },
+ )
+ self.close_session()
+ self.assertEqual(order.config_id, self.pos_config)
diff --git a/addons/point_of_sale/tests/test_pos_accounting_http.py b/addons/point_of_sale/tests/test_pos_accounting_http.py
new file mode 100644
index 00000000000000..7249e20d0417ff
--- /dev/null
+++ b/addons/point_of_sale/tests/test_pos_accounting_http.py
@@ -0,0 +1,68 @@
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+import json
+
+from odoo.tests import HttpCase
+
+from odoo.addons.point_of_sale.tests.test_pos_accounting import TestPosAccounting
+
+
+class TestPosAccountingHttp(HttpCase, TestPosAccounting):
+ def _get_url(self, pos_config=None):
+ pos_config = pos_config or self.pos_config
+ return f"/pos/ui/{pos_config.id}"
+
+ def start_pos_tour(self, tour_name, **kwargs):
+ self.start_tour(self._get_url(pos_config=kwargs.get('pos_config')), tour_name, login=self.env.user.login, **kwargs)
+
+ def test_baseline_between_frontend_and_backend(self):
+ company = self.pos_config.company_id
+ company.tax_calculation_rounding_method = 'round_globally'
+
+ only_categ = self.env['pos.category'].create(
+ {'name': 'Only Category'},
+ )
+ self.pos_config.write({
+ 'limit_categories': True,
+ 'iface_available_categ_ids': [(6, 0, [only_categ.id])],
+ })
+ tax_16 = self.env['account.tax'].create({
+ 'name': 'Tax 16%',
+ 'amount': 16,
+ })
+ self.env['product.product'].create([{
+ 'name': 'Test Product 1',
+ 'list_price': 7051.73,
+ 'pos_categ_ids': [(6, 0, [only_categ.id])],
+ 'taxes_id': [(6, 0, [tax_16.id])],
+ 'available_in_pos': True,
+ }, {
+ 'name': 'Test Product 2',
+ 'list_price': 352.59,
+ 'pos_categ_ids': [(6, 0, [only_categ.id])],
+ 'taxes_id': [(6, 0, [tax_16.id])],
+ 'available_in_pos': True,
+ }])
+
+ def get_frontend_data(self, frontend_data):
+ frontend_data = json.loads(frontend_data)
+ base_lines = self.lines._prepare_base_lines_for_taxes_computation()
+ zipped = zip(frontend_data['baseLines'], base_lines)
+ for frontend_line, backend_line in zipped:
+ if frontend_line.get('is_refund', False) != backend_line['is_refund']:
+ error = "Refund status mismatch between frontend and backend"
+ raise ValueError(error)
+
+ if frontend_line.get('quantity', 0) != backend_line['quantity']:
+ error = "Quantity mismatch between frontend and backend"
+ raise ValueError(error)
+
+ if frontend_line.get('sign') != backend_line['sign']:
+ error = "Sign mismatch between frontend and backend"
+ raise ValueError(error)
+
+ # Add function to model
+ order_model = self.env.registry.models['pos.order']
+ order_model.get_frontend_data = get_frontend_data
+
+ self.open_pos_session()
+ self.start_pos_tour('test_baseline_between_frontend_and_backend')
diff --git a/addons/point_of_sale/tests/test_pos_basic_config.py b/addons/point_of_sale/tests/test_pos_basic_config.py
index 0fa0d28f497e00..9ce16be6b884d5 100644
--- a/addons/point_of_sale/tests/test_pos_basic_config.py
+++ b/addons/point_of_sale/tests/test_pos_basic_config.py
@@ -1,15 +1,10 @@
-# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo
-from odoo import fields
from odoo.addons.point_of_sale.tests.common import TestPoSCommon
from odoo.exceptions import ValidationError, UserError
-from freezegun import freeze_time
-from dateutil.relativedelta import relativedelta
from datetime import datetime, timedelta
-import unittest.mock
@odoo.tests.tagged('post_install', '-at_install')
@@ -32,820 +27,6 @@ def setUp(self):
self.product_multi_tax = self.create_product('Multi-tax product', self.categ_basic, 100, 100, (self.taxes['tax8'] | self.taxes['tax9']).ids)
self.company_data_2 = self.setup_other_company()
- def test_orders_no_invoiced(self):
- """ Test for orders without invoice
-
- 3 orders
- - first 2 orders with cash payment
- - last order with bank payment
-
- Orders
- ======
- +---------+----------+-----------+----------+-----+-------+
- | order | payments | invoiced? | product | qty | total |
- +---------+----------+-----------+----------+-----+-------+
- | order 1 | cash | no | product1 | 10 | 100 |
- | | | | product2 | 5 | 100 |
- +---------+----------+-----------+----------+-----+-------+
- | order 2 | cash | no | product2 | 7 | 140 |
- | | | | product3 | 1 | 30 |
- +---------+----------+-----------+----------+-----+-------+
- | order 3 | bank | no | product1 | 1 | 10 |
- | | | | product2 | 3 | 60 |
- | | | | product3 | 5 | 150 |
- +---------+----------+-----------+----------+-----+-------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | sale | -590 |
- | pos receivable cash | 370 |
- | pos receivable bank | 220 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
- start_qty_available = {
- self.product1: self.product1.qty_available,
- self.product2: self.product2.qty_available,
- self.product3: self.product3.qty_available,
- }
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- # check product qty_available after syncing the order
- self.assertEqual(
- self.product1.qty_available + 11,
- start_qty_available[self.product1],
- )
- self.assertEqual(
- self.product2.qty_available + 15,
- start_qty_available[self.product2],
- )
- self.assertEqual(
- self.product3.qty_available + 6,
- start_qty_available[self.product3],
- )
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 5)], 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product2, 7), (self.product3, 1)], 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product1, 1), (self.product3, 5), (self.product2, 3)], 'payments': [(self.bank_pm1, 220)], 'uuid': '00100-010-0003'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 590, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 220, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 370, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((370, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 370, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 370, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((220, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 220, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 220, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_orders_with_invoiced(self):
- """ Test for orders: one with invoice
-
- 3 orders
- - order 1, paid by cash
- - order 2, paid by bank
- - order 3, paid by bank, invoiced
-
- Orders
- ======
- +---------+----------+---------------+----------+-----+-------+
- | order | payments | invoiced? | product | qty | total |
- +---------+----------+---------------+----------+-----+-------+
- | order 1 | cash | no | product1 | 6 | 60 |
- | | | | product2 | 3 | 60 |
- | | | | product3 | 1 | 30 |
- +---------+----------+---------------+----------+-----+-------+
- | order 2 | bank | no | product1 | 1 | 10 |
- | | | | product2 | 20 | 400 |
- +---------+----------+---------------+----------+-----+-------+
- | order 3 | bank | yes, customer | product1 | 10 | 100 |
- | | | | product3 | 1 | 30 |
- +---------+----------+---------------+----------+-----+-------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | sale | -560 |
- | pos receivable cash | 150 |
- | pos receivable bank | 540 |
- | receivable | -130 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
- start_qty_available = {
- self.product1: self.product1.qty_available,
- self.product2: self.product2.qty_available,
- self.product3: self.product3.qty_available,
- }
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- # check product qty_available after syncing the order
- self.assertEqual(
- self.product1.qty_available + 17,
- start_qty_available[self.product1],
- )
- self.assertEqual(
- self.product2.qty_available + 23,
- start_qty_available[self.product2],
- )
- self.assertEqual(
- self.product3.qty_available + 2,
- start_qty_available[self.product3],
- )
-
- # check account move in the invoiced order
- invoiced_order = self.pos_session.order_ids.filtered(lambda order: order.account_move)
- self.assertEqual(1, len(invoiced_order), 'Only one order is invoiced in this test.')
-
- # check account_move of orders before validating the session.
- self.assertTrue(invoiced_order.account_move, msg="Invoiced orders must have account_move.")
- uninvoiced_orders = self.pos_session.order_ids - invoiced_order
- self.assertTrue(
- all(not order.account_move for order in uninvoiced_orders),
- msg="Uninvoiced orders do not have account_move."
- )
-
- def _after_closing_cb():
- # check state of orders after validating the session.
- uninvoiced_orders = self.pos_session.order_ids.filtered(lambda order: not order.is_invoiced)
- self.assertTrue(
- all([order.state == 'done' for order in uninvoiced_orders]),
- msg="State should be 'done' for uninvoiced orders after validating the session."
- )
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 6), (self.product2, 3), (self.product3, 1), ], 'payments': [(self.cash_pm1, 150)], 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 1), (self.product2, 20), ], 'payments': [(self.bank_pm1, 410)], 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product3, 1), ], 'payments': [(self.bank_pm1, 130)], 'is_invoiced': True, 'customer': self.customer, 'uuid': '00100-010-0003'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {
- '00100-010-0003': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 30, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 130, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 130), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 130, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 130, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'after_closing_cb': _after_closing_cb,
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 560, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 540, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 150, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 130, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((150, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 150, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 150, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((540, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 540, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 540, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_orders_with_zero_valued_invoiced(self):
- """One invoiced order but with zero receivable line balance."""
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product0, 1)], 'payments': [(self.bank_pm1, 0)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 0), False),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': False,
- 'cash_statement': [],
- 'bank_payments': [],
- },
- })
-
- def test_return_order_invoiced(self):
-
- def _before_closing_cb():
- order = self.pos_session.order_ids.filtered(lambda order: '666-666-666' in order.uuid)
-
- # refund
- order.refund()
- refund_order = self.pos_session.order_ids.filtered(lambda order: order.state == 'draft')
-
- # pay the refund
- context_make_payment = {"active_ids": [refund_order.id], "active_id": refund_order.id}
- make_payment = self.env['pos.make.payment'].with_context(context_make_payment).create({
- 'payment_method_id': self.cash_pm1.id,
- 'amount': -100,
- })
- make_payment.check()
-
- # invoice refund
- refund_order.action_pos_order_invoice()
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments': [(self.cash_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '666-666-666'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {
- '666-666-666': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_pm1, 100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [],
- },
- })
-
- def test_return_order(self):
- """ Test return order
-
- 2 orders
- - 2nd order is returned
-
- Orders
- ======
- +------------------+----------+-----------+----------+-----+-------+
- | order | payments | invoiced? | product | qty | total |
- +------------------+----------+-----------+----------+-----+-------+
- | order 1 | bank | no | product1 | 1 | 10 |
- | | | | product2 | 5 | 100 |
- +------------------+----------+-----------+----------+-----+-------+
- | order 2 | cash | no | product1 | 3 | 30 |
- | | | | product2 | 2 | 40 |
- | | | | product3 | 1 | 30 |
- +------------------+----------+-----------+----------+-----+-------+
- | order 3 (return) | cash | no | product1 | -3 | -30 |
- | | | | product2 | -2 | -40 |
- | | | | product3 | -1 | -30 |
- +------------------+----------+-----------+----------+-----+-------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | sale (sales) | -210 |
- | sale (refund) | 100 |
- | pos receivable bank | 110 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
- start_qty_available = {
- self.product1: self.product1.qty_available,
- self.product2: self.product2.qty_available,
- self.product3: self.product3.qty_available,
- }
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(2, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- # return order
- order_to_return = self.pos_session.order_ids.filtered(lambda order: '12345-123-1234' in order.uuid)
- order_to_return.refund()
- refund_order = self.pos_session.order_ids.filtered(lambda order: order.state == 'draft')
-
- # check if amount to pay
- self.assertAlmostEqual(refund_order.amount_total - refund_order.amount_paid, -100)
-
- # pay the refund
- context_make_payment = {"active_ids": [refund_order.id], "active_id": refund_order.id}
- make_payment = self.env['pos.make.payment'].with_context(context_make_payment).create({
- 'payment_method_id': self.cash_pm1.id,
- 'amount': -100,
- })
- make_payment.check()
- self.assertEqual(refund_order.state, 'paid', 'Payment is registered, order should be paid.')
- self.assertAlmostEqual(refund_order.amount_paid, -100.0, msg='Amount paid for return order should be negative.')
-
- # check product qty_available after syncing the order
- self.assertEqual(
- self.product1.qty_available + 1,
- start_qty_available[self.product1],
- )
- self.assertEqual(
- self.product2.qty_available + 5,
- start_qty_available[self.product2],
- )
- self.assertEqual(
- self.product3.qty_available,
- start_qty_available[self.product3],
- )
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 1), (self.product2, 5)], 'payments': [(self.bank_pm1, 110)], 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 3), (self.product2, 2), (self.product3, 1)], 'payments': [(self.cash_pm1, 100)], 'uuid': '12345-123-1234'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 210, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 110, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((110, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 110, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 110, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_split_cash_payments(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 5)], 'payments': [(self.cash_split_pm1, 100), (self.bank_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product2, 7), (self.product3, 1)], 'payments': [(self.cash_split_pm1, 70), (self.bank_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product1, 1), (self.product3, 5), (self.product2, 3)], 'payments': [(self.cash_split_pm1, 120), (self.bank_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0003'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 590, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 300, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 70, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 120, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- }),
- ((70, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 70, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 70, 'reconciled': True},
- ]
- }),
- ((120, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 120, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 120, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((300, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 300, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 300, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_rounding_method(self):
- # set the cash rounding method
- self.config.cash_rounding = True
- self.config.rounding_method = self.env['account.cash.rounding'].create({
- 'name': 'add_invoice_line',
- 'rounding': 0.05,
- 'strategy': 'add_invoice_line',
- 'profit_account_id': self.company['default_cash_difference_income_account_id'].copy().id,
- 'loss_account_id': self.company['default_cash_difference_expense_account_id'].copy().id,
- 'rounding_method': 'HALF-UP',
- })
-
- self.open_new_session()
-
- """ Test for orders: one with invoice
-
- 3 orders
- - order 1, paid by cash
- - order 2, paid by bank
- - order 3, paid by bank, invoiced
-
- Orders
- ======
- +---------+----------+---------------+----------+-----+-------+
- | order | payments | invoiced? | product | qty | total |
- +---------+----------+---------------+----------+-----+-------+
- | order 1 | bank | no | product1 | 6 | 60 |
- | | | | product4 | 4 | 39.84 |
- +---------+----------+---------------+----------+-----+-------+
- | order 2 | bank | yes | product4 | 3 | 29.88 |
- | | | | product2 | 20 | 400 |
- +---------+----------+---------------+----------+-----+-------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | sale | -596,56 |
- | pos receivable bank | 516,64 |
- | Rounding applied | -0,01 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
-
- # create orders
- orders = []
-
- # create orders
- orders = []
- orders.append(self.create_ui_order_data(
- [(self.product4, 3), (self.product2, 20)],
- payments=[(self.bank_pm1, 429.90)]
- ))
-
- orders.append(self.create_ui_order_data(
- [(self.product1, 6), (self.product4, 4)],
- payments=[(self.bank_pm1, 99.85)]
- ))
-
- # sync orders
- self.env['pos.order'].sync_from_ui(orders)
-
- self.assertEqual(orders[0]['amount_return'], 0, msg='The amount return should be 0')
- self.assertEqual(orders[1]['amount_return'], 0, msg='The amount return should be 0')
-
- # close the session
- self.pos_session.action_pos_session_validate()
-
- # check values after the session is closed
- session_account_move = self.pos_session.move_id
-
- rounding_line = session_account_move.line_ids.filtered(lambda line: line.name == 'Rounding line')
- self.assertAlmostEqual(rounding_line.credit, 0.03, msg='The credit should be equals to 0.03')
-
- def test_correct_partner_on_invoice_receivables(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.cash_split_pm1 | self.bank_pm1 | self.bank_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.cash_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.bank_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.cash_split_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0003'},
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.bank_split_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0004'},
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.cash_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0005'},
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.bank_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0006'},
- {'pos_order_lines_ui_args': [(self.product99, 1)], 'payments':[(self.cash_split_pm1, 99)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0007'},
- {'pos_order_lines_ui_args': [(self.product99, 1)], 'payments':[(self.bank_split_pm1, 99)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0008'},
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.bank_pm1, 100)], 'customer': self.other_customer, 'is_invoiced': True, 'uuid': '00100-010-0009'},
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.bank_pm1, 100)], 'customer': self.other_customer, 'is_invoiced': True, 'uuid': '00100-010-0010'},
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'payments':[(self.bank_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0011'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_pm1, 100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '00100-010-0002': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '00100-010-0003': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_split_pm1, 100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '00100-010-0004': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_split_pm1, 100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '00100-010-0009': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 100), {
- 'line_ids': [
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '00100-010-0010': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 100), {
- 'line_ids': [
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '00100-010-0011': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 398, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 500, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 99, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 99, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 400, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- }),
- ((99, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 99, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 99, 'reconciled': True},
- ]
- }),
- ((200, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- }),
- ((99, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 99, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 99, 'reconciled': True},
- ]
- }),
- ((500, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 500, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 500, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_cash_register_if_no_order(self):
- # Process one order with product3
- self.open_new_session(0)
- session = self.pos_session
- order_data = self.create_ui_order_data([(self.product3, 1)])
- amount_paid = order_data['amount_paid']
- with (
- self.assertLogs('odoo.addons.point_of_sale.models.pos_order') as cm,
- unittest.mock.patch('odoo.addons.point_of_sale.models.pos_order.randrange', return_value=1996)
- ):
- self.env['ir.config_parameter'].sudo().set_bool('point_of_sale.log_order_data', True)
- res = self.env['pos.order'].sync_from_ui([order_data])
- # Basic check for logs on order synchronization
- order_log_str = self.env['pos.order']._get_order_log_representation(order_data)
- odoo_order_id = res['pos.order'][0]['id']
- self.assertEqual(len(cm.output), 4)
- self.assertEqual(cm.output[0], f"INFO:odoo.addons.point_of_sale.models.pos_order:PoS synchronisation #1996 started for PoS orders references: [{order_log_str}]")
- self.assertTrue(cm.output[1].startswith(f'INFO:odoo.addons.point_of_sale.models.pos_order:PoS synchronisation #1996 processing order {order_log_str} order full data:'))
- self.assertEqual(cm.output[2], f'INFO:odoo.addons.point_of_sale.models.pos_order:PoS synchronisation #1996 order {order_log_str} created pos.order #{odoo_order_id}')
- self.assertEqual(cm.output[3], 'INFO:odoo.addons.point_of_sale.models.pos_order:PoS synchronisation #1996 finished')
-
- session.post_closing_cash_details(amount_paid)
- session.close_session_from_ui()
-
- self.assertEqual(session.cash_register_balance_start, 0)
- self.assertEqual(session.cash_register_balance_end_real, amount_paid)
-
- # Open/Close session without any order in cash control
- self.open_new_session(amount_paid)
- session = self.pos_session
- session.post_closing_cash_details(amount_paid)
- session.close_session_from_ui()
- self.assertEqual(session.cash_register_balance_start, amount_paid)
- self.assertEqual(session.cash_register_balance_end_real, amount_paid)
- self.assertEqual(self.config.last_session_closing_cash, amount_paid)
-
- def test_start_balance_with_two_pos(self):
- """ When having several POS with cash control, this tests ensures that each POS has its correct opening amount """
-
- def open_and_check(pos_data):
- self.config = pos_data['config']
- self.open_new_session(pos_data['amount_paid'])
- session = self.pos_session
- self.assertEqual(session.cash_register_balance_start, pos_data['amount_paid'])
-
- pos01_config = self.config
- self.cash_journal = self.env['account.journal'].create(
- {'name': 'CASH journal', 'type': 'cash', 'code': 'CSH00'})
- self.cash_payment_method = self.env['pos.payment.method'].create({
- 'name': 'Cash Test',
- 'journal_id': self.cash_journal.id,
- 'receivable_account_id': pos01_config.payment_method_ids.filtered(lambda s: s.is_cash_count)[
- 1].receivable_account_id.id
- })
- pos02_config = pos01_config.copy({
- 'payment_method_ids': self.cash_payment_method
- })
- pos01_data = {'config': pos01_config, 'p_qty': 1, 'amount_paid': 0}
- pos02_data = {'config': pos02_config, 'p_qty': 3, 'amount_paid': 0}
-
- for pos_data in [pos01_data, pos02_data]:
- open_and_check(pos_data)
- session = self.pos_session
-
- order_data = self.create_ui_order_data([(self.product3, pos_data['p_qty'])])
- pos_data['amount_paid'] += order_data['amount_paid']
- self.env['pos.order'].sync_from_ui([order_data])
-
- session.post_closing_cash_details(pos_data['amount_paid'])
- session.close_session_from_ui()
-
- open_and_check(pos01_data)
- open_and_check(pos02_data)
-
def test_pos_session_name_sequencing(self):
""" This test check if the session name is correctly set according to the sequence """
@@ -897,194 +78,6 @@ def test_load_data_picks_the_company_website_domain(self):
self.assertEqual(response['pos.config'][0]['_base_url'], company_website.domain)
- def test_invoice_past_refund(self):
- """ Test invoicing a past refund
-
- Orders
- ======
- +------------------+----------+-----------+----------+-----+-------+
- | order | payments | invoiced? | product | qty | total |
- +------------------+----------+-----------+----------+-----+-------+
- | order 1 | cash | no | product3 | 1 | 30 |
- +------------------+----------+-----------+----------+-----+-------+
- | order 2 (return) | cash | no | product3 | -1 | -30 |
- +------------------+----------+-----------+----------+-----+-------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | sale (sales) | -30 |
- | sale (refund) | 30 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
- def _before_closing_cb():
- # Return the order
- order_to_return = self.pos_session.order_ids.filtered(lambda order: '12345-123-1234' in order.uuid)
- order_to_return.refund()
- refund_order = self.pos_session.order_ids.filtered(lambda order: order.state == 'draft')
-
- # Check if there's an amount to pay
- self.assertAlmostEqual(refund_order.amount_total - refund_order.amount_paid, -30)
-
- # Pay the refund
- context_make_payment = {"active_ids": [refund_order.id], "active_id": refund_order.id}
- make_payment = self.env['pos.make.payment'].with_context(context_make_payment).create({
- 'payment_method_id': self.cash_pm1.id,
- 'amount': -30,
- })
- make_payment.check()
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product3, 1)], 'payments': [(self.cash_pm1, 30)], 'uuid': '12345-123-1234'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 30, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 30, 'credit': 0, 'reconciled': False},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [],
- },
- })
-
- closed_session = self.pos_session
- self.assertTrue(closed_session.state == 'closed', 'Session should be closed.')
-
- return_to_invoice = closed_session.order_ids[1]
- test_customer = self.env['res.partner'].create({'name': 'Test Customer'})
- new_session_date = return_to_invoice.date_order + relativedelta(days=2)
-
- with freeze_time(new_session_date):
- # Create a new session after 2 days
- self.open_new_session(0)
- # Invoice the uninvoiced refund
- return_to_invoice.write({'partner_id': test_customer.id})
- return_to_invoice.action_pos_order_invoice()
- # Check the credit note
- self.assertTrue(return_to_invoice.account_move, 'Invoice should be created.')
- self.assertEqual(return_to_invoice.account_move.move_type, 'out_refund', 'Invoice should be a credit note.')
- self.assertEqual(return_to_invoice.account_move.invoice_date, new_session_date.date(), 'Invoice date should be the same as the session it is created in.')
- self.assertRecordValues(return_to_invoice.account_move, [{
- 'amount_untaxed': 30,
- 'amount_tax': 0,
- 'amount_total': 30,
- }])
- self.assertRecordValues(return_to_invoice.account_move.line_ids, [
- {'account_id': self.sales_account.id, 'balance': 30},
- {'account_id': self.receivable_account.id, 'balance': -30},
- ])
-
- def test_invoice_past_order(self):
- # create 1 uninvoiced order then close the session
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product99, 1)], 'payments': [(self.bank_pm1, 99)], 'customer': False, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 99, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 99, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((99, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 99, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 99, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- # keep reference of the closed session
- closed_session = self.pos_session
- self.assertTrue(closed_session.state == 'closed', 'Session should be closed.')
-
- order_to_invoice = closed_session.order_ids[0]
- test_customer = self.env['res.partner'].create({'name': 'Test Customer'})
-
- with freeze_time(fields.Datetime.now() + relativedelta(days=2)):
- # create new session after 2 days
- self.open_new_session(0)
- # invoice the uninvoiced order
- order_to_invoice.write({'partner_id': test_customer.id})
- order_to_invoice.action_pos_order_invoice()
- # check invoice
- invoice = order_to_invoice.account_move
- self.assertTrue(invoice, 'Invoice should be created.')
- self.assertNotEqual(invoice.invoice_date, order_to_invoice.date_order.date(), 'Invoice date should not be the same as order date since the session was closed.')
-
- # check that the payment date is set to the order date which
- # is the real payment date and not to the invoice_date
- payment = invoice.line_ids.full_reconcile_id.reconciled_line_ids.move_id - invoice
- self.assertEqual(payment.date, order_to_invoice.date_order.date())
-
- def test_invoice_past_order_affecting_taxes(self):
- """ Test whether two taxes affecting each other don't trigger a recomputation on invoice generation
- """
- # Create 1 uninvoiced order then close the session
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product_multi_tax, 1)], 'payments': [(self.bank_pm1, 117.72)], 'customer': False, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 8, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 9.72, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 117.72, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((117.72, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 117.72, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 117.72, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- closed_session = self.pos_session
- self.assertTrue(closed_session.state == 'closed', 'Session should be closed.')
-
- order_to_invoice = closed_session.order_ids[0]
- test_customer = self.env['res.partner'].create({'name': 'Test Customer'})
-
- # Create a new session
- self.open_new_session(0)
- # Invoice the uninvoiced order
- order_to_invoice.write({'partner_id': test_customer.id})
- order_to_invoice.action_pos_order_invoice()
- # Check the invoice for the lines
- self.assertTrue(order_to_invoice.account_move, 'Invoice should be created.')
- self.assertRecordValues(order_to_invoice.account_move.line_ids, [
- {'account_id': self.sales_account.id, 'balance': -100, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'balance': -8, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'balance': -9.72, 'reconciled': False},
- {'account_id': self.receivable_account.id, 'balance': 117.72, 'reconciled': True},
- ])
-
def test_limited_products_loading(self):
self.env['ir.config_parameter'].sudo().set_int('point_of_sale.limited_product_count', 3)
@@ -1115,86 +108,6 @@ def get_top_product_ids(count):
self.env['pos.order'].sync_from_ui([self.create_ui_order_data([(self.product3, 1)])])
self.assertEqual(get_top_product_ids(3), [self.product1.id, self.product2.id, self.product3.id])
- def test_closing_entry_by_product(self):
- # set the Group by Product at Closing Entry
- self.config.use_closing_entry_by_product = True
- self.open_new_session()
-
- # 4 orders
-
- # Orders
- # ======
- # +---------+----------+---------------+----------+-----+-------+
- # | order | payments | invoiced? | product | qty | total |
- # +---------+----------+---------------+----------+-----+-------+
- # | order 1 | bank | no | product1 | 2 | 60 |
- # | | | | product4 | 3 | 39.84 |
- # +---------+----------+---------------+----------+-----+-------+
- # | order 2 | bank | yes | product4 | 1 | 29.88 |
- # | | | | product2 | 5 | 400 |
- # +---------+----------+---------------+----------+-----+-------+
- # | order 3 | bank | yes | product1 | 3 | 29.88 |
- # | | | | product2 | 10 | 400 |
- # +---------+----------+---------------+----------+-----+-------+
- # | order 4 | bank | yes | product1 | 5 | 29.88 |
- # | | | | product0 | 10| 400 |
- # +---------+----------+---------------+----------+-----+-------+
-
- # Expected Output
- # +---------------+-----------+
- # | invoice_line | Quantity |
- # +---------------+-----------+
- # | Product 0 | 10 |
- # +---------------+-----------+
- # | Product 1 | 10 |
- # +---------------+-----------+
- # | Product 2 | 15 |
- # +---------------+-----------+
- # | Product 4 | 4 |
- # +---------------+-----------+
-
- # create orders
- orders = []
-
- # create orders
- orders = []
- orders.append(self.create_ui_order_data(
- [(self.product1, 2), (self.product4, 3)],
- payments=[(self.bank_pm1, 49.88)]
- ))
- orders.append(self.create_ui_order_data(
- [(self.product4, 1), (self.product2, 5)],
- payments=[(self.bank_pm1, 109.96)]
- ))
- orders.append(self.create_ui_order_data(
- [(self.product1, 3), (self.product2, 10)],
- payments=[(self.bank_pm1, 230)]
- ))
- orders.append(self.create_ui_order_data(
- [(self.product1, 5), (self.product0, 10)],
- payments=[(self.bank_pm1, 50)]
- ))
-
- # sync orders
- self.env['pos.order'].sync_from_ui(orders)
- # close the session
- self.pos_session.action_pos_session_validate()
-
- # check values after the session is closed
- session_account_move = self.pos_session.move_id
-
- # Define expected quantities for each product
- expected_product_quantity = {
- self.product0: 10,
- self.product1: 10,
- self.product2: 15,
- self.product4: 4,
- }
- # Iterate through invoice lines and assert the expected quantities
- for i in session_account_move.line_ids:
- if i.product_id and expected_product_quantity.get(i.product_id):
- self.assertEqual(i.quantity, expected_product_quantity.get(i.product_id), f"Unexpected quantity for {i.product_id.name}")
-
def test_pos_payment_method_copy(self):
"""
Test POS payment method copy:
@@ -1228,21 +141,26 @@ def test_single_config_global_invoice(self):
# sync orders
self.env['pos.order'].sync_from_ui(orders)
# close the session
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
pos_orders = self.env['pos.order'].search([])
# set customer for the orders
pos_orders.write({'partner_id': self.customer.id})
# create consolidated invoice
- self.env['pos.make.invoice'].create({"consolidated_billing": True}).with_context({"active_ids": pos_orders.ids}).action_create_invoices()
+ self.env['pos.make.invoice'].create({
+ "consolidated_billing": True,
+ }).with_context({
+ "active_ids": pos_orders.ids,
+ }).action_create_invoices()
# check if have single invoice
self.assertEqual(len(pos_orders), 2)
self.assertEqual(len(pos_orders.account_move), 1)
self.assertEqual(pos_orders.account_move.partner_id, self.customer)
self.assertEqual(pos_orders.account_move.amount_total, sum(pos_orders.mapped('amount_total')))
- self.assertEqual(pos_orders.account_move.payment_state, 'paid')
+ self.assertEqual(pos_orders.account_move.payment_state, 'in_payment')
self.assertEqual(pos_orders.account_move.state, 'posted')
+ self.assertEqual(pos_orders.account_move.amount_residual, 0)
def test_multi_config_global_invoice(self):
self.open_new_session()
@@ -1256,7 +174,7 @@ def test_multi_config_global_invoice(self):
payments=[(self.bank_pm1, 50)]
))
self.env['pos.order'].sync_from_ui(orders)
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
# open new session & create orders
self.open_new_session()
@@ -1270,40 +188,28 @@ def test_multi_config_global_invoice(self):
payments=[(self.bank_pm1, 109.96)]
))
self.env['pos.order'].sync_from_ui(orders2)
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
pos_orders = self.env['pos.order'].search([])
# set customer for the orders
pos_orders.write({'partner_id': self.customer.id})
# create consolidated invoice
- self.env['pos.make.invoice'].create({"consolidated_billing": True}).with_context({"active_ids": pos_orders.ids}).action_create_invoices()
+ self.env['pos.make.invoice'].create({
+ "consolidated_billing": True,
+ }).with_context({
+ "active_ids": pos_orders.ids,
+ }).action_create_invoices()
# check if have single invoice
self.assertEqual(len(pos_orders), 4)
+ self.assertTrue(all(order.state == 'done' for order in pos_orders))
self.assertEqual(len(pos_orders.account_move), 1)
+ self.assertNotEqual(self.pos_session.move_ids, pos_orders.account_move)
self.assertEqual(pos_orders.account_move.partner_id, self.customer)
self.assertEqual(pos_orders.account_move.amount_total, round(sum(pos_orders.mapped('amount_total')), 2))
- self.assertEqual(pos_orders.account_move.payment_state, 'paid')
+ self.assertEqual(pos_orders.account_move.payment_state, 'in_payment')
self.assertEqual(pos_orders.account_move.state, 'posted')
-
- def test_double_syncing_same_order(self):
- """ Test that double syncing the same order doesn't create duplicates records
- """
- self.open_new_session()
-
- # Create an order
- order_data = self.create_ui_order_data([(self.product1, 1)], payments=[(self.cash_pm1, 10)], customer=self.customer, is_invoiced=True)
- order_data['access_token'] = '0123456789'
- res = self.env['pos.order'].sync_from_ui([order_data])
- order_id = res['pos.order'][0]['id']
-
- # Sync the same order again
- res = self.env['pos.order'].sync_from_ui([order_data])
- self.assertEqual(res['pos.order'][0]['id'], order_id, 'Syncing the same order should not create a new one')
-
- order = self.env['pos.order'].browse(order_id)
- self.assertEqual(len(order.payment_ids), 1, 'Order should have one payment')
- self.assertEqual(self.env['account.move'].search_count([('pos_order_ids', 'in', order.ids)]), 1, 'Order should have one invoice')
+ self.assertEqual(pos_orders.account_move.amount_residual, 0)
def test_pos_archived_combination(self):
product = self.env['product.template'].create({
@@ -1430,6 +336,7 @@ def test_cannot_archive_journal_linked_to_pos_payment_method(self):
})
test_payment_method = self.env['pos.payment.method'].create({
'name': 'Test PM',
+ 'type': 'cash',
'journal_id': test_journal.id,
'receivable_account_id': self.cash_pm1.receivable_account_id.id,
})
diff --git a/addons/point_of_sale/tests/test_pos_controller.py b/addons/point_of_sale/tests/test_pos_controller.py
index 621866cfbf0752..1701b21896c4f9 100644
--- a/addons/point_of_sale/tests/test_pos_controller.py
+++ b/addons/point_of_sale/tests/test_pos_controller.py
@@ -61,7 +61,7 @@ def test_qr_code_receipt(self):
}
self.url_open(f'/pos/ticket/validate?access_token={self.pos_order.access_token}', data=get_invoice_data)
self.assertEqual(self.env['res.partner'].sudo().search_count([('name', '=', 'AAA Partner')]), 1)
- self.assertTrue(self.pos_order.is_invoiced, "The pos order should have an invoice")
+ self.assertTrue(self.pos_order.is_singly_invoiced, "The pos order should have an invoice")
self.assertTrue(len(self.pos_order.pos_reference) >= 12, "The pos reference should not be less than 12 characters")
def test_qr_code_receipt_user_connected(self):
@@ -107,7 +107,7 @@ def test_qr_code_receipt_user_connected(self):
})
self.main_pos_config.current_session_id.close_session_from_ui()
res = self.url_open(f'/pos/ticket/validate?access_token={self.pos_order.access_token}', timeout=30000)
- self.assertTrue(self.pos_order.is_invoiced, "The pos order should have an invoice")
+ self.assertTrue(self.pos_order.is_singly_invoiced, "The pos order should have an invoice")
self.assertTrue("my/invoices" in res.url)
def test_qr_code_receipt_user_not_connected(self):
@@ -150,6 +150,7 @@ def test_qr_code_receipt_user_not_connected(self):
self.main_pos_config.current_session_id.close_session_from_ui()
self.start_tour('/pos/ticket', 'invoicePoSOrderWithSelfInvocing', login=None)
self.assertTrue(self.pos_order.account_move, "The pos order should have an invoice after self invoicing")
+ self.assertNotEqual(self.pos_order.account_move, self.pos_order.session_id.move_ids)
def test_qr_code_receipt_user_updated(self):
"""This test make sure that when the user is already connected he correctly gets redirected to the invoice."""
diff --git a/addons/point_of_sale/tests/test_pos_invoice_consolidation.py b/addons/point_of_sale/tests/test_pos_invoice_consolidation.py
index e1c19ad0ae95a5..ec02437658f1fe 100644
--- a/addons/point_of_sale/tests/test_pos_invoice_consolidation.py
+++ b/addons/point_of_sale/tests/test_pos_invoice_consolidation.py
@@ -127,18 +127,24 @@ def test_consolidation_non_cash_with_cash_rounding_enabled(self):
'rounding_method': rounding.id,
})
- non_cash_pm = self.config.payment_method_ids.filtered(lambda pm: not pm.is_cash_count)[:1]
+ non_cash_pm = self.config.payment_method_ids.filtered(lambda pm: pm.type != 'cash')[:1]
self.assertTrue(non_cash_pm, "Need at least one non-cash payment method on the POS config.")
-
+ self.product2.lst_price = 9.99
with self.with_user(self.user1.login):
orders = self._create_orders([
{'pos_order_lines_ui_args': [(self.product1, 1)], 'customer': self.customer, 'is_invoiced': False},
- {'pos_order_lines_ui_args': [(self.product1, -1)], 'customer': self.customer, 'is_invoiced': False},
+ {
+ 'pos_order_lines_ui_args': [(self.product2, 1)],
+ 'customer': self.customer,
+ 'is_invoiced': False,
+ 'payments': [(self.cash_pm1, 10)]},
])
orders = sum(orders.values(), self.env['pos.order'])
- orders.payment_ids.write({'payment_method_id': non_cash_pm.id})
- orders.payment_ids[:1].write({'amount': orders.payment_ids[:1].amount + 1})
-
+ self.assertEqual(len(orders), 2, "Should have created 2 orders")
+ self.assertEqual(orders.mapped('amount_total'), [10.0, 9.99])
+ self.assertEqual(orders.mapped('amount_paid'), [10.0, 10.0])
+ self.assertEqual(orders.mapped('amount_difference'), [0.0, 0.01])
+ self.assertEqual(orders.mapped('amount_return'), [0.0, 0.0])
self.env['pos.make.invoice'].create({'consolidated_billing': True}).with_context(active_ids=orders.ids).action_create_invoices()
self.assertEqual(len(orders.account_move), 1)
diff --git a/addons/point_of_sale/tests/test_pos_margin.py b/addons/point_of_sale/tests/test_pos_margin.py
index cdbb0db51cb6c1..2f6e23c7d7874e 100644
--- a/addons/point_of_sale/tests/test_pos_margin.py
+++ b/addons/point_of_sale/tests/test_pos_margin.py
@@ -45,7 +45,7 @@ def test_positive_margin(self):
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), 0.42)
# close session
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
def test_negative_margin(self):
"""
@@ -77,7 +77,7 @@ def test_negative_margin(self):
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), -0.92)
# close session
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
def test_full_margin(self):
"""
@@ -109,7 +109,7 @@ def test_full_margin(self):
self.assertEqual(self.pos_session.order_ids[2].margin_percent, 1)
# close session
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
def test_tax_margin(self):
"""
@@ -143,7 +143,7 @@ def test_tax_margin(self):
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), 0.42)
# close session
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
def test_other_currency_margin(self):
"""
@@ -181,7 +181,7 @@ def test_other_currency_margin(self):
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), 0.42)
# close session
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
# set the config back
self.config = current_config
@@ -223,7 +223,7 @@ def test_tax_and_other_currency_margin(self):
self.assertEqual(self.pos_session.order_ids[2].margin_percent, 0.4167)
# close session
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
# set the config back
self.config = current_config
@@ -240,9 +240,11 @@ def test_return_margin(self):
self.open_new_session()
# create orders
- orders = [self.create_ui_order_data([(product1, -1)]),
- self.create_ui_order_data([(product2, -1)]),
- self.create_ui_order_data([(product1, -2), (product2, -2)])]
+ orders = [
+ self.create_ui_order_data([(product1, -1)], pos_order_ui_args={'is_refund': True}),
+ self.create_ui_order_data([(product2, -1)], pos_order_ui_args={'is_refund': True}),
+ self.create_ui_order_data([(product1, -2), (product2, -2)], pos_order_ui_args={'is_refund': True}),
+ ]
# sync orders
self.env['pos.order'].sync_from_ui(orders)
@@ -258,4 +260,4 @@ def test_return_margin(self):
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), 0.42)
# close session
- self.pos_session.action_pos_session_validate()
+ self.pos_session.close_session_from_ui()
diff --git a/addons/point_of_sale/tests/test_pos_multiple_receivable_accounts.py b/addons/point_of_sale/tests/test_pos_multiple_receivable_accounts.py
deleted file mode 100644
index 4093197e33556d..00000000000000
--- a/addons/point_of_sale/tests/test_pos_multiple_receivable_accounts.py
+++ /dev/null
@@ -1,287 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import odoo
-
-from odoo import tools
-from odoo.addons.point_of_sale.tests.common import TestPoSCommon
-
-@odoo.tests.tagged('post_install', '-at_install')
-class TestPoSMultipleReceivableAccounts(TestPoSCommon):
- """ Test for invoiced orders with customers having receivable account different from default
-
- Thus, for this test, there are two receivable accounts involved and are set in the
- customers.
- self.customer -> self.receivable_account
- self.other_customer -> self.other_receivable_account
-
- ADDITIONALLY, this tests different sales account on the products.
-
- NOTE That both receivable accounts above are different from the pos receivable account.
- """
-
- def setUp(self):
- super(TestPoSMultipleReceivableAccounts, self).setUp()
- self.config = self.basic_config
- self.product1 = self.create_product(
- 'Product 1',
- self.categ_basic,
- lst_price=10.99,
- standard_price=5.0,
- tax_ids=self.taxes['tax7'].ids,
- )
- self.product2 = self.create_product(
- 'Product 2',
- self.categ_basic,
- lst_price=19.99,
- standard_price=10.0,
- tax_ids=self.taxes['tax10'].ids,
- sale_account=self.other_sale_account,
- )
- self.product3 = self.create_product(
- 'Product 3',
- self.categ_basic,
- lst_price=30.99,
- standard_price=15.0,
- tax_ids=self.taxes['tax_group_7_10'].ids,
- )
-
- def test_01_invoiced_order_from_other_customer(self):
- """
- Orders
- ======
- +---------+----------+-----------+----------+-----+---------+--------------------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+-----------+----------+-----+---------+--------------------------+--------+
- | order 1 | cash | no | product1 | 10 | 109.9 | 7.69 [7%] | 117.59 |
- | | | | product2 | 10 | 181.73 | 18.17 [10%] | 199.9 |
- | | | | product3 | 10 | 281.73 | 19.72 [7%] + 28.17 [10%] | 329.62 |
- +---------+----------+-----------+----------+-----+---------+--------------------------+--------+
- | order 2 | bank | no | product1 | 5 | 54.95 | 3.85 [7%] | 58.80 |
- | | | | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- +---------+----------+-----------+----------+-----+---------+--------------------------+--------+
- | order 3 | bank | yes | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- | | | | product3 | 5 | 140.86 | 9.86 [7%] + 14.09 [10%] | 164.81 |
- +---------+----------+-----------+----------+-----+---------+--------------------------+--------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | sale_account | -164.85 |
- | sale_account | -281.73 |
- | other_sale_account | -272.59 |
- | tax 7% | -31.26 |
- | tax 10% | -55.43 |
- | pos receivable cash | 647.11 |
- | pos receivable bank | 423.51 |
- | other receivable | -264.76 |
- +---------------------+---------+
- | Total balance | 0.00 |
- +---------------------+---------+
- """
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- # check if there is one invoiced order
- self.assertEqual(len(self.pos_session.order_ids.filtered(lambda order: order.account_move)), 1, 'There should only be one invoiced order.')
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10), (self.product3, 10)], 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'payments': [(self.bank_pm1, 158.75)], 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm1, 264.76)], 'is_invoiced': True, 'customer': self.other_customer, 'uuid': '09876-098-0987'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {
- '09876-098-0987': {
- 'invoice': {
- 'line_ids_predicate': lambda line: line.account_id in self.other_sale_account | self.sales_account | self.other_receivable_account,
- 'line_ids': [
- {'account_id': self.other_sale_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 90.86, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 140.87, 'reconciled': False},
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 264.76, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 264.76), {
- 'line_ids': [
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 264.76, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 264.76, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 31.26, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 55.44, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 164.85, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': False, 'debit': 0, 'credit': 272.59, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 281.72, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 423.51, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 647.11, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 264.76, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((647.11, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 647.11, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 647.11, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((423.51, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 423.51, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 423.51, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_02_all_orders_invoiced_mixed_customers(self):
- """
- Orders
- ======
- +---------+----------+---------------------+----------+-----+---------+--------------------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+---------------------+----------+-----+---------+--------------------------+--------+
- | order 1 | cash | yes, other_customer | product1 | 10 | 109.90 | 7.69 [7%] | 117.59 |
- | | | | product2 | 10 | 181.73 | 18.17 [10%] | 199.90 |
- | | | | product3 | 10 | 281.73 | 19.72 [7%] + 28.17 [10%] | 329.62 |
- +---------+----------+---------------------+----------+-----+---------+--------------------------+--------+
- | order 2 | bank | yes, customer | product1 | 5 | 54.95 | 3.85 [7%] | 58.80 |
- | | | | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- +---------+----------+---------------------+----------+-----+---------+--------------------------+--------+
- | order 3 | bank | yes, other customer | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- | | | | product3 | 5 | 140.86 | 9.86 [7%] + 14.09 [10%] | 164.81 |
- +---------+----------+---------------------+----------+-----+---------+--------------------------+--------+
-
- Expected Result
- ===============
- +----------------------+---------+
- | account | balance |
- +----------------------+---------+
- | pos receivable cash | 647.11 |
- | pos receivable bank | 423.51 |
- | received bank | -423.51 |
- | received cash | -647.11 |
- +----------------------+---------+
- | Total balance | 0.00 |
- +----------------------+---------+
-
- """
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- # check if there is one invoiced order
- self.assertEqual(len(self.pos_session.order_ids.filtered(lambda order: order.account_move)), 3, 'All orders should be invoiced.')
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10), (self.product3, 10)], 'is_invoiced': True, 'customer': self.other_customer, 'uuid': '09876-098-0987'},
- {'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'payments': [(self.bank_pm1, 158.75)], 'is_invoiced': True, 'customer': self.customer, 'uuid': '09876-098-0988'},
- {'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm1, 264.76)], 'is_invoiced': True, 'customer': self.other_customer, 'uuid': '09876-098-0989'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {
- '09876-098-0987': {
- 'invoice': {
- 'line_ids_predicate': lambda line: line.account_id in self.other_sale_account | self.sales_account | self.other_receivable_account,
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 109.90, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 181.73, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 281.72, 'reconciled': False},
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 647.11, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_pm1, 647.11), {
- 'line_ids': [
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 647.11, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 647.11, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '09876-098-0988': {
- 'invoice': {
- 'line_ids_predicate': lambda line: line.account_id in self.other_sale_account | self.sales_account | self.c1_receivable,
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 54.95, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 90.86, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 158.75, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 158.75), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 158.75, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 158.75, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '09876-098-0989': {
- 'invoice': {
- 'line_ids_predicate': lambda line: line.account_id in self.other_sale_account | self.sales_account | self.other_receivable_account,
- 'line_ids': [
- {'account_id': self.other_sale_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 90.86, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 140.87, 'reconciled': False},
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 264.76, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 264.76), {
- 'line_ids': [
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 264.76, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 264.76, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 423.51, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 647.11, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 647.11, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 423.51, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((647.11, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 647.11, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 647.11, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((423.51, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 423.51, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 423.51, 'reconciled': True},
- ]
- }),
- ],
- },
- })
diff --git a/addons/point_of_sale/tests/test_pos_other_currency_config.py b/addons/point_of_sale/tests/test_pos_other_currency_config.py
index db50a9e7903933..e80307a91286a3 100644
--- a/addons/point_of_sale/tests/test_pos_other_currency_config.py
+++ b/addons/point_of_sale/tests/test_pos_other_currency_config.py
@@ -34,206 +34,6 @@ def test_01_check_product_cost(self):
self.assertAlmostEqual(self.config.pricelist_id._get_product_price(self.product3, 1), 15.00)
self.assertAlmostEqual(self.config.pricelist_id._get_product_price(self.product7, 1), 3.50)
- def test_02_orders_without_invoice(self):
- """ orders without invoice
-
- Orders
- ======
- +---------+----------+-----------+----------+-----+-------+
- | order | payments | invoiced? | product | qty | total |
- +---------+----------+-----------+----------+-----+-------+
- | order 1 | cash | no | product1 | 10 | 50 |
- | | | | product2 | 10 | 129.9 |
- | | | | product3 | 10 | 150 |
- +---------+----------+-----------+----------+-----+-------+
- | order 2 | cash | no | product1 | 5 | 25 |
- | | | | product2 | 5 | 64.95 |
- +---------+----------+-----------+----------+-----+-------+
- | order 3 | bank | no | product2 | 5 | 64.95 |
- | | | | product3 | 5 | 75 |
- +---------+----------+-----------+----------+-----+-------+
-
- Expected Result
- ===============
- +---------------------+---------+-----------------+
- | account | balance | amount_currency |
- +---------------------+---------+-----------------+
- | sale_account | -1119.6 | -559.80 |
- | pos receivable bank | 279.9 | 139.95 |
- | pos receivable cash | 839.7 | 419.85 |
- +---------------------+---------+-----------------+
- | Total balance | 0.0 | 0.00 |
- +---------------------+---------+-----------------+
- """
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- self._run_test({
- 'payment_methods': self.cash_pm2 | self.bank_pm2,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10), (self.product3, 10)], 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm2, 139.95)], 'uuid': '00100-010-0003'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 1119.6, 'reconciled': False, 'amount_currency': -559.80},
- {'account_id': self.bank_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 279.9, 'credit': 0, 'reconciled': True, 'amount_currency': 139.95},
- {'account_id': self.cash_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 839.7, 'credit': 0, 'reconciled': True, 'amount_currency': 419.85},
- ],
- },
- 'cash_statement': [
- ((419.85, ), {
- 'line_ids': [
- {'account_id': self.cash_pm2.journal_id.default_account_id.id, 'partner_id': False, 'debit': 839.7, 'credit': 0, 'reconciled': False, 'amount_currency': 419.85},
- {'account_id': self.cash_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 839.7, 'reconciled': True, 'amount_currency': -419.85},
- ]
- }),
- ],
- 'bank_payments': [
- ((139.95, ), {
- 'line_ids': [
- {'account_id': self.bank_pm2.outstanding_account_id.id, 'partner_id': False, 'debit': 279.9, 'credit': 0, 'reconciled': False, 'amount_currency': 139.95},
- {'account_id': self.bank_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 279.9, 'reconciled': True, 'amount_currency': -139.95},
- ]
- }),
- ],
- },
- })
-
- def test_03_orders_with_invoice(self):
- """ orders with invoice
-
- Orders
- ======
- +---------+----------+---------------+----------+-----+-------+
- | order | payments | invoiced? | product | qty | total |
- +---------+----------+---------------+----------+-----+-------+
- | order 1 | cash | no | product1 | 10 | 50 |
- | | | | product2 | 10 | 129.9 |
- | | | | product3 | 10 | 150 |
- +---------+----------+---------------+----------+-----+-------+
- | order 2 | cash | yes, customer | product1 | 5 | 25 |
- | | | | product2 | 5 | 64.95 |
- +---------+----------+---------------+----------+-----+-------+
- | order 3 | bank | yes, customer | product2 | 5 | 64.95 |
- | | | | product3 | 5 | 75 |
- +---------+----------+---------------+----------+-----+-------+
-
- Expected Result
- ===============
- +---------------------+---------+-----------------+
- | account | balance | amount_currency |
- +---------------------+---------+-----------------+
- | sale_account | -659.8 | -329.90 |
- | pos receivable bank | 279.9 | 139.95 |
- | pos receivable cash | 839.7 | 419.85 |
- | invoice receivable | -179.9 | -89.95 |
- | invoice receivable | -279.9 | -139.95 |
- +---------------------+---------+-----------------+
- | Total balance | 0.0 | 0.00 |
- +---------------------+---------+-----------------+
- """
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- self._run_test({
- 'payment_methods': self.cash_pm2 | self.bank_pm2,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10), (self.product3, 10)], 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'is_invoiced': True, 'customer': self.customer, 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm2, 139.95)], 'is_invoiced': True, 'customer': self.customer, 'uuid': '00100-010-0003'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {
- '00100-010-0002': {
- 'payments': [
- ((self.cash_pm2, 89.95), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 179.90, 'reconciled': True, 'amount_currency': -89.95},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 179.90, 'credit': 0, 'reconciled': False, 'amount_currency': 89.95},
- ]
- }),
- ],
- },
- '00100-010-0003': {
- 'payments': [
- ((self.bank_pm2, 139.95), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 279.9, 'reconciled': True, 'amount_currency': -139.95},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 279.9, 'credit': 0, 'reconciled': False, 'amount_currency': 139.95},
- ]
- }),
- ],
- },
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 659.8, 'reconciled': False, 'amount_currency': -329.90},
- {'account_id': self.bank_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 279.9, 'credit': 0, 'reconciled': True, 'amount_currency': 139.95},
- {'account_id': self.cash_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 839.7, 'credit': 0, 'reconciled': True, 'amount_currency': 419.85},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 179.90, 'reconciled': True, 'amount_currency': -89.95},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 279.9, 'reconciled': True, 'amount_currency': -139.95},
- ],
- },
- 'cash_statement': [
- ((419.85, ), {
- 'line_ids': [
- {'account_id': self.cash_pm2.journal_id.default_account_id.id, 'partner_id': False, 'debit': 839.7, 'credit': 0, 'reconciled': False, 'amount_currency': 419.85},
- {'account_id': self.cash_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 839.7, 'reconciled': True, 'amount_currency': -419.85},
- ]
- }),
- ],
- 'bank_payments': [
- ((139.95, ), {
- 'line_ids': [
- {'account_id': self.bank_pm2.outstanding_account_id.id, 'partner_id': False, 'debit': 279.9, 'credit': 0, 'reconciled': False, 'amount_currency': 139.95},
- {'account_id': self.bank_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 279.9, 'reconciled': True, 'amount_currency': -139.95},
- ]
- }),
- ],
- },
- })
-
- def test_05_tax_base_amount(self):
- self._run_test({
- 'payment_methods': self.cash_pm2,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product7, 7)], 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 3.43, 'reconciled': False, 'amount_currency': -1.715, 'tax_base_amount': 49},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 49, 'reconciled': False, 'amount_currency': -24.5, 'tax_base_amount': 0},
- {'account_id': self.cash_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 52.43, 'credit': 0, 'reconciled': True, 'amount_currency': 26.215, 'tax_base_amount': 0},
- ],
- },
- 'cash_statement': [
- ((26.215, ), {
- 'line_ids': [
- {'account_id': self.cash_pm2.journal_id.default_account_id.id, 'partner_id': False, 'debit': 52.43, 'credit': 0, 'reconciled': False, 'amount_currency': 26.215},
- {'account_id': self.cash_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 52.43, 'reconciled': True, 'amount_currency': -26.215},
- ]
- }),
- ],
- 'bank_payments': [],
- },
- })
-
def test_bank_journal_balance(self):
"""Verify that debit and credit are balanced when adding a difference to the bank."""
@@ -271,7 +71,7 @@ def test_bank_journal_balance(self):
order_payment.with_context(**payment_context).check()
# Close session with counted +10 for bank compared with expected
- session_id.action_pos_session_closing_control(bank_payment_method_diffs={self.bank_pm2.id: 10.00}) # Real 20, expected 10, diff 10
+ session_id.close_session_from_ui() # Real 20, expected 10, diff 10
# Check debit/credit session's balance
for move in session_id._get_related_account_moves():
diff --git a/addons/point_of_sale/tests/test_pos_products_with_tax.py b/addons/point_of_sale/tests/test_pos_products_with_tax.py
index 9f3d278e6ecd7c..7a13e2d57b22d8 100644
--- a/addons/point_of_sale/tests/test_pos_products_with_tax.py
+++ b/addons/point_of_sale/tests/test_pos_products_with_tax.py
@@ -45,514 +45,6 @@ def setUp(self):
tax_ids=[self.taxes['tax_fixed006'].id, self.taxes['tax_fixed012'].id, self.taxes['tax21'].id],
)
- def test_orders_no_invoiced(self):
- """ Test for orders without invoice
-
- Orders
- ======
- +---------+----------+-----------+----------+-----+---------+-----------------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+-----------+----------+-----+---------+-----------------------+--------+
- | order 1 | cash | no | product1 | 10 | 100 | 7 | 107 |
- | | | | product2 | 5 | 90.91 | 9.09 | 100 |
- +---------+----------+-----------+----------+-----+---------+-----------------------+--------+
- | order 2 | cash | no | product2 | 7 | 127.27 | 12.73 | 140 |
- | | | | product3 | 4 | 109.09 | 10.91[10%] + 7.64[7%] | 127.64 |
- +---------+----------+-----------+----------+-----+---------+-----------------------+--------+
- | order 3 | bank | no | product1 | 1 | 10 | 0.7 | 10.7 |
- | | | | product2 | 3 | 54.55 | 5.45 | 60 |
- | | | | product3 | 5 | 136.36 | 13.64[10%] + 9.55[7%] | 159.55 |
- +---------+----------+-----------+----------+-----+---------+-----------------------+--------+
-
- Calculated taxes
- ================
- total tax 7% only + group tax (10+7%)
- (7 + 0.7) + (7.64 + 9.55) = 7.7 + 17.19 = 24.89
- total tax 10% only + group tax (10+7%)
- (9.09 + 12.73 + 5.45) + (10.91 + 13.64) = 27.27 + 24.55 = 51.82
-
- Thus, manually_calculated_taxes = (-24,89, -51.82)
- """
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 5)], 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product2, 7), (self.product3, 4)], 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product1, 1), (self.product3, 5), (self.product2, 3)], 'payments': [(self.bank_pm1, 230.25)], 'uuid': '00100-010-0003'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 24.89, 'reconciled': False, 'display_type': 'tax'},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 51.82, 'reconciled': False, 'display_type': 'tax'},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 110, 'reconciled': False, 'display_type': 'product'},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 272.73, 'reconciled': False, 'display_type': 'product'},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 245.45, 'reconciled': False, 'display_type': 'product'},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 230.25, 'credit': 0, 'reconciled': True, 'display_type': 'payment_term'},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 474.64, 'credit': 0, 'reconciled': True, 'display_type': 'payment_term'},
- ],
- },
- 'cash_statement': [
- ((474.64, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 474.64, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 474.64, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((230.25, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 230.25, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 230.25, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_orders_with_invoiced(self):
- """ Test for orders: one with invoice
-
- Orders
- ======
- +---------+----------+---------------+----------+-----+---------+---------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+---------------+----------+-----+---------+---------------+--------+
- | order 1 | cash | no | product1 | 6 | 60 | 4.2 | 64.2 |
- | | | | product2 | 3 | 54.55 | 5.45 | 60 |
- | | | | product3 | 1 | 27.27 | 2.73 + 1.91 | 31.91 |
- +---------+----------+---------------+----------+-----+---------+---------------+--------+
- | order 2 | bank | no | product1 | 1 | 10 | 0.7 | 10.7 |
- | | | | product2 | 20 | 363.64 | 36.36 | 400 |
- +---------+----------+---------------+----------+-----+---------+---------------+--------+
- | order 3 | bank | yes, customer | product1 | 10 | 100 | 7 | 107 |
- | | | | product3 | 10 | 272.73 | 27.27 + 19.09 | 319.09 |
- +---------+----------+---------------+----------+-----+---------+---------------+--------+
-
- Calculated taxes
- ================
- total tax 7% only
- 4.2 + 0.7 => 4.9 + 1.91 = 6.81
- total tax 10% only
- 5.45 + 36.36 => 41.81 + 2.73 = 44.54
-
- Thus, manually_calculated_taxes = (-6.81, -44.54)
- """
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(4, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- # check account move in the invoiced order
- invoiced_orders = self.pos_session.order_ids.filtered(lambda order: order.is_invoiced)
- self.assertEqual(2, len(invoiced_orders), 'Only one order is invoiced in this test.')
- invoices = invoiced_orders.mapped('account_move')
- self.assertAlmostEqual(sum(invoices.mapped('amount_total')), 481.08)
-
- def _after_closing_cb():
- session_move = self.pos_session.move_id
- tax_lines = session_move.line_ids.filtered(lambda line: line.account_id == self.tax_received_account)
-
- manually_calculated_taxes = (-6.81, -44.54)
- self.assertAlmostEqual(sum(manually_calculated_taxes), sum(tax_lines.mapped('balance')))
- for t1, t2 in zip(sorted(manually_calculated_taxes), sorted(tax_lines.mapped('balance'))):
- self.assertAlmostEqual(t1, t2, msg='Taxes should be correctly combined.')
-
- base_amounts = (97.27, 445.46) # computation does not include invoiced order.
- self.assertAlmostEqual(sum(base_amounts), sum(tax_lines.mapped('tax_base_amount')))
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product3, 1), (self.product1, 6), (self.product2, 3)], 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product2, 20), (self.product1, 1)], 'payments': [(self.bank_pm1, 410.7)], 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product3, 10)], 'payments': [(self.bank_pm1, 426.09)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '09876-098-0987'},
- {'pos_order_lines_ui_args': [(self.product4, 1)], 'payments': [(self.bank_pm1, 54.99)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0004'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {
- '09876-098-0987': {
- 'payments': [
- ((self.bank_pm1, 426.09), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 426.09, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 426.09, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '00100-010-0004': {
- 'payments': [
- ((self.bank_pm1, 54.99), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 54.99, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 54.99, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- },
- 'after_closing_cb': _after_closing_cb,
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 6.81, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 44.54, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 27.27, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 70, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 418.19, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 891.78, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 156.11, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 481.08, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((156.11, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 156.11, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 156.11, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((891.78, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 891.78, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 891.78, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_return_order(self):
- """ Test return order
-
- Order (invoiced)
- ======
- +----------+----------+---------------+----------+-----+---------+-------------+-------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +----------+----------+---------------+----------+-----+---------+-------------+-------+
- | order 1 | cash | yes, customer | product1 | 3 | 30 | 2.1 | 32.1 |
- | | | | product2 | 2 | 36.36 | 3.64 | 40 |
- | | | | product3 | 1 | 27.27 | 2.73 + 1.91 | 31.91 |
- +----------+----------+---------------+----------+-----+---------+-------------+-------+
-
- The order is invoiced so the tax of the invoiced order is in the account_move of the order.
- However, the return order is not invoiced, thus, the journal items are in the session_move,
- which will contain the tax lines of the returned products.
-
- manually_calculated_taxes = (4.01, 6.37)
- """
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(1, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- # return order
- order_to_return = self.pos_session.order_ids.filtered(lambda order: '12345-123-1234' in order.uuid)
- order_to_return.refund()
-
- refund_order = self.pos_session.order_ids.filtered(lambda order: order.state == 'draft')
- context_make_payment = {"active_ids": [refund_order.id], "active_id": refund_order.id}
- make_payment = self.env['pos.make.payment'].with_context(context_make_payment).create({
- 'payment_method_id': self.cash_pm1.id,
- 'amount': -104.01,
- })
- make_payment.check()
- self.assertEqual(refund_order.state, 'paid', 'Payment is registered, order should be paid.')
- self.assertAlmostEqual(refund_order.amount_paid, -104.01, msg='Amount paid for return order should be negative.')
-
- def _after_closing_cb():
- manually_calculated_taxes = (4.01, 6.36) # should be positive since it is return order
- tax_lines = self.pos_session.move_id.line_ids.filtered(lambda line: line.account_id == self.tax_received_account)
- self.assertAlmostEqual(sum(manually_calculated_taxes), sum(tax_lines.mapped('balance')))
- for t1, t2 in zip(sorted(manually_calculated_taxes), sorted(tax_lines.mapped('balance'))):
- self.assertAlmostEqual(t1, t2, msg='Taxes should be correctly combined and should be debit.')
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 3), (self.product2, 2), (self.product3, 1)], 'payments': [(self.cash_pm1, 104.01)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '12345-123-1234'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {
- '12345-123-1234': {
- 'payments': [
- ((self.cash_pm1, 104.01), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 104.01, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 104.01, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- },
- 'after_closing_cb': _after_closing_cb,
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 4.01, 'credit': 0, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 6.36, 'credit': 0, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 30, 'credit': 0, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 36.37, 'credit': 0, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 27.27, 'credit': 0, 'reconciled': False},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 104.01, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [],
- },
- })
-
- def test_pos_create_correct_account_move(self):
- """ Test for orders with global rounding disabled
-
- Orders
- ======
- +---------+----------+-----------+----------+------+----------+------------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+-----------+----------+------+----------+------------------+--------+
- | order 1 | cash | no | product1 | 1 | 10.0 | 2.10 | 12.10 |
- | | | | product2 | -1 | -5.0 | -1.05 | -6.05 |
- +---------+----------+-----------+----------+------+----------+------------------+--------+
- """
- tax_21_incl = self.taxes['tax21']
- product1 = self.create_product(
- name='Product 1',
- category=self.categ_basic,
- lst_price=12.10,
- tax_ids=tax_21_incl.ids,
- )
- product2 = self.create_product(
- name='Product 2',
- category=self.categ_basic,
- lst_price=6.05,
- tax_ids=tax_21_incl.ids,
- )
- self.open_new_session()
- self.env['pos.order'].sync_from_ui([self.create_ui_order_data([
- (product1, 1),
- (product2, -1),
- ])])
- self.pos_session.action_pos_session_validate()
-
- lines = self.pos_session.move_id.line_ids.sorted('balance')
- self.assertEqual(2, len(lines.filtered(lambda l: l.tax_ids)), "Taxes should have been set on 2 lines")
- self.assertEqual(4, len(lines.filtered(lambda l: l.tax_tag_ids)), "Tags should have been set on 4 lines")
- self.assertRecordValues(lines, [
- # pylint: disable=bad-whitespace
- {'account_id': self.sale_account.id, 'balance': -10.0, 'tax_ids': tax_21_incl.ids, 'tax_tag_ids': self.tax_tag_invoice_base.ids},
- {'account_id': self.tax_received_account.id, 'balance': -2.10, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_invoice_tax.ids},
- {'account_id': self.tax_received_account.id, 'balance': 1.05, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_refund_tax.ids},
- {'account_id': self.sale_account.id, 'balance': 5.00, 'tax_ids': tax_21_incl.ids, 'tax_tag_ids': self.tax_tag_refund_base.ids},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'balance': 6.05, 'tax_ids': [], 'tax_tag_ids': []},
- ])
-
- def test_pos_create_account_move_round_globally(self):
- """ Test for orders with global rounding enabled
-
- Orders
- ======
- +---------+----------+-----------+----------+------+----------+------------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+-----------+----------+------+----------+------------------+--------+
- | order 1 | cash | no | product1 | 1 | 10.0 | 2.10 | 12.10 |
- | | | | product2 | -1 | -5.0 | -1.05 | -6.05 |
- +---------+----------+-----------+----------+------+----------+------------------+--------+
- """
- tax_21_incl = self.taxes['tax21']
- tax_21_incl.company_id.tax_calculation_rounding_method = 'round_globally'
-
- product1 = self.create_product(
- name='Product 1',
- category=self.categ_basic,
- lst_price=12.10,
- tax_ids=tax_21_incl.ids,
- )
- product2 = self.create_product(
- name='Product 2',
- category=self.categ_basic,
- lst_price=6.05,
- tax_ids=tax_21_incl.ids,
- )
- self.open_new_session()
- self.env['pos.order'].sync_from_ui([self.create_ui_order_data([
- (product1, 1),
- (product2, -1),
- ])])
- self.pos_session.action_pos_session_validate()
-
- lines = self.pos_session.move_id.line_ids.sorted('balance')
- self.assertEqual(2, len(lines.filtered(lambda l: l.tax_ids)), "Taxes should have been set on 2 lines")
- self.assertEqual(4, len(lines.filtered(lambda l: l.tax_tag_ids)), "Tags should have been set on 4 lines")
- self.assertRecordValues(lines, [
- # pylint: disable=bad-whitespace
- {'account_id': self.sale_account.id, 'balance': -10.0, 'tax_ids': tax_21_incl.ids, 'tax_tag_ids': self.tax_tag_invoice_base.ids},
- {'account_id': self.tax_received_account.id, 'balance': -2.10, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_invoice_tax.ids},
- {'account_id': self.tax_received_account.id, 'balance': 1.05, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_refund_tax.ids},
- {'account_id': self.sale_account.id, 'balance': 5.00, 'tax_ids': tax_21_incl.ids, 'tax_tag_ids': self.tax_tag_refund_base.ids},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'balance': 6.05, 'tax_ids': [], 'tax_tag_ids': []},
- ])
-
- def test_pos_create_correct_account_move_round_globally_discount(self):
- """ Test for orders with global rounding enabled
-
- Orders
- ======
- +---------+----------+------+----------+------+---------------------+-----------+---------------------------+---------+--------+--------+
- | order | payments | inv? | product | qty | original price unit | Discount | price unit after discount | untaxed | tax | total |
- +---------+----------+------+----------+------+---------------------+-----------+---------------------------+---------+--------+--------+
- | order 1 | cash | no | product1 | 1 | 12.10 | 5% | 10.89 | 9.00 | 1.89 | 10.89 |
- | | | | product2 | -1 | 6.05 | 5% | 5.45 | -4.50 | -0.95 | -5.445 |
- +---------+----------+------+----------+------+---------------------+-----------+---------------------------+---------+--------+--------+
- """
- tax_21_incl = self.taxes['tax21']
- tax_21_incl.company_id.tax_calculation_rounding_method = 'round_globally'
-
- product1 = self.create_product(
- name='Product 1',
- category=self.categ_basic,
- lst_price=12.10,
- tax_ids=tax_21_incl.ids,
- )
- product2 = self.create_product(
- name='Product 2',
- category=self.categ_basic,
- lst_price=6.05,
- tax_ids=tax_21_incl.ids,
- )
- self.open_new_session()
- self.env['pos.order'].sync_from_ui([self.create_ui_order_data([
- (product1, 1, 10),
- (product2, -1, 10),
- ])])
- self.pos_session.action_pos_session_validate()
-
- lines = self.pos_session.move_id.line_ids.sorted('balance')
-
- self.assertEqual(2, len(lines.filtered(lambda l: l.tax_ids)), "Taxes should have been set on 2 lines")
- self.assertEqual(4, len(lines.filtered(lambda l: l.tax_tag_ids)), "Tags should have been set on 4 lines")
- self.assertRecordValues(lines, [
- # pylint: disable=bad-whitespace
- {'account_id': self.sale_account.id, 'balance': - 9.0, 'tax_ids': tax_21_incl.ids, 'tax_tag_ids': self.tax_tag_invoice_base.ids},
- {'account_id': self.tax_received_account.id, 'balance': -1.89, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_invoice_tax.ids},
- {'account_id': self.tax_received_account.id, 'balance': 0.95, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_refund_tax.ids},
- {'account_id': self.sale_account.id, 'balance': 4.5, 'tax_ids': tax_21_incl.ids, 'tax_tag_ids': self.tax_tag_refund_base.ids},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'balance': 5.44, 'tax_ids': [], 'tax_tag_ids': []},
- ])
-
- def test_pos_create_correct_account_move_round_globally_discount_real_use_case(self):
- """ Test for orders with global rounding enabled
-
- Orders
- ======
- +---------+----------+------+----------+------+---------------------+-----------+---------------------------+---------+--------+--------+
- | order | payments | inv? | product | qty | original price unit | Discount | price unit after discount | untaxed | tax | total |
- +---------+----------+------+----------+------+---------------------+-----------+---------------------------+---------+--------+--------+
- | order 1 | cash | no | product1 | 6 | 11.80 | 5% | 11.21 | 55.59 | 11.67 | 67.26 |
- | | | | product2 | -6 | 15.30 | 5% | 14.535 | -72.07 | -15.14 | -87.21 |
- +---------+----------+------+----------+------+---------------------+-----------+---------------------------+---------+--------+--------+
- """
- tax_21_incl = self.taxes['tax21']
- tax_21_incl.company_id.tax_calculation_rounding_method = 'round_globally'
-
- product1 = self.create_product(
- name='Product 1',
- category=self.categ_basic,
- lst_price=11.80,
- tax_ids=tax_21_incl.ids,
- )
- product2 = self.create_product(
- name='Product 2',
- category=self.categ_basic,
- lst_price=15.30,
- tax_ids=tax_21_incl.ids,
- )
- self.open_new_session()
- self.env['pos.order'].sync_from_ui([self.create_ui_order_data([
- (product1, 6, 5),
- (product2, -6, 5),
- ])])
- self.pos_session.action_pos_session_validate()
-
- lines = self.pos_session.move_id.line_ids.sorted('balance')
-
- self.assertEqual(2, len(lines.filtered(lambda l: l.tax_ids)), "Taxes should have been set on 2 lines")
- self.assertEqual(4, len(lines.filtered(lambda l: l.tax_tag_ids)), "Tags should have been set on 4 lines")
- self.assertRecordValues(lines, [
- # pylint: disable=bad-whitespace
- {'account_id': self.sale_account.id, 'balance': -55.59, 'tax_ids': tax_21_incl.ids, 'tax_tag_ids': self.tax_tag_invoice_base.ids},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'balance': -19.95, 'tax_ids': [], 'tax_tag_ids': []},
- {'account_id': self.tax_received_account.id, 'balance': -11.67, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_invoice_tax.ids},
- {'account_id': self.tax_received_account.id, 'balance': 15.14, 'tax_ids': [], 'tax_tag_ids': self.tax_tag_refund_tax.ids},
- {'account_id': self.sale_account.id, 'balance': 72.07, 'tax_ids': tax_21_incl.ids, 'tax_tag_ids': self.tax_tag_refund_base.ids},
- ])
-
- def test_fixed_tax_positive_qty(self):
-
- fixed_tax = self.env['account.tax'].create({
- 'name': 'fixed amount tax',
- 'amount_type': 'fixed',
- 'amount': 1,
- 'invoice_repartition_line_ids': [
- (0, 0, {
- 'repartition_type': 'base',
- 'tag_ids': [(6, 0, self.tax_tag_invoice_base.ids)],
- }),
- (0, 0, {
- 'repartition_type': 'tax',
- 'account_id': self.tax_received_account.id,
- 'tag_ids': [(6, 0, self.tax_tag_invoice_tax.ids)],
- }),
- ],
- })
-
- zero_amount_product = self.env['product.product'].create({
- 'name': 'Zero Amount Product',
- 'available_in_pos': True,
- 'list_price': 0,
- 'taxes_id': [(6, 0, [fixed_tax.id])],
- })
-
- self.open_new_session()
- self.env['pos.order'].sync_from_ui([self.create_ui_order_data([
- (zero_amount_product, 1),
- ])])
- self.pos_session.action_pos_session_validate()
-
- lines = self.pos_session.move_id.line_ids.sorted('balance')
-
- self.assertRecordValues(lines, [
- {'account_id': self.tax_received_account.id, 'balance': -1},
- {'account_id': self.sale_account.id, 'balance': 0},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'balance': 1},
- ])
-
- def test_tax_is_used_when_in_transactions(self):
- ''' Ensures that a tax is set to used when it is part of some transactions '''
-
- # Call another test that uses product_1
- tax_pos = self.product1.taxes_id
- self.assertFalse(tax_pos.is_used)
- self.test_orders_no_invoiced()
- tax_pos.invalidate_model(fnames=['is_used'])
- self.assertTrue(tax_pos.is_used)
-
def test_pos_loaded_product_taxes_on_branch(self):
""" Check loaded product taxes on branch company """
# create the following branch hierarchy:
@@ -651,6 +143,7 @@ def test_pos_loaded_product_taxes_on_branch(self):
xx_cash_journal = self.company_data['default_journal_cash'].copy({'company_id': branch_xx.id})
xx_cash_payment_method = self.env['pos.payment.method'].create({
'name': 'XX Cash Payment',
+ 'type': 'cash',
'receivable_account_id': xx_account_receivable.id,
'journal_id': xx_cash_journal.id,
'company_id': branch_xx.id,
@@ -732,25 +225,3 @@ def test_combo_product_variant_error(self):
with self.assertRaises(UserError):
with Form(self.variant_product.product_tmpl_id) as product:
product.type = "combo"
-
- def test_tax_change_blocked_when_open_pos_session(self):
- """Changing a POS sale tax must be blocked when a POS session is open"""
- tax = self.taxes['tax7']
-
- self.open_new_session()
- self.assertEqual(self.pos_session.state, 'opened')
-
- self.env['pos.order'].sync_from_ui([self.create_ui_order_data([
- (self.product1, 1),
- ])])
-
- self.assertTrue(self.pos_session.order_ids)
- self.assertTrue(self.env['pos.order.line'].search([
- ('order_id.session_id', '=', self.pos_session.id),
- ('tax_ids', 'in', tax.ids),
- ], limit=1))
-
- with self.assertRaises(UserError):
- tax.write({
- 'price_include_override': 'tax_included',
- })
diff --git a/addons/point_of_sale/tests/test_pos_setup.py b/addons/point_of_sale/tests/test_pos_setup.py
index b734a81d420116..d1c7eefb4fc385 100644
--- a/addons/point_of_sale/tests/test_pos_setup.py
+++ b/addons/point_of_sale/tests/test_pos_setup.py
@@ -75,7 +75,8 @@ def test_archive_used_journal(self):
'invoice_reference_type': 'invoice',
'invoice_reference_model': 'odoo'
})
- payment_method = self.env['pos.payment.method'].create({'name': 'Lets Pay for Tests', 'journal_id': journal.id})
+ payment_method = self.env['pos.payment.method'].create({
+ 'name': 'Lets Pay for Tests', 'journal_id': journal.id, 'type': 'bank'})
self.basic_config.write({'payment_method_ids': [payment_method.id]})
journal.write({'pos_payment_method_ids': [payment_method.id]})
session = self.env['pos.session'].create(
diff --git a/addons/point_of_sale/tests/test_pos_simple_invoiced_orders.py b/addons/point_of_sale/tests/test_pos_simple_invoiced_orders.py
deleted file mode 100644
index 55af3dfd4d1582..00000000000000
--- a/addons/point_of_sale/tests/test_pos_simple_invoiced_orders.py
+++ /dev/null
@@ -1,790 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import odoo
-
-from odoo.addons.point_of_sale.tests.common import TestPoSCommon
-
-
-@odoo.tests.tagged('post_install', '-at_install')
-class TestPosSimpleInvoicedOrders(TestPoSCommon):
- """
- Each test case only make a single **invoiced** order.
- Name of each test corresponds to a sheet in: https://docs.google.com/spreadsheets/d/1mt2jRSDU7OONPBFjwyTcnhRjITQI8rGMLLQA5K3fAjo/edit?usp=sharing
- """
-
- def setUp(self):
- super(TestPosSimpleInvoicedOrders, self).setUp()
- self.config = self.basic_config
- self.product100 = self.create_product('Product_100', self.categ_basic, 100, 50)
-
- def test_01b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_pm1, 100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_02b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'journal_id': self.config.invoice_journal_id.id,
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 100), {
- 'journal_id': self.config.journal_id.id,
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'journal_id': self.config.journal_id.id,
- 'line_ids': [
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((100, ), {
- 'journal_id': self.bank_pm1.journal_id.id,
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_03b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.pay_later_pm, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'journal_id': self.config.invoice_journal_id.id,
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- },
- 'payments': [],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': False,
- 'cash_statement': [],
- 'bank_payments': [],
- },
- })
-
- def test_04b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_split_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'journal_id': self.config.invoice_journal_id.id,
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_split_pm1, 100), {
- 'journal_id': self.config.journal_id.id,
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'journal_id': self.config.journal_id.id,
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((100, ), {
- 'journal_id': self.bank_split_pm1.journal_id.id,
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_05b(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_split_pm1, 100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_split_pm1, 100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_10b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_pm1, 200), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True, 'partially_reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_pm1, 200), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': False, 'partially_reconciled': True, 'amount_residual': -100},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False, 'amount_residual': 200},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_11b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_pm1, 200), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True, 'partially_reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 200), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': False, 'partially_reconciled': True, 'amount_residual': -100},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False, 'amount_residual': 200},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_12b(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_split_pm1, 200), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True, 'partially_reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_split_pm1, 200), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': False, 'partially_reconciled': True, 'amount_residual': -100},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False, 'amount_residual': 200},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_13b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_split_pm1, 200), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True, 'partially_reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_split_pm1, 200), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': False, 'partially_reconciled': True, 'amount_residual': -100},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False, 'amount_residual': 200},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_14b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_pm1, 200), (self.cash_pm1, -100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_pm1, 200), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- ]
- }),
- ((self.cash_pm1, -100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_15b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_pm1, 200), (self.cash_pm1, -100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 200), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- ]
- }),
- ((self.cash_pm1, -100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((-100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_16b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_split_pm1, 200), (self.cash_pm1, -100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.bank_split_pm1, 200), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- ]
- }),
- ((self.cash_pm1, -100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((-100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_17b(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_split_pm1, 200), (self.cash_split_pm1, -100)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- },
- 'payments': [
- ((self.cash_split_pm1, 200), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- ]
- }),
- ((self.cash_split_pm1, -100), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- }),
- ((-100, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_18b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_pm1, 50), (self.pay_later_pm, 50)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False, 'amount_residual': -100},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False, 'partially_reconciled': True, 'amount_residual': 50},
- ]
- },
- 'payments': [
- ((self.cash_pm1, 50), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 50, 'reconciled': True, 'partially_reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 50, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((50, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 50, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_19b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_pm1, 50), (self.pay_later_pm, 50)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False, 'amount_residual': -100},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False, 'partially_reconciled': True, 'amount_residual': 50},
- ]
- },
- 'payments': [
- ((self.bank_pm1, 50), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 50, 'reconciled': True, 'partially_reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 50, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((50, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 50, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_20b(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_split_pm1, 50), (self.pay_later_pm, 50)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False, 'amount_residual': -100},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False, 'partially_reconciled': True, 'amount_residual': 50},
- ]
- },
- 'payments': [
- ((self.bank_split_pm1, 50), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 50, 'reconciled': True, 'partially_reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 50, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((50, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 50, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_21b(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_split_pm1, 50), (self.pay_later_pm, 50)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'invoice': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False, 'amount_residual': -100},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False, 'partially_reconciled': True, 'amount_residual': 50},
- ]
- },
- 'payments': [
- ((self.cash_split_pm1, 50), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 50, 'reconciled': True, 'partially_reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- }
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 50, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((50, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 50, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
diff --git a/addons/point_of_sale/tests/test_pos_simple_orders.py b/addons/point_of_sale/tests/test_pos_simple_orders.py
deleted file mode 100644
index 943c485383d4bc..00000000000000
--- a/addons/point_of_sale/tests/test_pos_simple_orders.py
+++ /dev/null
@@ -1,589 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import odoo
-
-from odoo.addons.point_of_sale.tests.common import TestPoSCommon
-
-
-@odoo.tests.tagged('post_install', '-at_install')
-class TestPosSimpleOrders(TestPoSCommon):
- """
- Each test case only make a single order.
- Name of each test corresponds to a sheet in: https://docs.google.com/spreadsheets/d/1mt2jRSDU7OONPBFjwyTcnhRjITQI8rGMLLQA5K3fAjo/edit?usp=sharing
- """
-
- def setUp(self):
- super(TestPosSimpleOrders, self).setUp()
- self.config = self.basic_config
- self.product100 = self.create_product('Product_100', self.categ_basic, 100, 50)
-
- def test_01(self):
- self._run_test({
- 'payment_methods': self.cash_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_02(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_03(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.pay_later_pm, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [],
- },
- })
-
- def test_04(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_split_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_05(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_split_pm1, 100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_06(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [], 'payments': [(self.cash_pm1, 100), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_07(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [], 'payments': [(self.bank_pm1, 100), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_08(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [], 'payments': [(self.bank_split_pm1, 100), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_09(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [], 'payments': [(self.cash_split_pm1, 100), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_10(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_pm1, 200), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_11(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_pm1, 200), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_12(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_split_pm1, 200), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_13(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_split_pm1, 200), (self.pay_later_pm, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_14(self):
- self._run_test({
- 'payment_methods': self.cash_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_pm1, 200), (self.cash_pm1, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_15(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_pm1, 200), (self.cash_pm1, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((-100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_16(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_split_pm1, 200), (self.cash_pm1, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((-100, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_17(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_split_pm1, 200), (self.cash_split_pm1, -100)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((200, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 200, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': True},
- ]
- }),
- ((-100, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_18(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_pm1, 50), (self.pay_later_pm, 50)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((50, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 50, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
-
- def test_19(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_pm1, 50), (self.pay_later_pm, 50)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': False},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((50, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 50, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_20(self):
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.bank_split_pm1, 50), (self.pay_later_pm, 50)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': True},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': False},
- ],
- },
- 'cash_statement': [],
- 'bank_payments': [
- ((50, ), {
- 'line_ids': [
- {'account_id': self.bank_split_pm1.outstanding_account_id.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 50, 'reconciled': True},
- ]
- })
- ],
- },
- })
-
- def test_21(self):
- self._run_test({
- 'payment_methods': self.cash_split_pm1 | self.pay_later_pm,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product100, 1)], 'payments': [(self.cash_split_pm1, 50), (self.pay_later_pm, 50)], 'customer': self.customer, 'is_invoiced': False, 'uuid': '00100-010-0001'},
- ],
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 100, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((50, ), {
- 'line_ids': [
- {'account_id': self.cash_split_pm1.journal_id.default_account_id.id, 'partner_id': self.customer.id, 'debit': 50, 'credit': 0, 'reconciled': False},
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 50, 'reconciled': True},
- ]
- })
- ],
- 'bank_payments': [],
- },
- })
diff --git a/addons/point_of_sale/tests/test_pos_with_fiscal_position.py b/addons/point_of_sale/tests/test_pos_with_fiscal_position.py
deleted file mode 100644
index 3b1173eaf79284..00000000000000
--- a/addons/point_of_sale/tests/test_pos_with_fiscal_position.py
+++ /dev/null
@@ -1,432 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from odoo import Command
-import odoo
-from odoo.addons.point_of_sale.tests.common import TestPoSCommon
-
-@odoo.tests.tagged('post_install', '-at_install')
-class TestPoSWithFiscalPosition(TestPoSCommon):
- """ Tests to pos orders with fiscal position.
-
- keywords/phrases: fiscal position
- """
-
- @classmethod
- def setUpClass(cls):
- super(TestPoSWithFiscalPosition, cls).setUpClass()
-
- cls.config = cls.basic_config
- cls.company.tax_calculation_rounding_method = 'round_per_line'
-
- cls.new_tax_17 = cls.env['account.tax'].create({'name': 'New Tax 17%', 'amount': 17})
- cls.new_tax_17.invoice_repartition_line_ids.write({'account_id': cls.tax_received_account.id})
-
- cls.fpos = cls._create_fiscal_position()
- cls.fpos_no_tax_dest = cls._create_fiscal_position_no_tax_dest()
-
- cls.product1 = cls.create_product(
- 'Product 1',
- cls.categ_basic,
- lst_price=10.99,
- standard_price=5.0,
- tax_ids=cls.taxes['tax7'].ids,
- )
- cls.product2 = cls.create_product(
- 'Product 2',
- cls.categ_basic,
- lst_price=19.99,
- standard_price=10.0,
- tax_ids=cls.taxes['tax10'].ids,
- )
- cls.product3 = cls.create_product(
- 'Product 3',
- cls.categ_basic,
- lst_price=30.99,
- standard_price=15.0,
- tax_ids=cls.taxes['tax7'].ids,
- )
-
- @classmethod
- def _create_fiscal_position(cls):
- fpos = cls.env['account.fiscal.position'].create({'name': 'Test Fiscal Position'})
-
- account_fpos = cls.env['account.fiscal.position.account'].create({
- 'position_id': fpos.id,
- 'account_src_id': cls.sale_account.id,
- 'account_dest_id': cls.other_sale_account.id,
- })
- fpos.write({
- 'account_ids': [(6, 0, account_fpos.ids)],
- })
- cls.new_tax_17.write({
- 'fiscal_position_ids': [Command.link(fpos.id)],
- 'original_tax_ids': [Command.link(cls.taxes['tax7'].id)],
- })
- return fpos
-
- @classmethod
- def _create_fiscal_position_no_tax_dest(cls):
- fpos_no_tax_dest = cls.env['account.fiscal.position'].create({'name': 'Test Fiscal Position'})
- account_fpos = cls.env['account.fiscal.position.account'].create({
- 'position_id': fpos_no_tax_dest.id,
- 'account_src_id': cls.sale_account.id,
- 'account_dest_id': cls.other_sale_account.id,
- })
- fpos_no_tax_dest.write({
- 'account_ids': [(6, 0, account_fpos.ids)],
- })
- cls.env['account.tax'].create({
- 'name': 'Exempt',
- 'amount': 0,
- 'fiscal_position_ids': [Command.link(fpos_no_tax_dest.id)],
- 'original_tax_ids': [Command.link(cls.taxes['tax7'].id)],
- })
- return fpos_no_tax_dest
-
- def test_01_no_invoice_fpos(self):
- """ orders without invoice
-
- Orders
- ======
- +---------+----------+---------------+----------+-----+---------+-----------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+---------------+----------+-----+---------+-----------------+--------+
- | order 1 | cash | yes, customer | product1 | 10 | 109.90 | 18.68 [7%->17%] | 128.58 |
- | | | | product2 | 10 | 181.73 | 18.17 [10%] | 199.90 |
- | | | | product3 | 10 | 309.90 | 52.68 [7%->17%] | 362.58 |
- +---------+----------+---------------+----------+-----+---------+-----------------+--------+
- | order 2 | cash | yes, customer | product1 | 5 | 54.95 | 9.34 [7%->17%] | 64.29 |
- | | | | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- +---------+----------+---------------+----------+-----+---------+-----------------+--------+
- | order 3 | bank | no | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- | | | | product3 | 5 | 154.95 | 10.85 [7%] | 165.8 |
- +---------+----------+---------------+----------+-----+---------+-----------------+--------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | sale_account | -154.95 | (for the 7% base amount)
- | sale_account | -90.86 | (for the 10% base amount)
- | other_sale_account | -474.75 | (for the 17% base amount)
- | other_sale_account | -272.59 | (for the 10% base amount)
- | tax 17% | -80.70 |
- | tax 10% | -36.35 |
- | tax 7% | -10.85 |
- | pos receivable bank | 265.75 |
- | pos receivable cash | 855.30 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
-
- self.customer.write({'property_account_position_id': self.fpos.id})
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10), (self.product3, 10)], 'customer': self.customer, 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'customer': self.customer, 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm1, 265.75)], 'uuid': '00100-010-0003'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 80.70, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 36.35, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 10.85, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': False, 'debit': 0, 'credit': 474.75, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': False, 'debit': 0, 'credit': 272.59, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 90.86, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 154.95, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 265.75, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 855.30, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((855.30, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 855.30, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 855.30, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((265.75, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 265.75, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 265.75, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_02_no_invoice_fpos_no_tax_dest(self):
- """ Customer with fiscal position that maps a tax to no tax.
-
- Orders
- ======
- +---------+----------+---------------+----------+-----+---------+-------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+---------------+----------+-----+---------+-------------+--------+
- | order 1 | bank | yes, customer | product1 | 10 | 109.90 | 0 | 109.90 |
- | | | | product2 | 10 | 181.73 | 18.17 [10%] | 199.90 |
- | | | | product3 | 10 | 309.90 | 0 | 309.90 |
- +---------+----------+---------------+----------+-----+---------+-------------+--------+
- | order 2 | cash | yes, customer | product1 | 5 | 54.95 | 0 | 54.95 |
- | | | | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- +---------+----------+---------------+----------+-----+---------+-------------+--------+
- | order 3 | bank | no | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- | | | | product3 | 5 | 154.95 | 10.85 [7%] | 165.80 |
- +---------+----------+---------------+----------+-----+---------+-------------+--------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | sale_account | -154.95 | (for the 7% base amount)
- | sale_account | -90.86 | (for the 10% base amount)
- | other_sale_account | -272.59 | (for the 10% base amount)
- | other_sale_account | -474.75 | (no tax)
- | tax 10% | -36.35 |
- | tax 7% | -10.85 |
- | pos receivable bank | 885.45 |
- | pos receivable cash | 154.9 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
-
- self.customer.write({'property_account_position_id': self.fpos_no_tax_dest.id})
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10), (self.product3, 10)], 'payments': [(self.bank_pm1, 619.7)], 'customer': self.customer, 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'customer': self.customer, 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm1, 265.75)], 'uuid': '00100-010-0003'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 36.35, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 10.85, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': False, 'debit': 0, 'credit': 474.75, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': False, 'debit': 0, 'credit': 272.59, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 90.86, 'reconciled': False},
- {'account_id': self.sales_account.id, 'partner_id': False, 'debit': 0, 'credit': 154.95, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 885.45, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 154.9, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((154.9, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 154.9, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 154.9, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((885.45, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 885.45, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 885.45, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_03_invoiced_fpos(self):
- """ Invoice 2 orders.
-
- Orders
- ======
- +---------+----------+---------------------+----------+-----+---------+-----------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+---------------------+----------+-----+---------+-----------------+--------+
- | order 1 | bank | yes, customer | product1 | 10 | 109.90 | 18.68 [7%->17%] | 128.58 |
- | | | | product2 | 10 | 181.73 | 18.17 [10%] | 199.90 |
- | | | | product3 | 10 | 309.90 | 52.68 [7%->17%] | 362.58 |
- +---------+----------+---------------------+----------+-----+---------+-----------------+--------+
- | order 2 | cash | no, customer | product1 | 5 | 54.95 | 9.34 [7%->17%] | 64.29 |
- | | | | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- +---------+----------+---------------------+----------+-----+---------+-----------------+--------+
- | order 3 | cash | yes, other_customer | product2 | 5 | 90.86 | 9.09 [10%] | 99.95 |
- | | | | product3 | 5 | 154.95 | 10.85 [7%] | 165.80 |
- +---------+----------+---------------------+----------+-----+---------+-----------------+--------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | other_sale_account | -54.95 | (for the 17% base amount)
- | other_sale_account | -90.86 | (for the 10% base amount)
- | tax 10% | -9.09 |
- | tax 17% | -9.34 |
- | pos receivable cash | 429.99 |
- | pos receivable bank | 691.06 |
- | receivable | -691.06 |
- | other receivable | -265.75 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
-
- self.customer.write({'property_account_position_id': self.fpos.id})
-
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(3, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- invoiced_order_1 = self.pos_session.order_ids.filtered(lambda order: '00100-010-0001' in order.uuid)
- invoiced_order_2 = self.pos_session.order_ids.filtered(lambda order: '00100-010-0003' in order.uuid)
-
- self.assertTrue(invoiced_order_1, msg='Invoiced order 1 should exist.')
- self.assertTrue(invoiced_order_2, msg='Invoiced order 2 should exist.')
- self.assertTrue(invoiced_order_1.account_move, msg='Invoiced order 1 should have invoice (account_move).')
- self.assertTrue(invoiced_order_2.account_move, msg='Invoiced order 2 should have invoice (account_move).')
-
- self._run_test({
- 'payment_methods': self.cash_pm1 | self.bank_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10), (self.product3, 10)], 'payments': [(self.bank_pm1, 691.06)], 'customer': self.customer, 'is_invoiced': True, 'uuid': '00100-010-0001'},
- {'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'customer': self.customer, 'uuid': '00100-010-0002'},
- {'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'customer': self.other_customer, 'is_invoiced': True, 'uuid': '00100-010-0003'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {
- '00100-010-0001': {
- 'payments': [
- ((self.bank_pm1, 691.06), {
- 'line_ids': [
- {'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 691.06, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 691.06, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- '00100-010-0003': {
- 'payments': [
- ((self.cash_pm1, 265.75), {
- 'line_ids': [
- {'account_id': self.other_receivable_account.id, 'partner_id': self.other_customer.id, 'debit': 0, 'credit': 265.75, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 265.75, 'credit': 0, 'reconciled': False},
- ]
- }),
- ],
- },
- },
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 9.34, 'reconciled': False},
- {'account_id': self.tax_received_account.id, 'partner_id': False, 'debit': 0, 'credit': 9.09, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': False, 'debit': 0, 'credit': 54.95, 'reconciled': False},
- {'account_id': self.other_sale_account.id, 'partner_id': False, 'debit': 0, 'credit': 90.86, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 691.06, 'credit': 0, 'reconciled': True},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 429.99, 'credit': 0, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 691.06, 'reconciled': True},
- {'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 265.75, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((429.99, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 429.99, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 429.99, 'reconciled': True},
- ]
- }),
- ],
- 'bank_payments': [
- ((691.06, ), {
- 'line_ids': [
- {'account_id': self.bank_pm1.outstanding_account_id.id, 'partner_id': False, 'debit': 691.06, 'credit': 0, 'reconciled': False},
- {'account_id': self.bank_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 691.06, 'reconciled': True},
- ]
- }),
- ],
- },
- })
-
- def test_04_remove_tax_if_not_in_fp(self):
- """ Tax a, with only fiscal position a set, should be removed if fiscal position b is set on order
-
- Orders
- ======
- +---------+----------+---------------------+----------+-----+---------+------------------+--------+
- | order | payments | invoiced? | product | qty | untaxed | tax | total |
- +---------+----------+---------------------+----------+-----+---------+------------------+--------+
- | order 1 | cash | yes, customer | product1 | 10 | 109.90 | 18.68 [7%->None] | 109.90 |
- +---------+----------+---------------------+----------+-----+---------+-----------------+--------+
-
- Expected Result
- ===============
- +---------------------+---------+
- | account | balance |
- +---------------------+---------+
- | other_sale_account | -109.90 |
- | pos receivable cash | 109.90 |
- +---------------------+---------+
- | Total balance | 0.0 |
- +---------------------+---------+
- """
- def _before_closing_cb():
- # check values before closing the session
- self.assertEqual(1, self.pos_session.order_count)
- orders_total = sum(order.amount_total for order in self.pos_session.order_ids)
- self.assertAlmostEqual(orders_total, self.pos_session.total_payments_amount, msg='Total order amount should be equal to the total payment amount.')
-
- self.new_tax_17.original_tax_ids = None # cancel tax replacement
- self.customer.property_account_position_id = self.fpos # enable applying fpos on order
- dummy_fp = self.env['account.fiscal.position'].create({'name': 'Dummy FP'})
- self.taxes['tax7'].fiscal_position_ids |= dummy_fp # set a dummy fp on tax, as 'normal' taxes should have fp and and a tax without fp is never replaced
-
- self._run_test({
- 'payment_methods': self.cash_pm1,
- 'orders': [
- {'pos_order_lines_ui_args': [(self.product1, 10)], 'customer': self.customer, 'uuid': '00100-010-0001'},
- ],
- 'before_closing_cb': _before_closing_cb,
- 'journal_entries_before_closing': {},
- 'journal_entries_after_closing': {
- 'session_journal_entry': {
- 'line_ids': [
- {'account_id': self.other_sale_account.id, 'partner_id': False, 'debit': 0, 'credit': 109.9, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 109.9, 'credit': 0, 'reconciled': True},
- ],
- },
- 'cash_statement': [
- ((109.9, ), {
- 'line_ids': [
- {'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 109.9, 'credit': 0, 'reconciled': False},
- {'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 109.9, 'reconciled': True},
- ]
- }),
- ],
- },
- })
diff --git a/addons/point_of_sale/tests/test_report_session.py b/addons/point_of_sale/tests/test_report_session.py
index 6d1603920f2342..c4cf77a4b492a8 100644
--- a/addons/point_of_sale/tests/test_report_session.py
+++ b/addons/point_of_sale/tests/test_report_session.py
@@ -59,13 +59,10 @@ def test_report_session(self):
self.make_payment(order, self.bank_split_pm1, 60)
self.make_payment(order, self.bank_pm1, 50)
- self.config.current_session_id.action_pos_session_closing_control(bank_payment_method_diffs={self.bank_split_pm1.id: 50, self.bank_pm1.id: 40})
+ self.config.current_session_id.close_session_from_ui()
# PoS Orders have negative IDs to avoid conflict, so reports[0] will correspond to the newest order
report = self.env['report.point_of_sale.report_saledetails'].get_sale_details(session_ids=[session_id])
- split_payment_bank = [p for p in report['payments'] if p.get('id', 0) == self.bank_split_pm1.id]
- self.assertEqual(split_payment_bank[0]['cash_moves'][0]['amount'], 50)
- bank_payment = [p for p in report['payments'] if p.get('id', 0) == self.bank_pm1.id]
# self.assertEqual(bank_payment[0]['cash_moves'][0]['amount'], 40) TODO WAN
self.assertEqual(report['products_info']['total'], 100, "Total amount of products should be 100, as we want total without tax")
self.assertEqual(report['products'][0]['products'][0]['base_amount'], 100, "Base amount of product should be 100, as we want price without tax")
@@ -103,7 +100,7 @@ def test_report_session_2(self):
order = self.env['pos.order'].create(order_info)
self.make_payment(order, self.cash_pm1, 100)
- self.config.current_session_id.action_pos_session_closing_control()
+ self.config.current_session_id.close_session_from_ui()
self.config.open_ui()
session_id_2 = self.config.current_session_id.id
@@ -114,7 +111,7 @@ def test_report_session_2(self):
order = self.env['pos.order'].create(order_info)
self.make_payment(order, self.cash_pm1, 100)
- self.config.current_session_id.action_pos_session_closing_control()
+ self.config.current_session_id.close_session_from_ui()
report = self.env['report.point_of_sale.report_saledetails'].get_sale_details()
for payment in report['payments']:
@@ -131,17 +128,19 @@ def test_report_listing(self):
cash_payment_method = self.env['pos.payment.method'].create({
'name': 'Cash',
+ 'type': 'cash',
'receivable_account_id': self.company_data['default_account_receivable'].id,
'journal_id': self.company_data['default_journal_cash'].id,
'company_id': self.env.company.id,
})
bank_payment_method = self.env['pos.payment.method'].create({
'name': 'Bank',
+ 'type': 'bank',
'journal_id': self.company_data['default_journal_bank'].id,
'receivable_account_id': self.company_data['default_account_receivable'].id,
'company_id': self.env.company.id,
})
- self.config.write({'payment_method_ids': [(4, bank_payment_method.id), (4, cash_payment_method.id)]})
+ self.config.write({'payment_method_ids': [(5, 0), (4, bank_payment_method.id), (4, cash_payment_method.id)]})
self.open_new_session()
session = self.pos_session
@@ -227,7 +226,7 @@ def test_report_session_3(self):
order_info['lines'][0][2]['qty'] = 59.7
order = self.env['pos.order'].create(order_info)
self.make_payment(order, self.bank_pm1, 0)
- self.config.current_session_id.action_pos_session_closing_control()
+ self.config.current_session_id.close_session_from_ui()
report = self.env['report.point_of_sale.report_saledetails'].get_sale_details()
self.assertEqual(report['products'][0]['products'][0]['quantity'], 74.6, "Quantity of product should be 74.6, as we want the sum of the quantity of the two orders")
@@ -272,8 +271,8 @@ def test_report_bank_expected_different_than_counted(self):
self.make_payment(order1, self.bank_pm1, 100)
- self.config.current_session_id.action_pos_session_closing_control(
- bank_payment_method_diffs={self.bank_pm1.id: -20})
+ self.config.current_session_id.close_session_from_ui(
+ payment_method_closing={self.bank_pm1.id: 80})
report = self.env['report.point_of_sale.report_saledetails'].get_sale_details(session_ids=[session1_id])
self.assertEqual(report['payments'][1]['money_difference'], -20)
@@ -306,7 +305,8 @@ def test_report_bank_expected_different_than_counted(self):
self.make_payment(order2, self.bank_pm1, 100)
- self.config.current_session_id.action_pos_session_closing_control(bank_payment_method_diffs={self.bank_pm1.id: -20})
+ self.config.current_session_id.close_session_from_ui(
+ payment_method_closing={self.bank_pm1.id: 80})
report = self.env['report.point_of_sale.report_saledetails'].get_sale_details(session_ids=[session2_id])
self.assertEqual(report['payments'][1]['money_difference'], -20)
@@ -350,7 +350,7 @@ def test_report_session_4(self):
}
order = self.env['pos.order'].create(order_info)
self.make_payment(order, self.bank_pm1, 156.25)
- self.config.current_session_id.action_pos_session_closing_control()
+ self.config.current_session_id.close_session_from_ui()
report = self.env['report.point_of_sale.report_saledetails'].get_sale_details()
self.assertEqual(report["taxes_info"]["base_amount"], 100, "Base amount should be equal to 100")
@@ -360,7 +360,7 @@ def test_report_session_category_qty_round(self):
quantities = [12.45, 88.21, 45.09, 7.33, 56.12, 92.84, 31.56, 19.47, 64.91, 5.02, 77.38, 41.65, 23.19, 99.72, 10.88]
products = [self.create_product(f'Product {i}', self.categ_basic, 100) for i in range(len(quantities))]
total = sum(quantities)
- order_info = {
+ order_info = [{
'company_id': self.env.company.id,
'session_id': session_id_1,
'partner_id': self.partner_a.id,
@@ -380,15 +380,18 @@ def test_report_session_category_qty_round(self):
'amount_tax': 0.0,
'amount_return': 0.0,
'to_invoice': False,
- }
+ } for _ in range(5)]
- order = self.env['pos.order'].create(order_info)
- self.make_payment(order, self.bank_pm1, total)
- self.config.current_session_id.action_pos_session_closing_control()
+ for order_data in order_info:
+ order = self.env['pos.order'].create(order_data)
+ self.make_payment(order, self.bank_pm1, order.amount_total)
+ session = self.config.current_session_id
+ session.close_session_from_ui()
+ self.assertEqual(session.state, 'closed', "Session should be closed")
report = self.env['report.point_of_sale.report_saledetails'].get_sale_details()
- self.assertEqual(report['products'][0]['qty'], 675.82)
- self.assertEqual(report['products'][0]['total'], 675.82)
+ self.assertAlmostEqual(report['products'][0]['qty'], 675.82 * 5) # The test create 5 orders
+ self.assertAlmostEqual(report['products'][0]['total'], 675.82 * 5) # The test create 5 orders
def test_session_report_with_fp_and_discount(self):
fiscal_position = self.env['account.fiscal.position'].create({
diff --git a/addons/point_of_sale/tests/test_res_config_settings.py b/addons/point_of_sale/tests/test_res_config_settings.py
index 4b07e8196eb3b6..fab46f9ce01112 100644
--- a/addons/point_of_sale/tests/test_res_config_settings.py
+++ b/addons/point_of_sale/tests/test_res_config_settings.py
@@ -43,21 +43,19 @@ def test_properly_set_pos_config_x2many_fields(self):
Command.create({
'name': 'Bank 1',
'receivable_account_id': self.env.company.account_default_pos_receivable_account_id.id,
- 'is_cash_count': False,
- 'split_transactions': False,
+ 'type': 'bank',
'company_id': self.env.company.id,
}),
Command.create({
'name': 'Bank 2',
'receivable_account_id': self.env.company.account_default_pos_receivable_account_id.id,
- 'is_cash_count': False,
- 'split_transactions': False,
+ 'type': 'bank',
'company_id': self.env.company.id,
}),
Command.create({
'name': 'Cash',
'receivable_account_id': self.env.company.account_default_pos_receivable_account_id.id,
- 'is_cash_count': True,
+ 'type': 'cash',
'company_id': self.env.company.id,
})
]
diff --git a/addons/point_of_sale/views/point_of_sale_dashboard.xml b/addons/point_of_sale/views/point_of_sale_dashboard.xml
index 6b6177c628b9b4..eb94d2474c2582 100644
--- a/addons/point_of_sale/views/point_of_sale_dashboard.xml
+++ b/addons/point_of_sale/views/point_of_sale_dashboard.xml
@@ -152,13 +152,13 @@
Closing
-
+
-