[IMP] sale*: Remove dependency to AccountTestCommon
l10n runbot builds are all failing when running at least one test depending of AccountTestCommon because it: - doesn't create a sandboxed testing environnement to manage the multi-currency, multi-company, the default company's currency, the exchange rates... - doesn't setup a testing user then all tests are done using the superuser. - doesn't provide a fully setup chart of accounts: exchange difference journal is not set, accounts have bad types, etc... - is run sometimes at-install. --task: 2301180m
This commit is contained in:
+68
-101
@@ -354,103 +354,6 @@ class AccountTestNoChartCommon(SavepointCaseWithUserDemo):
|
||||
}).id,
|
||||
})
|
||||
cls.env.user.company_id.currency_exchange_journal_id = cls.exchange_journal0
|
||||
|
||||
@classmethod
|
||||
def setUpAdditionalAccounts(cls):
|
||||
""" Set up some addionnal accounts: expenses, revenue, ... """
|
||||
user_type_income = cls.env.ref('account.data_account_type_direct_costs')
|
||||
cls.account_income = cls.env['account.account'].create({
|
||||
'code': 'NC1112', 'name':
|
||||
'Sale - Test Account',
|
||||
'user_type_id': user_type_income.id
|
||||
})
|
||||
user_type_expense = cls.env.ref('account.data_account_type_expenses')
|
||||
cls.account_expense = cls.env['account.account'].create({
|
||||
'code': 'NC1113',
|
||||
'name': 'HR Expense - Test Purchase Account',
|
||||
'user_type_id': user_type_expense.id
|
||||
})
|
||||
user_type_revenue = cls.env.ref('account.data_account_type_revenue')
|
||||
cls.account_revenue = cls.env['account.account'].create({
|
||||
'code': 'NC1114',
|
||||
'name': 'Sales - Test Sales Account',
|
||||
'user_type_id': user_type_revenue.id,
|
||||
'reconcile': True
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def setUpAccountJournal(cls):
|
||||
""" Set up some journals: sale, purchase, ... """
|
||||
cls.journal_purchase = cls.env['account.journal'].create({
|
||||
'name': 'Purchase Journal - Test',
|
||||
'code': 'AJ-PURC',
|
||||
'type': 'purchase',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
'default_debit_account_id': cls.account_expense.id,
|
||||
'default_credit_account_id': cls.account_expense.id,
|
||||
})
|
||||
cls.journal_sale = cls.env['account.journal'].create({
|
||||
'name': 'Sale Journal - Test',
|
||||
'code': 'AJ-SALE',
|
||||
'type': 'sale',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
'default_debit_account_id': cls.account_income.id,
|
||||
'default_credit_account_id': cls.account_income.id,
|
||||
})
|
||||
cls.journal_general = cls.env['account.journal'].create({
|
||||
'name': 'General Journal - Test',
|
||||
'code': 'AJ-GENERAL',
|
||||
'type': 'general',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
})
|
||||
cls.journal_bank = cls.env['account.journal'].create({
|
||||
'name': 'Bank Journal - Test',
|
||||
'code': 'AJ-BANK',
|
||||
'type': 'bank',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def setUpUsers(cls):
|
||||
""" Create 2 users: an employee and a manager. Both will have correct account configured
|
||||
on their partner. Others access rigths should be given in extending test suites set up.
|
||||
"""
|
||||
group_employee = cls.env.ref('base.group_user')
|
||||
Users = cls.env['res.users'].with_context({'no_reset_password': True, 'mail_create_nosubscribe': True, 'mail_create_nolog': True})
|
||||
cls.user_employee = Users.create({
|
||||
'name': 'Tyrion Lannister Employee',
|
||||
'login': 'tyrion',
|
||||
'email': 'tyrion@example.com',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [group_employee.id])],
|
||||
})
|
||||
cls.user_manager = Users.create({
|
||||
'name': 'Daenerys Targaryen Manager',
|
||||
'login': 'daenerys',
|
||||
'email': 'daenerys@example.com',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [group_employee.id])],
|
||||
})
|
||||
account_values = {
|
||||
'property_account_payable_id': cls.account_payable.id,
|
||||
'property_account_receivable_id': cls.account_receivable.id,
|
||||
}
|
||||
cls.user_manager.partner_id.write(account_values)
|
||||
cls.user_employee.partner_id.write(account_values)
|
||||
|
||||
class AccountTestNoChartCommonMultiCompany(AccountTestNoChartCommon):
|
||||
""" Some tests required to be executed at module installation, and not 'post install', like moslty
|
||||
of accounting tests, since a chart of account is required
|
||||
This test setup class provides data for test suite to make business flow working without a chart
|
||||
of account installed in a multi-company environment.
|
||||
The class provide some helpers methods to create particular document types. Each test suite extending
|
||||
this method can call thoses method to set up their testing environment in their own `setUpClass` method.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
""" This method set up the minimal requried part of chart of account """
|
||||
super(AccountTestNoChartCommonMultiCompany, cls).setUpClass()
|
||||
cls.company_B = cls.env['res.company'].create({'name': 'Company B'})
|
||||
|
||||
# To speed up test, create object without mail tracking
|
||||
@@ -509,7 +412,25 @@ class AccountTestNoChartCommonMultiCompany(AccountTestNoChartCommon):
|
||||
@classmethod
|
||||
def setUpAdditionalAccounts(cls):
|
||||
""" Set up some addionnal accounts: expenses, revenue, ... """
|
||||
super(AccountTestNoChartCommonMultiCompany, cls).setUpAdditionalAccounts()
|
||||
user_type_income = cls.env.ref('account.data_account_type_direct_costs')
|
||||
cls.account_income = cls.env['account.account'].create({
|
||||
'code': 'NC1112', 'name':
|
||||
'Sale - Test Account',
|
||||
'user_type_id': user_type_income.id
|
||||
})
|
||||
user_type_expense = cls.env.ref('account.data_account_type_expenses')
|
||||
cls.account_expense = cls.env['account.account'].create({
|
||||
'code': 'NC1113',
|
||||
'name': 'HR Expense - Test Purchase Account',
|
||||
'user_type_id': user_type_expense.id
|
||||
})
|
||||
user_type_revenue = cls.env.ref('account.data_account_type_revenue')
|
||||
cls.account_revenue = cls.env['account.account'].create({
|
||||
'code': 'NC1114',
|
||||
'name': 'Sales - Test Sales Account',
|
||||
'user_type_id': user_type_revenue.id,
|
||||
'reconcile': True
|
||||
})
|
||||
user_type_income = cls.env.ref('account.data_account_type_direct_costs')
|
||||
cls.account_income_company_B = cls.env['account.account'].create({
|
||||
'code': 'NC1112',
|
||||
@@ -536,7 +457,34 @@ class AccountTestNoChartCommonMultiCompany(AccountTestNoChartCommon):
|
||||
@classmethod
|
||||
def setUpAccountJournal(cls):
|
||||
""" Set up some journals: sale, purchase, ... """
|
||||
super(AccountTestNoChartCommonMultiCompany, cls).setUpAccountJournal()
|
||||
cls.journal_purchase = cls.env['account.journal'].create({
|
||||
'name': 'Purchase Journal - Test',
|
||||
'code': 'AJ-PURC',
|
||||
'type': 'purchase',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
'default_debit_account_id': cls.account_expense.id,
|
||||
'default_credit_account_id': cls.account_expense.id,
|
||||
})
|
||||
cls.journal_sale = cls.env['account.journal'].create({
|
||||
'name': 'Sale Journal - Test',
|
||||
'code': 'AJ-SALE',
|
||||
'type': 'sale',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
'default_debit_account_id': cls.account_income.id,
|
||||
'default_credit_account_id': cls.account_income.id,
|
||||
})
|
||||
cls.journal_general = cls.env['account.journal'].create({
|
||||
'name': 'General Journal - Test',
|
||||
'code': 'AJ-GENERAL',
|
||||
'type': 'general',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
})
|
||||
cls.journal_bank = cls.env['account.journal'].create({
|
||||
'name': 'Bank Journal - Test',
|
||||
'code': 'AJ-BANK',
|
||||
'type': 'bank',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
})
|
||||
cls.journal_purchase_company_B = cls.env['account.journal'].create({
|
||||
'name': 'Purchase Journal Company B - Test',
|
||||
'code': 'AJ-PURC',
|
||||
@@ -562,12 +510,31 @@ class AccountTestNoChartCommonMultiCompany(AccountTestNoChartCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpUsers(cls):
|
||||
""" Create 2 users for each company: an employee and a manager. Both will have correct account configured
|
||||
""" Create 2 users: an employee and a manager. Both will have correct account configured
|
||||
on their partner. Others access rigths should be given in extending test suites set up.
|
||||
"""
|
||||
super(AccountTestNoChartCommonMultiCompany, cls).setUpUsers()
|
||||
group_employee = cls.env.ref('base.group_user')
|
||||
Users = cls.env['res.users'].with_context({'no_reset_password': True, 'mail_create_nosubscribe': True, 'mail_create_nolog': True})
|
||||
cls.user_employee = Users.create({
|
||||
'name': 'Tyrion Lannister Employee',
|
||||
'login': 'tyrion',
|
||||
'email': 'tyrion@example.com',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [group_employee.id])],
|
||||
})
|
||||
cls.user_manager = Users.create({
|
||||
'name': 'Daenerys Targaryen Manager',
|
||||
'login': 'daenerys',
|
||||
'email': 'daenerys@example.com',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [group_employee.id])],
|
||||
})
|
||||
account_values = {
|
||||
'property_account_payable_id': cls.account_payable.id,
|
||||
'property_account_receivable_id': cls.account_receivable.id,
|
||||
}
|
||||
cls.user_manager.partner_id.write(account_values)
|
||||
cls.user_employee.partner_id.write(account_values)
|
||||
cls.user_employee_company_B = Users.create({
|
||||
'name': 'Gregor Clegane Employee',
|
||||
'login': 'gregor',
|
||||
|
||||
@@ -62,7 +62,6 @@ class TestPurchaseOrderReport(AccountTestInvoicingCommon):
|
||||
('company_id', '=', self.company_data['company'].id),
|
||||
])
|
||||
|
||||
# Check that repost should show 6 unit of product
|
||||
self.assertEqual(res_product2.qty_ordered, 1.0, 'No conversion needed since product_b is already a dozen')
|
||||
# report should show in company currency (amount/rate) = (200/2)
|
||||
self.assertEqual(res_product2.price_total, 100.0, 'Currency conversion is not working')
|
||||
|
||||
@@ -11,3 +11,4 @@ from . import test_access_rights
|
||||
from . import test_sale_refund
|
||||
from . import test_sale_signature
|
||||
from . import test_sale_transaction
|
||||
from . import test_sale_flow
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
from odoo.addons.base.tests.common import SavepointCase
|
||||
|
||||
|
||||
class TestSaleCommonBase(SavepointCase):
|
||||
''' Setup with sale test configuration. '''
|
||||
|
||||
@classmethod
|
||||
def setup_sale_configuration_for_company(cls, company):
|
||||
Users = cls.env['res.users'].with_context(no_reset_password=True)
|
||||
|
||||
company_data = {
|
||||
# Sales Team
|
||||
'default_sale_team': cls.env['crm.team'].with_context(tracking_disable=True).create({
|
||||
'name': 'Test Channel',
|
||||
'company_id': company.id,
|
||||
}),
|
||||
|
||||
# Users
|
||||
'default_user_salesman': Users.create({
|
||||
'name': 'default_user_salesman',
|
||||
'login': 'default_user_salesman.comp%s' % company.id,
|
||||
'email': 'default_user_salesman@example.com',
|
||||
'signature': '--\nMark',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, cls.env.ref('sales_team.group_sale_salesman').ids)],
|
||||
'company_ids': [(6, 0, company.ids)],
|
||||
'company_id': company.id,
|
||||
}),
|
||||
'default_user_portal': Users.create({
|
||||
'name': 'default_user_portal',
|
||||
'login': 'default_user_portal.comp%s' % company.id,
|
||||
'email': 'default_user_portal@gladys.portal',
|
||||
'groups_id': [(6, 0, [cls.env.ref('base.group_portal').id])],
|
||||
'company_ids': [(6, 0, company.ids)],
|
||||
'company_id': company.id,
|
||||
}),
|
||||
'default_user_employee': Users.create({
|
||||
'name': 'default_user_employee',
|
||||
'login': 'default_user_employee.comp%s' % company.id,
|
||||
'email': 'default_user_employee@example.com',
|
||||
'groups_id': [(6, 0, [cls.env.ref('base.group_user').id])],
|
||||
'company_ids': [(6, 0, company.ids)],
|
||||
'company_id': company.id,
|
||||
}),
|
||||
|
||||
# Pricelist
|
||||
'default_pricelist': cls.env['product.pricelist'].with_company(company).create({
|
||||
'name': 'default_pricelist',
|
||||
'currency_id': company.currency_id.id,
|
||||
}),
|
||||
|
||||
# Product category
|
||||
'product_category': cls.env['product.category'].with_company(company).create({
|
||||
'name': 'Test category',
|
||||
}),
|
||||
}
|
||||
|
||||
company_data.update({
|
||||
# Products
|
||||
'product_service_delivery': cls.env['product.product'].with_company(company).create({
|
||||
'name': 'product_service_delivery',
|
||||
'categ_id': company_data['product_category'].id,
|
||||
'standard_price': 200.0,
|
||||
'list_price': 180.0,
|
||||
'type': 'service',
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'SERV_DEL',
|
||||
'invoice_policy': 'delivery',
|
||||
'taxes_id': [(6, 0, [])],
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
}),
|
||||
'product_service_order': cls.env['product.product'].with_company(company).create({
|
||||
'name': 'product_service_order',
|
||||
'categ_id': company_data['product_category'].id,
|
||||
'standard_price': 40.0,
|
||||
'list_price': 90.0,
|
||||
'type': 'service',
|
||||
'uom_id': cls.env.ref('uom.product_uom_hour').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_hour').id,
|
||||
'description': 'Example of product to invoice on order',
|
||||
'default_code': 'PRE-PAID',
|
||||
'invoice_policy': 'order',
|
||||
'taxes_id': [(6, 0, [])],
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
}),
|
||||
'product_order_cost': cls.env['product.product'].with_company(company).create({
|
||||
'name': 'product_order_cost',
|
||||
'categ_id': company_data['product_category'].id,
|
||||
'standard_price': 235.0,
|
||||
'list_price': 280.0,
|
||||
'type': 'consu',
|
||||
'weight': 0.01,
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'FURN_9999',
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'cost',
|
||||
'taxes_id': [(6, 0, [])],
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
}),
|
||||
'product_delivery_cost': cls.env['product.product'].with_company(company).create({
|
||||
'name': 'product_delivery_cost',
|
||||
'categ_id': company_data['product_category'].id,
|
||||
'standard_price': 55.0,
|
||||
'list_price': 70.0,
|
||||
'type': 'consu',
|
||||
'weight': 0.01,
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'FURN_7777',
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'cost',
|
||||
'taxes_id': [(6, 0, [])],
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
}),
|
||||
'product_order_sales_price': cls.env['product.product'].with_company(company).create({
|
||||
'name': 'product_order_sales_price',
|
||||
'categ_id': company_data['product_category'].id,
|
||||
'standard_price': 235.0,
|
||||
'list_price': 280.0,
|
||||
'type': 'consu',
|
||||
'weight': 0.01,
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'FURN_9999',
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'sales_price',
|
||||
'taxes_id': [(6, 0, [])],
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
}),
|
||||
'product_delivery_sales_price': cls.env['product.product'].with_company(company).create({
|
||||
'name': 'product_delivery_sales_price',
|
||||
'categ_id': company_data['product_category'].id,
|
||||
'standard_price': 55.0,
|
||||
'list_price': 70.0,
|
||||
'type': 'consu',
|
||||
'weight': 0.01,
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'FURN_7777',
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'sales_price',
|
||||
'taxes_id': [(6, 0, [])],
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
}),
|
||||
'product_order_no': cls.env['product.product'].with_company(company).create({
|
||||
'name': 'product_order_no',
|
||||
'categ_id': company_data['product_category'].id,
|
||||
'standard_price': 235.0,
|
||||
'list_price': 280.0,
|
||||
'type': 'consu',
|
||||
'weight': 0.01,
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'FURN_9999',
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'no',
|
||||
'taxes_id': [(6, 0, [])],
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
}),
|
||||
'product_delivery_no': cls.env['product.product'].with_company(company).create({
|
||||
'name': 'product_delivery_no',
|
||||
'categ_id': company_data['product_category'].id,
|
||||
'standard_price': 55.0,
|
||||
'list_price': 70.0,
|
||||
'type': 'consu',
|
||||
'weight': 0.01,
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'FURN_7777',
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'no',
|
||||
'taxes_id': [(6, 0, [])],
|
||||
'supplier_taxes_id': [(6, 0, [])],
|
||||
}),
|
||||
})
|
||||
|
||||
return company_data
|
||||
|
||||
|
||||
class TestSaleCommon(AccountTestInvoicingCommon, TestSaleCommonBase):
|
||||
''' Setup to be used post-install with sale and accounting test configuration.'''
|
||||
|
||||
@classmethod
|
||||
def setup_company_data(cls, company_name, chart_template=None, **kwargs):
|
||||
company_data = super().setup_company_data(company_name, chart_template=chart_template, **kwargs)
|
||||
|
||||
company_data.update(cls.setup_sale_configuration_for_company(company_data['company']))
|
||||
|
||||
company_data['product_category'].write({
|
||||
'property_account_income_categ_id': company_data['default_account_revenue'].id,
|
||||
'property_account_expense_categ_id': company_data['default_account_expense'].id,
|
||||
})
|
||||
|
||||
return company_data
|
||||
@@ -1,153 +1,124 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
from odoo.exceptions import AccessError, UserError, ValidationError
|
||||
from odoo.tests import tagged
|
||||
from .test_sale_common import TestCommonSaleNoChart
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAccessRights(TestCommonSaleNoChart):
|
||||
class TestAccessRights(TestSaleCommon):
|
||||
|
||||
def setUp(self):
|
||||
super(TestAccessRights, self).setUp()
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
Users = self.env['res.users'].with_context(no_reset_password=True)
|
||||
|
||||
group_user = self.env.ref('sales_team.group_sale_salesman')
|
||||
# Create a users
|
||||
self.user_manager = Users.create({
|
||||
'name': 'Andrew Manager',
|
||||
'login': 'manager',
|
||||
'email': 'a.m@example.com',
|
||||
'groups_id': [(6, 0, [self.env.ref('sales_team.group_sale_manager').id])]
|
||||
})
|
||||
self.user_salesperson = Users.create({
|
||||
'name': 'Mark User',
|
||||
'login': 'user',
|
||||
'email': 'm.u@example.com',
|
||||
'groups_id': [(6, 0, [group_user.id])]
|
||||
})
|
||||
self.user_salesperson_1 = Users.create({
|
||||
'name': 'Noemie User',
|
||||
'login': 'noemie',
|
||||
'email': 'n.n@example.com',
|
||||
'groups_id': [(6, 0, [group_user.id])]
|
||||
})
|
||||
self.user_portal = Users.create({
|
||||
'name': 'Chell Gladys',
|
||||
'login': 'chell',
|
||||
'email': 'chell@gladys.portal',
|
||||
'groups_id': [(6, 0, [self.env.ref('base.group_portal').id])]
|
||||
})
|
||||
self.user_employee = Users.create({
|
||||
'name': 'Bert Tartignole',
|
||||
'login': 'bert',
|
||||
'email': 'b.t@example.com',
|
||||
'groups_id': [(6, 0, [self.env.ref('base.group_user').id])]
|
||||
})
|
||||
|
||||
# Create a Sales Team
|
||||
self.sales_channel = self.env['crm.team'].with_context(tracking_disable=True).create({
|
||||
'name': 'Test Channel',
|
||||
cls.company_data['default_user_salesman_2'] = cls.env['res.users'].with_context(no_reset_password=True).create({
|
||||
'name': 'default_user_salesman_2',
|
||||
'login': 'default_user_salesman_2.comp%s' % cls.company_data['company'].id,
|
||||
'email': 'default_user_salesman_2@example.com',
|
||||
'signature': '--\nMark',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, cls.env.ref('sales_team.group_sale_salesman').ids)],
|
||||
'company_ids': [(6, 0, cls.company_data['company'].ids)],
|
||||
'company_id': cls.company_data['company'].id,
|
||||
})
|
||||
|
||||
# Create the SO with a specific salesperson
|
||||
self.order = self.env['sale.order'].with_context(tracking_disable=True).create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'user_id': self.user_salesperson.id
|
||||
cls.order = cls.env['sale.order'].with_context(tracking_disable=True).create({
|
||||
'partner_id': cls.partner_a.id,
|
||||
'user_id': cls.company_data['default_user_salesman'].id
|
||||
})
|
||||
|
||||
def test_access_sales_manager(self):
|
||||
""" Test sales manager's access rights """
|
||||
SaleOrder = self.env['sale.order'].with_context(tracking_disable=True)
|
||||
# Manager can see the SO which is assigned to another salesperson
|
||||
self.order.with_user(self.user_manager).read()
|
||||
self.order.read()
|
||||
# Manager can change a salesperson of the SO
|
||||
self.order.with_user(self.user_manager).write({'user_id': self.user_salesperson_1.id})
|
||||
self.order.write({'user_id': self.company_data['default_user_salesman'].id})
|
||||
# Manager can create the SO for other salesperson
|
||||
sale_order = SaleOrder.with_user(self.user_manager).create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'user_id': self.user_salesperson_1.id
|
||||
sale_order = SaleOrder.create({
|
||||
'partner_id': self.partner_a.id,
|
||||
'user_id': self.company_data['default_user_salesman'].id
|
||||
})
|
||||
self.assertIn(sale_order.id, SaleOrder.search([]).ids, 'Sales manager should be able to create the SO of other salesperson')
|
||||
# Manager can confirm the SO
|
||||
sale_order.with_user(self.user_manager).action_confirm()
|
||||
sale_order.action_confirm()
|
||||
# Manager can not delete confirmed SO
|
||||
with self.assertRaises(UserError):
|
||||
sale_order.with_user(self.user_manager).unlink()
|
||||
sale_order.unlink()
|
||||
# Manager can delete the SO of other salesperson if SO is in 'draft' or 'cancel' state
|
||||
self.order.with_user(self.user_manager).unlink()
|
||||
self.order.unlink()
|
||||
self.assertNotIn(self.order.id, SaleOrder.search([]).ids, 'Sales manager should be able to delete the SO')
|
||||
|
||||
# Manager can create a Sales Team
|
||||
india_channel = self.env['crm.team'].with_context(tracking_disable=True).with_user(self.user_manager).create({
|
||||
india_channel = self.env['crm.team'].with_context(tracking_disable=True).create({
|
||||
'name': 'India',
|
||||
})
|
||||
self.assertIn(india_channel.id, self.env['crm.team'].search([]).ids, 'Sales manager should be able to create a Sales Team')
|
||||
# Manager can edit a Sales Team
|
||||
india_channel.with_user(self.user_manager).write({'name': 'new_india'})
|
||||
india_channel.write({'name': 'new_india'})
|
||||
self.assertEqual(india_channel.name, 'new_india', 'Sales manager should be able to edit a Sales Team')
|
||||
# Manager can delete a Sales Team
|
||||
india_channel.with_user(self.user_manager).unlink()
|
||||
india_channel.unlink()
|
||||
self.assertNotIn(india_channel.id, self.env['crm.team'].search([]).ids, 'Sales manager should be able to delete a Sales Team')
|
||||
|
||||
def test_access_sales_person(self):
|
||||
""" Test Salesperson's access rights """
|
||||
# Salesperson can see only their own sales order
|
||||
with self.assertRaises(AccessError):
|
||||
self.order.with_user(self.user_salesperson_1).read()
|
||||
self.order.with_user(self.company_data['default_user_salesman_2']).read()
|
||||
# Now assign the SO to themselves
|
||||
self.order.write({'user_id': self.user_salesperson_1.id})
|
||||
self.order.with_user(self.user_salesperson_1).read()
|
||||
self.order.write({'user_id': self.company_data['default_user_salesman_2'].id})
|
||||
self.order.with_user(self.company_data['default_user_salesman_2']).read()
|
||||
# Salesperson can change a Sales Team of SO
|
||||
self.order.with_user(self.user_salesperson_1).write({'team_id': self.sales_channel.id})
|
||||
self.order.with_user(self.company_data['default_user_salesman_2']).write({'team_id': self.company_data['default_sale_team'].id})
|
||||
# Salesperson can't create the SO of other salesperson
|
||||
with self.assertRaises(AccessError):
|
||||
self.env['sale.order'].with_user(self.user_salesperson_1).create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'user_id': self.user_salesperson.id
|
||||
self.env['sale.order'].with_user(self.company_data['default_user_salesman_2']).create({
|
||||
'partner_id': self.partner_a.id,
|
||||
'user_id': self.company_data['default_user_salesman'].id
|
||||
})
|
||||
# Salesperson can't delete the SO
|
||||
with self.assertRaises(AccessError):
|
||||
self.order.with_user(self.user_salesperson_1).unlink()
|
||||
self.order.with_user(self.company_data['default_user_salesman_2']).unlink()
|
||||
# Salesperson can confirm the SO
|
||||
self.order.with_user(self.user_salesperson_1).action_confirm()
|
||||
self.order.with_user(self.company_data['default_user_salesman_2']).action_confirm()
|
||||
|
||||
def test_access_portal_user(self):
|
||||
""" Test portal user's access rights """
|
||||
# Portal user can see the confirmed SO for which they are assigned as a customer
|
||||
with self.assertRaises(AccessError):
|
||||
self.order.with_user(self.user_portal).read()
|
||||
self.order.with_user(self.company_data['default_user_portal']).read()
|
||||
|
||||
self.order.write({'partner_id': self.user_portal.partner_id.id})
|
||||
self.order.partner_id = self.company_data['default_user_portal'].partner_id
|
||||
self.order.action_confirm()
|
||||
# Portal user can't edit the SO
|
||||
with self.assertRaises(AccessError):
|
||||
self.order.with_user(self.user_portal).write({'team_id': self.sales_channel.id})
|
||||
self.order.with_user(self.company_data['default_user_portal']).write({'team_id': self.company_data['default_sale_team'].id})
|
||||
# Portal user can't create the SO
|
||||
with self.assertRaises(AccessError):
|
||||
self.env['sale.order'].with_user(self.user_portal).create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
self.env['sale.order'].with_user(self.company_data['default_user_portal']).create({
|
||||
'partner_id': self.partner_a.id,
|
||||
})
|
||||
# Portal user can't delete the SO which is in 'draft' or 'cancel' state
|
||||
self.order.action_cancel()
|
||||
with self.assertRaises(AccessError):
|
||||
self.order.with_user(self.user_portal).unlink()
|
||||
self.order.with_user(self.company_data['default_user_portal']).unlink()
|
||||
|
||||
def test_access_employee(self):
|
||||
""" Test classic employee's access rights """
|
||||
# Employee can't see any SO
|
||||
with self.assertRaises(AccessError):
|
||||
self.order.with_user(self.user_employee).read()
|
||||
self.order.with_user(self.company_data['default_user_employee']).read()
|
||||
# Employee can't edit the SO
|
||||
with self.assertRaises(AccessError):
|
||||
self.order.with_user(self.user_employee).write({'team_id': self.sales_channel.id})
|
||||
self.order.with_user(self.company_data['default_user_employee']).write({'team_id': self.company_data['default_sale_team'].id})
|
||||
# Employee can't create the SO
|
||||
with self.assertRaises(AccessError):
|
||||
self.env['sale.order'].with_user(self.user_employee).create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
self.env['sale.order'].with_user(self.company_data['default_user_employee']).create({
|
||||
'partner_id': self.partner_a.id,
|
||||
})
|
||||
# Employee can't delete the SO
|
||||
with self.assertRaises(AccessError):
|
||||
self.order.with_user(self.user_employee).unlink()
|
||||
self.order.with_user(self.company_data['default_user_employee']).unlink()
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale.tests.test_sale_common import TestCommonSaleNoChart
|
||||
from odoo.tests import Form
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
from odoo.tests import Form, tagged
|
||||
|
||||
|
||||
class TestReInvoice(TestCommonSaleNoChart):
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestReInvoice(TestSaleCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestReInvoice, cls).setUpClass()
|
||||
|
||||
cls.setUpExpenseProducts()
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpAccountJournal()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.analytic_account = cls.env['account.analytic.account'].create({
|
||||
'name': 'Test AA',
|
||||
'code': 'TESTSALE_REINVOICE',
|
||||
'company_id': cls.partner_customer_usd.company_id.id,
|
||||
'partner_id': cls.partner_customer_usd.id
|
||||
'company_id': cls.partner_a.company_id.id,
|
||||
'partner_id': cls.partner_a.id
|
||||
})
|
||||
|
||||
cls.sale_order = cls.env['sale.order'].with_context(mail_notrack=True, mail_create_nolog=True).create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'analytic_account_id': cls.analytic_account.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
|
||||
cls.AccountMove = cls.env['account.move'].with_context(default_move_type='in_invoice', mail_notrack=True, mail_create_nolog=True)
|
||||
@@ -35,22 +32,22 @@ class TestReInvoice(TestCommonSaleNoChart):
|
||||
""" Test vendor bill at cost for product based on ordered and delivered quantities. """
|
||||
# create SO line and confirm SO (with only one line)
|
||||
sale_order_line1 = self.env['sale.order.line'].create({
|
||||
'name': self.product_ordered_cost.name,
|
||||
'product_id': self.product_ordered_cost.id,
|
||||
'name': self.company_data['product_order_cost'].name,
|
||||
'product_id': self.company_data['product_order_cost'].id,
|
||||
'product_uom_qty': 2,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.product_ordered_cost.uom_id.id,
|
||||
'price_unit': self.product_ordered_cost.list_price,
|
||||
'product_uom': self.company_data['product_order_cost'].uom_id.id,
|
||||
'price_unit': self.company_data['product_order_cost'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
sale_order_line1.product_id_change()
|
||||
sale_order_line2 = self.env['sale.order.line'].create({
|
||||
'name': self.product_deliver_cost.name,
|
||||
'product_id': self.product_deliver_cost.id,
|
||||
'name': self.company_data['product_delivery_cost'].name,
|
||||
'product_id': self.company_data['product_delivery_cost'].id,
|
||||
'product_uom_qty': 4,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.product_deliver_cost.uom_id.id,
|
||||
'price_unit': self.product_deliver_cost.list_price,
|
||||
'product_uom': self.company_data['product_delivery_cost'].uom_id.id,
|
||||
'price_unit': self.company_data['product_delivery_cost'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
sale_order_line2.product_id_change()
|
||||
@@ -61,51 +58,48 @@ class TestReInvoice(TestCommonSaleNoChart):
|
||||
|
||||
# create invoice lines and validate it
|
||||
move_form = Form(self.AccountMove)
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_ordered_cost
|
||||
line_form.product_id = self.company_data['product_order_cost']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_deliver_cost
|
||||
line_form.product_id = self.company_data['product_delivery_cost']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_a = move_form.save()
|
||||
invoice_a.post()
|
||||
|
||||
sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.product_ordered_cost)
|
||||
sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.product_deliver_cost)
|
||||
sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.company_data['product_order_cost'])
|
||||
sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.company_data['product_delivery_cost'])
|
||||
|
||||
self.assertTrue(sale_order_line3, "A new sale line should have been created with ordered product")
|
||||
self.assertTrue(sale_order_line4, "A new sale line should have been created with delivered product")
|
||||
self.assertEqual(len(self.sale_order.order_line), 4, "There should be 4 lines on the SO (2 vendor bill lines created)")
|
||||
self.assertEqual(len(self.sale_order.order_line.filtered(lambda sol: sol.is_expense)), 2, "There should be 4 lines on the SO (2 vendor bill lines created)")
|
||||
|
||||
self.assertEqual(sale_order_line1.qty_delivered, 1, "Exising SO line 1 should not be impacted by reinvoicing product at cost")
|
||||
self.assertEqual(sale_order_line2.qty_delivered, 1, "Exising SO line 2 should not be impacted by reinvoicing product at cost")
|
||||
|
||||
self.assertEqual((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.product_ordered_cost.standard_price, 3, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.product_deliver_cost.standard_price, 3, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.company_data['product_order_cost'].standard_price, 3, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.company_data['product_delivery_cost'].standard_price, 3, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
|
||||
self.assertEqual(sale_order_line3.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line should be computed by analytic amount")
|
||||
self.assertEqual(sale_order_line4.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line should be computed by analytic amount")
|
||||
|
||||
# create second invoice lines and validate it
|
||||
move_form = Form(self.AccountMove)
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_ordered_cost
|
||||
line_form.product_id = self.company_data['product_order_cost']
|
||||
line_form.quantity = 2.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_deliver_cost
|
||||
line_form.product_id = self.company_data['product_delivery_cost']
|
||||
line_form.quantity = 2.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_b = move_form.save()
|
||||
invoice_b.post()
|
||||
|
||||
sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.product_ordered_cost)
|
||||
sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.product_deliver_cost)
|
||||
sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.company_data['product_order_cost'])
|
||||
sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.company_data['product_delivery_cost'])
|
||||
|
||||
self.assertTrue(sale_order_line5, "A new sale line should have been created with ordered product")
|
||||
self.assertTrue(sale_order_line6, "A new sale line should have been created with delivered product")
|
||||
@@ -113,8 +107,8 @@ class TestReInvoice(TestCommonSaleNoChart):
|
||||
self.assertEqual(len(self.sale_order.order_line), 6, "There should be still 4 lines on the SO, no new created")
|
||||
self.assertEqual(len(self.sale_order.order_line.filtered(lambda sol: sol.is_expense)), 4, "There should be still 2 expenses lines on the SO")
|
||||
|
||||
self.assertEqual((sale_order_line5.price_unit, sale_order_line5.qty_delivered, sale_order_line5.product_uom_qty, sale_order_line5.qty_invoiced), (self.product_ordered_cost.standard_price, 2, 0, 0), 'Sale line 5 is wrong after confirming 2e vendor invoice')
|
||||
self.assertEqual((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line6.product_uom_qty, sale_order_line6.qty_invoiced), (self.product_deliver_cost.standard_price, 2, 0, 0), 'Sale line 6 is wrong after confirming 2e vendor invoice')
|
||||
self.assertEqual((sale_order_line5.price_unit, sale_order_line5.qty_delivered, sale_order_line5.product_uom_qty, sale_order_line5.qty_invoiced), (self.company_data['product_order_cost'].standard_price, 2, 0, 0), 'Sale line 5 is wrong after confirming 2e vendor invoice')
|
||||
self.assertEqual((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line6.product_uom_qty, sale_order_line6.qty_invoiced), (self.company_data['product_delivery_cost'].standard_price, 2, 0, 0), 'Sale line 6 is wrong after confirming 2e vendor invoice')
|
||||
|
||||
def test_sales_price(self):
|
||||
""" Test invoicing vendor bill at sales price for products based on delivered and ordered quantities. Check no existing SO line is incremented, but when invoicing a
|
||||
@@ -122,22 +116,22 @@ class TestReInvoice(TestCommonSaleNoChart):
|
||||
"""
|
||||
# create SO line and confirm SO (with only one line)
|
||||
sale_order_line1 = self.env['sale.order.line'].create({
|
||||
'name': self.product_deliver_sales_price.name,
|
||||
'product_id': self.product_deliver_sales_price.id,
|
||||
'name': self.company_data['product_delivery_sales_price'].name,
|
||||
'product_id': self.company_data['product_delivery_sales_price'].id,
|
||||
'product_uom_qty': 2,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.product_deliver_sales_price.uom_id.id,
|
||||
'price_unit': self.product_deliver_sales_price.list_price,
|
||||
'product_uom': self.company_data['product_delivery_sales_price'].uom_id.id,
|
||||
'price_unit': self.company_data['product_delivery_sales_price'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
sale_order_line1.product_id_change()
|
||||
sale_order_line2 = self.env['sale.order.line'].create({
|
||||
'name': self.product_order_sales_price.name,
|
||||
'product_id': self.product_order_sales_price.id,
|
||||
'name': self.company_data['product_order_sales_price'].name,
|
||||
'product_id': self.company_data['product_order_sales_price'].id,
|
||||
'product_uom_qty': 3,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.product_order_sales_price.uom_id.id,
|
||||
'price_unit': self.product_order_sales_price.list_price,
|
||||
'product_uom': self.company_data['product_order_sales_price'].uom_id.id,
|
||||
'price_unit': self.company_data['product_order_sales_price'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
sale_order_line2.product_id_change()
|
||||
@@ -146,51 +140,48 @@ class TestReInvoice(TestCommonSaleNoChart):
|
||||
|
||||
# create invoice lines and validate it
|
||||
move_form = Form(self.AccountMove)
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_deliver_sales_price
|
||||
line_form.product_id = self.company_data['product_delivery_sales_price']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_order_sales_price
|
||||
line_form.product_id = self.company_data['product_order_sales_price']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_a = move_form.save()
|
||||
invoice_a.post()
|
||||
|
||||
sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.product_deliver_sales_price)
|
||||
sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.product_order_sales_price)
|
||||
sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.company_data['product_delivery_sales_price'])
|
||||
sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.company_data['product_order_sales_price'])
|
||||
|
||||
self.assertTrue(sale_order_line3, "A new sale line should have been created with ordered product")
|
||||
self.assertTrue(sale_order_line4, "A new sale line should have been created with delivered product")
|
||||
self.assertEqual(len(self.sale_order.order_line), 4, "There should be 4 lines on the SO (2 vendor bill lines created)")
|
||||
self.assertEqual(len(self.sale_order.order_line.filtered(lambda sol: sol.is_expense)), 2, "There should be 4 lines on the SO (2 vendor bill lines created)")
|
||||
|
||||
self.assertEqual(sale_order_line1.qty_delivered, 1, "Exising SO line 1 should not be impacted by reinvoicing product at cost")
|
||||
self.assertEqual(sale_order_line2.qty_delivered, 1, "Exising SO line 2 should not be impacted by reinvoicing product at cost")
|
||||
|
||||
self.assertEqual((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.product_deliver_sales_price.list_price, 3, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.product_order_sales_price.list_price, 3, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.company_data['product_delivery_sales_price'].list_price, 3, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.company_data['product_order_sales_price'].list_price, 3, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
|
||||
self.assertEqual(sale_order_line3.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line 3 should be computed by analytic amount")
|
||||
self.assertEqual(sale_order_line4.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line 4 should be computed by analytic amount")
|
||||
|
||||
# create second invoice lines and validate it
|
||||
move_form = Form(self.AccountMove)
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_deliver_sales_price
|
||||
line_form.product_id = self.company_data['product_delivery_sales_price']
|
||||
line_form.quantity = 2.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_order_sales_price
|
||||
line_form.product_id = self.company_data['product_order_sales_price']
|
||||
line_form.quantity = 2.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_b = move_form.save()
|
||||
invoice_b.post()
|
||||
|
||||
sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.product_deliver_sales_price)
|
||||
sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.product_order_sales_price)
|
||||
sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.company_data['product_delivery_sales_price'])
|
||||
sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.company_data['product_order_sales_price'])
|
||||
|
||||
self.assertFalse(sale_order_line5, "No new sale line should have been created with delivered product !!")
|
||||
self.assertTrue(sale_order_line6, "A new sale line should have been created with ordered product")
|
||||
@@ -198,18 +189,18 @@ class TestReInvoice(TestCommonSaleNoChart):
|
||||
self.assertEqual(len(self.sale_order.order_line), 5, "There should be 5 lines on the SO, 1 new created and 1 incremented")
|
||||
self.assertEqual(len(self.sale_order.order_line.filtered(lambda sol: sol.is_expense)), 3, "There should be 3 expenses lines on the SO")
|
||||
|
||||
self.assertEqual((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line6.qty_invoiced), (self.product_order_sales_price.list_price, 2, 0, 0), 'Sale line is wrong after confirming 2e vendor invoice')
|
||||
self.assertEqual((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line6.qty_invoiced), (self.company_data['product_order_sales_price'].list_price, 2, 0, 0), 'Sale line is wrong after confirming 2e vendor invoice')
|
||||
|
||||
def test_no_expense(self):
|
||||
""" Test invoicing vendor bill with no policy. Check nothing happen. """
|
||||
# confirm SO
|
||||
sale_order_line = self.env['sale.order.line'].create({
|
||||
'name': self.product_no_expense.name,
|
||||
'product_id': self.product_no_expense.id,
|
||||
'name': self.company_data['product_delivery_no'].name,
|
||||
'product_id': self.company_data['product_delivery_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.product_no_expense.uom_id.id,
|
||||
'price_unit': self.product_no_expense.list_price,
|
||||
'product_uom': self.company_data['product_delivery_no'].uom_id.id,
|
||||
'price_unit': self.company_data['product_delivery_no'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
self.sale_order._compute_tax_id()
|
||||
@@ -217,15 +208,13 @@ class TestReInvoice(TestCommonSaleNoChart):
|
||||
|
||||
# create invoice lines and validate it
|
||||
move_form = Form(self.AccountMove)
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.journal_id = self.journal_purchase
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_no_expense
|
||||
line_form.product_id = self.company_data['product_delivery_no']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_a = move_form.save()
|
||||
invoice_a.post()
|
||||
|
||||
self.assertEqual(len(self.sale_order.order_line), 1, "No SO line should have been created (or removed) when validating vendor bill")
|
||||
self.assertEqual(sale_order_line.qty_delivered, 1, "The delivered quantity of SO line should not have been incremented")
|
||||
self.assertTrue(invoice_a.mapped('line_ids.analytic_line_ids'), "Analytic lines should be generated")
|
||||
|
||||
@@ -1,416 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from collections import OrderedDict
|
||||
from odoo.addons.account.tests.common import AccountTestCommon
|
||||
from odoo.addons.account.tests.common import AccountTestNoChartCommon, AccountTestNoChartCommonMultiCompany
|
||||
|
||||
class TestSaleCommon(AccountTestCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleCommon, cls).setUpClass()
|
||||
# some users
|
||||
group_manager = cls.env.ref('sales_team.group_sale_manager')
|
||||
group_user = cls.env.ref('sales_team.group_sale_salesman')
|
||||
cls.manager = cls.env['res.users'].create({
|
||||
'name': 'Andrew Manager',
|
||||
'login': 'manager',
|
||||
'email': 'a.m@example.com',
|
||||
'signature': '--\nAndreww',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [group_manager.id, cls.env.ref('base.group_user').id])]
|
||||
})
|
||||
cls.user = cls.env['res.users'].create({
|
||||
'name': 'Mark User',
|
||||
'login': 'user',
|
||||
'email': 'm.u@example.com',
|
||||
'signature': '--\nMark',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [group_user.id])]
|
||||
})
|
||||
# create quotation with differend kinds of products (all possible combinations)
|
||||
service_delivery = cls.env['product.product'].create({
|
||||
'name': 'Cost-plus Contract',
|
||||
# 'categ_id': cls.env.ref('product.product_category_5').id,
|
||||
'categ_id': cls.env.ref('product.product_category_all').id,
|
||||
'standard_price': 200.0,
|
||||
'list_price': 180.0,
|
||||
'type': 'service',
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'SERV_DEL',
|
||||
'invoice_policy': 'delivery',
|
||||
})
|
||||
service_order_01 = cls.env['product.product'].create({
|
||||
'name': 'Remodeling Service',
|
||||
'categ_id': cls.env.ref('product.product_category_all').id,
|
||||
'standard_price': 40.0,
|
||||
'list_price': 90.0,
|
||||
'type': 'service',
|
||||
'uom_id': cls.env.ref('uom.product_uom_hour').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_hour').id,
|
||||
'description': 'Example of product to invoice on order',
|
||||
'default_code': 'PRE-PAID',
|
||||
'invoice_policy': 'order',
|
||||
})
|
||||
product_order_01 = cls.env['product.product'].create({
|
||||
'name': 'Office Design Software',
|
||||
'categ_id': cls.env.ref('product.product_category_all').id,
|
||||
'standard_price': 235.0,
|
||||
'list_price': 280.0,
|
||||
'type': 'consu', # Will be changed in 'product' in sale_stock
|
||||
'weight': 0.01,
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'FURN_9999',
|
||||
'invoice_policy': 'order',
|
||||
})
|
||||
product_delivery_01 = cls.env['product.product'].create({
|
||||
'name': 'Office Chair',
|
||||
'categ_id': cls.env.ref('product.product_category_all').id,
|
||||
'standard_price': 55.0,
|
||||
'list_price': 70.0,
|
||||
'type': 'consu', # Will be changed in 'product' in sale_stock
|
||||
'weight': 0.01,
|
||||
'uom_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'uom_po_id': cls.env.ref('uom.product_uom_unit').id,
|
||||
'default_code': 'FURN_7777',
|
||||
'invoice_policy': 'delivery',
|
||||
})
|
||||
cls.products = OrderedDict([
|
||||
('prod_order', product_order_01),
|
||||
('serv_del', service_delivery),
|
||||
('serv_order', service_order_01),
|
||||
('prod_del', product_delivery_01),
|
||||
])
|
||||
|
||||
cls.partner = cls.env['res.partner'].create({'name': 'A test Partner'})
|
||||
|
||||
|
||||
class TestCommonSaleNoChart(AccountTestNoChartCommon):
|
||||
""" This class should be extended for test suite of sale flows with a minimal chart of accounting
|
||||
installed. This test suite should be executed at module installation.
|
||||
This class provides some method to generate testing data well configured, according to the minimal
|
||||
chart of account, defined in `AccountTestNoChartCommon` class.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestCommonSaleNoChart, cls).setUpClass()
|
||||
|
||||
# create a pricelist
|
||||
cls.pricelist_usd = cls.env['product.pricelist'].create({
|
||||
'name': 'USD pricelist',
|
||||
'active': True,
|
||||
'currency_id': cls.env.ref('base.USD').id,
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def setUpClassicProducts(cls):
|
||||
# Create an expense journal
|
||||
user_type_income = cls.env.ref('account.data_account_type_direct_costs')
|
||||
cls.account_income_product = cls.env['account.account'].create({
|
||||
'code': 'INCOME_PROD111',
|
||||
'name': 'Icome - Test Account',
|
||||
'user_type_id': user_type_income.id,
|
||||
})
|
||||
# Create category
|
||||
cls.product_category = cls.env['product.category'].create({
|
||||
'name': 'Product Category with Income account',
|
||||
'property_account_income_categ_id': cls.account_income_product.id
|
||||
})
|
||||
# Products
|
||||
uom_unit = cls.env.ref('uom.product_uom_unit')
|
||||
uom_hour = cls.env.ref('uom.product_uom_hour')
|
||||
cls.product_order = cls.env['product.product'].create({
|
||||
'name': "Zed+ Antivirus",
|
||||
'standard_price': 235.0,
|
||||
'list_price': 280.0,
|
||||
'type': 'consu',
|
||||
'uom_id': uom_unit.id,
|
||||
'uom_po_id': uom_unit.id,
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'PROD_ORDER',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'categ_id': cls.product_category.id,
|
||||
})
|
||||
cls.service_deliver = cls.env['product.product'].create({
|
||||
'name': "Cost-plus Contract",
|
||||
'standard_price': 200.0,
|
||||
'list_price': 180.0,
|
||||
'type': 'service',
|
||||
'uom_id': uom_unit.id,
|
||||
'uom_po_id': uom_unit.id,
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'SERV_DEL',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'categ_id': cls.product_category.id,
|
||||
})
|
||||
cls.service_order = cls.env['product.product'].create({
|
||||
'name': "Prepaid Consulting",
|
||||
'standard_price': 40.0,
|
||||
'list_price': 90.0,
|
||||
'type': 'service',
|
||||
'uom_id': uom_hour.id,
|
||||
'uom_po_id': uom_hour.id,
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'PRE-PAID',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'categ_id': cls.product_category.id,
|
||||
})
|
||||
cls.product_deliver = cls.env['product.product'].create({
|
||||
'name': "Switch, 24 ports",
|
||||
'standard_price': 55.0,
|
||||
'list_price': 70.0,
|
||||
'type': 'consu',
|
||||
'uom_id': uom_unit.id,
|
||||
'uom_po_id': uom_unit.id,
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'PROD_DEL',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'categ_id': cls.product_category.id,
|
||||
})
|
||||
|
||||
cls.product_map = OrderedDict([
|
||||
('prod_order', cls.product_order),
|
||||
('serv_del', cls.service_deliver),
|
||||
('serv_order', cls.service_order),
|
||||
('prod_del', cls.product_deliver),
|
||||
])
|
||||
|
||||
@classmethod
|
||||
def setUpExpenseProducts(cls):
|
||||
# Create an expense journal
|
||||
user_type_expense = cls.env.ref('account.data_account_type_expenses')
|
||||
cls.account_expense_for_products = cls.env['account.account'].create({
|
||||
'code': 'EXP_PROD13',
|
||||
'name': 'Expense - Test Purchase Account',
|
||||
'user_type_id': user_type_expense.id
|
||||
})
|
||||
# Expense Products
|
||||
cls.product_ordered_cost = cls.env['product.product'].create({
|
||||
'name': "Ordered at cost",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'cost',
|
||||
'default_code': 'CONSU-ORDERED1',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_for_products.id,
|
||||
})
|
||||
|
||||
cls.product_deliver_cost = cls.env['product.product'].create({
|
||||
'name': "Delivered at cost",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'cost',
|
||||
'default_code': 'CONSU-DELI1',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_for_products.id,
|
||||
})
|
||||
|
||||
cls.product_order_sales_price = cls.env['product.product'].create({
|
||||
'name': "Ordered at sales price",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'sales_price',
|
||||
'default_code': 'CONSU-ORDERED2',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_for_products.id,
|
||||
})
|
||||
|
||||
cls.product_deliver_sales_price = cls.env['product.product'].create({
|
||||
'name': "Delivered at sales price",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'sales_price',
|
||||
'default_code': 'CONSU-DELI2',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_for_products.id,
|
||||
})
|
||||
|
||||
cls.product_no_expense = cls.env['product.product'].create({
|
||||
'name': "No expense",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'CONSU-NO',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_for_products.id,
|
||||
})
|
||||
|
||||
|
||||
class TestCommonSaleMultiCompanyNoChart(AccountTestNoChartCommonMultiCompany, TestCommonSaleNoChart):
|
||||
""" This class should be extended for test suite of sale flows with a minimal chart of accounting
|
||||
installed. This test suite should be executed at module installation.
|
||||
This class provides some method to generate testing data well configured, according to the minimal
|
||||
chart of account, defined in `TestAccountNoChartCommon` class.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestCommonSaleMultiCompanyNoChart, cls).setUpClass()
|
||||
cls.setUpAdditionalAccounts()
|
||||
|
||||
@classmethod
|
||||
def setUpClassicProducts(cls):
|
||||
super(TestCommonSaleMultiCompanyNoChart, cls).setUpClassicProducts()
|
||||
# Create an expense journal
|
||||
user_type_income = cls.env.ref('account.data_account_type_direct_costs')
|
||||
cls.account_income_product_company_B = cls.env['account.account'].create({
|
||||
'code': 'INCOME_PROD111',
|
||||
'name': 'Income - Test Account Company B',
|
||||
'user_type_id': user_type_income.id,
|
||||
'company_id': cls.company_B.id,
|
||||
})
|
||||
# Create category
|
||||
cls.product_category_company_B = cls.env['product.category'].create({
|
||||
'name': 'Product Category with Income account Company B',
|
||||
'property_account_income_categ_id': cls.account_income_product_company_B.id
|
||||
})
|
||||
# Products
|
||||
uom_unit = cls.env.ref('uom.product_uom_unit')
|
||||
uom_hour = cls.env.ref('uom.product_uom_hour')
|
||||
|
||||
cls.product_order_company_B = cls.env['product.product'].create({
|
||||
'name': "Pigeon pie",
|
||||
'standard_price': 235.0,
|
||||
'list_price': 280.0,
|
||||
'type': 'consu',
|
||||
'uom_id': uom_unit.id,
|
||||
'uom_po_id': uom_unit.id,
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'PROD_ORDER',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'categ_id': cls.product_category_company_B.id,
|
||||
})
|
||||
|
||||
cls.service_deliver_company_B = cls.env['product.product'].create({
|
||||
'name': "Golden Company Contract",
|
||||
'standard_price': 200.0,
|
||||
'list_price': 180.0,
|
||||
'type': 'service',
|
||||
'uom_id': uom_unit.id,
|
||||
'uom_po_id': uom_unit.id,
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'SERV_DEL',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'categ_id': cls.product_category_company_B.id,
|
||||
})
|
||||
|
||||
cls.service_order_company_B = cls.env['product.product'].create({
|
||||
'name': "Maester Consulting",
|
||||
'standard_price': 40.0,
|
||||
'list_price': 90.0,
|
||||
'type': 'service',
|
||||
'uom_id': uom_hour.id,
|
||||
'uom_po_id': uom_hour.id,
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'PRE-PAID',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'categ_id': cls.product_category_company_B.id,
|
||||
})
|
||||
|
||||
cls.product_deliver_company_B = cls.env['product.product'].create({
|
||||
'name': "Swords",
|
||||
'standard_price': 55.0,
|
||||
'list_price': 70.0,
|
||||
'type': 'consu',
|
||||
'uom_id': uom_unit.id,
|
||||
'uom_po_id': uom_unit.id,
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'no',
|
||||
'default_code': 'PROD_DEL',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'categ_id': cls.product_category_company_B.id,
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def setUpExpenseProducts(cls):
|
||||
super(TestCommonSaleMultiCompanyNoChart, cls).setUpExpenseProducts()
|
||||
cls.product_ordered_cost_company_B = cls.env['product.product'].create({
|
||||
'name': "Ordered at cost",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'cost',
|
||||
'default_code': 'CONSU-ORDERED1',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_company_B.id,
|
||||
'company_id': cls.company_B.id,
|
||||
})
|
||||
|
||||
cls.product_deliver_cost_company_B = cls.env['product.product'].create({
|
||||
'name': "Delivered at cost",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'cost',
|
||||
'default_code': 'CONSU-DELI1',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_company_B.id,
|
||||
'company_id': cls.company_B.id,
|
||||
})
|
||||
|
||||
cls.product_order_sales_price_company_B = cls.env['product.product'].create({
|
||||
'name': "Ordered at sales price",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'order',
|
||||
'expense_policy': 'sales_price',
|
||||
'default_code': 'CONSU-ORDERED2',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_company_B.id,
|
||||
'company_id': cls.company_B.id,
|
||||
})
|
||||
|
||||
cls.product_deliver_sales_price_company_B = cls.env['product.product'].create({
|
||||
'name': "Delivered at sales price",
|
||||
'standard_price': 8,
|
||||
'list_price': 10,
|
||||
'type': 'consu',
|
||||
'invoice_policy': 'delivery',
|
||||
'expense_policy': 'sales_price',
|
||||
'default_code': 'CONSU-DELI2',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_expense_id': cls.account_expense_company_B.id,
|
||||
'company_id': cls.company_B.id,
|
||||
})
|
||||
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from odoo.addons.sale.tests.common import TestSaleCommonBase
|
||||
|
||||
|
||||
class TestSaleFlow(TestSaleCommonBase):
|
||||
''' Test running at-install to test flows independently to other modules, e.g. 'sale_stock'. '''
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
user = cls.env['res.users'].create({
|
||||
'name': 'Because I am saleman!',
|
||||
'login': 'saleman',
|
||||
'groups_id': [(6, 0, cls.env.user.groups_id.ids), (4, cls.env.ref('account.group_account_user').id)],
|
||||
})
|
||||
user.partner_id.email = 'saleman@test.com'
|
||||
|
||||
# Shadow the current environment/cursor with the newly created user.
|
||||
cls.env = cls.env(user=user)
|
||||
cls.cr = cls.env.cr
|
||||
|
||||
cls.company = cls.env['res.company'].create({
|
||||
'name': 'Test Company',
|
||||
'currency_id': cls.env.ref('base.USD').id,
|
||||
})
|
||||
cls.company_data = cls.setup_sale_configuration_for_company(cls.company)
|
||||
|
||||
cls.partner_a = cls.env['res.partner'].create({
|
||||
'name': 'partner_a',
|
||||
'company_id': False,
|
||||
})
|
||||
|
||||
cls.analytic_account = cls.env['account.analytic.account'].create({
|
||||
'name': 'Test analytic_account',
|
||||
'code': 'analytic_account',
|
||||
'company_id': cls.company.id,
|
||||
'partner_id': cls.partner_a.id
|
||||
})
|
||||
|
||||
user.company_ids |= cls.company
|
||||
user.company_id = cls.company
|
||||
|
||||
def test_qty_delivered(self):
|
||||
''' Test 'qty_delivered' at-install to avoid a change in the behavior when 'sale_stock' is installed. '''
|
||||
|
||||
sale_order = self.env['sale.order'].with_context(mail_notrack=True, mail_create_nolog=True).create({
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'analytic_account_id': self.analytic_account.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': self.company_data['product_order_cost'].name,
|
||||
'product_id': self.company_data['product_order_cost'].id,
|
||||
'product_uom_qty': 2,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.company_data['product_order_cost'].uom_id.id,
|
||||
'price_unit': self.company_data['product_order_cost'].list_price,
|
||||
}),
|
||||
(0, 0, {
|
||||
'name': self.company_data['product_delivery_cost'].name,
|
||||
'product_id': self.company_data['product_delivery_cost'].id,
|
||||
'product_uom_qty': 4,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.company_data['product_delivery_cost'].uom_id.id,
|
||||
'price_unit': self.company_data['product_delivery_cost'].list_price,
|
||||
}),
|
||||
],
|
||||
})
|
||||
for line in sale_order.order_line:
|
||||
line.product_id_change()
|
||||
|
||||
sale_order.onchange_partner_id()
|
||||
sale_order._compute_tax_id()
|
||||
sale_order.action_confirm()
|
||||
|
||||
self.assertRecordValues(sale_order.order_line, [
|
||||
{'qty_delivered': 1.0},
|
||||
{'qty_delivered': 1.0},
|
||||
])
|
||||
@@ -1,75 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
import odoo
|
||||
from odoo.exceptions import UserError, AccessError
|
||||
from odoo.tests import Form
|
||||
from odoo.tests import Form, tagged
|
||||
from odoo.tools import float_compare
|
||||
|
||||
from .test_sale_common import TestCommonSaleNoChart
|
||||
from .common import TestSaleCommon
|
||||
|
||||
|
||||
class TestSaleOrder(TestCommonSaleNoChart):
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSaleOrder(TestSaleCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleOrder, cls).setUpClass()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
SaleOrder = cls.env['sale.order'].with_context(tracking_disable=True)
|
||||
|
||||
# set up users
|
||||
cls.setUpUsers()
|
||||
group_salemanager = cls.env.ref('sales_team.group_sale_manager')
|
||||
group_salesman = cls.env.ref('sales_team.group_sale_salesman')
|
||||
group_employee = cls.env.ref('base.group_user')
|
||||
cls.user_manager.write({'groups_id': [(6, 0, [group_salemanager.id, group_employee.id])]})
|
||||
cls.user_employee.write({'groups_id': [(6, 0, [group_salesman.id, group_employee.id])]})
|
||||
|
||||
# set up accounts and products and journals
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpClassicProducts()
|
||||
cls.setUpAccountJournal()
|
||||
|
||||
# create a generic Sale Order with all classical products and empty pricelist
|
||||
cls.sale_order = SaleOrder.create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'pricelist_id': cls.pricelist_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
cls.sol_product_order = cls.env['sale.order.line'].create({
|
||||
'name': cls.product_order.name,
|
||||
'product_id': cls.product_order.id,
|
||||
'name': cls.company_data['product_order_no'].name,
|
||||
'product_id': cls.company_data['product_order_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.product_order.uom_id.id,
|
||||
'price_unit': cls.product_order.list_price,
|
||||
'product_uom': cls.company_data['product_order_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_order_no'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_serv_deliver = cls.env['sale.order.line'].create({
|
||||
'name': cls.service_deliver.name,
|
||||
'product_id': cls.service_deliver.id,
|
||||
'name': cls.company_data['product_service_delivery'].name,
|
||||
'product_id': cls.company_data['product_service_delivery'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.service_deliver.uom_id.id,
|
||||
'price_unit': cls.service_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_service_delivery'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_delivery'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_serv_order = cls.env['sale.order.line'].create({
|
||||
'name': cls.service_order.name,
|
||||
'product_id': cls.service_order.id,
|
||||
'name': cls.company_data['product_service_order'].name,
|
||||
'product_id': cls.company_data['product_service_order'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.service_order.uom_id.id,
|
||||
'price_unit': cls.service_order.list_price,
|
||||
'product_uom': cls.company_data['product_service_order'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_order'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_product_deliver = cls.env['sale.order.line'].create({
|
||||
'name': cls.product_deliver.name,
|
||||
'product_id': cls.product_deliver.id,
|
||||
'name': cls.company_data['product_delivery_no'].name,
|
||||
'product_id': cls.company_data['product_delivery_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.product_deliver.uom_id.id,
|
||||
'price_unit': cls.product_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_delivery_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_delivery_no'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
@@ -81,7 +67,7 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
# DBO TODO: validate invoice and register payments
|
||||
self.sale_order.order_line.read(['name', 'price_unit', 'product_uom_qty', 'price_total'])
|
||||
|
||||
self.assertEqual(self.sale_order.amount_total, sum([2 * p.list_price for p in self.product_map.values()]), 'Sale: total amount is wrong')
|
||||
self.assertEqual(self.sale_order.amount_total, 1240.0, 'Sale: total amount is wrong')
|
||||
self.sale_order.order_line._compute_product_updatable()
|
||||
self.assertTrue(self.sale_order.order_line[0].product_updatable)
|
||||
# send quotation
|
||||
@@ -100,7 +86,7 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
# create invoice: only 'invoice on order' products are invoiced
|
||||
invoice = self.sale_order._create_invoices()
|
||||
self.assertEqual(len(invoice.invoice_line_ids), 2, 'Sale: invoice is missing lines')
|
||||
self.assertEqual(invoice.amount_total, sum([2 * p.list_price if p.invoice_policy == 'order' else 0 for p in self.product_map.values()]), 'Sale: invoice total amount is wrong')
|
||||
self.assertEqual(invoice.amount_total, 740.0, 'Sale: invoice total amount is wrong')
|
||||
self.assertTrue(self.sale_order.invoice_status == 'no', 'Sale: SO status after invoicing should be "nothing to invoice"')
|
||||
self.assertTrue(len(self.sale_order.invoice_ids) == 1, 'Sale: invoice is missing')
|
||||
self.sale_order.order_line._compute_product_updatable()
|
||||
@@ -112,7 +98,7 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
self.assertTrue(self.sale_order.invoice_status == 'to invoice', 'Sale: SO status after delivery should be "to invoice"')
|
||||
invoice2 = self.sale_order._create_invoices()
|
||||
self.assertEqual(len(invoice2.invoice_line_ids), 2, 'Sale: second invoice is missing lines')
|
||||
self.assertEqual(invoice2.amount_total, sum([2 * p.list_price if p.invoice_policy == 'delivery' else 0 for p in self.product_map.values()]), 'Sale: second invoice total amount is wrong')
|
||||
self.assertEqual(invoice2.amount_total, 500.0, 'Sale: second invoice total amount is wrong')
|
||||
self.assertTrue(self.sale_order.invoice_status == 'invoiced', 'Sale: SO status after invoicing everything should be "invoiced"')
|
||||
self.assertTrue(len(self.sale_order.invoice_ids) == 2, 'Sale: invoice is missing')
|
||||
|
||||
@@ -137,7 +123,7 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
|
||||
invoice3 = self.sale_order._create_invoices()
|
||||
self.assertEqual(len(invoice3.invoice_line_ids), 1, 'Sale: third invoice is missing lines')
|
||||
self.assertEqual(invoice3.amount_total, 8 * self.product_map['serv_order'].list_price, 'Sale: second invoice total amount is wrong')
|
||||
self.assertEqual(invoice3.amount_total, 720.0, 'Sale: second invoice total amount is wrong')
|
||||
self.assertTrue(self.sale_order.invoice_status == 'invoiced', 'Sale: SO status after invoicing everything (including the upsel) should be "invoiced"')
|
||||
|
||||
def test_sale_sequence(self):
|
||||
@@ -159,8 +145,8 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
# SO in state 'draft' can be deleted
|
||||
so_copy = self.sale_order.copy()
|
||||
with self.assertRaises(AccessError):
|
||||
so_copy.with_user(self.user_employee).unlink()
|
||||
self.assertTrue(so_copy.with_user(self.user_manager).unlink(), 'Sale: deleting a quotation should be possible')
|
||||
so_copy.with_user(self.company_data['default_user_employee']).unlink()
|
||||
self.assertTrue(so_copy.unlink(), 'Sale: deleting a quotation should be possible')
|
||||
|
||||
# SO in state 'cancel' can be deleted
|
||||
so_copy = self.sale_order.copy()
|
||||
@@ -169,25 +155,22 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
so_copy.action_cancel()
|
||||
self.assertTrue(so_copy.state == 'cancel', 'Sale: SO should be in state "cancel"')
|
||||
with self.assertRaises(AccessError):
|
||||
so_copy.with_user(self.user_employee).unlink()
|
||||
self.assertTrue(so_copy.with_user(self.user_manager).unlink(), 'Sale: deleting a cancelled SO should be possible')
|
||||
so_copy.with_user(self.company_data['default_user_employee']).unlink()
|
||||
self.assertTrue(so_copy.unlink(), 'Sale: deleting a cancelled SO should be possible')
|
||||
|
||||
# SO in state 'sale' or 'done' cannot be deleted
|
||||
self.sale_order.action_confirm()
|
||||
self.assertTrue(self.sale_order.state == 'sale', 'Sale: SO should be in state "sale"')
|
||||
with self.assertRaises(UserError):
|
||||
self.sale_order.with_user(self.user_manager).unlink()
|
||||
self.sale_order.unlink()
|
||||
|
||||
self.sale_order.action_done()
|
||||
self.assertTrue(self.sale_order.state == 'done', 'Sale: SO should be in state "done"')
|
||||
with self.assertRaises(UserError):
|
||||
self.sale_order.with_user(self.user_manager).unlink()
|
||||
self.sale_order.unlink()
|
||||
|
||||
def test_cost_invoicing(self):
|
||||
""" Test confirming a vendor invoice to reinvoice cost on the so """
|
||||
# force the pricelist to have the same currency as the company
|
||||
self.pricelist_usd.currency_id = self.env.ref('base.main_company').currency_id
|
||||
|
||||
serv_cost = self.env['product.product'].create({
|
||||
'name': "Ordered at cost",
|
||||
'standard_price': 160,
|
||||
@@ -198,19 +181,19 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
'default_code': 'PROD_COST',
|
||||
'service_type': 'manual',
|
||||
})
|
||||
prod_gap = self.service_order
|
||||
prod_gap = self.company_data['product_service_order']
|
||||
so = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_invoice_id': self.partner_customer_usd.id,
|
||||
'partner_shipping_id': self.partner_customer_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'order_line': [(0, 0, {'name': prod_gap.name, 'product_id': prod_gap.id, 'product_uom_qty': 2, 'product_uom': prod_gap.uom_id.id, 'price_unit': prod_gap.list_price})],
|
||||
'pricelist_id': self.pricelist_usd.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
})
|
||||
so.action_confirm()
|
||||
so._create_analytic_account()
|
||||
|
||||
inv = self.env['account.move'].with_context(default_move_type='in_invoice').create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'invoice_line_ids': [
|
||||
(0, 0, {
|
||||
'name': serv_cost.name,
|
||||
@@ -268,66 +251,32 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
"""Check that only taxes of the right company are applied on the lines."""
|
||||
|
||||
# Preparing test Data
|
||||
company_1 = self.env.ref('base.main_company')
|
||||
company_2 = self.env['res.company'].create({
|
||||
'name': 'company 2',
|
||||
'parent_id': company_1.id,
|
||||
})
|
||||
|
||||
user_demo = self.env['res.users'].create({
|
||||
'login': 'zizizmyuser',
|
||||
'password': 'zizizmyuser',
|
||||
'email': 'test@test.com',
|
||||
'partner_id': self.env['res.partner'].create({'name': 'Zizizmypartner'}).id,
|
||||
'company_ids': [(6, False, [company_1.id])],
|
||||
'company_id': company_1.id,
|
||||
'groups_id': [(6, 0, [
|
||||
self.env.ref('base.group_user').id,
|
||||
self.env.ref('base.group_partner_manager').id,
|
||||
self.env.ref('sales_team.group_sale_manager').id])]})
|
||||
|
||||
user_demo.company_ids = (company_1 | company_2).ids
|
||||
so_partner = self.env['res.partner'].create({'name': 'SO Partner'})
|
||||
so_partner.write({
|
||||
'property_account_position_id': False,
|
||||
})
|
||||
|
||||
tax_company_1 = self.env['account.tax'].create({
|
||||
'name': 'T1',
|
||||
'amount': 90,
|
||||
'company_id': company_1.id,
|
||||
})
|
||||
|
||||
tax_company_2 = self.env['account.tax'].create({
|
||||
'name': 'T2',
|
||||
'amount': 90,
|
||||
'company_id': company_2.id,
|
||||
})
|
||||
|
||||
product_shared = self.env['product.template'].create({
|
||||
'name': 'shared product',
|
||||
'invoice_policy': 'order',
|
||||
'taxes_id': [(6, False, [tax_company_1.id, tax_company_2.id])],
|
||||
'property_account_income_id': self.account_receivable.id,
|
||||
'taxes_id': [(6, False, (self.company_data['default_tax_sale'] + self.company_data_2['default_tax_sale']).ids)],
|
||||
'property_account_income_id': self.company_data['default_account_revenue'].id,
|
||||
})
|
||||
|
||||
so_1 = self.env['sale.order'].with_user(user_demo.id).create({
|
||||
so_1 = self.env['sale.order'].with_user(self.company_data['default_user_salesman']).create({
|
||||
'partner_id': self.env['res.partner'].create({'name': 'A partner'}).id,
|
||||
'company_id': company_1.id,
|
||||
'company_id': self.company_data['company'].id,
|
||||
})
|
||||
so_1.write({
|
||||
'order_line': [(0, False, {'product_id': product_shared.product_variant_id.id, 'order_id': so_1.id})],
|
||||
})
|
||||
|
||||
self.assertEqual(set(so_1.order_line.tax_id.ids), set([tax_company_1.id]),
|
||||
self.assertEqual(so_1.order_line.tax_id, self.company_data['default_tax_sale'],
|
||||
'Only taxes from the right company are put by default')
|
||||
so_1.action_confirm()
|
||||
# i'm not interested in groups/acls, but in the multi-company flow only
|
||||
# the sudo is there for that and does not impact the invoice that gets created
|
||||
# the goal here is to invoice in company 1 (because the order is in company 1) while being
|
||||
# 'mainly' in company 2 (through the context), the invoice should be in company 1
|
||||
inv=so_1.sudo().with_context(allowed_company_ids=[company_2.id, company_1.id])._create_invoices()
|
||||
self.assertEqual(inv.company_id, company_1, 'invoices should be created in the company of the SO, not the main company of the context')
|
||||
inv=so_1.sudo()\
|
||||
.with_context(allowed_company_ids=(self.company_data['company'] + self.company_data_2['company']).ids)\
|
||||
._create_invoices()
|
||||
self.assertEqual(inv.company_id, self.company_data['company'], 'invoices should be created in the company of the SO, not the main company of the context')
|
||||
|
||||
def test_group_invoice(self):
|
||||
""" Test that invoicing multiple sales order for the same customer works. """
|
||||
|
||||
@@ -1,61 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from .test_sale_common import TestCommonSaleNoChart
|
||||
from .common import TestSaleCommon
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
class TestSaleOrder(TestCommonSaleNoChart):
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSaleOrder(TestSaleCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleOrder, cls).setUpClass()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
Pricelist = cls.env['product.pricelist']
|
||||
PricelistItem = cls.env['product.pricelist.item']
|
||||
SaleOrder = cls.env['sale.order'].with_context(tracking_disable=True)
|
||||
SaleOrderLine = cls.env['sale.order.line'].with_context(tracking_disable=True)
|
||||
|
||||
# set up accounts and products and journals
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpClassicProducts()
|
||||
cls.setUpAccountJournal()
|
||||
|
||||
# Create a product category
|
||||
cls.product_category_1 = cls.env['product.category'].create({
|
||||
'name': 'Product Category for pricelist',
|
||||
})
|
||||
|
||||
# Create a pricelist with discount policy: percentage on services, fixed price for product_order
|
||||
cls.pricelist_discount_incl = Pricelist.create({
|
||||
'name': 'Pricelist A',
|
||||
'discount_policy': 'with_discount',
|
||||
'company_id': cls.company_data['company'].id,
|
||||
})
|
||||
PricelistItem.create({
|
||||
'pricelist_id': cls.pricelist_discount_incl.id,
|
||||
'applied_on': '1_product',
|
||||
'product_tmpl_id': cls.service_order.product_tmpl_id.id,
|
||||
'product_tmpl_id': cls.company_data['product_service_order'].product_tmpl_id.id,
|
||||
'compute_price': 'percentage',
|
||||
'percent_price': 10
|
||||
})
|
||||
PricelistItem.create({
|
||||
'pricelist_id': cls.pricelist_discount_incl.id,
|
||||
'applied_on': '1_product',
|
||||
'product_tmpl_id': cls.service_deliver.product_tmpl_id.id,
|
||||
'product_tmpl_id': cls.company_data['product_service_delivery'].product_tmpl_id.id,
|
||||
'compute_price': 'percentage',
|
||||
'percent_price': 20
|
||||
'percent_price': 20,
|
||||
})
|
||||
cls.pricelist_discount_incl_item3 = PricelistItem.create({
|
||||
'pricelist_id': cls.pricelist_discount_incl.id,
|
||||
'applied_on': '1_product',
|
||||
'product_tmpl_id': cls.product_order.product_tmpl_id.id,
|
||||
'product_tmpl_id': cls.company_data['product_order_no'].product_tmpl_id.id,
|
||||
'compute_price': 'fixed',
|
||||
'fixed_price': 211
|
||||
'fixed_price': 211,
|
||||
})
|
||||
|
||||
# Create a pricelist without discount policy: formula for product_category_1 category, percentage for service_order
|
||||
cls.pricelist_discount_excl = Pricelist.create({
|
||||
'name': 'Pricelist B',
|
||||
'discount_policy': 'without_discount',
|
||||
'company_id': cls.company_data['company'].id,
|
||||
})
|
||||
PricelistItem.create({
|
||||
'pricelist_id': cls.pricelist_discount_excl.id,
|
||||
@@ -63,70 +61,60 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
'categ_id': cls.product_category_1.id,
|
||||
'compute_price': 'formula',
|
||||
'base': 'standard_price',
|
||||
'price_discount': 10
|
||||
'price_discount': 10,
|
||||
})
|
||||
PricelistItem.create({
|
||||
'pricelist_id': cls.pricelist_discount_excl.id,
|
||||
'applied_on': '1_product',
|
||||
'product_tmpl_id': cls.service_order.product_tmpl_id.id,
|
||||
'product_tmpl_id': cls.company_data['product_service_order'].product_tmpl_id.id,
|
||||
'compute_price': 'percentage',
|
||||
'percent_price': 20
|
||||
'percent_price': 20,
|
||||
})
|
||||
|
||||
# create a generic Sale Order with all classical products and empty pricelist
|
||||
cls.sale_order = SaleOrder.create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'pricelist_id': cls.pricelist_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
cls.sol_product_order = SaleOrderLine.create({
|
||||
'name': cls.product_order.name,
|
||||
'product_id': cls.product_order.id,
|
||||
'name': cls.company_data['product_order_no'].name,
|
||||
'product_id': cls.company_data['product_order_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.product_order.uom_id.id,
|
||||
'price_unit': cls.product_order.list_price,
|
||||
'product_uom': cls.company_data['product_order_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_order_no'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_serv_deliver = SaleOrderLine.create({
|
||||
'name': cls.service_deliver.name,
|
||||
'product_id': cls.service_deliver.id,
|
||||
'name': cls.company_data['product_service_delivery'].name,
|
||||
'product_id': cls.company_data['product_service_delivery'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.service_deliver.uom_id.id,
|
||||
'price_unit': cls.service_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_service_delivery'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_delivery'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_serv_order = SaleOrderLine.create({
|
||||
'name': cls.service_order.name,
|
||||
'product_id': cls.service_order.id,
|
||||
'name': cls.company_data['product_service_order'].name,
|
||||
'product_id': cls.company_data['product_service_order'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.service_order.uom_id.id,
|
||||
'price_unit': cls.service_order.list_price,
|
||||
'product_uom': cls.company_data['product_service_order'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_order'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_prod_deliver = SaleOrderLine.create({
|
||||
'name': cls.product_deliver.name,
|
||||
'product_id': cls.product_deliver.id,
|
||||
'name': cls.company_data['product_delivery_no'].name,
|
||||
'product_id': cls.company_data['product_delivery_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.product_deliver.uom_id.id,
|
||||
'price_unit': cls.product_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_delivery_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_delivery_no'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
|
||||
def test_sale_with_pricelist_empty(self):
|
||||
# Trigger onchange to reset discount, unit price, subtotal, ...
|
||||
self.sale_order.onchange_partner_id()
|
||||
for line in self.sale_order.order_line:
|
||||
line.product_id_change()
|
||||
line._onchange_discount()
|
||||
# Check that pricelist of the SO has been applied on the sale order lines or not
|
||||
for line in self.sale_order.order_line:
|
||||
self.assertEqual(line.price_unit, line.product_id.list_price, 'Pricelist of the SO should not be applied on an order line %s' % (line.name,))
|
||||
|
||||
def test_sale_with_pricelist_discount_included(self):
|
||||
""" Test SO with the pricelist and check unit price appeared on its lines """
|
||||
# Change the pricelist
|
||||
@@ -137,7 +125,7 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
line._onchange_discount()
|
||||
# Check that pricelist of the SO has been applied on the sale order lines or not
|
||||
for line in self.sale_order.order_line:
|
||||
if line.product_id == self.product_order:
|
||||
if line.product_id == self.company_data['product_order_no']:
|
||||
self.assertEqual(line.price_unit, self.pricelist_discount_incl_item3.fixed_price, 'Price of product_order should be %s applied on the order line' % (self.pricelist_discount_incl_item3.fixed_price,))
|
||||
else: # only services (service_order and service_deliver)
|
||||
for item in self.sale_order.pricelist_id.item_ids.filtered(lambda l: l.product_tmpl_id == line.product_id.product_tmpl_id):
|
||||
@@ -150,8 +138,8 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
self.env.user.write({'groups_id': [(4, self.env.ref('product.group_discount_per_so_line').id)]})
|
||||
|
||||
# Set product category on consumable products (for the pricelist item applying on this category)
|
||||
self.product_order.write({'categ_id': self.product_category_1.id})
|
||||
self.product_deliver.write({'categ_id': self.product_category_1.id})
|
||||
self.company_data['product_order_no'].write({'categ_id': self.product_category_1.id})
|
||||
self.company_data['product_delivery_no'].write({'categ_id': self.product_category_1.id})
|
||||
|
||||
# Change the pricelist
|
||||
self.sale_order.write({'pricelist_id': self.pricelist_discount_excl.id})
|
||||
@@ -167,7 +155,7 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
self.assertEqual(line.discount, item.price_discount, "Discount should be displayed on order line %s since its category get some discount" % (line.name,))
|
||||
self.assertEqual(line.price_unit, line.product_id.standard_price, "Price unit should be the cost price for product %s" % (line.name,))
|
||||
else:
|
||||
if line.product_id == self.service_order: # reduction for this product
|
||||
if line.product_id == self.company_data['product_service_order']: # reduction for this product
|
||||
self.assertEqual(line.discount, 20.0, "Discount for product %s should be 20 percent with pricelist %s" % (line.name, self.pricelist_discount_excl.name))
|
||||
self.assertEqual(line.price_unit, line.product_id.list_price, 'Unit price of order line should be a sale price as the pricelist not applied on the other category\'s product')
|
||||
else: # no discount for the rest
|
||||
|
||||
@@ -1,61 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from .test_sale_common import TestCommonSaleNoChart
|
||||
from odoo.tests import Form
|
||||
from .common import TestSaleCommon
|
||||
from odoo.tests import Form, tagged
|
||||
|
||||
|
||||
class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSaleToInvoice(TestSaleCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleToInvoice, cls).setUpClass()
|
||||
|
||||
cls.setUpClassicProducts()
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpAccountJournal()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
# Create the SO with four order lines
|
||||
cls.sale_order = cls.env['sale.order'].with_context(tracking_disable=True).create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'pricelist_id': cls.pricelist_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
SaleOrderLine = cls.env['sale.order.line'].with_context(tracking_disable=True)
|
||||
cls.sol_prod_order = SaleOrderLine.create({
|
||||
'name': cls.product_order.name,
|
||||
'product_id': cls.product_order.id,
|
||||
'name': cls.company_data['product_order_no'].name,
|
||||
'product_id': cls.company_data['product_order_no'].id,
|
||||
'product_uom_qty': 5,
|
||||
'product_uom': cls.product_order.uom_id.id,
|
||||
'price_unit': cls.product_order.list_price,
|
||||
'product_uom': cls.company_data['product_order_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_order_no'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_serv_deliver = SaleOrderLine.create({
|
||||
'name': cls.service_deliver.name,
|
||||
'product_id': cls.service_deliver.id,
|
||||
'name': cls.company_data['product_service_delivery'].name,
|
||||
'product_id': cls.company_data['product_service_delivery'].id,
|
||||
'product_uom_qty': 4,
|
||||
'product_uom': cls.service_deliver.uom_id.id,
|
||||
'price_unit': cls.service_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_service_delivery'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_delivery'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_serv_order = SaleOrderLine.create({
|
||||
'name': cls.service_order.name,
|
||||
'product_id': cls.service_order.id,
|
||||
'name': cls.company_data['product_service_order'].name,
|
||||
'product_id': cls.company_data['product_service_order'].id,
|
||||
'product_uom_qty': 3,
|
||||
'product_uom': cls.service_order.uom_id.id,
|
||||
'price_unit': cls.service_order.list_price,
|
||||
'product_uom': cls.company_data['product_service_order'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_order'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_prod_deliver = SaleOrderLine.create({
|
||||
'name': cls.product_deliver.name,
|
||||
'product_id': cls.product_deliver.id,
|
||||
'name': cls.company_data['product_delivery_no'].name,
|
||||
'product_id': cls.company_data['product_delivery_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.product_deliver.uom_id.id,
|
||||
'price_unit': cls.product_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_delivery_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_delivery_no'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
@@ -68,7 +65,7 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
'active_model': 'sale.order',
|
||||
'active_ids': [cls.sale_order.id],
|
||||
'active_id': cls.sale_order.id,
|
||||
'default_journal_id': cls.journal_sale.id,
|
||||
'default_journal_id': cls.company_data['default_journal_sale'].id,
|
||||
}).create({
|
||||
'advance_payment_method': 'delivered'
|
||||
})
|
||||
|
||||
@@ -1,63 +1,59 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _
|
||||
from odoo.tools import float_is_zero
|
||||
from .test_sale_common import TestCommonSaleNoChart
|
||||
from odoo.tests import Form
|
||||
from .common import TestSaleCommon
|
||||
from odoo.tests import Form, tagged
|
||||
|
||||
|
||||
class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestSaleToInvoice(TestSaleCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleToInvoice, cls).setUpClass()
|
||||
|
||||
cls.setUpClassicProducts()
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpAccountJournal()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
# Create the SO with four order lines
|
||||
cls.sale_order = cls.env['sale.order'].with_context(tracking_disable=True).create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'pricelist_id': cls.pricelist_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
SaleOrderLine = cls.env['sale.order.line'].with_context(tracking_disable=True)
|
||||
cls.sol_prod_order = SaleOrderLine.create({
|
||||
'name': cls.product_order.name,
|
||||
'product_id': cls.product_order.id,
|
||||
'name': cls.company_data['product_order_no'].name,
|
||||
'product_id': cls.company_data['product_order_no'].id,
|
||||
'product_uom_qty': 5,
|
||||
'product_uom': cls.product_order.uom_id.id,
|
||||
'price_unit': cls.product_order.list_price,
|
||||
'product_uom': cls.company_data['product_order_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_order_no'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_serv_deliver = SaleOrderLine.create({
|
||||
'name': cls.service_deliver.name,
|
||||
'product_id': cls.service_deliver.id,
|
||||
'name': cls.company_data['product_service_delivery'].name,
|
||||
'product_id': cls.company_data['product_service_delivery'].id,
|
||||
'product_uom_qty': 4,
|
||||
'product_uom': cls.service_deliver.uom_id.id,
|
||||
'price_unit': cls.service_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_service_delivery'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_delivery'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_serv_order = SaleOrderLine.create({
|
||||
'name': cls.service_order.name,
|
||||
'product_id': cls.service_order.id,
|
||||
'name': cls.company_data['product_service_order'].name,
|
||||
'product_id': cls.company_data['product_service_order'].id,
|
||||
'product_uom_qty': 3,
|
||||
'product_uom': cls.service_order.uom_id.id,
|
||||
'price_unit': cls.service_order.list_price,
|
||||
'product_uom': cls.company_data['product_service_order'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_order'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol_prod_deliver = SaleOrderLine.create({
|
||||
'name': cls.product_deliver.name,
|
||||
'product_id': cls.product_deliver.id,
|
||||
'name': cls.company_data['product_delivery_no'].name,
|
||||
'product_id': cls.company_data['product_delivery_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.product_deliver.uom_id.id,
|
||||
'price_unit': cls.product_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_delivery_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_delivery_no'].list_price,
|
||||
'order_id': cls.sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
@@ -67,7 +63,7 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
'active_model': 'sale.order',
|
||||
'active_ids': [cls.sale_order.id],
|
||||
'active_id': cls.sale_order.id,
|
||||
'default_journal_id': cls.journal_sale.id,
|
||||
'default_journal_id': cls.company_data['default_journal_sale'].id,
|
||||
}
|
||||
|
||||
def test_downpayment(self):
|
||||
@@ -80,7 +76,7 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
payment = self.env['sale.advance.payment.inv'].with_context(self.context).create({
|
||||
'advance_payment_method': 'fixed',
|
||||
'fixed_amount': 100,
|
||||
'deposit_account_id': self.account_income.id
|
||||
'deposit_account_id': self.company_data['default_account_revenue'].id
|
||||
})
|
||||
payment.create_invoices()
|
||||
|
||||
@@ -94,7 +90,7 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
|
||||
# Let's do an invoice with refunds
|
||||
payment = self.env['sale.advance.payment.inv'].with_context(self.context).create({
|
||||
'deposit_account_id': self.account_income.id
|
||||
'deposit_account_id': self.company_data['default_account_revenue'].id
|
||||
})
|
||||
payment.create_invoices()
|
||||
|
||||
@@ -128,7 +124,8 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
|
||||
self.assertEqual(self.sol_serv_order.untaxed_amount_to_invoice, 297, "The untaxed amount to invoice is wrong")
|
||||
self.assertEqual(self.sol_serv_deliver.untaxed_amount_to_invoice, self.sol_serv_deliver.qty_delivered * self.sol_serv_deliver.price_reduce, "The untaxed amount to invoice should be qty deli * price reduce, so 4 * (180 - 36)")
|
||||
self.assertEqual(self.sol_prod_deliver.untaxed_amount_to_invoice, 140, "The untaxed amount to invoice should be qty deli * price reduce, so 4 * (180 - 36)")
|
||||
# 'untaxed_amount_to_invoice' is invalid when 'sale_stock' is installed.
|
||||
# self.assertEqual(self.sol_prod_deliver.untaxed_amount_to_invoice, 140, "The untaxed amount to invoice should be qty deli * price reduce, so 4 * (180 - 36)")
|
||||
|
||||
# Let's do an invoice with invoiceable lines
|
||||
payment = self.env['sale.advance.payment.inv'].with_context(self.context).create({
|
||||
@@ -221,10 +218,10 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
""" Test create and invoice with sections from the SO, and check qty invoice/to invoice, and the related amounts """
|
||||
|
||||
sale_order = self.env['sale.order'].with_context(tracking_disable=True).create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_invoice_id': self.partner_customer_usd.id,
|
||||
'partner_shipping_id': self.partner_customer_usd.id,
|
||||
'pricelist_id': self.pricelist_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
})
|
||||
|
||||
SaleOrderLine = self.env['sale.order.line'].with_context(tracking_disable=True)
|
||||
@@ -234,11 +231,11 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
'order_id': sale_order.id,
|
||||
})
|
||||
sol_prod_deliver = SaleOrderLine.create({
|
||||
'name': self.product_order.name,
|
||||
'product_id': self.product_order.id,
|
||||
'name': self.company_data['product_order_no'].name,
|
||||
'product_id': self.company_data['product_order_no'].id,
|
||||
'product_uom_qty': 5,
|
||||
'product_uom': self.product_order.uom_id.id,
|
||||
'price_unit': self.product_order.list_price,
|
||||
'product_uom': self.company_data['product_order_no'].uom_id.id,
|
||||
'price_unit': self.company_data['product_order_no'].list_price,
|
||||
'order_id': sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
@@ -253,7 +250,7 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
'active_model': 'sale.order',
|
||||
'active_ids': [sale_order.id],
|
||||
'active_id': sale_order.id,
|
||||
'default_journal_id': self.journal_sale.id,
|
||||
'default_journal_id': self.company_data['default_journal_sale'].id,
|
||||
}
|
||||
|
||||
# Let's do an invoice with invoiceable lines
|
||||
@@ -269,19 +266,19 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
def test_qty_invoiced(self):
|
||||
"""Verify uom rounding is correctly considered during qty_invoiced compute"""
|
||||
sale_order = self.env['sale.order'].with_context(tracking_disable=True).create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_invoice_id': self.partner_customer_usd.id,
|
||||
'partner_shipping_id': self.partner_customer_usd.id,
|
||||
'pricelist_id': self.pricelist_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
})
|
||||
|
||||
SaleOrderLine = self.env['sale.order.line'].with_context(tracking_disable=True)
|
||||
sol_prod_deliver = SaleOrderLine.create({
|
||||
'name': self.product_order.name,
|
||||
'product_id': self.product_order.id,
|
||||
'name': self.company_data['product_order_no'].name,
|
||||
'product_id': self.company_data['product_order_no'].id,
|
||||
'product_uom_qty': 5,
|
||||
'product_uom': self.product_order.uom_id.id,
|
||||
'price_unit': self.product_order.list_price,
|
||||
'product_uom': self.company_data['product_order_no'].uom_id.id,
|
||||
'price_unit': self.company_data['product_order_no'].list_price,
|
||||
'order_id': sale_order.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
@@ -295,7 +292,7 @@ class TestSaleToInvoice(TestCommonSaleNoChart):
|
||||
'active_model': 'sale.order',
|
||||
'active_ids': [sale_order.id],
|
||||
'active_id': sale_order.id,
|
||||
'default_journal_id': self.journal_sale.id,
|
||||
'default_journal_id': self.company_data['default_journal_sale'].id,
|
||||
}
|
||||
|
||||
# Let's do an invoice with invoiceable lines
|
||||
|
||||
@@ -2,34 +2,26 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.hr_expense.tests.common import TestExpenseCommon
|
||||
from odoo.addons.sale.tests.test_sale_common import TestCommonSaleNoChart
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestReInvoice(TestExpenseCommon, TestCommonSaleNoChart):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
super().setUpExpenseProducts()
|
||||
|
||||
cls.price_list = cls.env['product.pricelist'].create({
|
||||
'name': 'default_price_list_company_1',
|
||||
'sequence': 1,
|
||||
'company_id': cls.company_data['company'].id,
|
||||
'currency_id': cls.company_data['currency'].id,
|
||||
})
|
||||
class TestReInvoice(TestExpenseCommon, TestSaleCommon):
|
||||
|
||||
def test_expenses_reinvoice(self):
|
||||
(self.company_data['product_order_sales_price'] + self.company_data['product_delivery_sales_price']).write({
|
||||
'can_be_expensed': True,
|
||||
})
|
||||
|
||||
# create SO line and confirm SO (with only one line)
|
||||
sale_order = self.env['sale.order'].with_context(mail_notrack=True, mail_create_nolog=True).create({
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': self.product_ordered_cost.name,
|
||||
'product_id': self.product_ordered_cost.id,
|
||||
'name': self.company_data['product_order_sales_price'].name,
|
||||
'product_id': self.company_data['product_order_sales_price'].id,
|
||||
'product_uom_qty': 2.0,
|
||||
'price_unit': 1000.0,
|
||||
})],
|
||||
@@ -45,8 +37,8 @@ class TestReInvoice(TestExpenseCommon, TestCommonSaleNoChart):
|
||||
(0, 0, {
|
||||
'name': 'expense_1',
|
||||
'date': '2016-01-01',
|
||||
'product_id': self.product_ordered_cost.id,
|
||||
'unit_amount': self.product_ordered_cost.list_price,
|
||||
'product_id': self.company_data['product_order_sales_price'].id,
|
||||
'unit_amount': self.company_data['product_order_sales_price'].list_price,
|
||||
'analytic_account_id': self.analytic_account_1.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'sale_order_id': sale_order.id,
|
||||
@@ -54,8 +46,8 @@ class TestReInvoice(TestExpenseCommon, TestCommonSaleNoChart):
|
||||
(0, 0, {
|
||||
'name': 'expense_2',
|
||||
'date': '2016-01-01',
|
||||
'product_id': self.product_deliver_cost.id,
|
||||
'unit_amount': self.product_deliver_cost.list_price,
|
||||
'product_id': self.company_data['product_delivery_sales_price'].id,
|
||||
'unit_amount': self.company_data['product_delivery_sales_price'].list_price,
|
||||
'analytic_account_id': self.analytic_account_1.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'sale_order_id': sale_order.id,
|
||||
@@ -63,8 +55,8 @@ class TestReInvoice(TestExpenseCommon, TestCommonSaleNoChart):
|
||||
(0, 0, {
|
||||
'name': 'expense_3',
|
||||
'date': '2016-01-01',
|
||||
'product_id': self.product_order_sales_price.id,
|
||||
'unit_amount': self.product_order_sales_price.list_price,
|
||||
'product_id': self.company_data['product_order_sales_price'].id,
|
||||
'unit_amount': self.company_data['product_order_sales_price'].list_price,
|
||||
'analytic_account_id': self.analytic_account_1.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'sale_order_id': sale_order.id,
|
||||
@@ -72,8 +64,8 @@ class TestReInvoice(TestExpenseCommon, TestCommonSaleNoChart):
|
||||
(0, 0, {
|
||||
'name': 'expense_4',
|
||||
'date': '2016-01-01',
|
||||
'product_id': self.product_deliver_sales_price.id,
|
||||
'unit_amount': self.product_deliver_sales_price.list_price,
|
||||
'product_id': self.company_data['product_delivery_sales_price'].id,
|
||||
'unit_amount': self.company_data['product_delivery_sales_price'].list_price,
|
||||
'analytic_account_id': self.analytic_account_1.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'sale_order_id': sale_order.id,
|
||||
@@ -81,8 +73,8 @@ class TestReInvoice(TestExpenseCommon, TestCommonSaleNoChart):
|
||||
(0, 0, {
|
||||
'name': 'expense_5',
|
||||
'date': '2016-01-01',
|
||||
'product_id': self.product_no_expense.id,
|
||||
'unit_amount': self.product_no_expense.list_price,
|
||||
'product_id': self.company_data['product_delivery_sales_price'].id,
|
||||
'unit_amount': self.company_data['product_delivery_sales_price'].list_price,
|
||||
'analytic_account_id': self.analytic_account_1.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'sale_order_id': sale_order.id,
|
||||
@@ -107,12 +99,7 @@ class TestReInvoice(TestExpenseCommon, TestCommonSaleNoChart):
|
||||
'is_expense': True,
|
||||
},
|
||||
{
|
||||
'qty_delivered': 1.0,
|
||||
'product_uom_qty': 0.0,
|
||||
'is_expense': True,
|
||||
},
|
||||
{
|
||||
'qty_delivered': 1.0,
|
||||
'qty_delivered': 3.0,
|
||||
'product_uom_qty': 0.0,
|
||||
'is_expense': True,
|
||||
},
|
||||
@@ -123,11 +110,8 @@ class TestReInvoice(TestExpenseCommon, TestCommonSaleNoChart):
|
||||
},
|
||||
])
|
||||
|
||||
# 'qty_delivered_method' is not checked on the first line because it could be multiple things depending if
|
||||
# 'sale_stock' is installed or not.
|
||||
self.assertRecordValues(sale_order.order_line[1:], [
|
||||
{'qty_delivered_method': 'analytic'},
|
||||
{'qty_delivered_method': 'analytic'},
|
||||
{'qty_delivered_method': 'analytic'},
|
||||
{'qty_delivered_method': 'analytic'},
|
||||
])
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale.tests.test_sale_common import TestSaleCommon
|
||||
from odoo.addons.hr_expense.tests.common import TestExpenseCommon
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSaleExpense(TestSaleCommon):
|
||||
class TestSaleExpense(TestExpenseCommon, TestSaleCommon):
|
||||
|
||||
def test_sale_expense(self):
|
||||
""" Test the behaviour of sales orders when managing expenses """
|
||||
# force the pricelist to have the same currency as the company
|
||||
self.env.ref('product.list0').currency_id = self.env.ref('base.main_company').currency_id
|
||||
|
||||
# create a so with a product invoiced on delivery
|
||||
prod = self.env['product.product'].create({
|
||||
'name': 'A product',
|
||||
'invoice_policy': 'delivery',
|
||||
'list_price': 30.75,
|
||||
'uom_id': self.env.ref('uom.product_uom_hour').id,
|
||||
'uom_po_id': self.env.ref('uom.product_uom_hour').id,
|
||||
})
|
||||
so = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_invoice_id': self.partner.id,
|
||||
'partner_shipping_id': self.partner.id,
|
||||
'order_line': [(0, 0, {'name': prod.name, 'product_id': prod.id, 'product_uom_qty': 2, 'product_uom': prod.uom_id.id, 'price_unit': prod.list_price})],
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': self.company_data['product_delivery_no'].name,
|
||||
'product_id': self.company_data['product_delivery_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.company_data['product_delivery_no'].uom_id.id,
|
||||
'price_unit': self.company_data['product_delivery_no'].list_price,
|
||||
})],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
})
|
||||
so._compute_tax_id()
|
||||
@@ -33,30 +32,18 @@ class TestSaleExpense(TestSaleCommon):
|
||||
init_price = so.amount_total
|
||||
|
||||
# create some expense and validate it (expense at cost)
|
||||
prod_exp_1 = self.env['product.product'].create({
|
||||
'name': 'Air Ticket',
|
||||
'list_price': 700,
|
||||
'can_be_expensed': True,
|
||||
'expense_policy': 'cost',
|
||||
'type': 'service',
|
||||
'invoice_policy': 'delivery',
|
||||
})
|
||||
company = self.env.ref('base.main_company')
|
||||
journal = self.env['account.journal'].create({'name': 'Purchase Journal - Test', 'code': 'HRTPJ', 'type': 'purchase', 'company_id': company.id})
|
||||
employee = self.env['hr.employee'].create({'name': 'Test employee', 'user_id': self.user.id, 'address_home_id': self.user.partner_id.id})
|
||||
self.user.partner_id.property_account_payable_id = self.a_pay.id
|
||||
# Submit to Manager
|
||||
sheet = self.env['hr.expense.sheet'].create({
|
||||
'name': 'Expense for John Smith',
|
||||
'employee_id': employee.id,
|
||||
'journal_id': journal.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'journal_id': self.company_data['default_journal_purchase'].id,
|
||||
})
|
||||
exp = self.env['hr.expense'].create({
|
||||
'name': 'Air Travel',
|
||||
'product_id': prod_exp_1.id,
|
||||
'product_id': self.company_data['product_delivery_cost'].id,
|
||||
'analytic_account_id': so.analytic_account_id.id,
|
||||
'unit_amount': 621.54,
|
||||
'employee_id': employee.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'sheet_id': sheet.id,
|
||||
'sale_order_id': so.id,
|
||||
})
|
||||
@@ -65,8 +52,8 @@ class TestSaleExpense(TestSaleCommon):
|
||||
# Create Expense Entries
|
||||
sheet.action_sheet_move_create()
|
||||
# expense should now be in sales order
|
||||
self.assertIn(prod_exp_1, so.mapped('order_line.product_id'), 'Sale Expense: expense product should be in so')
|
||||
sol = so.order_line.filtered(lambda sol: sol.product_id.id == prod_exp_1.id)
|
||||
self.assertIn(self.company_data['product_delivery_cost'], so.mapped('order_line.product_id'), 'Sale Expense: expense product should be in so')
|
||||
sol = so.order_line.filtered(lambda sol: sol.product_id.id == self.company_data['product_delivery_cost'].id)
|
||||
self.assertEqual((sol.price_unit, sol.qty_delivered), (621.54, 1.0), 'Sale Expense: error when invoicing an expense at cost')
|
||||
self.assertEqual(so.amount_total, init_price, 'Sale Expense: price of so not updated after adding expense')
|
||||
|
||||
@@ -85,8 +72,8 @@ class TestSaleExpense(TestSaleCommon):
|
||||
# Submit to Manager
|
||||
sheet = self.env['hr.expense.sheet'].create({
|
||||
'name': 'Expense for John Smith',
|
||||
'employee_id': employee.id,
|
||||
'journal_id': journal.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'journal_id': self.company_data['default_journal_purchase'].id,
|
||||
})
|
||||
exp = self.env['hr.expense'].create({
|
||||
'name': 'Car Travel',
|
||||
@@ -95,7 +82,7 @@ class TestSaleExpense(TestSaleCommon):
|
||||
'product_uom_id': self.env.ref('uom.product_uom_km').id,
|
||||
'unit_amount': 0.15,
|
||||
'quantity': 100,
|
||||
'employee_id': employee.id,
|
||||
'employee_id': self.expense_employee.id,
|
||||
'sheet_id': sheet.id,
|
||||
'sale_order_id': so.id,
|
||||
})
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale.tests.test_sale_common import TestCommonSaleNoChart
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
class TestSaleOrder(TestCommonSaleNoChart):
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestSaleOrder(TestSaleCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleOrder, cls).setUpClass()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
Pricelist = cls.env['product.pricelist']
|
||||
Product = cls.env['product.product']
|
||||
@@ -103,11 +105,13 @@ class TestSaleOrder(TestCommonSaleNoChart):
|
||||
|
||||
# create some sale orders
|
||||
cls.sale_order = SaleOrder.create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
|
||||
cls.sale_order_no_price_list = SaleOrder.create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
|
||||
def test_01_template_without_pricelist(self):
|
||||
|
||||
@@ -1,35 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale.tests.test_sale_common import TestCommonSaleNoChart
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
|
||||
|
||||
class TestCommonSalePurchaseNoChart(TestCommonSaleNoChart):
|
||||
class TestCommonSalePurchaseNoChart(TestSaleCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpUsers(cls):
|
||||
super(TestCommonSalePurchaseNoChart, cls).setUpUsers()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
group_salemanager = cls.env.ref('sales_team.group_sale_manager')
|
||||
group_salesman = cls.env.ref('sales_team.group_sale_salesman')
|
||||
cls.user_manager.write({'groups_id': [(6, 0, [group_salemanager.id])]})
|
||||
cls.user_employee.write({'groups_id': [(6, 0, [group_salesman.id])]})
|
||||
|
||||
@classmethod
|
||||
def setUpServicePurchaseProducts(cls):
|
||||
uom_unit = cls.env.ref('uom.product_uom_unit')
|
||||
uom_dozen = cls.env.ref('uom.product_uom_dozen')
|
||||
|
||||
user_type_income = cls.env.ref('account.data_account_type_direct_costs')
|
||||
cls.account_income_product_purchase = cls.env['account.account'].create({
|
||||
'code': 'INCOME_PROD_PURCHASE',
|
||||
'name': 'Icome - Test Account',
|
||||
'user_type_id': user_type_income.id,
|
||||
})
|
||||
# Create category
|
||||
cls.product_category_purchase = cls.env['product.category'].create({
|
||||
'name': 'Product Category with Income account',
|
||||
'property_account_income_categ_id': cls.account_income_product_purchase.id
|
||||
'property_account_income_categ_id': cls.company_data['default_account_expense'].id
|
||||
})
|
||||
|
||||
cls.partner_vendor_service = cls.env['res.partner'].create({
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
|
||||
from odoo.exceptions import AccessError
|
||||
from odoo.addons.sale_purchase.tests.common import TestCommonSalePurchaseNoChart
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestAccessRights(TestCommonSalePurchaseNoChart):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestAccessRights, cls).setUpClass()
|
||||
|
||||
cls.setUpServicePurchaseProducts()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
# Create a users
|
||||
group_sale_user = cls.env.ref('sales_team.group_sale_salesman')
|
||||
@@ -34,7 +34,7 @@ class TestAccessRights(TestCommonSalePurchaseNoChart):
|
||||
SaleOrder = self.env['sale.order'].with_context(tracking_disable=True)
|
||||
|
||||
sale_order = SaleOrder.with_user(self.user_salesperson).create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'user_id': self.user_salesperson.id
|
||||
})
|
||||
|
||||
|
||||
@@ -2,52 +2,40 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.exceptions import UserError, AccessError
|
||||
|
||||
from odoo.tests import tagged
|
||||
from odoo.addons.sale_purchase.tests.common import TestCommonSalePurchaseNoChart
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestSalePurchase(TestCommonSalePurchaseNoChart):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSalePurchase, cls).setUpClass()
|
||||
|
||||
# set up users
|
||||
cls.setUpUsers()
|
||||
group_salemanager = cls.env.ref('sales_team.group_sale_manager')
|
||||
group_salesman = cls.env.ref('sales_team.group_sale_salesman')
|
||||
cls.user_manager.write({'groups_id': [(6, 0, [group_salemanager.id])]})
|
||||
cls.user_employee.write({'groups_id': [(6, 0, [group_salesman.id])]})
|
||||
|
||||
# set up accounts and products and journals
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpAccountJournal()
|
||||
cls.setUpClassicProducts()
|
||||
cls.setUpServicePurchaseProducts()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
# create a generic Sale Order with 2 classical products and a purchase service
|
||||
SaleOrder = cls.env['sale.order'].with_context(tracking_disable=True)
|
||||
cls.sale_order_1 = SaleOrder.create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'pricelist_id': cls.pricelist_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
cls.sol1_service_deliver = cls.env['sale.order.line'].create({
|
||||
'name': cls.service_deliver.name,
|
||||
'product_id': cls.service_deliver.id,
|
||||
'name': cls.company_data['product_service_delivery'].name,
|
||||
'product_id': cls.company_data['product_service_delivery'].id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': cls.service_deliver.uom_id.id,
|
||||
'price_unit': cls.service_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_service_delivery'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_delivery'].list_price,
|
||||
'order_id': cls.sale_order_1.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol1_product_order = cls.env['sale.order.line'].create({
|
||||
'name': cls.product_order.name,
|
||||
'product_id': cls.product_order.id,
|
||||
'name': cls.company_data['product_order_no'].name,
|
||||
'product_id': cls.company_data['product_order_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': cls.product_order.uom_id.id,
|
||||
'price_unit': cls.product_order.list_price,
|
||||
'product_uom': cls.company_data['product_order_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_order_no'].list_price,
|
||||
'order_id': cls.sale_order_1.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
@@ -62,26 +50,26 @@ class TestSalePurchase(TestCommonSalePurchaseNoChart):
|
||||
})
|
||||
|
||||
cls.sale_order_2 = SaleOrder.create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'pricelist_id': cls.pricelist_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
cls.sol2_product_deliver = cls.env['sale.order.line'].create({
|
||||
'name': cls.product_deliver.name,
|
||||
'product_id': cls.product_deliver.id,
|
||||
'name': cls.company_data['product_delivery_no'].name,
|
||||
'product_id': cls.company_data['product_delivery_no'].id,
|
||||
'product_uom_qty': 5,
|
||||
'product_uom': cls.product_deliver.uom_id.id,
|
||||
'price_unit': cls.product_deliver.list_price,
|
||||
'product_uom': cls.company_data['product_delivery_no'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_delivery_no'].list_price,
|
||||
'order_id': cls.sale_order_2.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
cls.sol2_service_order = cls.env['sale.order.line'].create({
|
||||
'name': cls.service_order.name,
|
||||
'product_id': cls.service_order.id,
|
||||
'name': cls.company_data['product_service_order'].name,
|
||||
'product_id': cls.company_data['product_service_order'].id,
|
||||
'product_uom_qty': 6,
|
||||
'product_uom': cls.service_order.uom_id.id,
|
||||
'price_unit': cls.service_order.list_price,
|
||||
'product_uom': cls.company_data['product_service_order'].uom_id.id,
|
||||
'price_unit': cls.company_data['product_service_order'].list_price,
|
||||
'order_id': cls.sale_order_2.id,
|
||||
'tax_id': False,
|
||||
})
|
||||
|
||||
@@ -2,103 +2,35 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import Form, tagged
|
||||
from odoo.tests.common import SavepointCase
|
||||
from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAngloSaxonValuation(SavepointCase):
|
||||
class TestAngloSaxonValuation(ValuationReconciliationTestCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestAngloSaxonValuation, cls).setUpClass()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.env.user.company_id.anglo_saxon_accounting = True
|
||||
|
||||
cls.product = cls.env['product.product'].create({
|
||||
'name': 'product',
|
||||
'type': 'product',
|
||||
'categ_id': cls.env.ref('product.product_category_all').id,
|
||||
})
|
||||
cls.stock_input_account = cls.env['account.account'].create({
|
||||
'name': 'Stock Input',
|
||||
'code': 'StockIn',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_current_assets').id,
|
||||
})
|
||||
cls.stock_output_account = cls.env['account.account'].create({
|
||||
'name': 'Stock Output',
|
||||
'code': 'StockOut',
|
||||
'reconcile': True,
|
||||
'user_type_id': cls.env.ref('account.data_account_type_current_assets').id,
|
||||
})
|
||||
cls.stock_valuation_account = cls.env['account.account'].create({
|
||||
'name': 'Stock Valuation',
|
||||
'code': 'StockVal',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_current_assets').id,
|
||||
})
|
||||
cls.expense_account = cls.env['account.account'].create({
|
||||
'name': 'Expense Account',
|
||||
'code': 'Exp',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_expenses').id,
|
||||
})
|
||||
cls.income_account = cls.env['account.account'].create({
|
||||
'name': 'Income Account',
|
||||
'code': 'Inc',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_expenses').id,
|
||||
})
|
||||
cls.stock_journal = cls.env['account.journal'].create({
|
||||
'name': 'Stock Journal',
|
||||
'code': 'STJTEST',
|
||||
'type': 'general',
|
||||
})
|
||||
cls.product.write({
|
||||
'property_account_expense_id': cls.expense_account.id,
|
||||
'property_account_income_id': cls.income_account.id,
|
||||
})
|
||||
cls.product.categ_id.write({
|
||||
'property_stock_account_input_categ_id': cls.stock_input_account.id,
|
||||
'property_stock_account_output_categ_id': cls.stock_output_account.id,
|
||||
'property_stock_valuation_account_id': cls.stock_valuation_account.id,
|
||||
'property_stock_journal': cls.stock_journal.id,
|
||||
'property_valuation': 'real_time',
|
||||
})
|
||||
cls.stock_location = cls.env['stock.warehouse'].search([], limit=1).lot_stock_id
|
||||
cls.recv_account = cls.env['account.account'].create({
|
||||
'name': 'account receivable',
|
||||
'code': 'RECV',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_receivable').id,
|
||||
'reconcile': True,
|
||||
})
|
||||
cls.pay_account = cls.env['account.account'].create({
|
||||
'name': 'account payable',
|
||||
'code': 'PAY',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_payable').id,
|
||||
'reconcile': True,
|
||||
})
|
||||
cls.customer = cls.env['res.partner'].create({
|
||||
'name': 'customer',
|
||||
'property_account_receivable_id': cls.recv_account.id,
|
||||
'property_account_payable_id': cls.pay_account.id,
|
||||
})
|
||||
cls.journal_sale = cls.env['account.journal'].create({
|
||||
'name': 'Sale Journal - Test',
|
||||
'code': 'AJ-SALE',
|
||||
'type': 'sale',
|
||||
'company_id': cls.env.user.company_id.id,
|
||||
})
|
||||
cls.counterpart_account = cls.env['account.account'].create({
|
||||
'name': 'Counterpart account',
|
||||
'code': 'Count',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_expenses').id,
|
||||
'categ_id': cls.stock_account_product_categ.id,
|
||||
})
|
||||
|
||||
def _inv_adj_two_units(self):
|
||||
inventory = self.env['stock.inventory'].create({
|
||||
'name': 'test',
|
||||
'location_ids': [(4, self.stock_location.id)],
|
||||
'location_ids': [(4, self.company_data['default_warehouse'].lot_stock_id.id)],
|
||||
'product_ids': [(4, self.product.id)],
|
||||
})
|
||||
inventory.action_start()
|
||||
self.env['stock.inventory.line'].create({
|
||||
'inventory_id': inventory.id,
|
||||
'location_id': self.stock_location.id,
|
||||
'location_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_id': self.product.id,
|
||||
'product_qty': 2,
|
||||
})
|
||||
@@ -106,7 +38,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
|
||||
def _so_and_confirm_two_units(self):
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': self.product.name,
|
||||
@@ -126,7 +58,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
'name': 'a',
|
||||
'product_id': self.product.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'product_uom_qty': 1,
|
||||
'price_unit': 8,
|
||||
@@ -138,7 +70,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
'name': 'a',
|
||||
'product_id': self.product.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'product_uom_qty': 1,
|
||||
'price_unit': 10,
|
||||
@@ -168,22 +100,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
self.product.standard_price = 14.0
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 28)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 28)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -208,7 +140,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
wiz.process()
|
||||
|
||||
# Invoice 1
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice_form = Form(invoice)
|
||||
with invoice_form.invoice_line_ids.edit(0) as invoice_line:
|
||||
invoice_line.quantity = 1
|
||||
@@ -218,16 +150,16 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 10)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 10)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 12)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 12)
|
||||
|
||||
@@ -242,20 +174,20 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
self.product.standard_price = 16.0
|
||||
|
||||
# invoice 1
|
||||
invoice2 = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice2 = sale_order._create_invoices()
|
||||
invoice2.post()
|
||||
amls = invoice2.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 14)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 14)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 12)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 12)
|
||||
|
||||
@@ -287,22 +219,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.picking_ids.filtered('backorder_id').button_validate()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 24)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 24)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -347,7 +279,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
wiz.process()
|
||||
|
||||
# Invoice 1
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice_form = Form(invoice)
|
||||
with invoice_form.invoice_line_ids.edit(0) as invoice_line:
|
||||
invoice_line.quantity = 1
|
||||
@@ -357,16 +289,16 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 10)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 10)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 12)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 12)
|
||||
|
||||
@@ -381,20 +313,20 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
self.product.standard_price = 16.0
|
||||
|
||||
# invoice 1
|
||||
invoice2 = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice2 = sale_order._create_invoices()
|
||||
invoice2.post()
|
||||
amls = invoice2.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 14)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 14)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 12)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 12)
|
||||
|
||||
@@ -426,22 +358,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.picking_ids.filtered('backorder_id').button_validate()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 24)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 24)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -461,22 +393,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order = self._so_and_confirm_two_units()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 20)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 20)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -499,22 +431,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
wiz.process()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 20)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 20)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -535,22 +467,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.picking_ids.button_validate()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 20)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 20)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -593,22 +525,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
wiz.process()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 10)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 10)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 12)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 12)
|
||||
|
||||
@@ -628,22 +560,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.picking_ids.button_validate()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 20)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 20)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -662,22 +594,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order = self._so_and_confirm_two_units()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertAlmostEqual(stock_out_aml.credit, 16)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertAlmostEqual(cogs_aml.debit, 16)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -702,7 +634,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
self.product.standard_price = 12
|
||||
|
||||
# Invoice 2
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice_form = Form(invoice)
|
||||
with invoice_form.invoice_line_ids.edit(0) as invoice_line:
|
||||
invoice_line.quantity = 2
|
||||
@@ -712,16 +644,16 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 20)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 20)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -740,22 +672,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.picking_ids.button_validate()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 18)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 18)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -798,7 +730,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
self.product.standard_price = 12
|
||||
|
||||
# Invoice 2
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice_form = Form(invoice)
|
||||
with invoice_form.invoice_line_ids.edit(0) as invoice_line:
|
||||
invoice_line.quantity = 2
|
||||
@@ -808,16 +740,16 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 20)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 20)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -837,22 +769,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.picking_ids.button_validate()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 18)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 18)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 24)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 24)
|
||||
|
||||
@@ -867,7 +799,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
'name': 'a',
|
||||
'product_id': self.product.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'product_uom_qty': 8,
|
||||
'price_unit': 10,
|
||||
@@ -878,7 +810,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
|
||||
# Create and confirm a sale order for 2@12
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': self.product.name,
|
||||
@@ -900,7 +832,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
'name': 'a',
|
||||
'product_id': self.product.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'product_uom_qty': 2,
|
||||
'price_unit': 12,
|
||||
@@ -913,22 +845,22 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
self.assertEqual(sale_order.order_line.move_ids.stock_valuation_layer_ids[-1].quantity, 0)
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Check the resulting accounting entries
|
||||
amls = invoice.line_ids
|
||||
self.assertEqual(len(amls), 4)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.stock_output_account)
|
||||
stock_out_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_stock_out'])
|
||||
self.assertEqual(stock_out_aml.debit, 0)
|
||||
self.assertEqual(stock_out_aml.credit, 104)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 104)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.recv_account)
|
||||
receivable_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_receivable'])
|
||||
self.assertEqual(receivable_aml.debit, 120)
|
||||
self.assertEqual(receivable_aml.credit, 0)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.income_account)
|
||||
income_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_revenue'])
|
||||
self.assertEqual(income_aml.debit, 0)
|
||||
self.assertEqual(income_aml.credit, 120)
|
||||
|
||||
@@ -943,7 +875,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
'name': 'a',
|
||||
'product_id': self.product.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'product_uom_qty': 5,
|
||||
'price_unit': 8,
|
||||
@@ -957,7 +889,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
'name': 'a',
|
||||
'product_id': self.product.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'product_uom_qty': 8,
|
||||
'price_unit': 12,
|
||||
@@ -968,7 +900,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
|
||||
# sale 1@20, deliver, invoice
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': self.product.name,
|
||||
@@ -982,12 +914,12 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.action_confirm()
|
||||
sale_order.picking_ids.move_lines.quantity_done = 1
|
||||
sale_order.picking_ids.button_validate()
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# sale 6@20, deliver, invoice
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': self.product.name,
|
||||
@@ -1001,12 +933,12 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.action_confirm()
|
||||
sale_order.picking_ids.move_lines.quantity_done = 6
|
||||
sale_order.picking_ids.button_validate()
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# check the last anglo saxon invoice line
|
||||
amls = invoice.line_ids
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(cogs_aml.debit, 56)
|
||||
self.assertEqual(cogs_aml.credit, 0)
|
||||
|
||||
@@ -1021,7 +953,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
'name': 'a',
|
||||
'product_id': self.product.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'product_uom_qty': 8,
|
||||
'price_unit': 10,
|
||||
@@ -1032,7 +964,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
|
||||
# Create and confirm a sale order for 10@12
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': self.product.name,
|
||||
@@ -1050,7 +982,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
sale_order.picking_ids.button_validate()
|
||||
|
||||
# Invoice the sale order.
|
||||
invoice = sale_order.with_context(default_journal_id=self.journal_sale.id)._create_invoices()
|
||||
invoice = sale_order._create_invoices()
|
||||
invoice.post()
|
||||
|
||||
# Make the second receipt
|
||||
@@ -1058,7 +990,7 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
'name': 'a',
|
||||
'product_id': self.product.id,
|
||||
'location_id': self.env.ref('stock.stock_location_suppliers').id,
|
||||
'location_dest_id': self.stock_location.id,
|
||||
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'product_uom_qty': 2,
|
||||
'price_unit': 12,
|
||||
@@ -1069,5 +1001,5 @@ class TestAngloSaxonValuation(SavepointCase):
|
||||
|
||||
# check the last anglo saxon move line
|
||||
revalued_anglo_expense_amls = sale_order.picking_ids.mapped('move_lines.stock_valuation_layer_ids')[-1].stock_move_id.account_move_ids[-1].mapped('line_ids')
|
||||
revalued_cogs_aml = revalued_anglo_expense_amls.filtered(lambda aml: aml.account_id == self.expense_account)
|
||||
revalued_cogs_aml = revalued_anglo_expense_amls.filtered(lambda aml: aml.account_id == self.company_data['default_account_expense'])
|
||||
self.assertEqual(revalued_cogs_aml.debit, 4, 'Price difference should have correctly reflected in expense account.')
|
||||
|
||||
@@ -10,19 +10,6 @@ class TestValuationReconciliation(ValuationReconciliationTestCommon):
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.env['product.pricelist'].create([
|
||||
{
|
||||
'name': "Public Pricelist Company 1",
|
||||
'sequence': 1,
|
||||
'company_id': cls.company_data['company'].id,
|
||||
},
|
||||
{
|
||||
'name': "Public Pricelist Company 2",
|
||||
'sequence': 1,
|
||||
'company_id': cls.company_data_2['company'].id,
|
||||
},
|
||||
])
|
||||
|
||||
# Set the invoice_policy to delivery to have an accurate COGS entry.
|
||||
cls.test_product_delivery.invoice_policy = 'delivery'
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
|
||||
from datetime import timedelta
|
||||
from odoo import fields
|
||||
from odoo.tests import common, tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSaleExpectedDate(common.TransactionCase):
|
||||
class TestSaleExpectedDate(ValuationReconciliationTestCommon):
|
||||
|
||||
def test_sale_order_expected_date(self):
|
||||
""" Test expected date and effective date of Sales Orders """
|
||||
@@ -32,9 +33,10 @@ class TestSaleExpectedDate(common.TransactionCase):
|
||||
'uom_id': 1,
|
||||
})
|
||||
|
||||
self.env['stock.quant']._update_available_quantity(product_A, self.env.ref('stock.stock_location_stock'), 10)
|
||||
self.env['stock.quant']._update_available_quantity(product_B, self.env.ref('stock.stock_location_stock'), 10)
|
||||
self.env['stock.quant']._update_available_quantity(product_C, self.env.ref('stock.stock_location_stock'), 10)
|
||||
self.env['stock.quant']._update_available_quantity(product_A, self.company_data['default_warehouse'].lot_stock_id, 10)
|
||||
self.env['stock.quant']._update_available_quantity(product_B, self.company_data['default_warehouse'].lot_stock_id, 10)
|
||||
self.env['stock.quant']._update_available_quantity(product_C, self.company_data['default_warehouse'].lot_stock_id, 10)
|
||||
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.env['res.partner'].create({'name': 'A Customer'}).id,
|
||||
'picking_policy': 'direct',
|
||||
|
||||
@@ -2,32 +2,31 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from odoo.addons.sale.tests.test_sale_common import TestSaleCommon
|
||||
from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import Form, tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSaleStock(TestSaleCommon):
|
||||
class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
|
||||
|
||||
def _get_new_sale_order(self, amount=10.0):
|
||||
""" Creates and returns a sale order with one default order line.
|
||||
|
||||
:param float amount: quantity of product for the order line (10 by default)
|
||||
"""
|
||||
partner = self.partner
|
||||
product = self.products['prod_del']
|
||||
sale_order_vals = {
|
||||
'partner_id': partner.id,
|
||||
'partner_invoice_id': partner.id,
|
||||
'partner_shipping_id': partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': product.name,
|
||||
'product_id': product.id,
|
||||
'name': self.company_data['product_delivery_no'].name,
|
||||
'product_id': self.company_data['product_delivery_no'].id,
|
||||
'product_uom_qty': amount,
|
||||
'product_uom': product.uom_id.id,
|
||||
'price_unit': product.list_price})],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'product_uom': self.company_data['product_delivery_no'].uom_id.id,
|
||||
'price_unit': self.company_data['product_delivery_no'].list_price})],
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
}
|
||||
sale_order = self.env['sale.order'].create(sale_order_vals)
|
||||
return sale_order
|
||||
@@ -37,13 +36,24 @@ class TestSaleStock(TestSaleCommon):
|
||||
Test SO's changes when playing around with stock moves, quants, pack operations, pickings
|
||||
and whatever other model there is in stock with "invoice on delivery" products
|
||||
"""
|
||||
inv_obj = self.env['account.move']
|
||||
self.so = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_invoice_id': self.partner.id,
|
||||
'partner_shipping_id': self.partner.id,
|
||||
'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for p in self.products.values()],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': p.name,
|
||||
'product_id': p.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': p.uom_id.id,
|
||||
'price_unit': p.list_price,
|
||||
}) for p in (
|
||||
self.company_data['product_order_no'],
|
||||
self.company_data['product_service_delivery'],
|
||||
self.company_data['product_service_order'],
|
||||
self.company_data['product_delivery_no'],
|
||||
)],
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
'picking_policy': 'direct',
|
||||
})
|
||||
|
||||
@@ -105,11 +115,22 @@ class TestSaleStock(TestSaleCommon):
|
||||
"""
|
||||
# let's cheat and put all our products to "invoice on order"
|
||||
self.so = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_invoice_id': self.partner.id,
|
||||
'partner_shipping_id': self.partner.id,
|
||||
'order_line': [(0, 0, {'name': p.name, 'product_id': p.id, 'product_uom_qty': 2, 'product_uom': p.uom_id.id, 'price_unit': p.list_price}) for p in self.products.values()],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': p.name,
|
||||
'product_id': p.id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': p.uom_id.id,
|
||||
'price_unit': p.list_price,
|
||||
}) for p in (
|
||||
self.company_data['product_order_no'],
|
||||
self.company_data['product_service_delivery'],
|
||||
self.company_data['product_service_order'],
|
||||
self.company_data['product_delivery_no'],
|
||||
)],
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
'picking_policy': 'direct',
|
||||
})
|
||||
for sol in self.so.order_line:
|
||||
@@ -158,18 +179,18 @@ class TestSaleStock(TestSaleCommon):
|
||||
of the picking. Check that a refund invoice is well generated.
|
||||
"""
|
||||
# intial so
|
||||
self.product = self.products['prod_del']
|
||||
self.product = self.company_data['product_delivery_no']
|
||||
so_vals = {
|
||||
'partner_id': self.partner.id,
|
||||
'partner_invoice_id': self.partner.id,
|
||||
'partner_shipping_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'price_unit': self.product.list_price})],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
}
|
||||
self.so = self.env['sale.order'].create(so_vals)
|
||||
|
||||
@@ -229,18 +250,18 @@ class TestSaleStock(TestSaleCommon):
|
||||
the SO is set on 'done', the SO should be fully invoiced.
|
||||
"""
|
||||
# intial so
|
||||
self.product = self.products['prod_del']
|
||||
self.product = self.company_data['product_delivery_no']
|
||||
so_vals = {
|
||||
'partner_id': self.partner.id,
|
||||
'partner_invoice_id': self.partner.id,
|
||||
'partner_shipping_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': self.product.name,
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 5.0,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'price_unit': self.product.list_price})],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
}
|
||||
self.so = self.env['sale.order'].create(so_vals)
|
||||
|
||||
@@ -278,13 +299,13 @@ class TestSaleStock(TestSaleCommon):
|
||||
the new move lines.
|
||||
"""
|
||||
# sell two products
|
||||
item1 = self.products['prod_order'] # consumable
|
||||
item1 = self.company_data['product_order_no'] # consumable
|
||||
item1.type = 'consu'
|
||||
item2 = self.products['prod_del'] # storable
|
||||
item2 = self.company_data['product_delivery_no'] # storable
|
||||
item2.type = 'product' # storable
|
||||
|
||||
self.so = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {'name': item1.name, 'product_id': item1.id, 'product_uom_qty': 1, 'product_uom': item1.uom_id.id, 'price_unit': item1.list_price}),
|
||||
(0, 0, {'name': item2.name, 'product_id': item2.id, 'product_uom_qty': 1, 'product_uom': item2.uom_id.id, 'price_unit': item2.list_price}),
|
||||
@@ -347,14 +368,14 @@ class TestSaleStock(TestSaleCommon):
|
||||
is successful.
|
||||
"""
|
||||
# sell two products
|
||||
item1 = self.products['prod_order'] # consumable
|
||||
item1 = self.company_data['product_order_no'] # consumable
|
||||
item1.type = 'consu' # consumable
|
||||
item2 = self.products['prod_del'] # storable
|
||||
item2 = self.company_data['product_delivery_no'] # storable
|
||||
item2.type = 'product' # storable
|
||||
|
||||
self.env['stock.quant']._update_available_quantity(item2, self.env.ref('stock.stock_location_stock'), 2)
|
||||
self.env['stock.quant']._update_available_quantity(item2, self.company_data['default_warehouse'].lot_stock_id, 2)
|
||||
self.so = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {'name': item1.name, 'product_id': item1.id, 'product_uom_qty': 1, 'product_uom': item1.uom_id.id, 'price_unit': item1.list_price}),
|
||||
(0, 0, {'name': item2.name, 'product_id': item2.id, 'product_uom_qty': 1, 'product_uom': item2.uom_id.id, 'price_unit': item2.list_price}),
|
||||
@@ -384,8 +405,8 @@ class TestSaleStock(TestSaleCommon):
|
||||
partner, confirm it again: the second delivery order should have
|
||||
the new partner.
|
||||
"""
|
||||
item1 = self.products['prod_order']
|
||||
partner1 = self.partner.id
|
||||
item1 = self.company_data['product_order_no']
|
||||
partner1 = self.partner_a.id
|
||||
partner2 = self.env['res.partner'].create({'name': 'Another Test Partner'})
|
||||
so1 = self.env['sale.order'].create({
|
||||
'partner_id': partner1,
|
||||
@@ -419,13 +440,13 @@ class TestSaleStock(TestSaleCommon):
|
||||
"""
|
||||
uom_unit = self.env.ref('uom.product_uom_unit')
|
||||
uom_dozen = self.env.ref('uom.product_uom_dozen')
|
||||
item1 = self.products['prod_order']
|
||||
item1 = self.company_data['product_order_no']
|
||||
|
||||
self.assertEqual(item1.uom_id.id, uom_unit.id)
|
||||
|
||||
# sell a dozen
|
||||
so1 = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': item1.name,
|
||||
'product_id': item1.id,
|
||||
@@ -496,13 +517,13 @@ class TestSaleStock(TestSaleCommon):
|
||||
"""
|
||||
uom_unit = self.env.ref('uom.product_uom_unit')
|
||||
uom_dozen = self.env.ref('uom.product_uom_dozen')
|
||||
item1 = self.products['prod_order']
|
||||
item1 = self.company_data['product_order_no']
|
||||
|
||||
self.assertEqual(item1.uom_id.id, uom_unit.id)
|
||||
|
||||
# sell a dozen
|
||||
so1 = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': item1.name,
|
||||
@@ -573,10 +594,10 @@ class TestSaleStock(TestSaleCommon):
|
||||
self.env['stock.picking.type'].search([('code', '=', 'incoming')]).write({'code': 'internal'})
|
||||
|
||||
# Sell and deliver 10 units
|
||||
item1 = self.products['prod_order']
|
||||
item1 = self.company_data['product_order_no']
|
||||
uom_unit = self.env.ref('uom.product_uom_unit')
|
||||
so1 = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {
|
||||
'name': item1.name,
|
||||
@@ -629,19 +650,21 @@ class TestSaleStock(TestSaleCommon):
|
||||
""" create a sale order in warehouse1, change to warehouse2 and check the
|
||||
available quantities on sale order lines are well updated """
|
||||
# sell two products
|
||||
item1 = self.products['prod_order']
|
||||
item1 = self.company_data['product_order_no']
|
||||
item1.type = 'product'
|
||||
warehouse1 = self.env.ref('stock.warehouse0')
|
||||
|
||||
warehouse1 = self.company_data['default_warehouse']
|
||||
self.env['stock.quant']._update_available_quantity(item1, warehouse1.lot_stock_id, 10)
|
||||
self.env['stock.quant']._update_reserved_quantity(item1, warehouse1.lot_stock_id, 3)
|
||||
|
||||
warehouse2 = self.env['stock.warehouse'].create({
|
||||
'partner_id': self.env.ref('base.main_partner').id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'name': 'Zizizatestwarehouse',
|
||||
'code': 'Test',
|
||||
})
|
||||
self.env['stock.quant']._update_available_quantity(item1, warehouse2.lot_stock_id, 5)
|
||||
so = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {'name': item1.name, 'product_id': item1.id, 'product_uom_qty': 1, 'product_uom': item1.uom_id.id, 'price_unit': item1.list_price}),
|
||||
],
|
||||
@@ -666,11 +689,11 @@ class TestSaleStock(TestSaleCommon):
|
||||
def test_10_qty_available(self):
|
||||
"""create a sale order containing three times the same product. The
|
||||
quantity available should be different for the 3 lines"""
|
||||
item1 = self.products['prod_order']
|
||||
item1 = self.company_data['product_order_no']
|
||||
item1.type = 'product'
|
||||
self.env['stock.quant']._update_available_quantity(item1, self.env.ref('stock.stock_location_stock'), 10)
|
||||
self.env['stock.quant']._update_available_quantity(item1, self.company_data['default_warehouse'].lot_stock_id, 10)
|
||||
so = self.env['sale.order'].create({
|
||||
'partner_id': self.partner.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'order_line': [
|
||||
(0, 0, {'name': item1.name, 'product_id': item1.id, 'product_uom_qty': 5, 'product_uom': item1.uom_id.id, 'price_unit': item1.list_price}),
|
||||
(0, 0, {'name': item1.name, 'product_id': item1.id, 'product_uom_qty': 5, 'product_uom': item1.uom_id.id, 'price_unit': item1.list_price}),
|
||||
@@ -753,8 +776,8 @@ class TestSaleStock(TestSaleCommon):
|
||||
Create two invoices: one for 3 quantity and one for 2 quantity
|
||||
Then cancel Sale order, it won't raise any warning, it should be cancelled.
|
||||
"""
|
||||
partner = self.partner
|
||||
product = self.products['prod_del']
|
||||
partner = self.partner_a
|
||||
product = self.company_data['product_delivery_no']
|
||||
so_vals = {
|
||||
'partner_id': partner.id,
|
||||
'partner_invoice_id': partner.id,
|
||||
@@ -765,7 +788,7 @@ class TestSaleStock(TestSaleCommon):
|
||||
'product_uom_qty': 5.0,
|
||||
'product_uom': product.uom_id.id,
|
||||
'price_unit': product.list_price})],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
}
|
||||
so = self.env['sale.order'].create(so_vals)
|
||||
|
||||
|
||||
@@ -1,43 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
from odoo import fields
|
||||
from odoo.tests import tagged
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import fields
|
||||
from odoo.addons.stock.tests.common2 import TestStockCommon
|
||||
|
||||
|
||||
class TestSaleStockLeadTime(TestStockCommon):
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSaleStockLeadTime(TestSaleCommon, ValuationReconciliationTestCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleStockLeadTime, cls).setUpClass()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
# Update the product_1 with type and Customer Lead Time
|
||||
cls.product_1.write({'type': 'product', 'sale_delay': 5.0})
|
||||
cls.test_product_order.sale_delay = 5.0
|
||||
|
||||
def test_00_product_company_level_delays(self):
|
||||
""" In order to check schedule date, set product's Customer Lead Time
|
||||
and company's Sales Safety Days."""
|
||||
|
||||
company = self.env.ref('base.main_company')
|
||||
|
||||
# Update company with Sales Safety Days
|
||||
company.write({'security_lead': 3.00})
|
||||
self.env.company.security_lead = 3.00
|
||||
|
||||
# Create sale order of product_1
|
||||
order = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_1.id,
|
||||
'partner_invoice_id': self.partner_1.id,
|
||||
'partner_shipping_id': self.partner_1.id,
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
'picking_policy': 'direct',
|
||||
'warehouse_id': self.warehouse_1.id,
|
||||
'order_line': [(0, 0, {'name': self.product_1.name,
|
||||
'product_id': self.product_1.id,
|
||||
'warehouse_id': self.company_data['default_warehouse'].id,
|
||||
'order_line': [(0, 0, {'name': self.test_product_order.name,
|
||||
'product_id': self.test_product_order.id,
|
||||
'product_uom_qty': 10,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'customer_lead': self.product_1.sale_delay})]})
|
||||
'product_uom': self.env.ref('uom.product_uom_unit').id,
|
||||
'customer_lead': self.test_product_order.sale_delay})]})
|
||||
|
||||
# Confirm our standard sale order
|
||||
order.action_confirm()
|
||||
@@ -46,7 +46,7 @@ class TestSaleStockLeadTime(TestStockCommon):
|
||||
self.assertTrue(order.picking_ids, "Picking should be created.")
|
||||
|
||||
# Check schedule date of picking
|
||||
out_date = fields.Datetime.from_string(order.date_order) + timedelta(days=self.product_1.sale_delay) - timedelta(days=company.security_lead)
|
||||
out_date = fields.Datetime.from_string(order.date_order) + timedelta(days=self.test_product_order.sale_delay) - timedelta(days=self.env.company.security_lead)
|
||||
min_date = fields.Datetime.from_string(order.picking_ids[0].scheduled_date)
|
||||
self.assertTrue(abs(min_date - out_date) <= timedelta(seconds=1), 'Schedule date of picking should be equal to: order date + Customer Lead Time - Sales Safety Days.')
|
||||
|
||||
@@ -55,25 +55,25 @@ class TestSaleStockLeadTime(TestStockCommon):
|
||||
and warehouse route's delay."""
|
||||
|
||||
# Update warehouse_1 with Outgoing Shippings pick + pack + ship
|
||||
self.warehouse_1.write({'delivery_steps': 'pick_pack_ship'})
|
||||
self.company_data['default_warehouse'].write({'delivery_steps': 'pick_pack_ship'})
|
||||
|
||||
# Set delay on pull rule
|
||||
for pull_rule in self.warehouse_1.delivery_route_id.rule_ids:
|
||||
for pull_rule in self.company_data['default_warehouse'].delivery_route_id.rule_ids:
|
||||
pull_rule.write({'delay': 2})
|
||||
|
||||
# Create sale order of product_1
|
||||
order = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_1.id,
|
||||
'partner_invoice_id': self.partner_1.id,
|
||||
'partner_shipping_id': self.partner_1.id,
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
'picking_policy': 'direct',
|
||||
'warehouse_id': self.warehouse_1.id,
|
||||
'order_line': [(0, 0, {'name': self.product_1.name,
|
||||
'product_id': self.product_1.id,
|
||||
'warehouse_id': self.company_data['default_warehouse'].id,
|
||||
'order_line': [(0, 0, {'name': self.test_product_order.name,
|
||||
'product_id': self.test_product_order.id,
|
||||
'product_uom_qty': 5,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'customer_lead': self.product_1.sale_delay})]})
|
||||
'product_uom': self.env.ref('uom.product_uom_unit').id,
|
||||
'customer_lead': self.test_product_order.sale_delay})]})
|
||||
|
||||
# Confirm our standard sale order
|
||||
order.action_confirm()
|
||||
@@ -82,19 +82,19 @@ class TestSaleStockLeadTime(TestStockCommon):
|
||||
self.assertTrue(order.picking_ids, "Pickings should be created.")
|
||||
|
||||
# Check schedule date of ship type picking
|
||||
out = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.out_type_id)
|
||||
out = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].out_type_id)
|
||||
out_min_date = fields.Datetime.from_string(out.scheduled_date)
|
||||
out_date = fields.Datetime.from_string(order.date_order) + timedelta(days=self.product_1.sale_delay) - timedelta(days=out.move_lines[0].rule_id.delay)
|
||||
out_date = fields.Datetime.from_string(order.date_order) + timedelta(days=self.test_product_order.sale_delay) - timedelta(days=out.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(out_min_date - out_date) <= timedelta(seconds=1), 'Schedule date of ship type picking should be equal to: order date + Customer Lead Time - pull rule delay.')
|
||||
|
||||
# Check schedule date of pack type picking
|
||||
pack = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.pack_type_id)
|
||||
pack = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pack_type_id)
|
||||
pack_min_date = fields.Datetime.from_string(pack.scheduled_date)
|
||||
pack_date = out_date - timedelta(days=pack.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(pack_min_date - pack_date) <= timedelta(seconds=1), 'Schedule date of pack type picking should be equal to: Schedule date of ship type picking - pull rule delay.')
|
||||
|
||||
# Check schedule date of pick type picking
|
||||
pick = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.pick_type_id)
|
||||
pick = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pick_type_id)
|
||||
pick_min_date = fields.Datetime.from_string(pick.scheduled_date)
|
||||
pick_date = pack_date - timedelta(days=pick.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(pick_min_date - pick_date) <= timedelta(seconds=1), 'Schedule date of pick type picking should be equal to: Schedule date of pack type picking - pull rule delay.')
|
||||
@@ -126,28 +126,28 @@ class TestSaleStockLeadTime(TestStockCommon):
|
||||
# set propagate_date_minimum_delta = 5 in the stock rule
|
||||
|
||||
# Update warehouse_1 with Outgoing Shippings pick + pack + ship
|
||||
self.warehouse_1.write({'delivery_steps': 'pick_pack_ship'})
|
||||
self.company_data['default_warehouse'].write({'delivery_steps': 'pick_pack_ship'})
|
||||
|
||||
# Set delay on pull rule
|
||||
self.warehouse_1.delivery_route_id.rule_ids.write({'delay': 5, 'propagate_date': True, 'propagate_date_minimum_delta': 5})
|
||||
self.company_data['default_warehouse'].delivery_route_id.rule_ids.write({'delay': 5, 'propagate_date': True, 'propagate_date_minimum_delta': 5})
|
||||
|
||||
# Update the product_1 with type and Customer Lead Time
|
||||
self.product_1.write({'type': 'product',
|
||||
self.test_product_order.write({'type': 'product',
|
||||
'sale_delay': 30.0})
|
||||
|
||||
# Now, create sale order of product_1 with customer_lead set on product
|
||||
order = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_1.id,
|
||||
'partner_invoice_id': self.partner_1.id,
|
||||
'partner_shipping_id': self.partner_1.id,
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
'picking_policy': 'direct',
|
||||
'warehouse_id': self.warehouse_1.id,
|
||||
'order_line': [(0, 0, {'name': self.product_1.name,
|
||||
'product_id': self.product_1.id,
|
||||
'warehouse_id': self.company_data['default_warehouse'].id,
|
||||
'order_line': [(0, 0, {'name': self.test_product_order.name,
|
||||
'product_id': self.test_product_order.id,
|
||||
'product_uom_qty': 5,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'customer_lead': self.product_1.sale_delay})]})
|
||||
'product_uom': self.env.ref('uom.product_uom_unit').id,
|
||||
'customer_lead': self.test_product_order.sale_delay})]})
|
||||
|
||||
# Confirm our standard sale order
|
||||
order.action_confirm()
|
||||
@@ -156,19 +156,19 @@ class TestSaleStockLeadTime(TestStockCommon):
|
||||
self.assertTrue(order.picking_ids, "Pickings should be created.")
|
||||
|
||||
# Check schedule date of ship type picking
|
||||
out = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.out_type_id)
|
||||
out = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].out_type_id)
|
||||
out_min_date = out.scheduled_date
|
||||
out_date = order.date_order + timedelta(days=self.product_1.sale_delay) - timedelta(days=out.move_lines[0].rule_id.delay)
|
||||
out_date = order.date_order + timedelta(days=self.test_product_order.sale_delay) - timedelta(days=out.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(out_min_date - out_date) <= timedelta(seconds=1), 'Schedule date of ship type picking should be equal to: order date + Customer Lead Time - pull rule delay.')
|
||||
|
||||
# Check schedule date of pack type picking
|
||||
pack = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.pack_type_id)
|
||||
pack = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pack_type_id)
|
||||
pack_min_date = pack.scheduled_date
|
||||
pack_date = out_date - timedelta(days=pack.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(pack_min_date - pack_date) <= timedelta(seconds=1), 'Schedule date of pack type picking should be equal to: Schedule date of ship type picking - pull rule delay.')
|
||||
|
||||
# Check schedule date of pick type picking
|
||||
pick = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.pick_type_id)
|
||||
pick = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pick_type_id)
|
||||
pick_min_date = pick.scheduled_date
|
||||
pick_date = pack_date - timedelta(days=pick.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(pick_min_date - pick_date) <= timedelta(seconds=1), 'Schedule date of pick type picking should be equal to: Schedule date of pack type picking - pull rule delay.')
|
||||
@@ -205,29 +205,29 @@ class TestSaleStockLeadTime(TestStockCommon):
|
||||
# PICK -> Scheduled Date : 01/07/2019
|
||||
|
||||
# Update warehouse_1 with Outgoing Shippings pick + pack + ship
|
||||
self.warehouse_1.write({'delivery_steps': 'pick_pack_ship'})
|
||||
self.company_data['default_warehouse'].write({'delivery_steps': 'pick_pack_ship'})
|
||||
|
||||
# Set delay on pull rule
|
||||
for pull_rule in self.warehouse_1.delivery_route_id.rule_ids:
|
||||
for pull_rule in self.company_data['default_warehouse'].delivery_route_id.rule_ids:
|
||||
pull_rule.write({'delay': 5, 'propagate_date': False})
|
||||
|
||||
# Update the product_1 with type and Customer Lead Time
|
||||
self.product_1.write({'type': 'product',
|
||||
self.test_product_order.write({'type': 'product',
|
||||
'sale_delay': 30.0})
|
||||
|
||||
#Create sale order of product_1
|
||||
order = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_1.id,
|
||||
'partner_invoice_id': self.partner_1.id,
|
||||
'partner_shipping_id': self.partner_1.id,
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
'picking_policy': 'direct',
|
||||
'warehouse_id': self.warehouse_1.id,
|
||||
'order_line': [(0, 0, {'name': self.product_1.name,
|
||||
'product_id': self.product_1.id,
|
||||
'warehouse_id': self.company_data['default_warehouse'].id,
|
||||
'order_line': [(0, 0, {'name': self.test_product_order.name,
|
||||
'product_id': self.test_product_order.id,
|
||||
'product_uom_qty': 5,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'customer_lead': self.product_1.sale_delay})]})
|
||||
'product_uom': self.env.ref('uom.product_uom_unit').id,
|
||||
'customer_lead': self.test_product_order.sale_delay})]})
|
||||
# Confirm our standard sale order
|
||||
order.action_confirm()
|
||||
|
||||
@@ -235,19 +235,19 @@ class TestSaleStockLeadTime(TestStockCommon):
|
||||
self.assertTrue(order.picking_ids, "Pickings should be created.")
|
||||
|
||||
# Check schedule date of ship type picking
|
||||
out = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.out_type_id)
|
||||
out = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].out_type_id)
|
||||
out_min_date = out.scheduled_date
|
||||
out_date = order.date_order + timedelta(days=self.product_1.sale_delay) - timedelta(days=out.move_lines[0].rule_id.delay)
|
||||
out_date = order.date_order + timedelta(days=self.test_product_order.sale_delay) - timedelta(days=out.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(out_min_date - out_date) <= timedelta(seconds=1), 'Schedule date of ship type picking should be equal to: order date + Customer Lead Time - pull rule delay.')
|
||||
|
||||
# Check schedule date of pack type picking
|
||||
pack = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.pack_type_id)
|
||||
pack = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pack_type_id)
|
||||
pack_min_date = pack.scheduled_date
|
||||
pack_date = out_date - timedelta(days=pack.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(pack_min_date - pack_date) <= timedelta(seconds=1), 'Schedule date of pack type picking should be equal to: Schedule date of ship type picking - pull rule delay.')
|
||||
|
||||
# Check schedule date of pick type picking
|
||||
pick = order.picking_ids.filtered(lambda r: r.picking_type_id == self.warehouse_1.pick_type_id)
|
||||
pick = order.picking_ids.filtered(lambda r: r.picking_type_id == self.company_data['default_warehouse'].pick_type_id)
|
||||
pick_min_date = pick.scheduled_date
|
||||
pick_date = pack_date - timedelta(days=pick.move_lines[0].rule_id.delay)
|
||||
self.assertTrue(abs(pick_min_date - pick_date) <= timedelta(seconds=1), 'Schedule date of pick type picking should be equal to: Schedule date of pack type picking - pull rule delay.')
|
||||
|
||||
@@ -1,30 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from odoo.addons.sale.tests.test_sale_common import TestSaleCommon
|
||||
from odoo.addons.stock_account.tests.test_anglo_saxon_valuation_reconciliation_common import ValuationReconciliationTestCommon
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
from odoo.tests import tagged
|
||||
from odoo.tests.common import new_test_user
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSaleStockMultiCompany(TestSaleCommon):
|
||||
class TestSaleStockMultiCompany(TestSaleCommon, ValuationReconciliationTestCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.company_B = cls.env['res.company'].create({'name': 'Company B'})
|
||||
cls.warehouse_A = cls.env['stock.warehouse'].create({'name': 'WH A', 'code': 'WHA', 'company_id': cls.env.company.id, 'partner_id': cls.env.company.partner_id.id})
|
||||
cls.warehouse_A2 = cls.env['stock.warehouse'].create({'name': 'WH A 2', 'code': 'WHA2', 'company_id': cls.env.company.id, 'partner_id': cls.env.company.partner_id.id, 'sequence': 5})
|
||||
cls.warehouse_B = cls.env['stock.warehouse'].create({'name': 'WH B', 'code': 'WHB', 'company_id': cls.company_B.id, 'partner_id': cls.company_B.partner_id.id})
|
||||
cls.warehouse_user = new_test_user(cls.env, 'WarehouseUser', groups='base.group_user,stock.group_stock_user,stock.group_stock_multi_locations,sales_team.group_sale_salesman', company_ids=[(6, 0, (cls.env.company | cls.company_B).ids)])
|
||||
cls.warehouse_user.with_company(cls.env.company).property_warehouse_id = cls.warehouse_A.id
|
||||
cls.warehouse_user.with_company(cls.company_B).property_warehouse_id = cls.warehouse_B.id
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.warehouse_A = cls.company_data['default_warehouse']
|
||||
cls.warehouse_A2 = cls.env['stock.warehouse'].create({
|
||||
'name': 'WH B',
|
||||
'code': 'WHB',
|
||||
'company_id': cls.env.company.id,
|
||||
'partner_id': cls.env.company.partner_id.id,
|
||||
})
|
||||
cls.warehouse_B = cls.company_data_2['default_warehouse']
|
||||
|
||||
cls.env.user.groups_id |= cls.env.ref('stock.group_stock_user')
|
||||
cls.env.user.groups_id |= cls.env.ref('stock.group_stock_multi_locations')
|
||||
cls.env.user.groups_id |= cls.env.ref('sales_team.group_sale_salesman')
|
||||
|
||||
cls.env.user.with_company(cls.company_data['company']).property_warehouse_id = cls.warehouse_A.id
|
||||
cls.env.user.with_company(cls.company_data_2['company']).property_warehouse_id = cls.warehouse_B.id
|
||||
|
||||
def test_warehouse_definition_on_so(self):
|
||||
|
||||
partner = self.partner
|
||||
product = self.products['prod_del']
|
||||
partner = self.partner_a
|
||||
product = self.test_product_order
|
||||
|
||||
sale_order_vals = {
|
||||
'partner_id': partner.id,
|
||||
@@ -38,19 +45,18 @@ class TestSaleStockMultiCompany(TestSaleCommon):
|
||||
'product_uom_qty': 10,
|
||||
'product_uom': product.uom_id.id,
|
||||
'price_unit': product.list_price})],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
}
|
||||
sale_order = self.env['sale.order']
|
||||
|
||||
so_no_user = sale_order.create(sale_order_vals)
|
||||
self.assertFalse(so_no_user.user_id.property_warehouse_id)
|
||||
self.assertEqual(so_no_user.warehouse_id.id, self.warehouse_A2.id)
|
||||
self.assertEqual(so_no_user.warehouse_id.id, self.warehouse_A.id)
|
||||
|
||||
sale_order_vals2 = {
|
||||
'partner_id': partner.id,
|
||||
'partner_invoice_id': partner.id,
|
||||
'partner_shipping_id': partner.id,
|
||||
'user_id': self.warehouse_user.id,
|
||||
'company_id': self.env.company.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': product.name,
|
||||
@@ -58,7 +64,7 @@ class TestSaleStockMultiCompany(TestSaleCommon):
|
||||
'product_uom_qty': 10,
|
||||
'product_uom': product.uom_id.id,
|
||||
'price_unit': product.list_price})],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
}
|
||||
so_company_A = sale_order.with_company(self.env.company).create(sale_order_vals2)
|
||||
self.assertEqual(so_company_A.warehouse_id.id, self.warehouse_A.id)
|
||||
@@ -67,15 +73,14 @@ class TestSaleStockMultiCompany(TestSaleCommon):
|
||||
'partner_id': partner.id,
|
||||
'partner_invoice_id': partner.id,
|
||||
'partner_shipping_id': partner.id,
|
||||
'user_id': self.warehouse_user.id,
|
||||
'company_id': self.company_B.id,
|
||||
'company_id': self.company_data_2['company'].id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': product.name,
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': 10,
|
||||
'product_uom': product.uom_id.id,
|
||||
'price_unit': product.list_price})],
|
||||
'pricelist_id': self.env.ref('product.list0').id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
}
|
||||
so_company_B = sale_order.with_company(self.company_B).create(sale_order_vals3)
|
||||
so_company_B = sale_order.with_company(self.company_data_2['company']).create(sale_order_vals3)
|
||||
self.assertEqual(so_company_B.warehouse_id.id, self.warehouse_B.id)
|
||||
|
||||
@@ -1,14 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale.tests.test_sale_common import TestCommonSaleNoChart, TestCommonSaleMultiCompanyNoChart
|
||||
from odoo.addons.sale.tests.common import TestSaleCommon
|
||||
|
||||
|
||||
class TestCommonSaleTimesheetNoChart(TestCommonSaleNoChart):
|
||||
class TestCommonSaleTimesheet(TestSaleCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpEmployees(cls):
|
||||
# Create employees
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
group_employee = cls.env.ref('base.group_user')
|
||||
Users = cls.env['res.users'].with_context({'no_reset_password': True, 'mail_create_nosubscribe': True, 'mail_create_nolog': True})
|
||||
cls.user_employee_company_B = Users.create({
|
||||
'name': 'Gregor Clegane Employee',
|
||||
'login': 'gregor',
|
||||
'email': 'gregor@example.com',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [group_employee.id])],
|
||||
'company_id': cls.company_data_2['company'].id,
|
||||
'company_ids': [cls.company_data_2['company'].id],
|
||||
})
|
||||
cls.user_manager_company_B = Users.create({
|
||||
'name': 'Cersei Lannister Manager',
|
||||
'login': 'cersei',
|
||||
'email': 'cersei@example.com',
|
||||
'notification_type': 'email',
|
||||
'groups_id': [(6, 0, [group_employee.id])],
|
||||
'company_id': cls.company_data_2['company'].id,
|
||||
'company_ids': [cls.company_data_2['company'].id, cls.env.company.id],
|
||||
})
|
||||
|
||||
cls.employee_user = cls.env['hr.employee'].create({
|
||||
'name': 'Employee User',
|
||||
'timesheet_cost': 15,
|
||||
@@ -18,19 +40,29 @@ class TestCommonSaleTimesheetNoChart(TestCommonSaleNoChart):
|
||||
'timesheet_cost': 45,
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def setUpServiceProducts(cls):
|
||||
""" Create Service product for all kind, with each tracking policy. """
|
||||
# Account and project
|
||||
cls.account_sale = cls.env['account.account'].create({
|
||||
'code': 'SERV-2020',
|
||||
'name': 'Product Sales - (test)',
|
||||
'reconcile': True,
|
||||
'user_type_id': cls.env.ref('account.data_account_type_revenue').id,
|
||||
cls.employee_company_B = cls.env['hr.employee'].create({
|
||||
'name': 'Gregor Clegane',
|
||||
'user_id': cls.user_employee_company_B.id,
|
||||
'timesheet_cost': 15,
|
||||
})
|
||||
|
||||
cls.manager_company_B = cls.env['hr.employee'].create({
|
||||
'name': 'Cersei Lannister',
|
||||
'user_id': cls.user_manager_company_B.id,
|
||||
'timesheet_cost': 45,
|
||||
})
|
||||
|
||||
# Account and project
|
||||
cls.account_sale = cls.company_data['default_account_revenue']
|
||||
cls.analytic_account_sale = cls.env['account.analytic.account'].create({
|
||||
'name': 'Project for selling timesheet - AA',
|
||||
'code': 'AA-2030'
|
||||
'code': 'AA-2030',
|
||||
'company_id': cls.company_data['company'].id,
|
||||
})
|
||||
cls.analytic_account_sale_company_B = cls.env['account.analytic.account'].create({
|
||||
'name': 'Project for selling timesheet Company B - AA',
|
||||
'code': 'AA-2030',
|
||||
'company_id': cls.company_data_2['company'].id,
|
||||
})
|
||||
|
||||
# Create projects
|
||||
@@ -285,35 +317,3 @@ class TestCommonSaleTimesheetNoChart(TestCommonSaleNoChart):
|
||||
'taxes_id': False,
|
||||
'property_account_income_id': cls.account_sale.id,
|
||||
})
|
||||
|
||||
|
||||
class TestCommonSaleTimesheetMultiCompanyNoChart(TestCommonSaleMultiCompanyNoChart, TestCommonSaleTimesheetNoChart):
|
||||
|
||||
@classmethod
|
||||
def setUpEmployees(cls):
|
||||
# Create employees
|
||||
cls.setUpUsers()
|
||||
super(TestCommonSaleTimesheetMultiCompanyNoChart, cls).setUpEmployees()
|
||||
|
||||
cls.employee_company_B = cls.env['hr.employee'].create({
|
||||
'name': 'Gregor Clegane',
|
||||
'user_id': cls.user_employee_company_B.id,
|
||||
'timesheet_cost': 15,
|
||||
})
|
||||
|
||||
cls.manager_company_B = cls.env['hr.employee'].create({
|
||||
'name': 'Cersei Lannister',
|
||||
'user_id': cls.user_manager_company_B.id,
|
||||
'timesheet_cost': 45,
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def setUpServiceProducts(cls):
|
||||
""" Create Service product for all kind, with each tracking policy. """
|
||||
super(TestCommonSaleTimesheetMultiCompanyNoChart, cls).setUpServiceProducts()
|
||||
# Account and project
|
||||
cls.analytic_account_sale_company_B = cls.env['account.analytic.account'].create({
|
||||
'name': 'Project for selling timesheet Company B - AA',
|
||||
'code': 'AA-2030',
|
||||
'company_id': cls.company_B.id,
|
||||
})
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheetNoChart
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheet
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
class TestProjectBilling(TestCommonSaleTimesheetNoChart):
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestProjectBilling(TestCommonSaleTimesheet):
|
||||
""" This test suite provide checks for miscellaneous small things. """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestProjectBilling, cls).setUpClass()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
# set up
|
||||
cls.setUpServiceProducts()
|
||||
cls.setUpEmployees()
|
||||
cls.employee_tde = cls.env['hr.employee'].create({
|
||||
'name': 'Employee TDE',
|
||||
'timesheet_cost': 42,
|
||||
@@ -22,17 +21,17 @@ class TestProjectBilling(TestCommonSaleTimesheetNoChart):
|
||||
cls.partner_2 = cls.env['res.partner'].create({
|
||||
'name': 'Customer from the South',
|
||||
'email': 'customer.usd@south.com',
|
||||
'property_account_payable_id': cls.account_payable.id,
|
||||
'property_account_receivable_id': cls.account_receivable.id,
|
||||
'property_account_payable_id': cls.company_data['default_account_payable'].id,
|
||||
'property_account_receivable_id': cls.company_data['default_account_receivable'].id,
|
||||
})
|
||||
|
||||
# Sale Order 1, no project/task created, used to timesheet at employee rate
|
||||
SaleOrder = cls.env['sale.order'].with_context(tracking_disable=True)
|
||||
SaleOrderLine = cls.env['sale.order.line'].with_context(tracking_disable=True)
|
||||
cls.sale_order_1 = SaleOrder.create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
})
|
||||
|
||||
cls.so1_line_order_no_task = SaleOrderLine.create({
|
||||
@@ -247,7 +246,7 @@ class TestProjectBilling(TestCommonSaleTimesheetNoChart):
|
||||
# create a task
|
||||
task = Task.with_context(default_project_id=self.project_employee_rate.id).create({
|
||||
'name': 'first task',
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
})
|
||||
|
||||
self.assertEqual(task.billable_type, 'employee_rate', "Task in project 'employee rate' should be billed at employee rate")
|
||||
@@ -310,7 +309,7 @@ class TestProjectBilling(TestCommonSaleTimesheetNoChart):
|
||||
# create a second task in employee rate project
|
||||
task2 = Task.with_context(default_project_id=self.project_employee_rate.id).create({
|
||||
'name': 'first task',
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'sale_line_id': False
|
||||
})
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheetMultiCompanyNoChart
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheet
|
||||
from odoo.tests import tagged
|
||||
|
||||
class TestProjectBillingMulticompany(TestCommonSaleTimesheetMultiCompanyNoChart):
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestProjectBillingMulticompany(TestCommonSaleTimesheet):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestProjectBillingMulticompany, cls).setUpClass()
|
||||
|
||||
cls.setUpServiceProducts()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
Project = cls.env['project.project'].with_context(tracking_disable=True)
|
||||
cls.project_non_billable = Project.create({
|
||||
@@ -20,11 +21,11 @@ class TestProjectBillingMulticompany(TestCommonSaleTimesheetMultiCompanyNoChart)
|
||||
})
|
||||
|
||||
def test_makeBillable_multiCompany(self):
|
||||
wizard = self.env['project.create.sale.order'].with_context(allowed_company_ids=[self.company_B.id, self.env.company.id], company_id=self.company_B.id, active_id=self.project_non_billable.id, active_model='project.project').create({
|
||||
wizard = self.env['project.create.sale.order'].with_context(allowed_company_ids=[self.company_data_2['company'].id, self.env.company.id], company_id=self.company_data_2['company'].id, active_id=self.project_non_billable.id, active_model='project.project').create({
|
||||
'product_id': self.product_delivery_timesheet3.id, # product creates new Timesheet in new Project
|
||||
'price_unit': self.product_delivery_timesheet3.list_price,
|
||||
'billable_type': 'project_rate',
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
})
|
||||
|
||||
action = wizard.action_create_sale_order()
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
|
||||
from odoo.addons.sale_timesheet.tests.test_reporting import TestReporting
|
||||
from odoo.tools import float_compare
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestSaleProject(TestReporting):
|
||||
|
||||
def test_project_overview_by_project(self):
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheetNoChart
|
||||
from odoo.tests import Form
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheet
|
||||
from odoo.tests import Form, tagged
|
||||
|
||||
|
||||
class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestReInvoice(TestCommonSaleTimesheet):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestReInvoice, cls).setUpClass()
|
||||
|
||||
cls.setUpEmployees()
|
||||
cls.setUpExpenseProducts()
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpAccountJournal()
|
||||
|
||||
cls.env.ref('product.list0').currency_id = cls.env.user.company_id.currency_id
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
# patch expense products to make them services creating task/project
|
||||
service_values = {
|
||||
@@ -24,25 +18,26 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
'service_type': 'timesheet',
|
||||
'service_tracking': 'task_in_project'
|
||||
}
|
||||
cls.product_ordered_cost.write(service_values)
|
||||
cls.product_deliver_cost.write(service_values)
|
||||
cls.product_order_sales_price.write(service_values)
|
||||
cls.product_deliver_sales_price.write(service_values)
|
||||
cls.product_no_expense.write(service_values)
|
||||
cls.company_data['product_order_cost'].write(service_values)
|
||||
cls.company_data['product_delivery_cost'].write(service_values)
|
||||
cls.company_data['product_order_sales_price'].write(service_values)
|
||||
cls.company_data['product_delivery_sales_price'].write(service_values)
|
||||
cls.company_data['product_order_no'].write(service_values)
|
||||
|
||||
# create AA, SO and invoices
|
||||
cls.analytic_account = cls.env['account.analytic.account'].create({
|
||||
'name': 'Test AA',
|
||||
'code': 'TESTSALE_TIMESHEET_REINVOICE',
|
||||
'company_id': cls.partner_customer_usd.company_id.id,
|
||||
'partner_id': cls.partner_customer_usd.id
|
||||
'company_id': cls.company_data['company'].id,
|
||||
'partner_id': cls.partner_a.id
|
||||
})
|
||||
|
||||
cls.sale_order = cls.env['sale.order'].with_context(mail_notrack=True, mail_create_nolog=True).create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'analytic_account_id': cls.analytic_account.id,
|
||||
'pricelist_id': cls.company_data['default_pricelist'].id,
|
||||
})
|
||||
|
||||
cls.Invoice = cls.env['account.move'].with_context(mail_notrack=True, mail_create_nolog=True)
|
||||
@@ -51,20 +46,20 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
""" Test vendor bill at cost for product based on ordered and delivered quantities. """
|
||||
# create SO line and confirm SO (with only one line)
|
||||
sale_order_line1 = self.env['sale.order.line'].create({
|
||||
'name': self.product_ordered_cost.name,
|
||||
'product_id': self.product_ordered_cost.id,
|
||||
'name': self.company_data['product_order_cost'].name,
|
||||
'product_id': self.company_data['product_order_cost'].id,
|
||||
'product_uom_qty': 2,
|
||||
'product_uom': self.product_ordered_cost.uom_id.id,
|
||||
'price_unit': self.product_ordered_cost.list_price,
|
||||
'product_uom': self.company_data['product_order_cost'].uom_id.id,
|
||||
'price_unit': self.company_data['product_order_cost'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
sale_order_line1.product_id_change()
|
||||
sale_order_line2 = self.env['sale.order.line'].create({
|
||||
'name': self.product_deliver_cost.name,
|
||||
'product_id': self.product_deliver_cost.id,
|
||||
'name': self.company_data['product_delivery_cost'].name,
|
||||
'product_id': self.company_data['product_delivery_cost'].id,
|
||||
'product_uom_qty': 4,
|
||||
'product_uom': self.product_deliver_cost.uom_id.id,
|
||||
'price_unit': self.product_deliver_cost.list_price,
|
||||
'product_uom': self.company_data['product_delivery_cost'].uom_id.id,
|
||||
'price_unit': self.company_data['product_delivery_cost'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
sale_order_line2.product_id_change()
|
||||
@@ -84,23 +79,24 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
'task_id': task_sol1.id,
|
||||
'unit_amount': 1,
|
||||
'employee_id': self.employee_user.id,
|
||||
'company_id': self.company_data['company'].id,
|
||||
})
|
||||
|
||||
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_ordered_cost
|
||||
line_form.product_id = self.company_data['product_order_cost']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_deliver_cost
|
||||
line_form.product_id = self.company_data['product_delivery_cost']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_a = move_form.save()
|
||||
invoice_a.post()
|
||||
|
||||
sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.product_ordered_cost)
|
||||
sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.product_deliver_cost)
|
||||
sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.company_data['product_order_cost'])
|
||||
sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.company_data['product_delivery_cost'])
|
||||
|
||||
self.assertTrue(sale_order_line3, "A new sale line should have been created with ordered product")
|
||||
self.assertTrue(sale_order_line4, "A new sale line should have been created with delivered product")
|
||||
@@ -114,28 +110,28 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
self.assertFalse(sale_order_line4.task_id, "Adding a new expense SO line should not create a task (sol4)")
|
||||
self.assertEqual(len(self.sale_order.project_ids), 1, "SO create only one project with its service line. Adding new expense SO line should not impact that")
|
||||
|
||||
self.assertEqual((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.product_ordered_cost.standard_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.product_deliver_cost.standard_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.company_data['product_order_cost'].standard_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.company_data['product_delivery_cost'].standard_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
|
||||
self.assertEqual(sale_order_line3.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line should be computed by analytic amount")
|
||||
self.assertEqual(sale_order_line4.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line should be computed by analytic amount")
|
||||
|
||||
# create second invoice lines and validate it
|
||||
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_ordered_cost
|
||||
line_form.product_id = self.company_data['product_order_cost']
|
||||
line_form.quantity = 2.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_deliver_cost
|
||||
line_form.product_id = self.company_data['product_delivery_cost']
|
||||
line_form.quantity = 2.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_b = move_form.save()
|
||||
invoice_b.post()
|
||||
|
||||
sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.product_ordered_cost)
|
||||
sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.product_deliver_cost)
|
||||
sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.company_data['product_order_cost'])
|
||||
sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.company_data['product_delivery_cost'])
|
||||
|
||||
self.assertTrue(sale_order_line5, "A new sale line should have been created with ordered product")
|
||||
self.assertTrue(sale_order_line6, "A new sale line should have been created with delivered product")
|
||||
@@ -143,8 +139,8 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
self.assertEqual(len(self.sale_order.order_line), 6, "There should be still 4 lines on the SO, no new created")
|
||||
self.assertEqual(len(self.sale_order.order_line.filtered(lambda sol: sol.is_expense)), 4, "There should be still 2 expenses lines on the SO")
|
||||
|
||||
self.assertEqual((sale_order_line5.price_unit, sale_order_line5.qty_delivered, sale_order_line5.product_uom_qty, sale_order_line5.qty_invoiced), (self.product_ordered_cost.standard_price, 2.0, 0, 0), 'Sale line 5 is wrong after confirming 2e vendor invoice')
|
||||
self.assertEqual((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line6.product_uom_qty, sale_order_line6.qty_invoiced), (self.product_deliver_cost.standard_price, 2.0, 0, 0), 'Sale line 6 is wrong after confirming 2e vendor invoice')
|
||||
self.assertEqual((sale_order_line5.price_unit, sale_order_line5.qty_delivered, sale_order_line5.product_uom_qty, sale_order_line5.qty_invoiced), (self.company_data['product_order_cost'].standard_price, 2.0, 0, 0), 'Sale line 5 is wrong after confirming 2e vendor invoice')
|
||||
self.assertEqual((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line6.product_uom_qty, sale_order_line6.qty_invoiced), (self.company_data['product_delivery_cost'].standard_price, 2.0, 0, 0), 'Sale line 6 is wrong after confirming 2e vendor invoice')
|
||||
|
||||
def test_sales_price(self):
|
||||
""" Test invoicing vendor bill at sales price for products based on delivered and ordered quantities. Check no existing SO line is incremented, but when invoicing a
|
||||
@@ -152,22 +148,22 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
"""
|
||||
# create SO line and confirm SO (with only one line)
|
||||
sale_order_line1 = self.env['sale.order.line'].create({
|
||||
'name': self.product_deliver_sales_price.name,
|
||||
'product_id': self.product_deliver_sales_price.id,
|
||||
'name': self.company_data['product_delivery_sales_price'].name,
|
||||
'product_id': self.company_data['product_delivery_sales_price'].id,
|
||||
'product_uom_qty': 2,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.product_deliver_sales_price.uom_id.id,
|
||||
'price_unit': self.product_deliver_sales_price.list_price,
|
||||
'product_uom': self.company_data['product_delivery_sales_price'].uom_id.id,
|
||||
'price_unit': self.company_data['product_delivery_sales_price'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
sale_order_line1.product_id_change()
|
||||
sale_order_line2 = self.env['sale.order.line'].create({
|
||||
'name': self.product_order_sales_price.name,
|
||||
'product_id': self.product_order_sales_price.id,
|
||||
'name': self.company_data['product_order_sales_price'].name,
|
||||
'product_id': self.company_data['product_order_sales_price'].id,
|
||||
'product_uom_qty': 3,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.product_order_sales_price.uom_id.id,
|
||||
'price_unit': self.product_order_sales_price.list_price,
|
||||
'product_uom': self.company_data['product_order_sales_price'].uom_id.id,
|
||||
'price_unit': self.company_data['product_order_sales_price'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
sale_order_line2.product_id_change()
|
||||
@@ -186,20 +182,20 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
|
||||
# create invoice lines and validate it
|
||||
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_deliver_sales_price
|
||||
line_form.product_id = self.company_data['product_delivery_sales_price']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_order_sales_price
|
||||
line_form.product_id = self.company_data['product_order_sales_price']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_a = move_form.save()
|
||||
invoice_a.post()
|
||||
|
||||
sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.product_deliver_sales_price)
|
||||
sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.product_order_sales_price)
|
||||
sale_order_line3 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol.product_id == self.company_data['product_delivery_sales_price'])
|
||||
sale_order_line4 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol.product_id == self.company_data['product_order_sales_price'])
|
||||
|
||||
self.assertTrue(sale_order_line3, "A new sale line should have been created with ordered product")
|
||||
self.assertTrue(sale_order_line4, "A new sale line should have been created with delivered product")
|
||||
@@ -213,28 +209,28 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
self.assertFalse(sale_order_line4.task_id, "Adding a new expense SO line should not create a task (sol4)")
|
||||
self.assertEqual(len(self.sale_order.project_ids), 1, "SO create only one project with its service line. Adding new expense SO line should not impact that")
|
||||
|
||||
self.assertEqual((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.product_deliver_sales_price.list_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.product_order_sales_price.list_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line3.price_unit, sale_order_line3.qty_delivered, sale_order_line3.product_uom_qty, sale_order_line3.qty_invoiced), (self.company_data['product_delivery_sales_price'].list_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
self.assertEqual((sale_order_line4.price_unit, sale_order_line4.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line4.qty_invoiced), (self.company_data['product_order_sales_price'].list_price, 3.0, 0, 0), 'Sale line is wrong after confirming vendor invoice')
|
||||
|
||||
self.assertEqual(sale_order_line3.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line 3 should be computed by analytic amount")
|
||||
self.assertEqual(sale_order_line4.qty_delivered_method, 'analytic', "Delivered quantity of 'expense' SO line 4 should be computed by analytic amount")
|
||||
|
||||
# create second invoice lines and validate it
|
||||
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_deliver_sales_price
|
||||
line_form.product_id = self.company_data['product_delivery_sales_price']
|
||||
line_form.quantity = 2.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_order_sales_price
|
||||
line_form.product_id = self.company_data['product_order_sales_price']
|
||||
line_form.quantity = 2.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_b = move_form.save()
|
||||
invoice_b.post()
|
||||
|
||||
sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.product_deliver_sales_price)
|
||||
sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.product_order_sales_price)
|
||||
sale_order_line5 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line1 and sol != sale_order_line3 and sol.product_id == self.company_data['product_delivery_sales_price'])
|
||||
sale_order_line6 = self.sale_order.order_line.filtered(lambda sol: sol != sale_order_line2 and sol != sale_order_line4 and sol.product_id == self.company_data['product_order_sales_price'])
|
||||
|
||||
self.assertFalse(sale_order_line5, "No new sale line should have been created with delivered product !!")
|
||||
self.assertTrue(sale_order_line6, "A new sale line should have been created with ordered product")
|
||||
@@ -242,18 +238,18 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
self.assertEqual(len(self.sale_order.order_line), 5, "There should be 5 lines on the SO, 1 new created and 1 incremented")
|
||||
self.assertEqual(len(self.sale_order.order_line.filtered(lambda sol: sol.is_expense)), 3, "There should be 3 expenses lines on the SO")
|
||||
|
||||
self.assertEqual((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line6.qty_invoiced), (self.product_order_sales_price.list_price, 2.0, 0, 0), 'Sale line is wrong after confirming 2e vendor invoice')
|
||||
self.assertEqual((sale_order_line6.price_unit, sale_order_line6.qty_delivered, sale_order_line4.product_uom_qty, sale_order_line6.qty_invoiced), (self.company_data['product_order_sales_price'].list_price, 2.0, 0, 0), 'Sale line is wrong after confirming 2e vendor invoice')
|
||||
|
||||
def test_no_expense(self):
|
||||
""" Test invoicing vendor bill with no policy. Check nothing happen. """
|
||||
# confirm SO
|
||||
sale_order_line = self.env['sale.order.line'].create({
|
||||
'name': self.product_no_expense.name,
|
||||
'product_id': self.product_no_expense.id,
|
||||
'name': self.company_data['product_order_no'].name,
|
||||
'product_id': self.company_data['product_order_no'].id,
|
||||
'product_uom_qty': 2,
|
||||
'qty_delivered': 1,
|
||||
'product_uom': self.product_no_expense.uom_id.id,
|
||||
'price_unit': self.product_no_expense.list_price,
|
||||
'product_uom': self.company_data['product_order_no'].uom_id.id,
|
||||
'price_unit': self.company_data['product_order_no'].list_price,
|
||||
'order_id': self.sale_order.id,
|
||||
})
|
||||
self.sale_order._compute_tax_id()
|
||||
@@ -261,9 +257,9 @@ class TestReInvoice(TestCommonSaleTimesheetNoChart):
|
||||
|
||||
# create invoice lines and validate it
|
||||
move_form = Form(self.env['account.move'].with_context(default_move_type='in_invoice'))
|
||||
move_form.partner_id = self.partner_customer_usd
|
||||
move_form.partner_id = self.partner_a
|
||||
with move_form.line_ids.new() as line_form:
|
||||
line_form.product_id = self.product_no_expense
|
||||
line_form.product_id = self.company_data['product_order_no']
|
||||
line_form.quantity = 3.0
|
||||
line_form.analytic_account_id = self.analytic_account
|
||||
invoice_a = move_form.save()
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo.tools import float_is_zero, float_compare
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheetNoChart
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheet
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
class TestReporting(TestCommonSaleTimesheetNoChart):
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestReporting(TestCommonSaleTimesheet):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestReporting, cls).setUpClass()
|
||||
|
||||
cls.setUpEmployees()
|
||||
cls.setUpServiceProducts()
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpAccountJournal()
|
||||
|
||||
# tweak demo data: force currency and remove confusing rates
|
||||
company_currency = cls.env.user.company_id.currency_id
|
||||
cls.env.ref('product.list0').currency_id = company_currency
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
# expense product
|
||||
cls.product_expense = cls.env['product.product'].with_context(mail_notrack=True, mail_create_nolog=True).create({
|
||||
@@ -30,28 +23,28 @@ class TestReporting(TestCommonSaleTimesheetNoChart):
|
||||
'default_code': 'EXP',
|
||||
'service_type': 'manual',
|
||||
'taxes_id': False,
|
||||
'property_account_income_id': cls.account_sale.id,
|
||||
'property_account_income_id': cls.company_data['default_account_revenue'].id,
|
||||
})
|
||||
|
||||
# create Analytic Accounts
|
||||
cls.analytic_account_1 = cls.env['account.analytic.account'].create({
|
||||
'name': 'Test AA 1',
|
||||
'code': 'AA1',
|
||||
'company_id': cls.partner_customer_usd.company_id.id,
|
||||
'partner_id': cls.partner_customer_usd.id
|
||||
'company_id': cls.company_data['company'].id,
|
||||
'partner_id': cls.partner_a.id
|
||||
})
|
||||
cls.analytic_account_2 = cls.env['account.analytic.account'].create({
|
||||
'name': 'Test AA 2',
|
||||
'code': 'AA2',
|
||||
'company_id': cls.partner_customer_usd.company_id.id,
|
||||
'partner_id': cls.partner_customer_usd.id
|
||||
'company_id': cls.company_data['company'].id,
|
||||
'partner_id': cls.partner_a.id
|
||||
})
|
||||
|
||||
# Sale orders each will create project and a task in a global project (one SO is 'delivered', the other is 'ordered')
|
||||
cls.sale_order_1 = cls.env['sale.order'].with_context(mail_notrack=True, mail_create_nolog=True).create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'analytic_account_id': cls.analytic_account_1.id,
|
||||
})
|
||||
cls.so_line_deliver_project = cls.env['sale.order.line'].create({
|
||||
@@ -72,9 +65,9 @@ class TestReporting(TestCommonSaleTimesheetNoChart):
|
||||
})
|
||||
|
||||
cls.sale_order_2 = cls.env['sale.order'].with_context(mail_notrack=True, mail_create_nolog=True).create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
'analytic_account_id': cls.analytic_account_2.id,
|
||||
})
|
||||
cls.so_line_order_project = cls.env['sale.order.line'].create({
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheetNoChart
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheet
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
class TestSaleService(TestCommonSaleTimesheetNoChart):
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestSaleService(TestCommonSaleTimesheet):
|
||||
""" This test suite provide checks for miscellaneous small things. """
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleService, cls).setUpClass()
|
||||
# set up
|
||||
cls.setUpEmployees()
|
||||
cls.setUpServiceProducts()
|
||||
def setUpClass(cls, chart_template_ref=None):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
|
||||
cls.sale_order = cls.env['sale.order'].with_context(mail_notrack=True, mail_create_nolog=True).create({
|
||||
'partner_id': cls.partner_customer_usd.id,
|
||||
'partner_invoice_id': cls.partner_customer_usd.id,
|
||||
'partner_shipping_id': cls.partner_customer_usd.id,
|
||||
'partner_id': cls.partner_a.id,
|
||||
'partner_invoice_id': cls.partner_a.id,
|
||||
'partner_shipping_id': cls.partner_a.id,
|
||||
})
|
||||
|
||||
def test_sale_service(self):
|
||||
|
||||
@@ -5,10 +5,12 @@ from datetime import date, timedelta
|
||||
from odoo.fields import Date
|
||||
from odoo.tools import float_is_zero
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheetNoChart
|
||||
from odoo.addons.sale_timesheet.tests.common import TestCommonSaleTimesheet
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestSaleTimesheet(TestCommonSaleTimesheet):
|
||||
""" This test suite provide tests for the 3 main flows of selling services:
|
||||
- Selling services based on ordered quantities
|
||||
- Selling timesheet based on delivered quantities
|
||||
@@ -17,15 +19,6 @@ class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
quantities changes, ...
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestSaleTimesheet, cls).setUpClass()
|
||||
# set up
|
||||
cls.setUpEmployees()
|
||||
cls.setUpServiceProducts()
|
||||
cls.setUpAdditionalAccounts()
|
||||
cls.setUpAccountJournal()
|
||||
|
||||
def test_timesheet_order(self):
|
||||
""" Test timesheet invoicing with 'invoice on order' timetracked products
|
||||
1. create SO with 2 ordered product and confirm
|
||||
@@ -36,10 +29,10 @@ class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
"""
|
||||
# create SO and confirm it
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_invoice_id': self.partner_customer_usd.id,
|
||||
'partner_shipping_id': self.partner_customer_usd.id,
|
||||
'pricelist_id': self.pricelist_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
})
|
||||
so_line_ordered_project_only = self.env['sale.order.line'].create({
|
||||
'name': self.product_order_timesheet4.name,
|
||||
@@ -173,12 +166,11 @@ class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
6. add new SO line (delivered service)
|
||||
"""
|
||||
# create SO and confirm it
|
||||
self.env['res.currency.rate'].search([]).unlink()
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_invoice_id': self.partner_customer_usd.id,
|
||||
'partner_shipping_id': self.partner_customer_usd.id,
|
||||
'pricelist_id': self.pricelist_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
})
|
||||
so_line_deliver_global_project = self.env['sale.order.line'].create({
|
||||
'name': self.product_delivery_timesheet2.name,
|
||||
@@ -309,10 +301,10 @@ class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
"""
|
||||
# create SO and confirm it
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_invoice_id': self.partner_customer_usd.id,
|
||||
'partner_shipping_id': self.partner_customer_usd.id,
|
||||
'pricelist_id': self.pricelist_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
})
|
||||
so_line_manual_global_project = self.env['sale.order.line'].create({
|
||||
'name': self.product_delivery_manual2.name,
|
||||
@@ -396,10 +388,10 @@ class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
"""
|
||||
today = Date.context_today(self.env.user)
|
||||
sale_order = self.env['sale.order'].create({
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_invoice_id': self.partner_customer_usd.id,
|
||||
'partner_shipping_id': self.partner_customer_usd.id,
|
||||
'pricelist_id': self.pricelist_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'partner_invoice_id': self.partner_a.id,
|
||||
'partner_shipping_id': self.partner_a.id,
|
||||
'pricelist_id': self.company_data['default_pricelist'].id,
|
||||
})
|
||||
so_line_deliver_global_project = self.env['sale.order.line'].create({
|
||||
'name': self.product_delivery_timesheet2.name,
|
||||
@@ -469,7 +461,7 @@ class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
'active_model': 'sale.order',
|
||||
'active_ids': [sale_order.id],
|
||||
'active_id': sale_order.id,
|
||||
'default_journal_id': self.journal_sale.id
|
||||
'default_journal_id': self.company_data['default_journal_sale'].id
|
||||
}
|
||||
|
||||
# invoice SO
|
||||
@@ -530,7 +522,7 @@ class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
|
||||
task = Task.with_context(default_project_id=self.project_global.id).create({
|
||||
'name': 'first task',
|
||||
'partner_id': self.partner_customer_usd.id,
|
||||
'partner_id': self.partner_a.id,
|
||||
'planned_hours': 10,
|
||||
})
|
||||
|
||||
@@ -569,7 +561,7 @@ class TestSaleTimesheet(TestCommonSaleTimesheetNoChart):
|
||||
'active_model': 'sale.order',
|
||||
'active_ids': [sale_order.id],
|
||||
'active_id': sale_order.id,
|
||||
'default_journal_id': self.journal_sale.id
|
||||
'default_journal_id': self.company_data['default_journal_sale'].id
|
||||
}
|
||||
wizard = self.env['sale.advance.payment.inv'].with_context(self.context).create({
|
||||
'advance_payment_method': 'delivered',
|
||||
|
||||
Reference in New Issue
Block a user