From 0004c3f380d6c540ea2299e3679489b5b3554abf Mon Sep 17 00:00:00 2001 From: Magno Costa Date: Thu, 23 Nov 2023 18:08:40 -0300 Subject: [PATCH 1/4] [REF] l10n_br_stock_account: Make module compatible with the international cases --- l10n_br_stock_account/models/stock_move.py | 14 +++++++++++-- .../wizards/stock_invoice_onshipping.py | 20 +++++++++++-------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/l10n_br_stock_account/models/stock_move.py b/l10n_br_stock_account/models/stock_move.py index f5565219b81e..4446ec0d0a6b 100644 --- a/l10n_br_stock_account/models/stock_move.py +++ b/l10n_br_stock_account/models/stock_move.py @@ -113,12 +113,18 @@ def _prepare_merge_move_sort_method(self, move): return keys_sorted def _prepare_extra_move_vals(self, qty): - values = self._prepare_br_fiscal_dict() + values = {} + if self.fiscal_operation_id: + # Caso Brasil se caracteriza por ter Operação Fiscal + values = self._prepare_br_fiscal_dict() values.update(super()._prepare_extra_move_vals(qty)) return values def _prepare_move_split_vals(self, uom_qty): - values = self._prepare_br_fiscal_dict() + values = {} + if self.fiscal_operation_id: + # Caso Brasil se caracteriza por ter Operação Fiscal + values = self._prepare_br_fiscal_dict() values.update(super()._prepare_move_split_vals(uom_qty)) return values @@ -163,6 +169,10 @@ def _onchange_product_id_fiscal(self): def _split(self, qty, restrict_partner_id=False): new_moves_vals = super()._split(qty, restrict_partner_id) + if not self.fiscal_operation_id: + # Caso Brasil se caracteriza por ter Operação Fiscal + return new_moves_vals + self._onchange_commercial_quantity() self._onchange_fiscal_taxes() diff --git a/l10n_br_stock_account/wizards/stock_invoice_onshipping.py b/l10n_br_stock_account/wizards/stock_invoice_onshipping.py index 9fa4c2283666..f1faace8a6a2 100644 --- a/l10n_br_stock_account/wizards/stock_invoice_onshipping.py +++ b/l10n_br_stock_account/wizards/stock_invoice_onshipping.py @@ -58,26 +58,26 @@ def _get_journal(self): def _build_invoice_values_from_pickings(self, pickings): invoice, values = super()._build_invoice_values_from_pickings(pickings) - pick = fields.first(pickings) - if not pick.fiscal_operation_id: + picking = fields.first(pickings) + if not picking.fiscal_operation_id: # Caso de Fatura Internacional, sem os dados Fiscais do Brasil return invoice, values - fiscal_vals = pick._prepare_br_fiscal_dict() + fiscal_vals = picking._prepare_br_fiscal_dict() - document_type = pick.company_id.document_type_id - document_type_id = pick.company_id.document_type_id.id + document_type = picking.company_id.document_type_id + document_type_id = picking.company_id.document_type_id.id fiscal_vals["document_type_id"] = document_type_id document_serie = document_type.get_document_serie( - pick.company_id, pick.fiscal_operation_id + picking.company_id, picking.fiscal_operation_id ) if document_serie: fiscal_vals["document_serie_id"] = document_serie.id - if pick.fiscal_operation_id and pick.fiscal_operation_id.journal_id: - fiscal_vals["journal_id"] = pick.fiscal_operation_id.journal_id.id + if picking.fiscal_operation_id and picking.fiscal_operation_id.journal_id: + fiscal_vals["journal_id"] = picking.fiscal_operation_id.journal_id.id # Endereço de Entrega diferente do Endereço de Faturamento # so informado quando é diferente @@ -108,6 +108,10 @@ def _get_invoice_line_values(self, moves, invoice_values, invoice): values = super()._get_invoice_line_values(moves, invoice_values, invoice) move = fields.first(moves) + if not move.fiscal_operation_id: + # Caso Brasileiro se caracteriza pela Operação Fiscal + return values + fiscal_values = move._prepare_br_fiscal_dict() # A Fatura não pode ser criada com os campos price_unit e fiscal_price From cf597e445e52583bb8074665cc4228018f2f069c Mon Sep 17 00:00:00 2001 From: Magno Costa Date: Thu, 23 Nov 2023 18:14:55 -0300 Subject: [PATCH 2/4] [REF+IMP] l10n_br_stock_account: Demo Data, Reduce XML ID names, included Pickings for Simples Nacional and Product Inventory to avoid necessity for Force Qty Done during tests. --- l10n_br_stock_account/__manifest__.py | 1 + .../demo/l10n_br_stock_account_demo.xml | 366 ++++++++++++++---- .../demo/stock_inventory_demo.xml | 132 +++++++ 3 files changed, 413 insertions(+), 86 deletions(-) create mode 100644 l10n_br_stock_account/demo/stock_inventory_demo.xml diff --git a/l10n_br_stock_account/__manifest__.py b/l10n_br_stock_account/__manifest__.py index 0313c88c2e53..ab90d4e92152 100644 --- a/l10n_br_stock_account/__manifest__.py +++ b/l10n_br_stock_account/__manifest__.py @@ -33,6 +33,7 @@ "demo/company_demo.xml", "demo/l10n_br_stock_account_demo.xml", "demo/account_journal_demo.xml", + "demo/stock_inventory_demo.xml", ], "installable": True, "post_init_hook": "post_init_hook", diff --git a/l10n_br_stock_account/demo/l10n_br_stock_account_demo.xml b/l10n_br_stock_account/demo/l10n_br_stock_account_demo.xml index 3256fad2d61c..4b3e4c3c253d 100644 --- a/l10n_br_stock_account/demo/l10n_br_stock_account_demo.xml +++ b/l10n_br_stock_account/demo/l10n_br_stock_account_demo.xml @@ -61,7 +61,7 @@ --> - + @@ -72,14 +72,14 @@ - + Test - l10n_br_stock_account - 1 2 - + 2binvoiced @@ -95,25 +95,25 @@ - + - + - + - + Test - l10n_br_stock_account - 1 2 - + 2binvoiced @@ -129,26 +129,26 @@ - + - + - + - + Test - l10n_br_stock_account - 1 2 - + 2binvoiced @@ -164,19 +164,19 @@ - + - + - + - + @@ -187,14 +187,14 @@ - + Test - l10n_br_stock_account - 2 2 - + 2binvoiced @@ -210,25 +210,25 @@ - + - + - + - + Test - l10n_br_stock_account - 1 2 - + 2binvoiced @@ -244,26 +244,26 @@ - + - + - + - + Test - l10n_br_stock_account - 1 2 - + 2binvoiced @@ -279,15 +279,15 @@ - + - + - + @@ -295,7 +295,7 @@ relação com um Pedido de Venda/Compras a opção de ter um Endereço de Entrega diferente do de Faturamento precirá ser feita manualmente na Fatura/Doc Fiscal criados.--> - + @@ -308,7 +308,7 @@ - + Test - l10n_br_stock_account 1 - Endereço entrega diferente Faturamento @@ -317,7 +317,7 @@ 2 - + 2binvoiced @@ -333,18 +333,18 @@ - + - + - + - + Teste - l10n_br_stock_account 1 - Endereço entrega diferente Faturamento @@ -353,7 +353,7 @@ 2 - + 2binvoiced @@ -369,19 +369,19 @@ - + - + - + - + Teste - l10n_br_stock_account 1 - Endereço entrega diferente Faturamento @@ -390,7 +390,7 @@ 2 - + 2binvoiced @@ -406,19 +406,19 @@ - + - + - + - + @@ -431,7 +431,7 @@ - + Test - l10n_br_stock_account 1 - Endereço entrega diferente Faturamento @@ -440,7 +440,7 @@ 2 - + 2binvoiced @@ -456,18 +456,18 @@ - + - + - + - + Teste - l10n_br_stock_account 1 - Endereço entrega diferente Faturamento @@ -476,7 +476,7 @@ 2 - + 2binvoiced @@ -492,19 +492,19 @@ - + - + - + - + Teste - l10n_br_stock_account 1 - Endereço entrega diferente Faturamento @@ -513,7 +513,7 @@ 2 - + 2binvoiced @@ -529,22 +529,22 @@ - + - + - + - + - + Test - l10n_br_stock_account - 1 @@ -573,7 +573,7 @@ --> 3645.00 - + - + - + - + - + Test - l10n_br_stock_account - 1 2 12.50 - + - + - + - + - + - + Test - l10n_br_stock_account - 1 @@ -670,7 +670,7 @@ --> 3645.00 - + - + - + - + - + Test - l10n_br_stock_account - 1 2 12.50 - + - + - + - + + + + + + + + + + 2binvoiced + Teste l10n_br_stock_account - Simples Nacional + + + + + + Test - l10n_br_stock_account - 1 + + + + 2 + + 3645.00 + + + + + 2binvoiced + + + + 100 + 100 + 100 + + + + + + + + + + + + + + + + Test - l10n_br_stock_account - 1 + + + 2 + 12.50 + + + + + 2binvoiced + + + + 100 + 100 + 100 + + + + + + + + + + + + + + + + + + + + + 2binvoiced + Test l10n_br_stock_account - Simples Nacional + + + + + + Test - l10n_br_stock_account - 1 + + + + 2 + + 3645.00 + + + + + 2binvoiced + + + + 100 + 100 + 100 + + + + + + + + + + + + + + + + Test - l10n_br_stock_account - 1 + + + 2 + 12.50 + + + + + 2binvoiced + + + + 100 + 100 + 100 + + + + + + + + + + + + diff --git a/l10n_br_stock_account/demo/stock_inventory_demo.xml b/l10n_br_stock_account/demo/stock_inventory_demo.xml new file mode 100644 index 000000000000..21a1b6b1c180 --- /dev/null +++ b/l10n_br_stock_account/demo/stock_inventory_demo.xml @@ -0,0 +1,132 @@ + + + + + + Inventário Inicial l10n_br_stock_account - Empresa Principal + + + + + + + + 100.0 + + + + + + + + 100.0 + + + + + + + + + + + + + Inventário Inicial l10n_br_stock_account - Simples Nacional + + + + + + + + 100.0 + + + + + + + 100.0 + + + + + + + + + + + + + + Inventário Inicial l10n_br_stock_account - Lucro Presumido + + + + + + + + 100.0 + + + + + + + 100.0 + + + + + + + + + + + From 1c1a5e64bb04eb3ac114601c9055970cbfac5436 Mon Sep 17 00:00:00 2001 From: Magno Costa Date: Thu, 23 Nov 2023 18:18:27 -0300 Subject: [PATCH 3/4] [REF+IMP] l10n_br_stock_account: Tests, reducing duplicate code and included other tests. --- l10n_br_stock_account/tests/__init__.py | 1 + l10n_br_stock_account/tests/common.py | 86 ++++ .../tests/test_invoicing_picking.py | 475 +++++++----------- .../tests/test_stock_rule.py | 25 +- 4 files changed, 286 insertions(+), 301 deletions(-) create mode 100644 l10n_br_stock_account/tests/common.py diff --git a/l10n_br_stock_account/tests/__init__.py b/l10n_br_stock_account/tests/__init__.py index 43170eb97553..5f2833209746 100644 --- a/l10n_br_stock_account/tests/__init__.py +++ b/l10n_br_stock_account/tests/__init__.py @@ -1,2 +1,3 @@ +from . import common from . import test_invoicing_picking from . import test_stock_rule diff --git a/l10n_br_stock_account/tests/common.py b/l10n_br_stock_account/tests/common.py new file mode 100644 index 000000000000..c0a5b5767abb --- /dev/null +++ b/l10n_br_stock_account/tests/common.py @@ -0,0 +1,86 @@ +# Copyright (C) 2023-Today - Akretion (). +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import Form, TransactionCase + + +class TestBrPickingInvoicingCommon(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + def _change_user_company(self, company): + self.env.user.company_ids += company + self.env.user.company_id = company + + def _run_fiscal_onchanges(self, record): + record._onchange_fiscal_operation_id() + + def _run_fiscal_line_onchanges(self, record): + # Mixin Fiscal + record._onchange_commercial_quantity() + + # Stock Move + record._onchange_product_id_fiscal() + record._onchange_fiscal_operation_id() + record._onchange_fiscal_operation_line_id() + record._onchange_fiscal_taxes() + record._onchange_product_quantity() + + def picking_move_state(self, picking): + self._run_fiscal_onchanges(picking) + picking.action_confirm() + # Check product availability + picking.action_assign() + # Force product availability + for move in picking.move_ids_without_package: + self._run_fiscal_line_onchanges(move) + move.quantity_done = move.product_uom_qty + picking.button_validate() + + def create_invoice_wizard(self, pickings): + wizard_obj = self.env["stock.invoice.onshipping"].with_context( + active_ids=pickings.ids, + active_model=pickings._name, + ) + fields_list = wizard_obj.fields_get().keys() + wizard_values = wizard_obj.default_get(fields_list) + # One invoice per partner but group products + wizard_values.update({"group": "partner_product"}) + wizard = wizard_obj.create(wizard_values) + wizard.onchange_group() + wizard.action_generate() + domain = [("picking_ids", "in", pickings.ids)] + invoice = self.env["account.move"].search(domain) + return invoice + + def return_picking_wizard(self, picking): + # Return Picking + return_wizard_form = Form( + self.env["stock.return.picking"].with_context( + **dict(active_id=picking.id, active_model="stock.picking") + ) + ) + return_wizard_form.invoice_state = "2binvoiced" + self.return_wizard = return_wizard_form.save() + + result_wizard = self.return_wizard.create_returns() + self.assertTrue(result_wizard, "Create returns wizard fail.") + picking_devolution = self.env["stock.picking"].browse( + result_wizard.get("res_id") + ) + return picking_devolution + + def create_backorder_wizard(self, picking): + res_dict_for_back_order = picking.button_validate() + backorder_wizard = Form( + self.env[res_dict_for_back_order["res_model"]].with_context( + **res_dict_for_back_order["context"] + ) + ).save() + backorder_wizard.process() + backorder = self.env["stock.picking"].search( + [("backorder_id", "=", picking.id)] + ) + return backorder diff --git a/l10n_br_stock_account/tests/test_invoicing_picking.py b/l10n_br_stock_account/tests/test_invoicing_picking.py index 09df488d3c6d..43a85ea75f16 100644 --- a/l10n_br_stock_account/tests/test_invoicing_picking.py +++ b/l10n_br_stock_account/tests/test_invoicing_picking.py @@ -1,74 +1,31 @@ -# @ 2019 Akretion - www.akretion.com.br - -# Magno Costa -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +# Copyright (C) 2019-Today - Akretion (). +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo.tests import Form, SavepointCase +from odoo.tests import Form +from .common import TestBrPickingInvoicingCommon -class InvoicingPickingTest(SavepointCase): + +class InvoicingPickingTest(TestBrPickingInvoicingCommon): """Test invoicing picking""" @classmethod def setUpClass(cls): super().setUpClass() - cls.stock_picking = cls.env["stock.picking"] - cls.invoice_model = cls.env["account.move"] - cls.invoice_wizard = cls.env["stock.invoice.onshipping"] - cls.stock_return_picking = cls.env["stock.return.picking"] - cls.stock_picking_sp = cls.env.ref( - "l10n_br_stock_account.demo_main_l10n_br_stock_account-picking-1" - ) - cls.stock_picking_sp_lp = cls.env.ref( - "l10n_br_stock_account.demo_l10n_br_stock_account-picking-1" - ) - cls.partner = cls.env.ref("l10n_br_base.res_partner_cliente1_sp") - cls.company_lucro_presumido = cls.env.ref( - "l10n_br_base.empresa_lucro_presumido" - ) - cls.company = cls.env.ref("base.main_company") - - def _run_fiscal_onchanges(self, record): - record._onchange_fiscal_operation_id() - - def _run_fiscal_line_onchanges(self, record): - # Mixin Fiscal - record._onchange_commercial_quantity() - - # Stock Move - record._onchange_product_id_fiscal() - record._onchange_fiscal_operation_id() - record._onchange_fiscal_operation_line_id() - record._onchange_fiscal_taxes() - record._onchange_product_quantity() - - def _change_user_company(self, company): - self.env.user.company_ids += company - self.env.user.company_id = company def test_invoicing_picking(self): """Test Invoicing Picking""" - self._change_user_company(self.company) - + self._change_user_company(self.env.ref("base.main_company")) + picking = self.env.ref("l10n_br_stock_account.main_company-picking_1") # Testa os Impostos Dedutiveis - self.stock_picking_sp.fiscal_operation_id.deductible_taxes = True - nb_invoice_before = self.invoice_model.search_count([]) - self._run_fiscal_onchanges(self.stock_picking_sp) - - for line in self.stock_picking_sp.move_lines: - self._run_fiscal_line_onchanges(line) - - self.stock_picking_sp.action_confirm() - self.stock_picking_sp.action_assign() - - # Force product availability - for move in self.stock_picking_sp.move_ids_without_package: - move.quantity_done = move.product_uom_qty - self.stock_picking_sp.button_validate() - self.assertEqual(self.stock_picking_sp.state, "done", "Change state fail.") + picking.fiscal_operation_id.deductible_taxes = True + nb_invoice_before = self.env["account.move"].search_count([]) + self.picking_move_state(picking) # Verificar os Valores de Preço pois isso é usado na Valorização do # Estoque, o metodo do core é chamado pelo botão Validate - for line in self.stock_picking_sp.move_lines: + for line in picking.move_lines: # No Brasil o caso de Ordens de Entrega que não tem ligação com # Pedido de Venda precisam informar o Preço de Custo e não o de # Venda, ex.: Simples Remessa, Remessa p/ Industrialiazação e etc. @@ -82,31 +39,21 @@ def test_invoicing_picking(self): # ele traz o valor do lst_price e falha no teste abaixo # TODO - o fiscal_price aqui tbm deve ter um valor negativo ? - wizard_obj = self.invoice_wizard.with_context( - active_ids=self.stock_picking_sp.ids, - active_model=self.stock_picking_sp._name, - active_id=self.stock_picking_sp.id, - ) - fields_list = wizard_obj.fields_get().keys() - wizard_values = wizard_obj.default_get(fields_list) - wizard = wizard_obj.create(wizard_values) - wizard.onchange_group() - wizard.with_context(default_company_id=self.company.id).action_generate() - domain = [("picking_ids", "=", self.stock_picking_sp.id)] - invoice = self.invoice_model.search(domain) - + invoice = self.create_invoice_wizard(picking) self.assertTrue(invoice, "Invoice is not created.") - self.assertEqual(self.stock_picking_sp.invoice_state, "invoiced") - self.assertEqual(invoice.partner_id, self.partner) - self.assertIn(invoice, self.stock_picking_sp.invoice_ids) - self.assertIn(self.stock_picking_sp, invoice.picking_ids) - nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual( + invoice.partner_id, self.env.ref("l10n_br_base.res_partner_cliente1_sp") + ) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + nb_invoice_after = self.env["account.move"].search_count([]) self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice)) assert invoice.invoice_line_ids, "Error to create invoice line." for line in invoice.picking_ids: self.assertEqual( line.id, - self.stock_picking_sp.id, + picking.id, "Relation between invoice and picking are missing.", ) for line in invoice.invoice_line_ids: @@ -137,20 +84,7 @@ def test_invoicing_picking(self): "Mapping Fiscal Documentation_id on wizard to create invoice fail.", ) - picking = self.stock_picking_sp - return_wizard_form = Form( - self.stock_return_picking.with_context( - active_id=picking.id, active_model="stock.picking" - ) - ) - return_wizard_form.invoice_state = "2binvoiced" - self.return_wizard = return_wizard_form.save() - result_wizard = self.return_wizard.create_returns() - - self.assertTrue(result_wizard, "Create returns wizard fail.") - - picking_devolution = self.stock_picking.browse(result_wizard.get("res_id")) - + picking_devolution = self.return_picking_wizard(picking) self.assertEqual(picking_devolution.invoice_state, "2binvoiced") self.assertTrue( picking_devolution.fiscal_operation_id, "Missing Fiscal Operation." @@ -162,12 +96,7 @@ def test_invoicing_picking(self): self.assertTrue( line.fiscal_operation_line_id, "Missing Fiscal Operation Line." ) - picking_devolution.action_confirm() - picking_devolution.action_assign() - # Force product availability - for move in picking_devolution.move_ids_without_package: - move.quantity_done = move.product_uom_qty - picking_devolution.button_validate() + self.picking_move_state(picking_devolution) self.assertEqual(picking_devolution.state, "done", "Change state fail.") def test_picking_invoicing_by_product2(self): @@ -178,53 +107,24 @@ def test_picking_invoicing_by_product2(self): lines (and qty 2) :return: """ - nb_invoice_before = self.invoice_model.search_count([]) - self._change_user_company(self.company) - self.invoice_model.search_count([]) - self.partner.write({"type": "invoice"}) - picking = self.env.ref( - "l10n_br_stock_account.demo_main_l10n_br_stock_account-picking-1" - ) - picking.action_confirm() - # Check product availability - picking.action_assign() - # Force product availability - for move in picking.move_ids_without_package: - move.quantity_done = move.product_uom_qty - picking.button_validate() - picking2 = self.env.ref( - "l10n_br_stock_account.demo_main_l10n_br_stock_account-picking-2" - ) - # Check product availability - picking2.action_assign() - # Force product availability - for move in picking2.move_ids_without_package: - move.quantity_done = move.product_uom_qty - picking2.button_validate() + nb_invoice_before = self.env["account.move"].search_count([]) + self._change_user_company(self.env.ref("base.main_company")) + self.env["account.move"].search_count([]) + self.env.ref("l10n_br_base.res_partner_cliente1_sp").write({"type": "invoice"}) + picking = self.env.ref("l10n_br_stock_account.main_company-picking_1") + self.picking_move_state(picking) + picking2 = self.env.ref("l10n_br_stock_account.main_company-picking_2") + self.picking_move_state(picking2) self.assertEqual(picking.state, "done") self.assertEqual(picking2.state, "done") pickings = picking | picking2 - wizard_obj = self.invoice_wizard.with_context( - active_ids=pickings.ids, - active_model=pickings._name, - ) - fields_list = wizard_obj.fields_get().keys() - wizard_values = wizard_obj.default_get(fields_list) - # One invoice per partner but group products - wizard_values.update( - { - "group": "partner_product", - } - ) - wizard = wizard_obj.create(wizard_values) - wizard.onchange_group() - wizard.with_context(default_company_id=self.company.id).action_generate() - domain = [("picking_ids", "=", picking.id)] - invoice = self.invoice_model.search(domain) + invoice = self.create_invoice_wizard(pickings) self.assertEqual(len(invoice), 1) self.assertEqual(picking.invoice_state, "invoiced") self.assertEqual(picking2.invoice_state, "invoiced") - self.assertEqual(invoice.partner_id, self.partner) + self.assertEqual( + invoice.partner_id, self.env.ref("l10n_br_base.res_partner_cliente1_sp") + ) self.assertIn(invoice, picking.invoice_ids) self.assertIn(invoice, picking2.invoice_ids) self.assertIn(picking, invoice.picking_ids) @@ -247,7 +147,7 @@ def test_picking_invoicing_by_product2(self): invoice.unlink() for picking in pickings: self.assertEqual(picking.invoice_state, "2binvoiced") - nb_invoice_after = self.invoice_model.search_count([]) + nb_invoice_after = self.env["account.move"].search_count([]) # Should be equals because we delete the invoice self.assertEqual(nb_invoice_before, nb_invoice_after) @@ -259,49 +159,18 @@ def test_picking_invoicing_by_product3(self): with 3 lines (and qty 2) :return: """ - nb_invoice_before = self.invoice_model.search_count([]) - self._change_user_company(self.company) - self.invoice_model.search_count([]) - self.partner.write({"type": "invoice"}) - picking = self.env.ref( - "l10n_br_stock_account.demo_main_l10n_br_stock_account-picking-3" - ) - picking.action_confirm() - # Check product availability - picking.action_assign() - # Force product availability - for move in picking.move_ids_without_package: - move.quantity_done = move.product_uom_qty - picking.button_validate() - picking2 = self.env.ref( - "l10n_br_stock_account.demo_main_l10n_br_stock_account-picking-4" - ) - # Check product availability - picking2.action_assign() - # Force product availability - for move in picking2.move_ids_without_package: - move.quantity_done = move.product_uom_qty - picking2.button_validate() + nb_invoice_before = self.env["account.move"].search_count([]) + self._change_user_company(self.env.ref("base.main_company")) + self.env["account.move"].search_count([]) + self.env.ref("l10n_br_base.res_partner_cliente1_sp").write({"type": "invoice"}) + picking = self.env.ref("l10n_br_stock_account.main_company-picking_3") + self.picking_move_state(picking) + picking2 = self.env.ref("l10n_br_stock_account.main_company-picking_4") + self.picking_move_state(picking2) self.assertEqual(picking.state, "done") self.assertEqual(picking2.state, "done") pickings = picking | picking2 - wizard_obj = self.invoice_wizard.with_context( - active_ids=pickings.ids, - active_model=pickings._name, - ) - fields_list = wizard_obj.fields_get().keys() - wizard_values = wizard_obj.default_get(fields_list) - # One invoice per partner but group products - wizard_values.update( - { - "group": "partner_product", - } - ) - wizard = wizard_obj.create(wizard_values) - wizard.onchange_group() - wizard.with_context(default_company_id=self.company.id).action_generate() - domain = [("picking_ids", "in", (picking.id, picking2.id))] - invoicies = self.invoice_model.search(domain) + invoicies = self.create_invoice_wizard(pickings) self.assertEqual(len(invoicies), 2) self.assertEqual(picking.invoice_state, "invoiced") self.assertEqual(picking2.invoice_state, "invoiced") @@ -340,16 +209,14 @@ def test_picking_invoicing_by_product3(self): invoice_pick_2.unlink() for picking in pickings: self.assertEqual(picking.invoice_state, "2binvoiced") - nb_invoice_after = self.invoice_model.search_count([]) + nb_invoice_after = self.env["account.move"].search_count([]) # Should be equals because we delete the invoice self.assertEqual(nb_invoice_before, nb_invoice_after) def test_picking_split(self): """Test Picking Split created with Fiscal Values.""" - self._change_user_company(self.company) - picking2 = self.env.ref( - "l10n_br_stock_account.demo_main_l10n_br_stock_account-picking-2" - ) + self._change_user_company(self.env.ref("base.main_company")) + picking2 = self.env.ref("l10n_br_stock_account.main_company-picking_2") self._run_fiscal_onchanges(picking2) @@ -363,16 +230,8 @@ def test_picking_split(self): # Force Split move.quantity_done = 1 - res_dict_for_back_order = picking2.button_validate() - backorder_wizard = Form( - self.env[res_dict_for_back_order["res_model"]].with_context( - **res_dict_for_back_order["context"] - ) - ).save() - backorder_wizard.process() - backorder = self.env["stock.picking"].search( - [("backorder_id", "=", picking2.id)] - ) + # Return Wizard + backorder = self.create_backorder_wizard(picking2) self.assertEqual(backorder.invoice_state, "2binvoiced") self.assertTrue(backorder.fiscal_operation_id) @@ -382,35 +241,22 @@ def test_picking_split(self): self.assertEqual(line.invoice_state, "2binvoiced") self.assertTrue(line.fiscal_tax_ids, "Taxes in Split Picking are missing.") - backorder.action_confirm() - backorder.action_assign() - backorder.button_validate() + self.picking_move_state(backorder) # Testando o Lucro Presumido def test_invoicing_picking_lucro_presumido(self): """Test Invoicing Picking - Lucro Presumido""" - self._change_user_company(self.company_lucro_presumido) + self._change_user_company(self.env.ref("l10n_br_base.empresa_lucro_presumido")) + picking = self.env.ref("l10n_br_stock_account.lucro_presumido-picking_1") + nb_invoice_before = self.env["account.move"].search_count([]) - nb_invoice_before = self.invoice_model.search_count([]) - self._run_fiscal_onchanges(self.stock_picking_sp_lp) - - for line in self.stock_picking_sp_lp.move_lines: - self._run_fiscal_line_onchanges(line) - - self.stock_picking_sp_lp.action_confirm() - self.stock_picking_sp_lp.action_assign() - - # Force product availability - for move in self.stock_picking_sp_lp.move_ids_without_package: - move.quantity_done = move.product_uom_qty - - self.stock_picking_sp_lp.button_validate() - self.assertEqual(self.stock_picking_sp_lp.state, "done", "Change state fail.") + self.picking_move_state(picking) + self.assertEqual(picking.state, "done", "Change state fail.") # Verificar os Valores de Preço pois isso é usado na Valorização do # Estoque, o metodo do core é chamado pelo botão Validate - for line in self.stock_picking_sp_lp.move_lines: + for line in picking.move_lines: # No Brasil o caso de Ordens de Entrega que não tem ligação com # Pedido de Venda precisam informar o Preço de Custo e não o de # Venda, ex.: Simples Remessa, Remessa p/ Industrialiazação e etc. @@ -425,33 +271,21 @@ def test_invoicing_picking_lucro_presumido(self): # TODO - o fiscal_price aqui tbm deve ter um valor negativo ? self.assertEqual(line.fiscal_price, line.price_unit) - wizard_obj = self.invoice_wizard.with_context( - active_ids=self.stock_picking_sp_lp.ids, - active_model=self.stock_picking_sp_lp._name, - active_id=self.stock_picking_sp_lp.id, - ) - fields_list = wizard_obj.fields_get().keys() - wizard_values = wizard_obj.default_get(fields_list) - wizard = wizard_obj.create(wizard_values) - wizard.onchange_group() - wizard.with_context( - default_company_id=self.company_lucro_presumido.id - ).action_generate() - domain = [("picking_ids", "=", self.stock_picking_sp_lp.id)] - invoice = self.invoice_model.search(domain) - + invoice = self.create_invoice_wizard(picking) self.assertTrue(invoice, "Invoice is not created.") - self.assertEqual(self.stock_picking_sp_lp.invoice_state, "invoiced") - self.assertEqual(invoice.partner_id, self.partner) - self.assertIn(invoice, self.stock_picking_sp_lp.invoice_ids) - self.assertIn(self.stock_picking_sp_lp, invoice.picking_ids) - nb_invoice_after = self.invoice_model.search_count([]) + self.assertEqual(picking.invoice_state, "invoiced") + self.assertEqual( + invoice.partner_id, self.env.ref("l10n_br_base.res_partner_cliente1_sp") + ) + self.assertIn(invoice, picking.invoice_ids) + self.assertIn(picking, invoice.picking_ids) + nb_invoice_after = self.env["account.move"].search_count([]) self.assertEqual(nb_invoice_before, nb_invoice_after - len(invoice)) assert invoice.invoice_line_ids, "Error to create invoice line." for line in invoice.picking_ids: self.assertEqual( line.id, - self.stock_picking_sp_lp.id, + picking.id, "Relation between invoice and picking are missing.", ) for line in invoice.invoice_line_ids: @@ -476,20 +310,7 @@ def test_invoicing_picking_lucro_presumido(self): "Mapping Fiscal Documentation_id on wizard to create invoice fail.", ) - picking = self.stock_picking_sp_lp - return_wizard_form = Form( - self.stock_return_picking.with_context( - active_id=picking.id, active_model="stock.picking" - ) - ) - return_wizard_form.invoice_state = "2binvoiced" - self.return_wizard = return_wizard_form.save() - result_wizard = self.return_wizard.create_returns() - - self.assertTrue(result_wizard, "Create returns wizard fail.") - - picking_devolution = self.stock_picking.browse(result_wizard.get("res_id")) - + picking_devolution = self.return_picking_wizard(picking) self.assertEqual(picking_devolution.invoice_state, "2binvoiced") self.assertTrue( picking_devolution.fiscal_operation_id, "Missing Fiscal Operation." @@ -501,19 +322,14 @@ def test_invoicing_picking_lucro_presumido(self): self.assertTrue( line.fiscal_operation_line_id, "Missing Fiscal Operation Line." ) - picking_devolution.action_confirm() - picking_devolution.action_assign() - # Force product availability - for move in picking_devolution.move_ids_without_package: - move.quantity_done = move.product_uom_qty - picking_devolution.button_validate() + self.picking_move_state(picking_devolution) self.assertEqual(picking_devolution.state, "done", "Change state fail.") # Now test behaviour if the invoice is delete invoice.unlink() self.assertEqual(picking.invoice_state, "2binvoiced") - nb_invoice_after = self.invoice_model.search_count([]) + nb_invoice_after = self.env["account.move"].search_count([]) # Should be equals because we delete the invoice self.assertEqual(nb_invoice_before, nb_invoice_after) @@ -522,57 +338,52 @@ def test_fields_freight_insurance_other_costs(self): defined or By Line or By Total in Stock Picking. """ - self._change_user_company(self.company) - + self._change_user_company(self.env.ref("base.main_company")) # Por padrão a definição dos campos está por Linha - self.stock_picking_sp.company_id.delivery_costs = "line" + picking = self.env.ref("l10n_br_stock_account.main_company-picking_1") + picking.company_id.delivery_costs = "line" # Teste definindo os valores Por Linha - for line in self.stock_picking_sp.move_ids_without_package: + for line in picking.move_ids_without_package: line.price_unit = 100.0 line.freight_value = 10.0 line.insurance_value = 10.0 line.other_value = 10.0 line.quantity_done = line.product_uom_qty - self.stock_picking_sp.button_validate() - self.assertEqual(self.stock_picking_sp.state, "done", "Change state fail.") - - for line in self.stock_picking_sp.move_lines: - self._run_fiscal_line_onchanges(line) - - self.stock_picking_sp.action_confirm() + self.picking_move_state(picking) + self.assertEqual(picking.state, "done", "Change state fail.") # TODO: Os campos Totais não estão sendo atualizados mesmo # rodando os onchanges e confirmando o Picking, na tela esse # problema não acontece - self.stock_picking_sp._amount_all() + picking._amount_all() self.assertEqual( - self.stock_picking_sp.amount_freight_value, + picking.amount_freight_value, 30.0, "Unexpected value for the field Amount Freight in Stock Picking.", ) self.assertEqual( - self.stock_picking_sp.amount_insurance_value, + picking.amount_insurance_value, 30.0, "Unexpected value for the field Amount Insurance in Stock Picking.", ) self.assertEqual( - self.stock_picking_sp.amount_other_value, + picking.amount_other_value, 30.0, "Unexpected value for the field Amount Other in Stock Picking.", ) # Teste definindo os valores Por Total # Por padrão a definição dos campos está por Linha - self.stock_picking_sp.company_id.delivery_costs = "total" + picking.company_id.delivery_costs = "total" # Caso que os Campos na Linha tem valor - self.stock_picking_sp.amount_freight_value = 9.0 - self.stock_picking_sp.amount_insurance_value = 9.0 - self.stock_picking_sp.amount_other_value = 9.0 + picking.amount_freight_value = 9.0 + picking.amount_insurance_value = 9.0 + picking.amount_other_value = 9.0 - for line in self.stock_picking_sp.move_lines: + for line in picking.move_lines: self.assertEqual( line.freight_value, 3.0, @@ -590,21 +401,19 @@ def test_fields_freight_insurance_other_costs(self): ) # Caso que os Campos na Linha não tem valor - for line in self.stock_picking_sp.move_lines: + for line in picking.move_lines: line.price_unit = 100.0 line.freight_value = 0.0 line.insurance_value = 0.0 line.other_value = 0.0 - self.stock_picking_sp.company_id.delivery_costs = "total" + picking.company_id.delivery_costs = "total" - self.stock_picking_sp.amount_freight_value = 30.0 - self.stock_picking_sp.amount_insurance_value = 30.0 - self.stock_picking_sp.amount_other_value = 30.0 + picking.amount_freight_value = 30.0 + picking.amount_insurance_value = 30.0 + picking.amount_other_value = 30.0 - self.stock_picking_sp.action_confirm() - - for line in self.stock_picking_sp.move_lines: + for line in picking.move_lines: self.assertEqual( line.freight_value, 10.0, @@ -621,6 +430,15 @@ def test_fields_freight_insurance_other_costs(self): "Unexpected value for the field Other Values in Move line.", ) + invoice = self.create_invoice_wizard(picking) + # Confirm Invoice + invoice.action_post() + self.assertEqual(invoice.state, "posted", "Invoice should be in state Posted") + self.assertTrue( + invoice.fiscal_document_id, + "Freight, Insurance and Other Costs case should has Fiscal Document.", + ) + def test_compatible_with_international_case(self): """Test of compatible with international case, create Invoice but not for Brazil.""" picking = self.env.ref("stock_picking_invoicing.stock_picking_invoicing_2") @@ -628,22 +446,24 @@ def test_compatible_with_international_case(self): # Force product availability for move in picking.move_ids_without_package: self._run_fiscal_line_onchanges(move) - move.quantity_done = move.product_uom_qty - picking.button_validate() + # test split + move.product_uom_qty = 2 + move.quantity_done = 1 + + # Return Wizard + backorder = self.create_backorder_wizard(picking) + self.assertEqual(backorder.invoice_state, "2binvoiced") + self.assertFalse(backorder.fiscal_operation_id) + + for line in backorder.move_lines: + self.assertFalse(line.fiscal_operation_id) + self.assertFalse(line.fiscal_operation_line_id) + self.assertEqual(line.invoice_state, "2binvoiced") + + self.picking_move_state(backorder) + self.assertEqual(picking.state, "done") - wizard_obj = self.invoice_wizard.with_context( - active_ids=picking.ids, - active_model=picking._name, - active_id=picking.id, - fiscal_operation_journal=False, - ) - fields_list = wizard_obj.fields_get().keys() - wizard_values = wizard_obj.default_get(fields_list) - wizard = wizard_obj.create(wizard_values) - wizard.onchange_group() - wizard.action_generate() - domain = [("picking_ids", "=", picking.id)] - invoice = self.invoice_model.search(domain) + invoice = self.create_invoice_wizard(picking) # Confirm Invoice invoice.action_post() self.assertEqual(invoice.state, "posted", "Invoice should be in state Posted") @@ -656,3 +476,64 @@ def test_compatible_with_international_case(self): invoice.fiscal_document_id, "International case should not has Fiscal Document.", ) + + def test_picking_extra_vals(self): + """Test Picking Extra Vals created with Fiscal Values.""" + self._change_user_company(self.env.ref("base.main_company")) + picking = self.env.ref("l10n_br_stock_account.main_company-picking_2") + + self._run_fiscal_onchanges(picking) + + for line in picking.move_lines: + self._run_fiscal_line_onchanges(line) + # Force Split + line.quantity_done = 10 + + picking.button_validate() + + def test_form_stock_picking(self): + """Test Stock Picking with Form""" + + picking_form = Form( + self.env.ref("l10n_br_stock_account.main_company-picking_2") + ) + picking_form.save() + stock_move_form = Form( + self.env.ref("l10n_br_stock_account.main_company-move_2_1") + ) + stock_move_form.product_uom_qty = 10 + stock_move_form.save() + + def test_simples_nacional(self): + """Test case of Simples Nacional""" + self._change_user_company(self.env.ref("l10n_br_base.empresa_simples_nacional")) + picking = self.env.ref("l10n_br_stock_account.simples_nacional-picking_1") + self.picking_move_state(picking) + self.assertEqual(picking.state, "done", "Change state fail.") + # Testes falhando apenas no CI, a Operação Fiscal por algum motivo + # tem o campo journal_id preenchida com o Diário Miscelanios o que + # causa o erro abaixo + # File "/opt/odoo/addons/account/models/account_move.py", line 1931, + # in _check_journal_type + # raise ValidationError(_("The chosen journal has a type that is + # not compatible with your invoice type. Sales operations should go + # to 'sale' journals, and purchase operations to 'purchase' ones.")) + # odoo.exceptions.ValidationError: The chosen journal has a type that + # is not compatible with your invoice type. Sales operations should go + # to 'sale' journals, and purchase operations to 'purchase' ones. + # TODO: teria alguama forma de corrigir? Por enquanto está sendo + # preciso preenche o campo com o Diário correto para evitar o erro + journal = self.env.ref( + "l10n_br_stock_account.simples_remessa_journal_simples_nacional" + ) + of_simples_remessa = self.env.ref("l10n_br_fiscal.fo_simples_remessa") + of_simples_remessa.journal_id = journal + + invoice = self.create_invoice_wizard(picking) + # Confirm Invoice + invoice.action_post() + self.assertEqual(invoice.state, "posted", "Invoice should be in state Posted") + self.assertTrue( + invoice.fiscal_document_id, + "Simples Nacional case should has Fiscal Document.", + ) diff --git a/l10n_br_stock_account/tests/test_stock_rule.py b/l10n_br_stock_account/tests/test_stock_rule.py index e29bc857fcc7..5d7591d3b2f4 100644 --- a/l10n_br_stock_account/tests/test_stock_rule.py +++ b/l10n_br_stock_account/tests/test_stock_rule.py @@ -1,8 +1,8 @@ -# @ 2019 Akretion - www.akretion.com.br - -# Magno Costa -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +# Copyright (C) 2019-Today - Akretion (). +# @author Magno Costa +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo.tests.common import TransactionCase +from odoo.tests.common import Form, TransactionCase from odoo.tools import mute_logger @@ -112,3 +112,20 @@ def test_procument_order(self): # self.assertEqual( # move.fiscal_operation_line_id.name, 'Venda', # "The stock.move created has not operation_line_id field Venda") + + def test_stock_rule(self): + """Test Stock Rule""" + warehouse = self.env["stock.warehouse"].search( + [("company_id", "=", self.env.company.id)], limit=1 + ) + reception_route = warehouse.reception_route_id + reception_route.rule_ids.action_archive() + stock_rule_form = Form(self.env["stock.rule"]) + stock_rule_form.name = "Looping Rule" + stock_rule_form.route_id = reception_route + stock_rule_form.location_id = warehouse.lot_stock_id + stock_rule_form.location_src_id = warehouse.lot_stock_id + stock_rule_form.action = "pull_push" + stock_rule_form.procure_method = "make_to_order" + stock_rule_form.picking_type_id = warehouse.int_type_id + stock_rule_form.save() From 77ca2c49e057735b5a91da149afff7d72381fbee Mon Sep 17 00:00:00 2001 From: Magno Costa Date: Sat, 25 Nov 2023 12:22:34 -0300 Subject: [PATCH 4/4] [REF] l10n_br_purchase_stock: Tests, necessary increase the Minimum Quantity after include Stock Inventory to generate automatic Purchase Order. --- l10n_br_purchase_stock/tests/test_stock_rule.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l10n_br_purchase_stock/tests/test_stock_rule.py b/l10n_br_purchase_stock/tests/test_stock_rule.py index d7fc6e0043dc..a31073790a04 100644 --- a/l10n_br_purchase_stock/tests/test_stock_rule.py +++ b/l10n_br_purchase_stock/tests/test_stock_rule.py @@ -24,7 +24,7 @@ def test_stock_rule_purchase(self): orderpoint = self.env["stock.warehouse.orderpoint"].create( { "product_id": self.env.ref("product.product_product_12").id, - "product_min_qty": 100.0, + "product_min_qty": 1000.0, } )