mirror of
https://github.com/bringout/oca-ocb-sale.git
synced 2026-04-27 17:31:59 +02:00
Initial commit: Sale packages
This commit is contained in:
commit
14e3d26998
6469 changed files with 2479670 additions and 0 deletions
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_point_of_sale_flow
|
||||
from . import test_frontend
|
||||
from . import test_point_of_sale_ui
|
||||
from . import test_anglo_saxon
|
||||
from . import test_point_of_sale
|
||||
from . import test_pos_capture
|
||||
from . import test_pos_controller
|
||||
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_pos_stock_account
|
||||
from . import test_js
|
||||
from . import test_report_pos_order
|
||||
from . import test_res_config_settings
|
||||
|
|
@ -0,0 +1,720 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from random import randint
|
||||
from datetime import datetime
|
||||
|
||||
from odoo import fields, tools
|
||||
from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
|
||||
from odoo.tests.common import Form
|
||||
from odoo.tests import tagged
|
||||
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
class TestPointOfSaleCommon(ValuationReconciliationTestCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.company_data['company'].write({
|
||||
'point_of_sale_update_stock_quantities': 'real',
|
||||
})
|
||||
|
||||
cls.AccountBankStatement = cls.env['account.bank.statement']
|
||||
cls.AccountBankStatementLine = cls.env['account.bank.statement.line']
|
||||
cls.PosMakePayment = cls.env['pos.make.payment']
|
||||
cls.PosOrder = cls.env['pos.order']
|
||||
cls.PosSession = cls.env['pos.session']
|
||||
cls.company = cls.company_data['company']
|
||||
cls.product3 = cls.env['product.product'].create({
|
||||
'name': 'Product 3',
|
||||
'list_price': 450,
|
||||
})
|
||||
cls.product4 = cls.env['product.product'].create({
|
||||
'name': 'Product 4',
|
||||
'list_price': 750,
|
||||
})
|
||||
cls.partner1 = cls.env['res.partner'].create({'name': 'Partner 1'})
|
||||
cls.partner4 = cls.env['res.partner'].create({'name': 'Partner 4'})
|
||||
cls.pos_config = cls.env['pos.config'].create({
|
||||
'name': 'Main',
|
||||
'journal_id': cls.company_data['default_journal_sale'].id,
|
||||
'invoice_journal_id': cls.company_data['default_journal_sale'].id,
|
||||
})
|
||||
cls.led_lamp = cls.env['product.product'].create({
|
||||
'name': 'LED Lamp',
|
||||
'available_in_pos': True,
|
||||
'list_price': 0.90,
|
||||
})
|
||||
cls.whiteboard_pen = cls.env['product.product'].create({
|
||||
'name': 'Whiteboard Pen',
|
||||
'available_in_pos': True,
|
||||
'list_price': 1.20,
|
||||
})
|
||||
cls.newspaper_rack = cls.env['product.product'].create({
|
||||
'name': 'Newspaper Rack',
|
||||
'available_in_pos': True,
|
||||
'list_price': 1.28,
|
||||
})
|
||||
cls.cash_payment_method = cls.env['pos.payment.method'].create({
|
||||
'name': 'Cash',
|
||||
'receivable_account_id': cls.company_data['default_account_receivable'].id,
|
||||
'journal_id': cls.company_data['default_journal_cash'].id,
|
||||
'company_id': cls.env.company.id,
|
||||
})
|
||||
cls.bank_payment_method = cls.env['pos.payment.method'].create({
|
||||
'name': 'Bank',
|
||||
'journal_id': cls.company_data['default_journal_bank'].id,
|
||||
'receivable_account_id': cls.company_data['default_account_receivable'].id,
|
||||
'company_id': cls.env.company.id,
|
||||
})
|
||||
cls.credit_payment_method = cls.env['pos.payment.method'].create({
|
||||
'name': 'Credit',
|
||||
'receivable_account_id': cls.company_data['default_account_receivable'].id,
|
||||
'split_transactions': True,
|
||||
'company_id': cls.env.company.id,
|
||||
})
|
||||
cls.pos_config.write({'payment_method_ids': [(4, cls.credit_payment_method.id), (4, cls.bank_payment_method.id), (4, cls.cash_payment_method.id)]})
|
||||
|
||||
# Create POS journal
|
||||
cls.pos_config.journal_id = cls.env['account.journal'].create({
|
||||
'type': 'general',
|
||||
'name': 'Point of Sale - Test',
|
||||
'code': 'POSS - Test',
|
||||
'company_id': cls.env.company.id,
|
||||
'sequence': 20
|
||||
})
|
||||
|
||||
# create a VAT tax of 10%, included in the public price
|
||||
Tax = cls.env['account.tax']
|
||||
account_tax_10_incl = Tax.create({
|
||||
'name': 'VAT 10 perc Incl',
|
||||
'amount_type': 'percent',
|
||||
'amount': 10.0,
|
||||
'price_include': True,
|
||||
})
|
||||
|
||||
# assign this 10 percent tax on the [PCSC234] PC Assemble SC234 product
|
||||
# as a sale tax
|
||||
cls.product3.taxes_id = [(6, 0, [account_tax_10_incl.id])]
|
||||
|
||||
# create a VAT tax of 5%, which is added to the public price
|
||||
account_tax_05_incl = Tax.create({
|
||||
'name': 'VAT 5 perc Incl',
|
||||
'amount_type': 'percent',
|
||||
'amount': 5.0,
|
||||
'price_include': False,
|
||||
})
|
||||
|
||||
# create a second VAT tax of 5% but this time for a child company, to
|
||||
# ensure that only product taxes of the current session's company are considered
|
||||
#(this tax should be ignore when computing order's taxes in following tests)
|
||||
account_tax_05_incl_chicago = Tax.create({
|
||||
'name': 'VAT 05 perc Excl (US)',
|
||||
'amount_type': 'percent',
|
||||
'amount': 5.0,
|
||||
'price_include': False,
|
||||
'company_id': cls.company_data_2['company'].id,
|
||||
})
|
||||
|
||||
cls.product4.company_id = False
|
||||
# I assign those 5 percent taxes on the PCSC349 product as a sale taxes
|
||||
cls.product4.write(
|
||||
{'taxes_id': [(6, 0, [account_tax_05_incl.id, account_tax_05_incl_chicago.id])]})
|
||||
|
||||
# Set account_id in the generated repartition lines. Automatically, nothing is set.
|
||||
invoice_rep_lines = (account_tax_05_incl | account_tax_10_incl).mapped('invoice_repartition_line_ids')
|
||||
refund_rep_lines = (account_tax_05_incl | account_tax_10_incl).mapped('refund_repartition_line_ids')
|
||||
|
||||
# Expense account, should just be something else than receivable/payable
|
||||
(invoice_rep_lines | refund_rep_lines).write({'account_id': cls.company_data['default_account_tax_sale'].id})
|
||||
|
||||
|
||||
class TestPoSCommon(ValuationReconciliationTestCommon):
|
||||
""" Set common values for different special test cases.
|
||||
|
||||
The idea is to set up common values here for the tests
|
||||
and implement different special scenarios by inheriting
|
||||
this class.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.company_data['company'].write({
|
||||
'point_of_sale_update_stock_quantities': 'real',
|
||||
'country_id': cls.env['res.country'].create({
|
||||
'name': 'PoS Land',
|
||||
'code': 'WOW',
|
||||
}),
|
||||
})
|
||||
|
||||
# Set basic defaults
|
||||
cls.company = cls.company_data['company']
|
||||
cls.pos_sale_journal = cls.env['account.journal'].create({
|
||||
'type': 'general',
|
||||
'name': 'Point of Sale Test',
|
||||
'code': 'POSS',
|
||||
'company_id': cls.company.id,
|
||||
'sequence': 20
|
||||
})
|
||||
cls.sales_account = cls.company_data['default_account_revenue']
|
||||
cls.invoice_journal = cls.company_data['default_journal_sale']
|
||||
cls.receivable_account = cls.company_data['default_account_receivable']
|
||||
cls.tax_received_account = cls.company_data['default_account_tax_sale']
|
||||
cls.company.account_default_pos_receivable_account_id = cls.env['account.account'].create({
|
||||
'code': 'X1012.POS',
|
||||
'name': 'Debtors - (POS)',
|
||||
'reconcile': True,
|
||||
'account_type': 'asset_receivable',
|
||||
})
|
||||
cls.pos_receivable_account = cls.company.account_default_pos_receivable_account_id
|
||||
cls.pos_receivable_cash = cls.copy_account(cls.company.account_default_pos_receivable_account_id, {'name': 'POS Receivable Cash'})
|
||||
cls.pos_receivable_bank = cls.copy_account(cls.company.account_default_pos_receivable_account_id, {'name': 'POS Receivable Bank'})
|
||||
cls.outstanding_bank = cls.copy_account(cls.company.account_journal_payment_debit_account_id, {'name': 'Outstanding Bank'})
|
||||
cls.c1_receivable = cls.copy_account(cls.receivable_account, {'name': 'Customer 1 Receivable'})
|
||||
cls.other_receivable_account = cls.env['account.account'].create({
|
||||
'name': 'Other Receivable',
|
||||
'code': 'RCV00',
|
||||
'account_type': 'asset_receivable',
|
||||
'internal_group': 'asset',
|
||||
'reconcile': True,
|
||||
})
|
||||
|
||||
# company_currency can be different from `base.USD` depending on the localization installed
|
||||
cls.company_currency = cls.company.currency_id
|
||||
# other_currency is a currency different from the company_currency
|
||||
# sometimes company_currency is different from USD, so handle appropriately.
|
||||
cls.other_currency = cls.currency_data['currency']
|
||||
|
||||
cls.currency_pricelist = cls.env['product.pricelist'].create({
|
||||
'name': 'Public Pricelist',
|
||||
'currency_id': cls.company_currency.id,
|
||||
})
|
||||
# Set Point of Sale configurations
|
||||
# basic_config
|
||||
# - derived from 'point_of_sale.pos_config_main' with added invoice_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()
|
||||
cls.other_currency_config = cls._create_other_currency_config()
|
||||
|
||||
# Set product categories
|
||||
# categ_basic
|
||||
# - just the plain 'product.product_category_all'
|
||||
# categ_anglo
|
||||
# - product category with fifo and real_time valuations
|
||||
# - used for checking anglo saxon accounting behavior
|
||||
cls.categ_basic = cls.env.ref('product.product_category_all')
|
||||
cls.env.company.anglo_saxon_accounting = True
|
||||
cls.categ_anglo = cls._create_categ_anglo()
|
||||
|
||||
# other basics
|
||||
cls.sale_account = cls.categ_basic.property_account_income_categ_id
|
||||
cls.other_sale_account = cls.env['account.account'].search([
|
||||
('company_id', '=', cls.company.id),
|
||||
('account_type', '=', 'income'),
|
||||
('id', '!=', cls.sale_account.id)
|
||||
], limit=1)
|
||||
|
||||
# Set customers
|
||||
cls.customer = cls.env['res.partner'].create({'name': 'Customer 1', 'property_account_receivable_id': cls.c1_receivable.id})
|
||||
cls.other_customer = cls.env['res.partner'].create({'name': 'Other Customer', 'property_account_receivable_id': cls.other_receivable_account.id})
|
||||
|
||||
# Set taxes
|
||||
# cls.taxes => dict
|
||||
# keys: 'tax7', 'tax10'(price_include=True), 'tax_group_7_10'
|
||||
cls.taxes = cls._create_taxes()
|
||||
|
||||
cls.stock_location_components = cls.env["stock.location"].create({
|
||||
'name': 'Shelf 1',
|
||||
'location_id': cls.company_data['default_warehouse'].lot_stock_id.id,
|
||||
})
|
||||
|
||||
|
||||
#####################
|
||||
## private methods ##
|
||||
#####################
|
||||
|
||||
@classmethod
|
||||
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.pos_sale_journal.id,
|
||||
'available_pricelist_ids': cls.currency_pricelist.ids,
|
||||
'pricelist_id': cls.currency_pricelist.id,
|
||||
})
|
||||
cls.cash_pm1 = cls.env['pos.payment.method'].create({
|
||||
'name': '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',
|
||||
'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,
|
||||
})
|
||||
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)]})
|
||||
return config
|
||||
|
||||
@classmethod
|
||||
def _create_other_currency_config(cls):
|
||||
(cls.other_currency.rate_ids | cls.company_currency.rate_ids).unlink()
|
||||
cls.env['res.currency.rate'].create({
|
||||
'rate': 0.5,
|
||||
'currency_id': cls.other_currency.id,
|
||||
'name': datetime.today().date(),
|
||||
})
|
||||
other_cash_journal = cls.env['account.journal'].create({
|
||||
'name': 'Cash Other',
|
||||
'type': 'cash',
|
||||
'company_id': cls.company.id,
|
||||
'code': 'CSHO',
|
||||
'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',
|
||||
'code': 'POSO',
|
||||
'company_id': cls.company.id,
|
||||
'sequence': 12,
|
||||
'currency_id': cls.other_currency.id
|
||||
})
|
||||
other_bank_journal = cls.env['account.journal'].create({
|
||||
'name': 'Bank Other',
|
||||
'type': 'bank',
|
||||
'company_id': cls.company.id,
|
||||
'code': 'BNKO',
|
||||
'sequence': 13,
|
||||
'currency_id': cls.other_currency.id
|
||||
})
|
||||
other_pricelist = cls.env['product.pricelist'].create({
|
||||
'name': 'Public Pricelist Other',
|
||||
'currency_id': cls.other_currency.id,
|
||||
})
|
||||
cls.cash_pm2 = cls.env['pos.payment.method'].create({
|
||||
'name': 'Cash Other',
|
||||
'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',
|
||||
'journal_id': other_bank_journal.id,
|
||||
'receivable_account_id': cls.pos_receivable_bank.id,
|
||||
'outstanding_account_id': cls.outstanding_bank.id,
|
||||
})
|
||||
|
||||
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,
|
||||
'pricelist_id': other_pricelist.id,
|
||||
'payment_method_ids': [cls.cash_pm2.id, cls.bank_pm2.id],
|
||||
})
|
||||
return config
|
||||
|
||||
@classmethod
|
||||
def _create_categ_anglo(cls):
|
||||
return cls.env['product.category'].create({
|
||||
'name': 'Anglo',
|
||||
'parent_id': False,
|
||||
'property_cost_method': 'fifo',
|
||||
'property_valuation': 'real_time',
|
||||
'property_stock_account_input_categ_id': cls.company_data['default_account_stock_in'].id,
|
||||
'property_stock_account_output_categ_id': cls.company_data['default_account_stock_out'].id,
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def _create_taxes(cls):
|
||||
""" Create taxes
|
||||
|
||||
tax7: 7%, excluded in product price
|
||||
tax10: 10%, included in product price
|
||||
tax21: 21%, included in product price
|
||||
"""
|
||||
def create_tag(name):
|
||||
return cls.env['account.account.tag'].create({
|
||||
'name': name,
|
||||
'applicability': 'taxes',
|
||||
'country_id': cls.env.company.account_fiscal_country_id.id
|
||||
})
|
||||
|
||||
cls.tax_tag_invoice_base = create_tag('Invoice Base tag')
|
||||
cls.tax_tag_invoice_tax = create_tag('Invoice Tax tag')
|
||||
cls.tax_tag_refund_base = create_tag('Refund Base tag')
|
||||
cls.tax_tag_refund_tax = create_tag('Refund Tax tag')
|
||||
|
||||
def create_tax(percentage, price_include=False, include_base_amount=False):
|
||||
return cls.env['account.tax'].create({
|
||||
'name': f'Tax {percentage}%',
|
||||
'amount': percentage,
|
||||
'price_include': price_include,
|
||||
'amount_type': 'percent',
|
||||
'include_base_amount': include_base_amount,
|
||||
'invoice_repartition_line_ids': [
|
||||
(0, 0, {
|
||||
'repartition_type': 'base',
|
||||
'tag_ids': [(6, 0, cls.tax_tag_invoice_base.ids)],
|
||||
}),
|
||||
(0, 0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': cls.tax_received_account.id,
|
||||
'tag_ids': [(6, 0, cls.tax_tag_invoice_tax.ids)],
|
||||
}),
|
||||
],
|
||||
'refund_repartition_line_ids': [
|
||||
(0, 0, {
|
||||
'repartition_type': 'base',
|
||||
'tag_ids': [(6, 0, cls.tax_tag_refund_base.ids)],
|
||||
}),
|
||||
(0, 0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': cls.tax_received_account.id,
|
||||
'tag_ids': [(6, 0, cls.tax_tag_refund_tax.ids)],
|
||||
}),
|
||||
],
|
||||
})
|
||||
def create_tax_fixed(amount, price_include=False):
|
||||
return cls.env['account.tax'].create({
|
||||
'name': f'Tax fixed amount {amount}',
|
||||
'amount': amount,
|
||||
'price_include': price_include,
|
||||
'include_base_amount': price_include,
|
||||
'amount_type': 'fixed',
|
||||
'invoice_repartition_line_ids': [
|
||||
(0, 0, {
|
||||
'repartition_type': 'base',
|
||||
'tag_ids': [(6, 0, cls.tax_tag_invoice_base.ids)],
|
||||
}),
|
||||
(0, 0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': cls.tax_received_account.id,
|
||||
'tag_ids': [(6, 0, cls.tax_tag_invoice_tax.ids)],
|
||||
}),
|
||||
],
|
||||
'refund_repartition_line_ids': [
|
||||
(0, 0, {
|
||||
'repartition_type': 'base',
|
||||
'tag_ids': [(6, 0, cls.tax_tag_refund_base.ids)],
|
||||
}),
|
||||
(0, 0, {
|
||||
'repartition_type': 'tax',
|
||||
'account_id': cls.tax_received_account.id,
|
||||
'tag_ids': [(6, 0, cls.tax_tag_refund_tax.ids)],
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
tax_fixed006 = create_tax_fixed(0.06, price_include=True)
|
||||
tax_fixed012 = create_tax_fixed(0.12, price_include=True)
|
||||
tax7 = create_tax(7, price_include=False)
|
||||
tax7base = create_tax(7, price_include=False, include_base_amount=True)
|
||||
tax10nobase = create_tax(10)
|
||||
tax10 = create_tax(10, price_include=True)
|
||||
tax21 = create_tax(21, price_include=True)
|
||||
|
||||
|
||||
tax_group_7_10 = tax7.copy()
|
||||
with Form(tax_group_7_10) as tax:
|
||||
tax.name = 'Tax 7+10%'
|
||||
tax.amount_type = 'group'
|
||||
tax.children_tax_ids.add(tax7)
|
||||
tax.children_tax_ids.add(tax10)
|
||||
|
||||
return {
|
||||
'tax7': tax7,
|
||||
'tax7base': tax7base,
|
||||
'tax10nobase': tax10nobase,
|
||||
'tax10': tax10,
|
||||
'tax21': tax21,
|
||||
'tax_fixed006': tax_fixed006,
|
||||
'tax_fixed012': tax_fixed012,
|
||||
'tax_group_7_10': tax_group_7_10
|
||||
}
|
||||
|
||||
####################
|
||||
## public methods ##
|
||||
####################
|
||||
|
||||
def create_random_uid(self):
|
||||
return ('%05d-%03d-%04d' % (randint(1, 99999), randint(1, 999), randint(1, 9999)))
|
||||
|
||||
def create_ui_order_data(self, pos_order_lines_ui_args, customer=False, is_invoiced=False, payments=None, uid=None):
|
||||
""" Mocks the order_data generated by the pos ui.
|
||||
|
||||
This is useful in making orders in an open pos session without making tours.
|
||||
Its functionality is tested in test_pos_create_ui_order_data.py.
|
||||
|
||||
Before use, make sure that self is set with:
|
||||
1. pricelist -> the pricelist of the current session
|
||||
2. currency -> currency of the current session
|
||||
3. pos_session -> the current session, equivalent to config.current_session_id
|
||||
4. cash_pm -> first cash payment method in the current session
|
||||
5. config -> the active pos.config
|
||||
|
||||
The above values should be set when `self.open_new_session` is called.
|
||||
|
||||
:param list(tuple) pos_order_lines_ui_args: pairs of `ordered product` and `quantity`
|
||||
or triplet of `ordered product`, `quantity` and discount
|
||||
:param list(tuple) payments: pair of `payment_method` and `amount`
|
||||
"""
|
||||
default_fiscal_position = self.config.default_fiscal_position_id
|
||||
fiscal_position = customer.property_account_position_id if customer else default_fiscal_position
|
||||
|
||||
def create_order_line(product, quantity, discount=0.0):
|
||||
price_unit = self.pricelist._get_product_price(product, quantity)
|
||||
tax_ids = fiscal_position.map_tax(product.taxes_id)
|
||||
price_unit_after_discount = price_unit * (1 - discount / 100.0)
|
||||
tax_values = (
|
||||
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,
|
||||
}
|
||||
)
|
||||
return (0, 0, {
|
||||
'discount': discount,
|
||||
'id': randint(1, 1000000),
|
||||
'pack_lot_ids': [],
|
||||
'price_unit': price_unit,
|
||||
'product_id': product.id,
|
||||
'price_subtotal': tax_values['total_excluded'],
|
||||
'price_subtotal_incl': tax_values['total_included'],
|
||||
'qty': quantity,
|
||||
'tax_ids': [(6, 0, tax_ids.ids)]
|
||||
})
|
||||
|
||||
def create_payment(payment_method, amount):
|
||||
return (0, 0, {
|
||||
'amount': amount,
|
||||
'name': fields.Datetime.to_string(fields.Datetime.now()),
|
||||
'payment_method_id': payment_method.id,
|
||||
})
|
||||
|
||||
uid = uid or self.create_random_uid()
|
||||
|
||||
# 1. generate the order lines
|
||||
order_lines = [
|
||||
create_order_line(product, quantity, discount and discount[0] or 0.0)
|
||||
for product, quantity, *discount
|
||||
in pos_order_lines_ui_args
|
||||
]
|
||||
|
||||
# 2. generate the payments
|
||||
total_amount_incl = sum(line[2]['price_subtotal_incl'] for line in order_lines)
|
||||
if payments is None:
|
||||
default_cash_pm = self.config.payment_method_ids.filtered(lambda pm: pm.is_cash_count)[: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)]
|
||||
else:
|
||||
payments = [
|
||||
create_payment(pm, amount)
|
||||
for pm, amount in payments
|
||||
]
|
||||
|
||||
# 3. complete the fields of the order_data
|
||||
total_amount_base = sum(line[2]['price_subtotal'] for line in order_lines)
|
||||
return {
|
||||
'data': {
|
||||
'amount_paid': sum(payment[2]['amount'] for payment in payments),
|
||||
'amount_return': 0,
|
||||
'amount_tax': total_amount_incl - total_amount_base,
|
||||
'amount_total': total_amount_incl,
|
||||
'creation_date': fields.Datetime.to_string(fields.Datetime.now()),
|
||||
'fiscal_position_id': fiscal_position.id,
|
||||
'pricelist_id': self.config.pricelist_id.id,
|
||||
'lines': order_lines,
|
||||
'name': 'Order %s' % uid,
|
||||
'partner_id': customer and customer.id,
|
||||
'pos_session_id': self.pos_session.id,
|
||||
'sequence_number': 2,
|
||||
'statement_ids': payments,
|
||||
'uid': uid,
|
||||
'user_id': self.env.user.id,
|
||||
'to_invoice': is_invoiced,
|
||||
},
|
||||
'id': uid,
|
||||
'to_invoice': is_invoiced,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def create_product(cls, name, category, lst_price, standard_price=None, tax_ids=None, sale_account=None):
|
||||
product = cls.env['product.product'].create({
|
||||
'type': 'product',
|
||||
'available_in_pos': True,
|
||||
'taxes_id': [(5, 0, 0)] if not tax_ids else [(6, 0, tax_ids)],
|
||||
'name': name,
|
||||
'categ_id': category.id,
|
||||
'lst_price': lst_price,
|
||||
'standard_price': standard_price if standard_price else 0.0,
|
||||
})
|
||||
if sale_account:
|
||||
product.property_account_income_id = sale_account
|
||||
return product
|
||||
|
||||
@classmethod
|
||||
def adjust_inventory(cls, products, quantities):
|
||||
""" Adjust inventory of the given products
|
||||
"""
|
||||
for product, qty in zip(products, quantities):
|
||||
cls.env['stock.quant'].with_context(inventory_mode=True).create({
|
||||
'product_id': product.id,
|
||||
'inventory_quantity': qty,
|
||||
'location_id': cls.stock_location_components.id,
|
||||
}).action_apply_inventory()
|
||||
|
||||
def open_new_session(self, opening_cash=0):
|
||||
""" Used to open new pos session in each configuration.
|
||||
|
||||
- The idea is to properly set values that are constant
|
||||
and commonly used in an open pos session.
|
||||
- Calling this method is also a prerequisite for using
|
||||
`self.create_ui_order_data` function.
|
||||
|
||||
Fields:
|
||||
* config : the pos.config currently being used.
|
||||
Its value is set at `self.setUp` of the inheriting
|
||||
test class.
|
||||
* pos_session : the current_session_id of config
|
||||
* currency : currency of the current pos.session
|
||||
* pricelist : the default pricelist of the session
|
||||
"""
|
||||
self.config.open_ui()
|
||||
self.pos_session = self.config.current_session_id
|
||||
self.currency = self.pos_session.currency_id
|
||||
self.pricelist = self.pos_session.config_id.pricelist_id
|
||||
self.pos_session.set_cashbox_pos(opening_cash, None)
|
||||
return self.pos_session
|
||||
|
||||
def _run_test(self, args):
|
||||
pos_session = self._start_pos_session(args['payment_methods'], args.get('opening_cash', 0))
|
||||
_logger.info('DONE: Start session.')
|
||||
orders_map = self._create_orders(args['orders'])
|
||||
_logger.info('DONE: Orders created.')
|
||||
before_closing_cb = args.get('before_closing_cb')
|
||||
if before_closing_cb:
|
||||
before_closing_cb()
|
||||
_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]
|
||||
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()
|
||||
after_closing_cb = args.get('after_closing_cb')
|
||||
if after_closing_cb:
|
||||
after_closing_cb()
|
||||
_logger.info('DONE: Call of after_closing_cb.')
|
||||
self._check_session_journal_entries(pos_session, expected_values=args['journal_entries_after_closing'])
|
||||
_logger.info('DONE: Checks for journal entries after closing the session.')
|
||||
|
||||
def _start_pos_session(self, payment_methods, opening_cash):
|
||||
self.config.write({'payment_method_ids': [(6, 0, payment_methods.ids)]})
|
||||
pos_session = self.open_new_session(opening_cash)
|
||||
self.assertEqual(self.config.payment_method_ids.ids, pos_session.payment_method_ids.ids, msg='Payment methods in the config should be the same as the session.')
|
||||
return pos_session
|
||||
|
||||
def _create_orders(self, order_data_params):
|
||||
'''Returns a dict mapping uid to its created pos.order record.'''
|
||||
result = {}
|
||||
for params in order_data_params:
|
||||
order_data = self.create_ui_order_data(**params)
|
||||
result[params['uid']] = self.env['pos.order'].browse([order['id'] for order in self.env['pos.order'].create_from_ui([order_data])])
|
||||
return result
|
||||
|
||||
def _check_invoice_journal_entries(self, pos_session, orders_map, expected_values):
|
||||
'''Checks the invoice, together with the payments, from each invoiced order.'''
|
||||
currency_rounding = pos_session.currency_id.rounding
|
||||
|
||||
for uid in orders_map:
|
||||
order = orders_map[uid]
|
||||
if not order.is_invoiced:
|
||||
continue
|
||||
invoice = order.account_move
|
||||
# allow not checking the invoice since pos is not creating the invoices
|
||||
if expected_values[uid].get('invoice'):
|
||||
self._assert_account_move(invoice, expected_values[uid]['invoice'])
|
||||
_logger.info('DONE: Check of invoice for order %s.', uid)
|
||||
|
||||
for pos_payment in order.payment_ids:
|
||||
if pos_payment.payment_method_id == self.pay_later_pm:
|
||||
# Skip the pay later payments since there are no journal entries
|
||||
# for them when invoicing.
|
||||
continue
|
||||
|
||||
# This predicate is used to match the pos_payment's journal entry to the
|
||||
# list of payments specified in the 'payments' field of the `_run_test`
|
||||
# args.
|
||||
def predicate(args):
|
||||
payment_method, amount = args
|
||||
first = payment_method == pos_payment.payment_method_id
|
||||
second = tools.float_is_zero(pos_payment.amount - amount, precision_rounding=currency_rounding)
|
||||
return first and second
|
||||
|
||||
self._find_then_assert_values(pos_payment.account_move_id, expected_values[uid]['payments'], predicate)
|
||||
_logger.info('DONE: Check of invoice payment (%s, %s) for order %s.', pos_payment.payment_method_id.name, pos_payment.amount, uid)
|
||||
|
||||
def _check_session_journal_entries(self, pos_session, expected_values):
|
||||
'''Checks the journal entries after closing the session excluding entries checked in `_check_invoice_journal_entries`.'''
|
||||
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'])
|
||||
_logger.info("DONE: Check of the session's account move.")
|
||||
|
||||
# check expected cash journal entries
|
||||
for statement_line in pos_session.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)
|
||||
|
||||
def _assert_account_move(self, account_move, expected_account_move_vals):
|
||||
if expected_account_move_vals:
|
||||
# We allow partial checks of the lines of the account move if `line_ids_predicate` is specified.
|
||||
# This means that only those that satisfy the predicate are compared to the expected account move line_ids.
|
||||
line_ids_predicate = expected_account_move_vals.pop('line_ids_predicate', lambda _: True)
|
||||
self.assertRecordValues(account_move.line_ids.filtered(line_ids_predicate), expected_account_move_vals.pop('line_ids'))
|
||||
self.assertRecordValues(account_move, [expected_account_move_vals])
|
||||
else:
|
||||
# if the expected_account_move_vals is falsy, the account_move should be falsy.
|
||||
self.assertFalse(account_move)
|
||||
|
|
@ -0,0 +1,394 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import time
|
||||
from odoo.tests import tagged
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
|
||||
|
||||
class TestAngloSaxonCommon(AccountTestInvoicingCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
cls.PosMakePayment = cls.env['pos.make.payment']
|
||||
cls.PosOrder = cls.env['pos.order']
|
||||
cls.Statement = cls.env['account.bank.statement']
|
||||
cls.company = cls.env.company
|
||||
cls.warehouse = cls.env['stock.warehouse'].search([('company_id', '=', cls.env.company.id)], limit=1)
|
||||
cls.partner = cls.env['res.partner'].create({'name': 'Partner 1'})
|
||||
cls.category = cls.env.ref('product.product_category_all')
|
||||
cls.category = cls.category.copy({'name': 'New category', 'property_valuation': 'real_time'})
|
||||
cls.account = cls.env['account.account'].create({'name': 'Receivable', 'code': 'RCV00', 'account_type': 'asset_receivable', 'reconcile': True})
|
||||
account_expense = cls.env['account.account'].create({'name': 'Expense', 'code': 'EXP00', 'account_type': 'expense', 'reconcile': True})
|
||||
account_income = cls.env['account.account'].create({'name': 'Income', 'code': 'INC00', 'account_type': 'income', 'reconcile': True})
|
||||
account_output = cls.env['account.account'].create({'name': 'Output', 'code': 'OUT00', 'account_type': 'expense', 'reconcile': True})
|
||||
account_valuation = cls.env['account.account'].create({'name': 'Valuation', 'code': 'STV00', 'account_type': 'expense', 'reconcile': True})
|
||||
cls.partner.property_account_receivable_id = cls.account
|
||||
cls.category.property_account_income_categ_id = account_income
|
||||
cls.category.property_account_expense_categ_id = account_expense
|
||||
cls.category.property_stock_account_input_categ_id = cls.account
|
||||
cls.category.property_stock_account_output_categ_id = account_output
|
||||
cls.category.property_stock_valuation_account_id = account_valuation
|
||||
cls.category.property_stock_journal = cls.env['account.journal'].create({'name': 'Stock journal', 'type': 'sale', 'code': 'STK00'})
|
||||
cls.pos_config = cls.env['pos.config'].create({
|
||||
'name': 'New POS config',
|
||||
})
|
||||
cls.product = cls.env['product.product'].create({
|
||||
'name': 'New product',
|
||||
'standard_price': 100,
|
||||
'available_in_pos': True,
|
||||
'type': 'product',
|
||||
})
|
||||
cls.company.anglo_saxon_accounting = True
|
||||
cls.company.point_of_sale_update_stock_quantities = 'real'
|
||||
cls.product.categ_id = cls.category
|
||||
cls.product.property_account_expense_id = account_expense
|
||||
cls.product.property_account_income_id = account_income
|
||||
sale_journal = cls.env['account.journal'].create({'name': 'POS journal', 'type': 'sale', 'code': 'POS00'})
|
||||
cls.pos_config.journal_id = sale_journal
|
||||
cls.cash_journal = cls.env['account.journal'].create({'name': 'CASH journal', 'type': 'cash', 'code': 'CSH00'})
|
||||
cls.sale_journal = cls.env['account.journal'].create({'name': 'SALE journal', 'type': 'sale', 'code': 'INV00'})
|
||||
cls.pos_config.invoice_journal_id = cls.sale_journal
|
||||
cls.cash_payment_method = cls.env['pos.payment.method'].create({
|
||||
'name': 'Cash Test',
|
||||
'journal_id': cls.cash_journal.id,
|
||||
'receivable_account_id': cls.account.id,
|
||||
})
|
||||
cls.pos_config.write({'payment_method_ids': [(6, 0, cls.cash_payment_method.ids)]})
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAngloSaxonFlow(TestAngloSaxonCommon):
|
||||
|
||||
def test_create_account_move_line(self):
|
||||
# This test will check that the correct journal entries are created when a product in real time valuation
|
||||
# is sold in a company using anglo-saxon
|
||||
self.pos_config.open_ui()
|
||||
current_session = self.pos_config.current_session_id
|
||||
self.cash_journal.loss_account_id = self.account
|
||||
current_session.set_cashbox_pos(0, None)
|
||||
|
||||
# I create a PoS order with 1 unit of New product at 450 EUR
|
||||
self.pos_order_pos0 = self.PosOrder.create({
|
||||
'company_id': self.company.id,
|
||||
'partner_id': self.partner.id,
|
||||
'pricelist_id': self.company.partner_id.property_product_pricelist.id,
|
||||
'session_id': self.pos_config.current_session_id.id,
|
||||
'lines': [(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': self.product.id,
|
||||
'price_unit': 450,
|
||||
'discount': 0.0,
|
||||
'qty': 1.0,
|
||||
'price_subtotal': 450,
|
||||
'price_subtotal_incl': 450,
|
||||
})],
|
||||
'amount_total': 450,
|
||||
'amount_tax': 0,
|
||||
'amount_paid': 0,
|
||||
'amount_return': 0,
|
||||
})
|
||||
|
||||
# I make a payment to fully pay the order
|
||||
context_make_payment = {"active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
|
||||
'amount': 450.0,
|
||||
'payment_method_id': self.cash_payment_method.id,
|
||||
})
|
||||
|
||||
# I click on the validate button to register the payment.
|
||||
context_payment = {'active_id': self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0.with_context(context_payment).check()
|
||||
|
||||
# I check that the order is marked as paid
|
||||
self.assertEqual(self.pos_order_pos0.state, 'paid', 'Order should be in paid state.')
|
||||
self.assertEqual(self.pos_order_pos0.amount_paid, 450, 'Amount paid for the order should be updated.')
|
||||
|
||||
# I close the current session to generate the journal entries
|
||||
current_session_id = self.pos_config.current_session_id
|
||||
current_session_id.post_closing_cash_details(450.0)
|
||||
current_session_id.close_session_from_ui()
|
||||
self.assertEqual(current_session_id.state, 'closed', 'Check that session is closed')
|
||||
|
||||
# Check if there is account_move in the order.
|
||||
# There shouldn't be because the order is not invoiced.
|
||||
self.assertFalse(self.pos_order_pos0.account_move, 'There should be no invoice in the order.')
|
||||
|
||||
# I test that the generated journal entries are correct.
|
||||
account_output = self.category.property_stock_account_output_categ_id
|
||||
expense_account = self.category.property_account_expense_categ_id
|
||||
aml = current_session.move_id.line_ids
|
||||
aml_output = aml.filtered(lambda l: l.account_id.id == account_output.id)
|
||||
aml_expense = aml.filtered(lambda l: l.account_id.id == expense_account.id)
|
||||
self.assertEqual(aml_output.credit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense.debit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
|
||||
|
||||
def _prepare_pos_order(self):
|
||||
""" Set the cost method of `self.product` as FIFO. Receive 5@5 and 5@1 and
|
||||
create a `pos.order` record selling 7 units @ 450.
|
||||
"""
|
||||
# check fifo Costing Method of product.category
|
||||
self.product.categ_id.property_cost_method = 'fifo'
|
||||
self.product.standard_price = 5.0
|
||||
self.env['stock.quant'].with_context(inventory_mode=True).create({
|
||||
'product_id': self.product.id,
|
||||
'inventory_quantity': 5.0,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
}).action_apply_inventory()
|
||||
self.product.standard_price = 1.0
|
||||
self.env['stock.quant'].with_context(inventory_mode=True).create({
|
||||
'product_id': self.product.id,
|
||||
'inventory_quantity': 10.0,
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
}).action_apply_inventory()
|
||||
self.assertEqual(self.product.value_svl, 30, "Value should be (5*5 + 5*1) = 30")
|
||||
self.assertEqual(self.product.quantity_svl, 10)
|
||||
|
||||
|
||||
self.pos_config.open_ui()
|
||||
pos_session = self.pos_config.current_session_id
|
||||
pos_session.set_cashbox_pos(0, None)
|
||||
|
||||
pos_order_values = {
|
||||
'company_id': self.company.id,
|
||||
'partner_id': self.partner.id,
|
||||
'pricelist_id': self.company.partner_id.property_product_pricelist.id,
|
||||
'session_id': self.pos_config.current_session_id.id,
|
||||
'lines': [(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': self.product.id,
|
||||
'price_unit': 450,
|
||||
'discount': 0.0,
|
||||
'qty': 7.0,
|
||||
'price_subtotal': 7 * 450,
|
||||
'price_subtotal_incl': 7 * 450,
|
||||
})],
|
||||
'amount_total': 7 * 450,
|
||||
'amount_tax': 0,
|
||||
'amount_paid': 0,
|
||||
'amount_return': 0,
|
||||
}
|
||||
|
||||
return self.PosOrder.create(pos_order_values)
|
||||
|
||||
def test_fifo_valuation_no_invoice(self):
|
||||
"""Register a payment and validate a session after selling a fifo
|
||||
product without making an invoice for the customer"""
|
||||
pos_order_pos0 = self._prepare_pos_order()
|
||||
context_make_payment = {"active_ids": [pos_order_pos0.id], "active_id": pos_order_pos0.id}
|
||||
self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
|
||||
'amount': 7 * 450.0,
|
||||
'payment_method_id': self.cash_payment_method.id,
|
||||
})
|
||||
|
||||
# register the payment
|
||||
context_payment = {'active_id': pos_order_pos0.id}
|
||||
self.pos_make_payment_0.with_context(context_payment).check()
|
||||
|
||||
# validate the session
|
||||
current_session_id = self.pos_config.current_session_id
|
||||
current_session_id.post_closing_cash_details(7 * 450.0)
|
||||
current_session_id.close_session_from_ui()
|
||||
|
||||
# check the anglo saxon move lines
|
||||
# with uninvoiced orders, the account_move field of pos.order is empty.
|
||||
# the accounting lines are in move_id of pos.session.
|
||||
session_move = pos_order_pos0.session_id.move_id
|
||||
line = session_move.line_ids.filtered(lambda l: l.debit and l.account_id == self.category.property_account_expense_categ_id)
|
||||
self.assertEqual(session_move.journal_id, self.pos_config.journal_id)
|
||||
self.assertEqual(line.debit, 27, 'As it is a fifo product, the move\'s value should be 5*5 + 2*1')
|
||||
|
||||
def test_fifo_valuation_with_invoice(self):
|
||||
"""Register a payment and validate a session after selling a fifo
|
||||
product and make an invoice for the customer"""
|
||||
pos_order_pos0 = self._prepare_pos_order()
|
||||
context_make_payment = {"active_ids": [pos_order_pos0.id], "active_id": pos_order_pos0.id}
|
||||
self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
|
||||
'amount': 7 * 450.0,
|
||||
'payment_method_id': self.cash_payment_method.id,
|
||||
})
|
||||
|
||||
# register the payment
|
||||
context_payment = {'active_id': pos_order_pos0.id}
|
||||
self.pos_make_payment_0.with_context(context_payment).check()
|
||||
|
||||
# Create the customer invoice
|
||||
pos_order_pos0.action_pos_order_invoice()
|
||||
|
||||
# check the anglo saxon move lines
|
||||
line = pos_order_pos0.account_move.line_ids.filtered(lambda l: l.debit and l.account_id == self.category.property_account_expense_categ_id)
|
||||
self.assertEqual(pos_order_pos0.account_move.journal_id, self.pos_config.invoice_journal_id)
|
||||
self.assertEqual(line.debit, 27, 'As it is a fifo product, the move\'s value should be 5*5 + 2*1')
|
||||
|
||||
def test_cogs_with_ship_later_no_invoicing(self):
|
||||
# This test will check that the correct journal entries are created when a product in real time valuation
|
||||
# is sold using the ship later option and no invoice is created in a company using anglo-saxon
|
||||
self.pos_config.open_ui()
|
||||
current_session = self.pos_config.current_session_id
|
||||
self.cash_journal.loss_account_id = self.account
|
||||
current_session.set_cashbox_pos(0, None)
|
||||
|
||||
# 2 step delivery method
|
||||
self.warehouse.delivery_steps = 'pick_ship'
|
||||
|
||||
# I create a PoS order with 1 unit of New product at 450 EUR
|
||||
self.pos_order_pos0 = self.PosOrder.create({
|
||||
'company_id': self.company.id,
|
||||
'partner_id': self.partner.id,
|
||||
'pricelist_id': self.company.partner_id.property_product_pricelist.id,
|
||||
'session_id': self.pos_config.current_session_id.id,
|
||||
'to_invoice': False,
|
||||
'to_ship': True,
|
||||
'lines': [(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': self.product.id,
|
||||
'price_unit': 450,
|
||||
'discount': 0.0,
|
||||
'qty': 1.0,
|
||||
'price_subtotal': 450,
|
||||
'price_subtotal_incl': 450,
|
||||
})],
|
||||
'amount_total': 450,
|
||||
'amount_tax': 0,
|
||||
'amount_paid': 0,
|
||||
'amount_return': 0,
|
||||
})
|
||||
|
||||
# I make a payment to fully pay the order
|
||||
context_make_payment = {"active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
|
||||
'amount': 450.0,
|
||||
'payment_method_id': self.cash_payment_method.id,
|
||||
})
|
||||
|
||||
# I click on the validate button to register the payment.
|
||||
context_payment = {'active_id': self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0.with_context(context_payment).check()
|
||||
|
||||
# I close the current session to generate the journal entries
|
||||
current_session_id = self.pos_config.current_session_id
|
||||
current_session_id.post_closing_cash_details(450.0)
|
||||
current_session_id.close_session_from_ui()
|
||||
self.assertEqual(current_session_id.state, 'closed', 'Check that session is closed')
|
||||
|
||||
self.assertEqual(len(current_session.picking_ids), 2, "There should be 2 pickings")
|
||||
current_session.picking_ids.move_ids_without_package.quantity_done = 1
|
||||
current_session.picking_ids.button_validate()
|
||||
|
||||
# I test that the generated journal entries are correct.
|
||||
account_output = self.category.property_stock_account_output_categ_id
|
||||
expense_account = self.category.property_account_expense_categ_id
|
||||
aml = current_session._get_related_account_moves().line_ids
|
||||
aml_output = aml.filtered(lambda l: l.account_id.id == account_output.id)
|
||||
aml_expense = aml.filtered(lambda l: l.account_id.id == expense_account.id)
|
||||
|
||||
self.assertEqual(len(aml_output), 3, "There should be 3 output account move lines")
|
||||
# 2 moves in POS journal (Pos order + manual entry at delivery)
|
||||
self.assertEqual(len(aml_output.move_id.filtered(lambda l: l.journal_id == self.pos_config.journal_id)), 2)
|
||||
# 1 move in stock journal (delivery from stock layers)
|
||||
self.assertEqual(len(aml_output.move_id.filtered(lambda l: l.journal_id == self.category.property_stock_journal)), 1)
|
||||
#Check the lines created after the picking validation
|
||||
self.assertEqual(aml_output[2].credit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_output[2].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_output[1].debit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_output[1].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense[1].debit, self.product.standard_price, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense[1].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
#Check the lines created by the PoS session
|
||||
self.assertEqual(aml_output[0].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_output[0].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense[0].credit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
self.assertEqual(aml_expense[0].debit, 0.0, "Cost of Good Sold entry missing or mismatching")
|
||||
|
||||
def test_action_pos_order_invoice(self):
|
||||
self.company.point_of_sale_update_stock_quantities = 'closing'
|
||||
|
||||
# Setup a running session, with a paid pos order that is not invoiced
|
||||
self.pos_config.open_ui()
|
||||
current_session = self.pos_config.current_session_id
|
||||
self.pos_order_pos0 = self.PosOrder.create({
|
||||
'company_id': self.company.id,
|
||||
'partner_id': self.partner.id,
|
||||
'session_id': self.pos_config.current_session_id.id,
|
||||
'lines': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'price_unit': 450,
|
||||
'qty': 1.0,
|
||||
'price_subtotal': 450,
|
||||
'price_subtotal_incl': 450,
|
||||
})],
|
||||
'amount_total': 450,
|
||||
'amount_tax': 0,
|
||||
'amount_paid': 0,
|
||||
'amount_return': 0,
|
||||
})
|
||||
context_make_payment = {"active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
|
||||
'amount': 450.0,
|
||||
'payment_method_id': self.cash_payment_method.id,
|
||||
})
|
||||
context_payment = {'active_id': self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0.with_context(context_payment).check()
|
||||
|
||||
# Invoice the pos order afterward (session still running)
|
||||
self.pos_order_pos0.action_pos_order_invoice()
|
||||
|
||||
# Check that the stock output journal item from the invoice is reconciled (with its counterpart from the valuation entry)
|
||||
stock_output_account = self.category.property_stock_account_output_categ_id
|
||||
related_amls = current_session._get_related_account_moves().line_ids
|
||||
stock_output_amls = related_amls.filtered_domain([('account_id', '=', stock_output_account.id)])
|
||||
|
||||
self.assertTrue(all(stock_output_amls.mapped('reconciled')))
|
||||
|
||||
def test_action_pos_order_invoice_with_discount(self):
|
||||
"""This test make sure that the line containing 'Discoun from' is correctly added to the invoice"""
|
||||
|
||||
# Setup a running session, with a paid pos order that is not invoiced
|
||||
self.pos_config.open_ui()
|
||||
pricelist = self.env['product.pricelist'].create({
|
||||
'name': 'Test Pricelist',
|
||||
'discount_policy': 'without_discount',
|
||||
'item_ids': [(0, 0, {
|
||||
'compute_price': 'percentage',
|
||||
'percent_price': 5,
|
||||
'min_quantity': 0,
|
||||
'applied_on': '3_global',
|
||||
})]
|
||||
})
|
||||
self.product.lst_price = 100
|
||||
self.pos_order_pos0 = self.PosOrder.create({
|
||||
'company_id': self.company.id,
|
||||
'partner_id': self.partner.id,
|
||||
'session_id': self.pos_config.current_session_id.id,
|
||||
'pricelist_id': pricelist.id,
|
||||
'lines': [(0, 0, {
|
||||
'product_id': self.product.id,
|
||||
'price_unit': 95,
|
||||
'qty': 1.0,
|
||||
'tax_ids': [(6, 0, self.product.taxes_id.ids)],
|
||||
'price_subtotal': 90.25,
|
||||
'price_subtotal_incl': 103.79,
|
||||
'discount': 5,
|
||||
})],
|
||||
'amount_total': 103.79,
|
||||
'amount_tax': 13.51,
|
||||
'amount_paid': 0,
|
||||
'amount_return': 0,
|
||||
'to_invoice': True,
|
||||
})
|
||||
context_make_payment = {"active_ids": [self.pos_order_pos0.id], "active_id": self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0 = self.PosMakePayment.with_context(context_make_payment).create({
|
||||
'amount': 450.0,
|
||||
'payment_method_id': self.cash_payment_method.id,
|
||||
})
|
||||
context_payment = {'active_id': self.pos_order_pos0.id}
|
||||
self.pos_make_payment_0.with_context(context_payment).check()
|
||||
|
||||
res = self.pos_order_pos0.action_pos_order_invoice()
|
||||
invoice = self.env['account.move'].browse(res['res_id'])
|
||||
self.assertTrue('Price discount from 100.00 -> 95.00' in invoice.invoice_line_ids.filtered(lambda l: l.display_type == "line_note").display_name)
|
||||
product_line = invoice.invoice_line_ids.filtered(lambda l: l.display_type == "product")
|
||||
self.assertEqual(product_line.price_unit, 95) # Only fiscal position applies
|
||||
self.assertEqual(product_line.discount, 5) # Disount is reflected
|
||||
self.assertEqual(product_line.price_subtotal, 90.25) # Discount applies on price_unit
|
||||
self.assertEqual(product_line.price_total, 103.79) # Taxes applied with price_total
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import logging
|
||||
|
||||
from odoo.tests import tagged, HttpCase
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@tagged("post_install", "-at_install")
|
||||
class WebSuite(HttpCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
env = self.env(user=self.env.ref('base.user_admin'))
|
||||
payment_method = env['pos.payment.method'].create({'name': 'Lets Pay for Tests'})
|
||||
env['product.product'].create({'name': 'Test Product', 'available_in_pos': True})
|
||||
self.main_pos_config = self.main_pos_config = env['pos.config'].create({
|
||||
'name': 'Shop',
|
||||
'payment_method_ids': [(4, payment_method.id)]
|
||||
})
|
||||
|
||||
def test_pos_js(self):
|
||||
# open a session, the /pos/ui controller will redirect to it
|
||||
self.main_pos_config.open_ui()
|
||||
self.main_pos_config.current_session_id.set_cashbox_pos(0, None)
|
||||
|
||||
# point_of_sale desktop test suite
|
||||
self.browser_js("/pos/ui/tests?mod=web", "", "", login="admin", timeout=1800)
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class TestPointOfSale(TransactionCase):
|
||||
def setUp(self):
|
||||
super(TestPointOfSale, self).setUp()
|
||||
|
||||
# ignore pre-existing pricelists for the purpose of this test
|
||||
self.env["product.pricelist"].search([]).write({"active": False})
|
||||
|
||||
self.currency = self.env.ref("base.USD")
|
||||
self.company1 = self.env["res.company"].create({
|
||||
"name": "company 1",
|
||||
"currency_id": self.currency.id
|
||||
})
|
||||
self.company2 = self.env["res.company"].create({
|
||||
"name": "company 2",
|
||||
"currency_id": self.currency.id
|
||||
})
|
||||
self.company2_pricelist = self.env["product.pricelist"].create({
|
||||
"name": "company 2 pricelist",
|
||||
"currency_id": self.currency.id,
|
||||
"company_id": self.company2.id,
|
||||
"sequence": 1, # force this pricelist to be first
|
||||
})
|
||||
|
||||
self.env.user.company_id = self.company1
|
||||
|
||||
def test_default_pricelist_with_company(self):
|
||||
""" Verify that the default pricelist belongs to the same company as the config """
|
||||
company1_pricelist = self.env["product.pricelist"].create({
|
||||
"name": "company 1 pricelist",
|
||||
"currency_id": self.currency.id,
|
||||
"company_id": self.company1.id,
|
||||
"sequence": 2,
|
||||
})
|
||||
|
||||
# make sure this doesn't pick the company2 pricelist
|
||||
new_config = self.env["pos.config"].create({
|
||||
"name": "usd config"
|
||||
})
|
||||
|
||||
self.assertEqual(new_config.pricelist_id, company1_pricelist,
|
||||
"POS config incorrectly has pricelist %s" % new_config.pricelist_id.display_name)
|
||||
|
||||
def test_default_pricelist_without_company(self):
|
||||
""" Verify that a default pricelist without a company works """
|
||||
universal_pricelist = self.env["product.pricelist"].create({
|
||||
"name": "universal pricelist",
|
||||
"currency_id": self.currency.id,
|
||||
"sequence": 2,
|
||||
})
|
||||
|
||||
# make sure this doesn't pick the company2 pricelist
|
||||
new_config = self.env["pos.config"].create({
|
||||
"name": "usd config"
|
||||
})
|
||||
|
||||
self.assertEqual(new_config.pricelist_id, universal_pricelist,
|
||||
"POS config incorrectly has pricelist %s" % new_config.pricelist_id.display_name)
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import HttpCase, tagged
|
||||
from odoo import tools
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestUi(HttpCase):
|
||||
|
||||
# Avoid "A Chart of Accounts is not yet installed in your current company."
|
||||
# Everything is set up correctly even without installed CoA
|
||||
@tools.mute_logger('odoo.http')
|
||||
def test_01_point_of_sale_tour(self):
|
||||
|
||||
self.start_tour("/web", 'point_of_sale_tour', login="admin")
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,173 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from unittest.mock import patch
|
||||
|
||||
import odoo
|
||||
from odoo.addons.point_of_sale.models.pos_order import PosOrder
|
||||
from odoo.addons.point_of_sale.models.pos_session import PosSession
|
||||
from odoo.addons.point_of_sale.tests.common import TestPoSCommon
|
||||
|
||||
|
||||
class IntendedException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def mocked_process_order(*args):
|
||||
# We just want the order process to crash (to see if it is captured)
|
||||
raise IntendedException()
|
||||
|
||||
|
||||
def mocked_handle_order_process_fail(self, order: dict, exception: Exception, draft: bool):
|
||||
# We DO NOT want to create a new env in the test as the current pos_session does not exist (as it was not committed)
|
||||
self._process_order_process_fail(order, exception)
|
||||
|
||||
|
||||
@odoo.tests.tagged('post_install', '-at_install')
|
||||
class TestPosCapture(TestPoSCommon):
|
||||
"""
|
||||
Test the capture system of failed to process orders
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestPosCapture, self).setUp()
|
||||
self.config = self.basic_config
|
||||
|
||||
self.product1 = self.create_product('Product 1', self.categ_basic, 10, 5)
|
||||
|
||||
def assert_activity_and_attachment(self, pos_session, number):
|
||||
pos_attachments_domain = [
|
||||
['res_model', '=', pos_session._name],
|
||||
['res_id', '=', pos_session.id]
|
||||
]
|
||||
self.assertEqual(len(pos_session.activity_ids), number)
|
||||
self.assertEqual(len(self.env['ir.attachment'].search(pos_attachments_domain)), number)
|
||||
|
||||
def test_capture_one_order(self):
|
||||
# open a session
|
||||
session = self.open_new_session()
|
||||
|
||||
orders = [self.create_ui_order_data([(self.product1, 1)])]
|
||||
|
||||
self.assert_activity_and_attachment(session, 0)
|
||||
with patch.object(PosOrder, '_process_order', mocked_process_order),\
|
||||
patch.object(PosSession, '_handle_order_process_fail', mocked_handle_order_process_fail),\
|
||||
self.assertLogs('odoo.addons.point_of_sale.models.pos_order', level=logging.ERROR) as logger_error_output:
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
except IntendedException:
|
||||
self.assertIn("An error occurred when processing the PoS order", logger_error_output.output[0])
|
||||
self.assert_activity_and_attachment(session, 1)
|
||||
self.assertEqual(session.activity_ids[0].user_id.id, self.env.user.id)
|
||||
|
||||
def test_capture_two_orders(self):
|
||||
"""Two order even with same content should have distinct captured file"""
|
||||
# open a session
|
||||
session = self.open_new_session()
|
||||
|
||||
order1 = [self.create_ui_order_data([(self.product1, 1)], uid='12345-678-1996')]
|
||||
order2 = [self.create_ui_order_data([(self.product1, 1)], uid='12345-678-1999')] # Different order with same content but different uuid
|
||||
|
||||
with patch.object(PosOrder, '_process_order', mocked_process_order),\
|
||||
patch.object(PosSession, '_handle_order_process_fail', mocked_handle_order_process_fail),\
|
||||
self.assertLogs('odoo.addons.point_of_sale.models.pos_order', level=logging.ERROR):
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(order1)
|
||||
except IntendedException:
|
||||
self.assert_activity_and_attachment(session, 1)
|
||||
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(order2)
|
||||
except IntendedException:
|
||||
self.assert_activity_and_attachment(session, 2)
|
||||
|
||||
def test_capture_one_order_twice(self):
|
||||
"""Should have only one attachment as we sync the same order twice"""
|
||||
# open a session
|
||||
session = self.open_new_session()
|
||||
|
||||
orders = [self.create_ui_order_data([(self.product1, 1)])]
|
||||
|
||||
self.assert_activity_and_attachment(session, 0)
|
||||
with patch.object(PosOrder, '_process_order', mocked_process_order),\
|
||||
patch.object(PosSession, '_handle_order_process_fail', mocked_handle_order_process_fail),\
|
||||
self.assertLogs('odoo.addons.point_of_sale.models.pos_order', level=logging.ERROR):
|
||||
for _ in range(2):
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
except IntendedException:
|
||||
self.assert_activity_and_attachment(session, 1)
|
||||
|
||||
def test_capture_order_same_uuid(self):
|
||||
"""Should have 2 attachments as the content is different"""
|
||||
# open a session
|
||||
session = self.open_new_session()
|
||||
|
||||
order1 = [self.create_ui_order_data([(self.product1, 1)], uid='12345-678-1996')]
|
||||
order2 = [self.create_ui_order_data([(self.product1, 2)], uid='12345-678-1996')]
|
||||
|
||||
self.assert_activity_and_attachment(session, 0)
|
||||
with patch.object(PosOrder, '_process_order', mocked_process_order),\
|
||||
patch.object(PosSession, '_handle_order_process_fail', mocked_handle_order_process_fail),\
|
||||
self.assertLogs('odoo.addons.point_of_sale.models.pos_order', level=logging.ERROR):
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(order1)
|
||||
except IntendedException:
|
||||
self.assert_activity_and_attachment(session, 1)
|
||||
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(order2)
|
||||
except IntendedException:
|
||||
self.assert_activity_and_attachment(session, 2)
|
||||
|
||||
def test_capture_one_order_and_removed(self):
|
||||
"""Check if the attachment and activity is automatically remove after the order sync"""
|
||||
# open a session
|
||||
session = self.open_new_session()
|
||||
|
||||
orders = [self.create_ui_order_data([(self.product1, 1)])]
|
||||
|
||||
self.assert_activity_and_attachment(session, 0)
|
||||
with patch.object(PosOrder, '_process_order', mocked_process_order),\
|
||||
patch.object(PosSession, '_handle_order_process_fail', mocked_handle_order_process_fail),\
|
||||
self.assertLogs('odoo.addons.point_of_sale.models.pos_order', level=logging.ERROR):
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
except IntendedException:
|
||||
pass
|
||||
|
||||
self.assert_activity_and_attachment(session, 1)
|
||||
# Resync the order, this time it should go through!
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
# Should automatically remove the attachment for this order after sync
|
||||
self.assert_activity_and_attachment(session, 0)
|
||||
|
||||
def test_capture_two_orders_and_removed(self):
|
||||
"""Check if the attachment and activity is automatically remove after the order sync (with 2 orders)"""
|
||||
# open a session
|
||||
session = self.open_new_session()
|
||||
|
||||
order1 = [self.create_ui_order_data([(self.product1, 1)], uid='12345-678-1996')]
|
||||
order2 = [self.create_ui_order_data([(self.product1, 1)], uid='12345-678-1999')] # Different order with same content but different uuid
|
||||
|
||||
with patch.object(PosOrder, '_process_order', mocked_process_order),\
|
||||
patch.object(PosSession, '_handle_order_process_fail', mocked_handle_order_process_fail),\
|
||||
self.assertLogs('odoo.addons.point_of_sale.models.pos_order', level=logging.ERROR):
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(order1)
|
||||
except IntendedException:
|
||||
self.assert_activity_and_attachment(session, 1)
|
||||
|
||||
try:
|
||||
self.env['pos.order'].create_from_ui(order2)
|
||||
except IntendedException:
|
||||
self.assert_activity_and_attachment(session, 2)
|
||||
|
||||
self.assert_activity_and_attachment(session, 2)
|
||||
# Resync the order, this time it should go through!
|
||||
self.env['pos.order'].create_from_ui(order2)
|
||||
# Should automatically remove the attachment for this order after sync
|
||||
self.assert_activity_and_attachment(session, 1)
|
||||
|
||||
self.env['pos.order'].create_from_ui(order1)
|
||||
# Should automatically remove the attachment for this order after sync
|
||||
self.assert_activity_and_attachment(session, 0)
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import odoo
|
||||
from odoo.addons.mail.tests.common import mail_new_test_user
|
||||
from odoo.addons.point_of_sale.tests.test_frontend import TestPointOfSaleHttpCommon
|
||||
|
||||
@odoo.tests.tagged('post_install', '-at_install')
|
||||
class TestPoSController(TestPointOfSaleHttpCommon):
|
||||
def test_qr_code_receipt(self):
|
||||
"""This test make sure that no user is created when a partner is set on the PoS order.
|
||||
It also makes sure that the invoice is correctly created.
|
||||
"""
|
||||
self.authenticate(None, None)
|
||||
self.new_partner = self.env['res.partner'].create({
|
||||
'name': 'AAA Partner',
|
||||
'zip': '12345',
|
||||
'country_id': self.env.ref('base.us').id,
|
||||
})
|
||||
self.product1 = self.env['product.product'].create({
|
||||
'name': 'Test Product 1',
|
||||
'type': 'product',
|
||||
'list_price': 10.0,
|
||||
'taxes_id': False,
|
||||
})
|
||||
self.main_pos_config.open_ui()
|
||||
self.pos_order = self.env['pos.order'].create({
|
||||
'company_id': self.env.company.id,
|
||||
'session_id': self.main_pos_config.current_session_id.id,
|
||||
'partner_id': self.new_partner.id,
|
||||
'access_token': '1234567890',
|
||||
'lines': [(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': self.product1.id,
|
||||
'price_unit': 10,
|
||||
'discount': 0.0,
|
||||
'qty': 1.0,
|
||||
'tax_ids': False,
|
||||
'price_subtotal': 10,
|
||||
'price_subtotal_incl': 10,
|
||||
})],
|
||||
'amount_tax': 10,
|
||||
'amount_total': 10,
|
||||
'amount_paid': 10.0,
|
||||
'amount_return': 10.0,
|
||||
})
|
||||
self.main_pos_config.current_session_id.close_session_from_ui()
|
||||
get_invoice_data = {
|
||||
'access_token': self.pos_order.access_token,
|
||||
'name': self.new_partner.name,
|
||||
'email': "test@test.com",
|
||||
'company_name': self.new_partner.company_name,
|
||||
'vat': self.new_partner.vat,
|
||||
'street': "Test street",
|
||||
'city': "Test City",
|
||||
'zipcode': self.new_partner.zip,
|
||||
'country_id': self.new_partner.country_id.id,
|
||||
'state_id': self.new_partner.state_id,
|
||||
'phone': "123456789",
|
||||
'csrf_token': odoo.http.Request.csrf_token(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")
|
||||
|
||||
def test_qr_code_receipt_user_connected(self):
|
||||
"""This test make sure that when the user is already connected he correctly gets redirected to the invoice."""
|
||||
self.partner_1 = self.env['res.partner'].create({
|
||||
'name': 'Valid Lelitre',
|
||||
'email': 'valid.lelitre@agrolait.com',
|
||||
})
|
||||
self.partner_1_user = mail_new_test_user(
|
||||
self.env,
|
||||
name=self.partner_1.name,
|
||||
login='partner_1',
|
||||
email=self.partner_1.email,
|
||||
groups='base.group_portal',
|
||||
)
|
||||
self.authenticate('partner_1', 'partner_1')
|
||||
|
||||
self.product1 = self.env['product.product'].create({
|
||||
'name': 'Test Product 1',
|
||||
'type': 'product',
|
||||
'list_price': 10.0,
|
||||
'taxes_id': False,
|
||||
})
|
||||
self.main_pos_config.open_ui()
|
||||
self.pos_order = self.env['pos.order'].create({
|
||||
'session_id': self.main_pos_config.current_session_id.id,
|
||||
'company_id': self.env.company.id,
|
||||
'access_token': '1234567890',
|
||||
'lines': [(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': self.product1.id,
|
||||
'price_unit': 10,
|
||||
'discount': 0.0,
|
||||
'qty': 1.0,
|
||||
'tax_ids': False,
|
||||
'price_subtotal': 10,
|
||||
'price_subtotal_incl': 10,
|
||||
})],
|
||||
'amount_tax': 10,
|
||||
'amount_total': 10,
|
||||
'amount_paid': 10.0,
|
||||
'amount_return': 10.0,
|
||||
})
|
||||
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("my/invoices" in res.url)
|
||||
|
|
@ -0,0 +1,400 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import odoo
|
||||
from odoo.addons.point_of_sale.tests.common import TestPoSCommon
|
||||
|
||||
|
||||
@odoo.tests.tagged('post_install', '-at_install')
|
||||
class TestPosMargin(TestPoSCommon):
|
||||
"""
|
||||
Test the margin computation on orders with basic configuration
|
||||
The tests contain the base scenarios.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestPosMargin, self).setUp()
|
||||
self.config = self.basic_config
|
||||
|
||||
self.stock_location = self.env['stock.warehouse'].create({
|
||||
'partner_id': self.env.user.partner_id.id,
|
||||
'name': 'Stock location',
|
||||
'code': 'WH'
|
||||
}).lot_stock_id
|
||||
self.customer_location = self.env.ref('stock.stock_location_customers')
|
||||
self.supplier_location = self.env.ref('stock.stock_location_suppliers')
|
||||
self.uom_unit = self.env.ref('uom.product_uom_unit')
|
||||
|
||||
|
||||
def test_positive_margin(self):
|
||||
"""
|
||||
Test margin where it should be more than zero
|
||||
"""
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 10, 5)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 50, 30)
|
||||
|
||||
# open a session
|
||||
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)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, 5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, 20)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin, 50)
|
||||
|
||||
# check margins percent
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, 0.5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0.4)
|
||||
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), 0.42)
|
||||
|
||||
# close session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
def test_negative_margin(self):
|
||||
"""
|
||||
Test margin where it should be less than zero
|
||||
"""
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 10, 15)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 50, 100)
|
||||
|
||||
# open a session
|
||||
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)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, -5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, -50)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin, -110)
|
||||
|
||||
# check margins percent
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, -0.5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, -1)
|
||||
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), -0.92)
|
||||
|
||||
# close session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
def test_full_margin(self):
|
||||
"""
|
||||
Test margin where the product cost is always 0
|
||||
"""
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 10)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 50)
|
||||
|
||||
# open a session
|
||||
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)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, 10)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, 50)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin, 120)
|
||||
|
||||
# check margins percent
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, 1)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 1)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin_percent, 1)
|
||||
|
||||
# close session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
def test_tax_margin(self):
|
||||
"""
|
||||
Test margin with tax on products
|
||||
Product 1 price without tax = 10
|
||||
Product 2 price without tax = 50
|
||||
"""
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 10, 5, self.taxes['tax7'].ids)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 55, 30, self.taxes['tax10'].ids)
|
||||
|
||||
# open a session
|
||||
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)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, 5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, 20)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin, 50)
|
||||
|
||||
# check margins percent
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, 0.5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0.4)
|
||||
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), 0.42)
|
||||
|
||||
# close session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
def test_other_currency_margin(self):
|
||||
"""
|
||||
Test margin with tax on products and with different currency
|
||||
The currency rate is 0.5 so the product price is halved in this currency.
|
||||
"""
|
||||
|
||||
# change the config
|
||||
current_config = self.config
|
||||
self.config = self.other_currency_config
|
||||
|
||||
# same parameters as test_positive_margin
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 10, 5)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 50, 30)
|
||||
|
||||
# open a session
|
||||
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)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins in the config currency
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, 2.5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, 10)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin, 25)
|
||||
|
||||
# check margins percent which should be the same as test_positive_margin
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, 0.5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0.4)
|
||||
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), 0.42)
|
||||
|
||||
# close session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
# set the config back
|
||||
self.config = current_config
|
||||
|
||||
def test_tax_and_other_currency_margin(self):
|
||||
"""
|
||||
Test margin with different currency between products and config with taxes.
|
||||
Product 1 price without tax = 10
|
||||
Product 2 price without tax = 50
|
||||
The currency rate is 0.5 so the product price is halved in this currency.
|
||||
"""
|
||||
|
||||
# change the config
|
||||
current_config = self.config
|
||||
self.config = self.other_currency_config
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 10, 5, self.taxes['tax7'].ids)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 55, 30, self.taxes['tax10'].ids)
|
||||
|
||||
# open a session
|
||||
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)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins in the config currency
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, 2.5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, 10)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin, 25)
|
||||
|
||||
# check margins percent which should be the same as test_tax_margin
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, 0.5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0.4)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin_percent, 0.4167)
|
||||
|
||||
# close session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
# set the config back
|
||||
self.config = current_config
|
||||
|
||||
def test_return_margin(self):
|
||||
"""
|
||||
Test margin where we return product (negative line quantity)
|
||||
"""
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 10, 5)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 50, 30)
|
||||
|
||||
# open a session
|
||||
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)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, -5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, -20)
|
||||
self.assertEqual(self.pos_session.order_ids[2].margin, -50)
|
||||
|
||||
# check margins percent
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, 0.5)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0.4)
|
||||
self.assertEqual(round(self.pos_session.order_ids[2].margin_percent, 2), 0.42)
|
||||
|
||||
# close session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
def test_fifo_margin_real_time(self):
|
||||
"""
|
||||
Test margin where there is product in FIFO with stock update in real time
|
||||
"""
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_anglo, 10, 5)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 50, 30)
|
||||
|
||||
move1 = self.env['stock.move'].create({
|
||||
'name': 'IN 2 unit @ 3 per unit',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': product1.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 2,
|
||||
'price_unit': 3,
|
||||
}).sudo()
|
||||
move1._action_confirm()
|
||||
move1._action_assign()
|
||||
move1.move_line_ids.qty_done = 2
|
||||
move1._action_done()
|
||||
|
||||
move2 = self.env['stock.move'].create({
|
||||
'name': 'IN 1 unit @ 7 per unit',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': product1.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1,
|
||||
'price_unit': 7,
|
||||
}).sudo()
|
||||
move2._action_confirm()
|
||||
move2._action_assign()
|
||||
move2.move_line_ids.qty_done = 1
|
||||
move2._action_done()
|
||||
|
||||
# open a session
|
||||
self.open_new_session()
|
||||
|
||||
# create orders
|
||||
orders = [self.create_ui_order_data([(product1, 1), (product2, 1)]),
|
||||
self.create_ui_order_data([(product1, 2)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, 27)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, 10)
|
||||
|
||||
# check margins percent
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, 0.45)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0.5)
|
||||
|
||||
# close session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
def test_avco_margin_closing_time(self):
|
||||
"""
|
||||
Test margin where there is product in AVCO with stock update in closing
|
||||
"""
|
||||
|
||||
self.categ_anglo.property_cost_method = 'average'
|
||||
product1 = self.create_product('Product 1', self.categ_anglo, 10, 5)
|
||||
product2 = self.create_product('Product 2', self.categ_basic, 50, 30)
|
||||
self.env.company.point_of_sale_update_stock_quantities = 'closing'
|
||||
|
||||
|
||||
move1 = self.env['stock.move'].create({
|
||||
'name': 'IN 2 unit @ 3 per unit',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': product1.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 2,
|
||||
'price_unit': 3,
|
||||
}).sudo()
|
||||
move1._action_confirm()
|
||||
move1._action_assign()
|
||||
move1.move_line_ids.qty_done = 2
|
||||
move1._action_done()
|
||||
|
||||
move2 = self.env['stock.move'].create({
|
||||
'name': 'IN 1 unit @ 6 per unit',
|
||||
'location_id': self.supplier_location.id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'product_id': product1.id,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'product_uom_qty': 1,
|
||||
'price_unit': 6,
|
||||
}).sudo()
|
||||
move2._action_confirm()
|
||||
move2._action_assign()
|
||||
move2.move_line_ids.qty_done = 1
|
||||
move2._action_done()
|
||||
|
||||
# open a session
|
||||
self.open_new_session()
|
||||
|
||||
# create orders
|
||||
orders = [self.create_ui_order_data([(product1, 1), (product2, 1)]),
|
||||
self.create_ui_order_data([(product1, 2)])]
|
||||
|
||||
# sync orders
|
||||
self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check margins which are not really computed so it should be 0
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, 0)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, 0)
|
||||
|
||||
# check margins percent (same as above)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0)
|
||||
|
||||
# close session
|
||||
total_cash_payment = sum(self.pos_session.mapped('order_ids.payment_ids').filtered(lambda payment: payment.payment_method_id.type == 'cash').mapped('amount'))
|
||||
self.pos_session.post_closing_cash_details(total_cash_payment)
|
||||
self.pos_session.close_session_from_ui()
|
||||
|
||||
# check margins
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin, 26)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin, 12)
|
||||
|
||||
# check margins percent
|
||||
self.assertEqual(self.pos_session.order_ids[0].margin_percent, 0.4333)
|
||||
self.assertEqual(self.pos_session.order_ids[1].margin_percent, 0.6)
|
||||
|
||||
self.env.company.point_of_sale_update_stock_quantities = 'real'
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
# -*- 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,
|
||||
)
|
||||
self.adjust_inventory([self.product1, self.product2, self.product3], [100, 50, 50])
|
||||
|
||||
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.state == 'invoiced')), 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)], 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'payments': [(self.bank_pm1, 158.75)], 'uid': '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, 'uid': '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.86, '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.43, '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.73, '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.state == 'invoiced')), 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, 'uid': '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, 'uid': '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, 'uid': '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.73, '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.86, '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},
|
||||
]
|
||||
}),
|
||||
],
|
||||
},
|
||||
})
|
||||
|
|
@ -0,0 +1,365 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import odoo
|
||||
|
||||
from odoo import tools
|
||||
from odoo.tests.common import Form
|
||||
from odoo.addons.point_of_sale.tests.common import TestPoSCommon
|
||||
|
||||
@odoo.tests.tagged('post_install', '-at_install')
|
||||
class TestPoSOtherCurrencyConfig(TestPoSCommon):
|
||||
""" Test PoS with basic configuration
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestPoSOtherCurrencyConfig, self).setUp()
|
||||
|
||||
self.config = self.other_currency_config
|
||||
self.product1 = self.create_product('Product 1', self.categ_basic, 10.0, 5)
|
||||
self.product2 = self.create_product('Product 2', self.categ_basic, 20.0, 10)
|
||||
self.product3 = self.create_product('Product 3', self.categ_basic, 30.0, 15)
|
||||
self.product4 = self.create_product('Product 4', self.categ_anglo, 100, 50)
|
||||
self.product5 = self.create_product('Product 5', self.categ_anglo, 200, 70)
|
||||
self.product6 = self.create_product('Product 6', self.categ_anglo, 45.3, 10.73)
|
||||
self.product7 = self.create_product('Product 7', self.categ_basic, 7, 7, tax_ids=self.taxes['tax7'].ids)
|
||||
self.adjust_inventory(
|
||||
[self.product1, self.product2, self.product3, self.product4, self.product5, self.product6, self.product7],
|
||||
[100, 50, 50, 100, 100, 100, 100]
|
||||
)
|
||||
# change the price of product2 to 12.99 fixed. No need to convert.
|
||||
pricelist_item = self.env['product.pricelist.item'].create({
|
||||
'product_tmpl_id': self.product2.product_tmpl_id.id,
|
||||
'fixed_price': 12.99,
|
||||
})
|
||||
self.config.pricelist_id.write({'item_ids': [(6, 0, (self.config.pricelist_id.item_ids | pricelist_item).ids)]})
|
||||
|
||||
self.output_account = self.categ_anglo.property_stock_account_output_categ_id
|
||||
self.expense_account = self.categ_anglo.property_account_expense_categ_id
|
||||
|
||||
def test_01_check_product_cost(self):
|
||||
# Product price should be half of the original price because currency rate is 0.5.
|
||||
# (see `self._create_other_currency_config` method)
|
||||
# Except for product2 where the price is specified in the pricelist.
|
||||
|
||||
self.assertAlmostEqual(self.config.pricelist_id._get_product_price(self.product1, 1), 5.00)
|
||||
self.assertAlmostEqual(self.config.pricelist_id._get_product_price(self.product2, 1), 12.99)
|
||||
self.assertAlmostEqual(self.config.pricelist_id._get_product_price(self.product3, 1), 15.00)
|
||||
self.assertAlmostEqual(self.config.pricelist_id._get_product_price(self.product4, 1), 50)
|
||||
self.assertAlmostEqual(self.config.pricelist_id._get_product_price(self.product5, 1), 100)
|
||||
self.assertAlmostEqual(self.config.pricelist_id._get_product_price(self.product6, 1), 22.65)
|
||||
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)], 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'uid': '00100-010-0002'},
|
||||
{'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm2, 139.95)], 'uid': '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)], 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'is_invoiced': True, 'customer': self.customer, 'uid': '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, 'uid': '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_04_anglo_saxon_products(self):
|
||||
"""
|
||||
======
|
||||
Orders
|
||||
======
|
||||
+---------+----------+-----------+----------+-----+----------+------------+
|
||||
| order | payments | invoiced? | product | qty | total | total cost |
|
||||
| | | | | | | |
|
||||
+---------+----------+-----------+----------+-----+----------+------------+
|
||||
| order 1 | cash | no | product4 | 7 | 700 | 350 |
|
||||
| | | | product5 | 7 | 1400 | 490 |
|
||||
+---------+----------+-----------+----------+-----+----------+------------+
|
||||
| order 2 | cash | no | product5 | 6 | 1200 | 420 |
|
||||
| | | | product4 | 6 | 600 | 300 |
|
||||
| | | | product6 | 49 | 2219.7 | 525.77 |
|
||||
+---------+----------+-----------+----------+-----+----------+------------+
|
||||
| order 3 | cash | no | product5 | 2 | 400 | 140 |
|
||||
| | | | product6 | 13 | 588.9 | 139.49 |
|
||||
+---------+----------+-----------+----------+-----+----------+------------+
|
||||
| order 4 | cash | no | product6 | 1 | 45.3 | 10.73 |
|
||||
+---------+----------+-----------+----------+-----+----------+------------+
|
||||
|
||||
===============
|
||||
Expected Result
|
||||
===============
|
||||
+---------------------+------------+-----------------+
|
||||
| account | balance | amount_currency |
|
||||
+---------------------+------------+-----------------+
|
||||
| sale_account | -7153.90 | -3576.95 |
|
||||
| pos_receivable-cash | 7153.90 | 3576.95 |
|
||||
| expense_account | 2375.99 | 2375.99 |
|
||||
| output_account | -2375.99 | -2375.99 |
|
||||
+---------------------+------------+-----------------+
|
||||
| Total balance | 0.00 | 0.00 |
|
||||
+---------------------+------------+-----------------+
|
||||
"""
|
||||
|
||||
self._run_test({
|
||||
'payment_methods': self.cash_pm2,
|
||||
'orders': [
|
||||
{'pos_order_lines_ui_args': [(self.product4, 7), (self.product5, 7)], 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product5, 6), (self.product4, 6), (self.product6, 49)], 'uid': '00100-010-0002'},
|
||||
{'pos_order_lines_ui_args': [(self.product5, 2), (self.product6, 13)], 'uid': '00100-010-0003'},
|
||||
{'pos_order_lines_ui_args': [(self.product6, 1)], 'uid': '00100-010-0004'},
|
||||
],
|
||||
'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': 7153.90, 'reconciled': False, 'amount_currency': -3576.95},
|
||||
{'account_id': self.expense_account.id, 'partner_id': False, 'debit': 2375.99, 'credit': 0, 'reconciled': False, 'amount_currency': 2375.99},
|
||||
{'account_id': self.cash_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 7153.90, 'credit': 0, 'reconciled': True, 'amount_currency': 3576.95},
|
||||
{'account_id': self.output_account.id, 'partner_id': False, 'debit': 0, 'credit': 2375.99, 'reconciled': True, 'amount_currency': -2375.99},
|
||||
],
|
||||
},
|
||||
'cash_statement': [
|
||||
((3576.95, ), {
|
||||
'line_ids': [
|
||||
{'account_id': self.cash_pm2.journal_id.default_account_id.id, 'partner_id': False, 'debit': 7153.90, 'credit': 0, 'reconciled': False, 'amount_currency': 3576.95},
|
||||
{'account_id': self.cash_pm2.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 7153.90, 'reconciled': True, 'amount_currency': -3576.95},
|
||||
]
|
||||
}),
|
||||
],
|
||||
'bank_payments': [],
|
||||
},
|
||||
})
|
||||
|
||||
def test_05_tax_base_amount(self):
|
||||
self._run_test({
|
||||
'payment_methods': self.cash_pm2,
|
||||
'orders': [
|
||||
{'pos_order_lines_ui_args': [(self.product7, 7)], 'uid': '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."""
|
||||
|
||||
# Make a sale paid by bank
|
||||
self.other_currency_config.open_ui()
|
||||
session_id = self.other_currency_config.current_session_id
|
||||
order = self.env['pos.order'].create({
|
||||
'company_id': self.env.company.id,
|
||||
'session_id': session_id.id,
|
||||
'partner_id': False,
|
||||
'lines': [(0, 0, {
|
||||
'name': 'OL/0001',
|
||||
'product_id': self.product1.id,
|
||||
'price_unit': 10.00,
|
||||
'discount': 0,
|
||||
'qty': 1,
|
||||
'tax_ids': False,
|
||||
'price_subtotal': 10.00,
|
||||
'price_subtotal_incl': 10.00,
|
||||
})],
|
||||
'pricelist_id': self.other_currency_config.pricelist_id.id,
|
||||
'amount_paid': 10.00,
|
||||
'amount_total': 10.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_pm2.id
|
||||
})
|
||||
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
|
||||
|
||||
# Check debit/credit session's balance
|
||||
for move in session_id._get_related_account_moves():
|
||||
debit = credit = 0.0
|
||||
for line in move.line_ids:
|
||||
debit += line.debit
|
||||
credit += line.credit
|
||||
self.assertEqual(tools.float_compare(debit, credit, precision_rounding=self.other_currency_config.currency_id.rounding), 0) # debit and credit should be equal
|
||||
|
|
@ -0,0 +1,543 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import tools
|
||||
|
||||
import odoo
|
||||
from odoo.addons.point_of_sale.tests.common import TestPoSCommon
|
||||
|
||||
@odoo.tests.tagged('post_install', '-at_install')
|
||||
class TestPoSProductsWithTax(TestPoSCommon):
|
||||
""" Test normal configuration PoS selling products with tax
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestPoSProductsWithTax, self).setUp()
|
||||
|
||||
self.config = self.basic_config
|
||||
self.product1 = self.create_product(
|
||||
'Product 1',
|
||||
self.categ_basic,
|
||||
10.0,
|
||||
5.0,
|
||||
tax_ids=self.taxes['tax7'].ids,
|
||||
)
|
||||
self.product2 = self.create_product(
|
||||
'Product 2',
|
||||
self.categ_basic,
|
||||
20.0,
|
||||
10.0,
|
||||
tax_ids=self.taxes['tax10'].ids,
|
||||
)
|
||||
self.product3 = self.create_product(
|
||||
'Product 3',
|
||||
self.categ_basic,
|
||||
30.0,
|
||||
15.0,
|
||||
tax_ids=self.taxes['tax_group_7_10'].ids,
|
||||
)
|
||||
self.product4 = self.create_product(
|
||||
'Product 4',
|
||||
self.categ_basic,
|
||||
54.99,
|
||||
tax_ids=[self.taxes['tax_fixed006'].id, self.taxes['tax_fixed012'].id, self.taxes['tax21'].id],
|
||||
)
|
||||
self.adjust_inventory([self.product1, self.product2, self.product3], [100, 50, 50])
|
||||
|
||||
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)], 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product2, 7), (self.product3, 4)], 'uid': '00100-010-0002'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 1), (self.product3, 5), (self.product2, 3)], 'payments': [(self.bank_pm1, 230.25)], 'uid': '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': 'product'},
|
||||
{'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 474.64, 'credit': 0, 'reconciled': True, 'display_type': 'product'},
|
||||
],
|
||||
},
|
||||
'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)], 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product2, 20), (self.product1, 1)], 'payments': [(self.bank_pm1, 410.7)], 'uid': '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, 'uid': '09876-098-0987'},
|
||||
{'pos_order_lines_ui_args': [(self.product4, 1)], 'payments': [(self.bank_pm1, 54.99)], 'customer': self.customer, 'is_invoiced': True, 'uid': '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.pos_reference)
|
||||
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.37) # 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, 'uid': '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.37, '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.36, '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'].create_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'].create_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'].create_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'].create_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'].create_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},
|
||||
])
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import tools
|
||||
import odoo
|
||||
from odoo.addons.point_of_sale.tests.common import TestPoSCommon
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
@odoo.tests.tagged('post_install', '-at_install')
|
||||
class TestPoSSetup(TestPoSCommon):
|
||||
""" This group of tests is for sanity check in setting up global records which will be used
|
||||
in each testing.
|
||||
|
||||
If a test fails here, then it means there are inconsistencies in what we expect in the setup.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TestPoSSetup, self).setUp()
|
||||
|
||||
self.config = self.basic_config
|
||||
self.products = [
|
||||
self.create_product('Product 1', self.categ_basic, lst_price=10.0, standard_price=5),
|
||||
self.create_product('Product 2', self.categ_basic, lst_price=20.0, standard_price=10),
|
||||
self.create_product('Product 3', self.categ_basic, lst_price=30.0, standard_price=15),
|
||||
]
|
||||
|
||||
def test_basic_config_values(self):
|
||||
|
||||
config = self.basic_config
|
||||
self.assertEqual(config.currency_id, self.company_currency)
|
||||
self.assertEqual(config.pricelist_id.currency_id, self.company_currency)
|
||||
|
||||
def test_other_currency_config_values(self):
|
||||
config = self.other_currency_config
|
||||
self.assertEqual(config.currency_id, self.other_currency)
|
||||
self.assertEqual(config.pricelist_id.currency_id, self.other_currency)
|
||||
|
||||
def test_product_categories(self):
|
||||
# check basic product category
|
||||
# it is expected to have standard and manual_periodic valuation
|
||||
self.assertEqual(self.categ_basic.property_cost_method, 'standard')
|
||||
self.assertEqual(self.categ_basic.property_valuation, 'manual_periodic')
|
||||
# check anglo saxon product category
|
||||
# this product categ is expected to have fifo and real_time valuation
|
||||
self.assertEqual(self.categ_anglo.property_cost_method, 'fifo')
|
||||
self.assertEqual(self.categ_anglo.property_valuation, 'real_time')
|
||||
|
||||
def test_product_price(self):
|
||||
def get_price(pricelist, product):
|
||||
return pricelist._get_product_price(product, 1)
|
||||
|
||||
|
||||
# check usd pricelist
|
||||
pricelist = self.basic_config.pricelist_id
|
||||
for product in self.products:
|
||||
self.assertAlmostEqual(get_price(pricelist, product), product.lst_price)
|
||||
|
||||
# check eur pricelist
|
||||
# exchange rate to the other currency is set to 0.5, thus, lst_price
|
||||
# is expected to have half its original value.
|
||||
pricelist = self.other_currency_config.pricelist_id
|
||||
for product in self.products:
|
||||
self.assertAlmostEqual(get_price(pricelist, product), product.lst_price * 0.5)
|
||||
|
||||
def test_taxes(self):
|
||||
tax7 = self.taxes['tax7']
|
||||
self.assertEqual(tax7.name, 'Tax 7%')
|
||||
self.assertAlmostEqual(tax7.amount, 7)
|
||||
self.assertEqual(tax7.invoice_repartition_line_ids.mapped('account_id').id, self.tax_received_account.id)
|
||||
tax10 = self.taxes['tax10']
|
||||
self.assertEqual(tax10.name, 'Tax 10%')
|
||||
self.assertAlmostEqual(tax10.amount, 10)
|
||||
self.assertEqual(tax10.price_include, True)
|
||||
self.assertEqual(tax10.invoice_repartition_line_ids.mapped('account_id').id, self.tax_received_account.id)
|
||||
tax_group_7_10 = self.taxes['tax_group_7_10']
|
||||
self.assertEqual(tax_group_7_10.name, 'Tax 7+10%')
|
||||
self.assertEqual(tax_group_7_10.amount_type, 'group')
|
||||
self.assertEqual(sorted(tax_group_7_10.children_tax_ids.ids), sorted((tax7 | tax10).ids))
|
||||
|
||||
def test_archive_used_journal(self):
|
||||
journal = self.cash_pm1.journal_id
|
||||
payment_method = self.env['pos.payment.method'].create({'name': 'Lets Pay for Tests', 'journal_id': journal.id})
|
||||
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(
|
||||
{
|
||||
'name': 'lets sell some tests',
|
||||
'config_id': self.basic_config.id,
|
||||
'user_id': self.env.user.id,
|
||||
'state': 'opened'
|
||||
}
|
||||
)
|
||||
order = self.env['pos.order'].create(
|
||||
{
|
||||
'name': 'MIX',
|
||||
'amount_tax': 0,
|
||||
'amount_total': 0,
|
||||
'amount_paid': 0,
|
||||
'amount_return': 0,
|
||||
'company_id': self.company.id,
|
||||
'pricelist_id': self.currency_pricelist.id,
|
||||
'session_id': session.id
|
||||
}
|
||||
)
|
||||
self.env['pos.payment'].create(
|
||||
{
|
||||
'amount': 100,
|
||||
'payment_date': '2025-01-01',
|
||||
'payment_method_id': payment_method.id,
|
||||
'pos_order_id': order.id
|
||||
}
|
||||
)
|
||||
with self.assertRaises(ValidationError):
|
||||
journal.action_archive()
|
||||
|
|
@ -0,0 +1,798 @@
|
|||
# -*- 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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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': [
|
||||
# needs to check the residual because it's supposed to be partial reconciled
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': False, '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, 'uid': '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': [
|
||||
# needs to check the residual because it's supposed to be partial reconciled
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': False, '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, 'uid': '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': [
|
||||
# needs to check the residual because it's supposed to be partial reconciled
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': False, '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, 'uid': '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': [
|
||||
# needs to check the residual because it's supposed to be partial reconciled
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 200, 'reconciled': False, '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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': 0},
|
||||
# needs to check the residual because it's supposed to be partial reconciled
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False, '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},
|
||||
{'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, 'uid': '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': 0},
|
||||
# needs to check the residual because it's supposed to be partial reconciled
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False, '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},
|
||||
{'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, 'uid': '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': 0},
|
||||
# needs to check the residual because it's supposed to be partial reconciled
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False, '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},
|
||||
{'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, 'uid': '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': 0},
|
||||
# needs to check the residual because it's supposed to be partial reconciled
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 100, 'credit': 0, 'reconciled': False, '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},
|
||||
{'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': [],
|
||||
},
|
||||
})
|
||||
|
|
@ -0,0 +1,589 @@
|
|||
# -*- 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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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, 'uid': '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': [],
|
||||
},
|
||||
})
|
||||
|
|
@ -0,0 +1,264 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import tools
|
||||
import odoo
|
||||
from odoo.addons.point_of_sale.tests.common import TestPoSCommon
|
||||
|
||||
@odoo.tests.tagged('post_install', '-at_install')
|
||||
class TestPoSStock(TestPoSCommon):
|
||||
""" Tests for anglo saxon accounting scenario.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(TestPoSStock, self).setUp()
|
||||
|
||||
self.config = self.basic_config
|
||||
self.product1 = self.create_product('Product 1', self.categ_anglo, 10.0, 5.0)
|
||||
self.product2 = self.create_product('Product 2', self.categ_anglo, 20.0, 10.0)
|
||||
self.product3 = self.create_product('Product 3', self.categ_basic, 30.0, 15.0)
|
||||
# start inventory with 10 items for each product
|
||||
self.adjust_inventory([self.product1, self.product2, self.product3], [10, 10, 10])
|
||||
|
||||
# change cost(standard_price) of anglo products
|
||||
# then set inventory from 10 -> 15
|
||||
self.product1.write({'standard_price': 6.0})
|
||||
self.product2.write({'standard_price': 6.0})
|
||||
self.adjust_inventory([self.product1, self.product2, self.product3], [15, 15, 15])
|
||||
|
||||
# change cost(standard_price) of anglo products
|
||||
# then set inventory from 15 -> 25
|
||||
self.product1.write({'standard_price': 13.0})
|
||||
self.product2.write({'standard_price': 13.0})
|
||||
self.adjust_inventory([self.product1, self.product2, self.product3], [25, 25, 25])
|
||||
|
||||
self.output_account = self.categ_anglo.property_stock_account_output_categ_id
|
||||
self.expense_account = self.categ_anglo.property_account_expense_categ_id
|
||||
self.valuation_account = self.categ_anglo.property_stock_valuation_account_id
|
||||
|
||||
def test_01_orders_no_invoiced(self):
|
||||
"""
|
||||
|
||||
Orders
|
||||
======
|
||||
+---------+----------+-----+-------------+------------+
|
||||
| order | product | qty | total price | total cost |
|
||||
+---------+----------+-----+-------------+------------+
|
||||
| order 1 | product1 | 10 | 100.0 | 50.0 | -> 10 items at cost of 5.0 is consumed, remains 5 items at 6.0 and 10 items at 13.0
|
||||
| | product2 | 10 | 200.0 | 100.0 | -> 10 items at cost of 10.0 is consumed, remains 5 items at 6.0 and 10 items at 13.0
|
||||
+---------+----------+-----+-------------+------------+
|
||||
| order 2 | product2 | 7 | 140.0 | 56.0 | -> 5 items at cost of 6.0 and 2 items at cost of 13.0, remains 8 items at cost of 13.0
|
||||
| | product3 | 7 | 210.0 | 0.0 |
|
||||
+---------+----------+-----+-------------+------------+
|
||||
| order 3 | product1 | 6 | 60.0 | 43.0 | -> 5 items at cost of 6.0 and 1 item at cost of 13.0, remains 9 items at cost of 13.0
|
||||
| | product2 | 6 | 120.0 | 78.0 | -> 6 items at cost of 13.0, remains 2 items at cost of 13.0
|
||||
| | product3 | 6 | 180.0 | 0.0 |
|
||||
+---------+----------+-----+-------------+------------+
|
||||
|
||||
Expected Result
|
||||
===============
|
||||
+---------------------+---------+
|
||||
| account | balance |
|
||||
+---------------------+---------+
|
||||
| sale_account | -1010.0 |
|
||||
| pos_receivable-cash | 1010.0 |
|
||||
| expense_account | 327.0 |
|
||||
| output_account | -327.0 |
|
||||
+---------------------+---------+
|
||||
| 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.')
|
||||
self.assertAlmostEqual(orders_total, 1010.0, msg='The orders\'s total amount should equal the computed.')
|
||||
|
||||
# check product qty_available after syncing the order
|
||||
self.assertEqual(self.product1.qty_available, 9)
|
||||
self.assertEqual(self.product2.qty_available, 2)
|
||||
self.assertEqual(self.product3.qty_available, 12)
|
||||
|
||||
# picking and stock moves should be in done state
|
||||
for order in self.pos_session.order_ids:
|
||||
self.assertEqual(order.picking_ids[0].state, 'done', 'Picking should be in done state.')
|
||||
self.assertTrue(all(state == 'done' for state in order.picking_ids[0].move_ids.mapped('state')), 'Move Lines should be in done state.')
|
||||
|
||||
self._run_test({
|
||||
'payment_methods': self.cash_pm1 | self.bank_pm1,
|
||||
'orders': [
|
||||
{'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10)], 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product2, 7), (self.product3, 7)], 'uid': '00100-010-0002'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 6), (self.product2, 6), (self.product3, 6)], 'uid': '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': 1010.0, 'reconciled': False},
|
||||
{'account_id': self.expense_account.id, 'partner_id': False, 'debit': 327, 'credit': 0, 'reconciled': False},
|
||||
{'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 1010.0, 'credit': 0, 'reconciled': True},
|
||||
{'account_id': self.output_account.id, 'partner_id': False, 'debit': 0, 'credit': 327, 'reconciled': True},
|
||||
],
|
||||
},
|
||||
'cash_statement': [
|
||||
((1010.0, ), {
|
||||
'line_ids': [
|
||||
{'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 1010.0, 'credit': 0, 'reconciled': False},
|
||||
{'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 1010.0, 'reconciled': True},
|
||||
]
|
||||
}),
|
||||
],
|
||||
'bank_payments': [],
|
||||
},
|
||||
})
|
||||
|
||||
def test_02_orders_with_invoice(self):
|
||||
"""
|
||||
|
||||
Orders
|
||||
======
|
||||
Same with test_01 but order 3 is invoiced.
|
||||
|
||||
Expected Result
|
||||
===============
|
||||
+---------------------+---------+
|
||||
| account | balance |
|
||||
+---------------------+---------+
|
||||
| sale_account | -650.0 |
|
||||
| pos_receivable-cash | 1010.0 |
|
||||
| receivable | -360.0 |
|
||||
| expense_account | 206.0 |
|
||||
| output_account | -206.0 |
|
||||
+---------------------+---------+
|
||||
| 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.')
|
||||
self.assertAlmostEqual(orders_total, 1010.0, msg='The orders\'s total amount should equal the computed.')
|
||||
|
||||
# check product qty_available after syncing the order
|
||||
self.assertEqual(self.product1.qty_available, 9)
|
||||
self.assertEqual(self.product2.qty_available, 2)
|
||||
self.assertEqual(self.product3.qty_available, 12)
|
||||
|
||||
# picking and stock moves should be in done state
|
||||
for order in self.pos_session.order_ids:
|
||||
self.assertEqual(order.picking_ids[0].state, 'done', 'Picking should be in done state.')
|
||||
self.assertTrue(all(state == 'done' for state in order.picking_ids[0].move_ids.mapped('state')), 'Move Lines should be in done state.')
|
||||
|
||||
self._run_test({
|
||||
'payment_methods': self.cash_pm1 | self.bank_pm1,
|
||||
'orders': [
|
||||
{'pos_order_lines_ui_args': [(self.product1, 10), (self.product2, 10)], 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product2, 7), (self.product3, 7)], 'uid': '00100-010-0002'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 6), (self.product2, 6), (self.product3, 6)], 'is_invoiced': True, 'customer': self.customer, 'uid': '00100-010-0003'},
|
||||
],
|
||||
'before_closing_cb': _before_closing_cb,
|
||||
'journal_entries_before_closing': {
|
||||
'00100-010-0003': {
|
||||
'payments': [
|
||||
((self.cash_pm1, 360.0), {
|
||||
'line_ids': [
|
||||
{'account_id': self.c1_receivable.id, 'partner_id': self.customer.id, 'debit': 0, 'credit': 360.0, 'reconciled': True},
|
||||
{'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 360.0, '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': 650, 'reconciled': False},
|
||||
{'account_id': self.expense_account.id, 'partner_id': False, 'debit': 206, 'credit': 0, 'reconciled': False},
|
||||
{'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 1010.0, 'credit': 0, 'reconciled': True},
|
||||
{'account_id': self.pos_receivable_account.id, 'partner_id': False, 'debit': 0, 'credit': 360, 'reconciled': True},
|
||||
{'account_id': self.output_account.id, 'partner_id': False, 'debit': 0, 'credit': 206, 'reconciled': True},
|
||||
],
|
||||
},
|
||||
'cash_statement': [
|
||||
((1010.0, ), {
|
||||
'line_ids': [
|
||||
{'account_id': self.cash_pm1.journal_id.default_account_id.id, 'partner_id': False, 'debit': 1010.0, 'credit': 0, 'reconciled': False},
|
||||
{'account_id': self.cash_pm1.receivable_account_id.id, 'partner_id': False, 'debit': 0, 'credit': 1010.0, 'reconciled': True},
|
||||
]
|
||||
}),
|
||||
],
|
||||
'bank_payments': [],
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
def test_03_order_product_w_owner(self):
|
||||
"""
|
||||
Test order via POS a product having stock owner.
|
||||
"""
|
||||
|
||||
group_owner = self.env.ref('stock.group_tracking_owner')
|
||||
self.env.user.write({'groups_id': [(4, group_owner.id)]})
|
||||
self.product4 = self.create_product('Product 3', self.categ_basic, 30.0, 15.0)
|
||||
self.env['stock.quant'].with_context(inventory_mode=True).create({
|
||||
'product_id': self.product4.id,
|
||||
'inventory_quantity': 10,
|
||||
'location_id': self.stock_location_components.id,
|
||||
'owner_id': self.partner_a.id,
|
||||
}).action_apply_inventory()
|
||||
|
||||
self.open_new_session()
|
||||
|
||||
# create orders
|
||||
orders = []
|
||||
orders.append(self.create_ui_order_data([(self.product4, 1)]))
|
||||
|
||||
# sync orders
|
||||
order = self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
# check values before closing the session
|
||||
self.assertEqual(1, self.pos_session.order_count)
|
||||
|
||||
# check product qty_available after syncing the order
|
||||
self.assertEqual(self.product4.qty_available, 9)
|
||||
|
||||
# picking and stock moves should be in done state
|
||||
for order in self.pos_session.order_ids:
|
||||
self.assertEqual(order.picking_ids[0].state, 'done', 'Picking should be in done state.')
|
||||
self.assertTrue(all(state == 'done' for state in order.picking_ids[0].move_ids.mapped('state')), 'Move Lines should be in done state.')
|
||||
self.assertTrue(self.partner_a == order.picking_ids[0].move_ids[0].move_line_ids[0].owner_id, 'Move Lines Owner should be taken into account.')
|
||||
|
||||
# close the session
|
||||
self.pos_session.action_pos_session_validate()
|
||||
|
||||
def test_04_order_refund(self):
|
||||
self.categ4 = self.env['product.category'].create({
|
||||
'name': 'Category 4',
|
||||
'property_cost_method': 'fifo',
|
||||
'property_valuation': 'real_time',
|
||||
})
|
||||
self.product4 = self.create_product('Product 4', self.categ4, 30.0, 15.0)
|
||||
|
||||
self.open_new_session()
|
||||
orders = []
|
||||
orders.append(self.create_ui_order_data([(self.product4, 1)]))
|
||||
order = self.env['pos.order'].create_from_ui(orders)
|
||||
|
||||
refund_action = self.env['pos.order'].browse(order[0]['id']).refund()
|
||||
refund = self.env['pos.order'].browse(refund_action['res_id'])
|
||||
|
||||
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_pm1.id,
|
||||
})
|
||||
refund_payment.with_context(**payment_context).check()
|
||||
|
||||
self.pos_session.action_pos_session_validate()
|
||||
expense_account_move_line = self.env['account.move.line'].search([('account_id', '=', self.expense_account.id)])
|
||||
self.assertEqual(expense_account_move_line.balance, 0.0, "Expense account should be 0.0")
|
||||
|
|
@ -0,0 +1,375 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import tools
|
||||
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.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,
|
||||
)
|
||||
cls.adjust_inventory([cls.product1, cls.product2, cls.product3], [100, 50, 50])
|
||||
|
||||
@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,
|
||||
})
|
||||
tax_fpos = cls.env['account.fiscal.position.tax'].create({
|
||||
'position_id': fpos.id,
|
||||
'tax_src_id': cls.taxes['tax7'].id,
|
||||
'tax_dest_id': cls.new_tax_17.id,
|
||||
})
|
||||
fpos.write({
|
||||
'account_ids': [(6, 0, account_fpos.ids)],
|
||||
'tax_ids': [(6, 0, tax_fpos.ids)],
|
||||
})
|
||||
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,
|
||||
})
|
||||
tax_fpos = cls.env['account.fiscal.position.tax'].create({
|
||||
'position_id': fpos_no_tax_dest.id,
|
||||
'tax_src_id': cls.taxes['tax7'].id,
|
||||
})
|
||||
fpos_no_tax_dest.write({
|
||||
'account_ids': [(6, 0, account_fpos.ids)],
|
||||
'tax_ids': [(6, 0, tax_fpos.ids)],
|
||||
})
|
||||
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, 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'customer': self.customer, 'uid': '00100-010-0002'},
|
||||
{'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm1, 265.75)], 'uid': '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, 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'customer': self.customer, 'uid': '00100-010-0002'},
|
||||
{'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'payments': [(self.bank_pm1, 265.75)], 'uid': '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.pos_reference)
|
||||
invoiced_order_2 = self.pos_session.order_ids.filtered(lambda order: '00100-010-0003' in order.pos_reference)
|
||||
|
||||
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, 'uid': '00100-010-0001'},
|
||||
{'pos_order_lines_ui_args': [(self.product1, 5), (self.product2, 5)], 'customer': self.customer, 'uid': '00100-010-0002'},
|
||||
{'pos_order_lines_ui_args': [(self.product2, 5), (self.product3, 5)], 'customer': self.other_customer, 'is_invoiced': True, 'uid': '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},
|
||||
]
|
||||
}),
|
||||
],
|
||||
},
|
||||
})
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
# -*- 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 TestReportPoSOrder(TestPoSCommon):
|
||||
|
||||
def setUp(self):
|
||||
super(TestReportPoSOrder, self).setUp()
|
||||
self.config = self.basic_config
|
||||
|
||||
def test_report_pos_order_0(self):
|
||||
"""Test the margin and price_total of a PoS Order with no taxes."""
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 150)
|
||||
|
||||
self.open_new_session()
|
||||
session = self.pos_session
|
||||
self.env['pos.order'].create({
|
||||
'session_id': session.id,
|
||||
'lines': [
|
||||
(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': product1.id,
|
||||
'price_unit': 150,
|
||||
'discount': 0,
|
||||
'qty': 1.0,
|
||||
'price_subtotal': 150,
|
||||
'price_subtotal_incl': 150,
|
||||
})
|
||||
],
|
||||
'amount_total': 150.0,
|
||||
'amount_tax': 0.0,
|
||||
'amount_paid': 0.0,
|
||||
'amount_return': 0.0,
|
||||
})
|
||||
# PoS Orders have negative IDs to avoid conflict, so reports[0] will correspond to the newest order
|
||||
reports = self.env['report.pos.order'].sudo().search([('product_id', '=', product1.id)], order='id')
|
||||
|
||||
self.assertEqual(reports[0].margin, 150)
|
||||
self.assertEqual(reports[0].price_total, 150)
|
||||
|
||||
def test_report_pos_order_1(self):
|
||||
"""Test the margin and price_total of a PoS Order with taxes."""
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 150, self.taxes['tax10'].id)
|
||||
|
||||
self.open_new_session()
|
||||
session = self.pos_session
|
||||
|
||||
self.env['pos.order'].create({
|
||||
'session_id': session.id,
|
||||
'lines': [(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': product1.id,
|
||||
'price_unit': 150,
|
||||
'discount': 0,
|
||||
'qty': 1.0,
|
||||
'price_subtotal': 150,
|
||||
'price_subtotal_incl': 165,
|
||||
}),],
|
||||
'amount_total': 165.0,
|
||||
'amount_tax': 15.0,
|
||||
'amount_paid': 0.0,
|
||||
'amount_return': 0.0,
|
||||
})
|
||||
|
||||
# PoS Orders have negative IDs to avoid conflict, so reports[0] will correspond to the newest order
|
||||
reports = self.env['report.pos.order'].sudo().search([('product_id', '=', product1.id)], order='id')
|
||||
|
||||
self.assertEqual(reports[0].margin, 150)
|
||||
self.assertEqual(reports[0].price_total, 165)
|
||||
|
||||
def test_report_pos_order_2(self):
|
||||
"""Test the margin and price_total of a PoS Order with discount and no taxes"""
|
||||
|
||||
product1 = self.create_product('Product 1', self.categ_basic, 150)
|
||||
|
||||
self.open_new_session()
|
||||
session = self.pos_session
|
||||
|
||||
self.env['pos.order'].create({
|
||||
'session_id': session.id,
|
||||
'lines': [
|
||||
(0, 0, {
|
||||
'name': "OL/0001",
|
||||
'product_id': product1.id,
|
||||
'price_unit': 150,
|
||||
'discount': 10,
|
||||
'qty': 1.0,
|
||||
'price_subtotal': 135,
|
||||
'price_subtotal_incl': 135,
|
||||
})
|
||||
],
|
||||
'amount_total': 135.0,
|
||||
'amount_tax': 0.0,
|
||||
'amount_paid': 0.0,
|
||||
'amount_return': 0.0,
|
||||
})
|
||||
|
||||
# PoS Orders have negative IDs to avoid conflict, so reports[0] will correspond to the newest order
|
||||
reports = self.env['report.pos.order'].sudo().search([('product_id', '=', product1.id)], order='id')
|
||||
|
||||
self.assertEqual(reports[0].margin, 135)
|
||||
self.assertEqual(reports[0].price_total, 135)
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
# -*- 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
|
||||
from odoo.tests.common import Form
|
||||
|
||||
|
||||
@odoo.tests.tagged('post_install', '-at_install')
|
||||
class TestConfigureShops(TestPoSCommon):
|
||||
""" Shops are now configured from the general settings.
|
||||
This test suite ensures that changes made in the general settings
|
||||
should reflect to the pos.config record pointed by the
|
||||
pos_config_id field.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
# If not enabled (like in demo data), landing on res.config will try
|
||||
# to disable module_sale_quotation_builder and raise an issue
|
||||
group_order_template = cls.env.ref('sale_management.group_sale_order_template', raise_if_not_found=False)
|
||||
if group_order_template:
|
||||
cls.env.ref('base.group_user').write({"implied_ids": [(4, group_order_template.id)]})
|
||||
|
||||
def _remove_on_payment_taxes(self):
|
||||
""" Call this when testing the res.config.settings with Form.
|
||||
The `on_payment` taxes need to be removed, otherwise, a warning will show in the log.
|
||||
"""
|
||||
self.env['account.tax'].search([
|
||||
('company_id', '=', self.env.company.id), ('tax_exigibility', '=', 'on_payment')
|
||||
]).unlink()
|
||||
|
||||
def test_should_not_affect_other_pos_config(self):
|
||||
""" Change in one pos.config should not reflect to the other.
|
||||
"""
|
||||
self._remove_on_payment_taxes()
|
||||
|
||||
pos_config1 = self.env['pos.config'].create({'name': 'Shop 1'})
|
||||
pos_config2 = self.env['pos.config'].create({'name': 'Shop 2'})
|
||||
self.assertEqual(pos_config1.receipt_header, False)
|
||||
self.assertEqual(pos_config2.receipt_header, False)
|
||||
|
||||
# Modify Shop 1.
|
||||
with Form(self.env['res.config.settings']) as form:
|
||||
form.pos_config_id = pos_config1
|
||||
form.pos_is_header_or_footer = True
|
||||
form.pos_receipt_header = 'xxxxx'
|
||||
|
||||
self.assertEqual(pos_config1.receipt_header, 'xxxxx')
|
||||
self.assertEqual(pos_config2.receipt_header, False)
|
||||
|
||||
# Modify Shop 2.
|
||||
with Form(self.env['res.config.settings']) as form:
|
||||
form.pos_config_id = pos_config2
|
||||
form.pos_is_header_or_footer = True
|
||||
form.pos_receipt_header = 'yyyyy'
|
||||
|
||||
self.assertEqual(pos_config1.receipt_header, 'xxxxx')
|
||||
self.assertEqual(pos_config2.receipt_header, 'yyyyy')
|
||||
|
||||
def test_is_header_or_footer_to_false(self):
|
||||
self._remove_on_payment_taxes()
|
||||
|
||||
pos_config = self.env['pos.config'].create({
|
||||
'name': 'Shop',
|
||||
'is_header_or_footer': True,
|
||||
'receipt_header': 'header val',
|
||||
'receipt_footer': 'footer val',
|
||||
})
|
||||
|
||||
with Form(self.env['res.config.settings']) as form:
|
||||
form.pos_config_id = pos_config
|
||||
form.pos_is_header_or_footer = False
|
||||
|
||||
self.assertEqual(pos_config.receipt_header, False)
|
||||
self.assertEqual(pos_config.receipt_footer, False)
|
||||
Loading…
Add table
Add a link
Reference in a new issue