diff --git a/l10n_br_fiscal/models/document.py b/l10n_br_fiscal/models/document.py index de7e82a83e98..9b3f40341f5e 100644 --- a/l10n_br_fiscal/models/document.py +++ b/l10n_br_fiscal/models/document.py @@ -72,23 +72,12 @@ class Document(models.Model): store=True, ) - document_number = fields.Char( - copy=False, - index=True, - ) - rps_number = fields.Char( string="RPS Number", copy=False, index=True, ) - document_key = fields.Char( - string="Key", - copy=False, - index=True, - ) - document_date = fields.Datetime( copy=False, ) @@ -100,10 +89,6 @@ class Document(models.Model): default=lambda self: self.env.user, ) - document_type_id = fields.Many2one( - comodel_name="l10n_br_fiscal.document.type", - ) - operation_name = fields.Char( copy=False, ) @@ -119,15 +104,6 @@ class Document(models.Model): copy=False, ) - document_serie_id = fields.Many2one( - comodel_name="l10n_br_fiscal.document.serie", - domain="[('active', '=', True)," "('document_type_id', '=', document_type_id)]", - ) - - document_serie = fields.Char( - string="Serie Number", - ) - document_related_ids = fields.One2many( comodel_name="l10n_br_fiscal.document.related", inverse_name="document_id", diff --git a/l10n_br_fiscal/models/document_fiscal_mixin_fields.py b/l10n_br_fiscal/models/document_fiscal_mixin_fields.py index e6e09296d547..a468e95ca923 100644 --- a/l10n_br_fiscal/models/document_fiscal_mixin_fields.py +++ b/l10n_br_fiscal/models/document_fiscal_mixin_fields.py @@ -443,3 +443,27 @@ def _operation_domain(self): ) force_compute_delivery_costs_by_total = fields.Boolean(default=False) + + document_type_id = fields.Many2one( + comodel_name="l10n_br_fiscal.document.type", + ) + + document_serie_id = fields.Many2one( + comodel_name="l10n_br_fiscal.document.serie", + domain="[('active', '=', True)," "('document_type_id', '=', document_type_id)]", + ) + + document_serie = fields.Char( + string="Serie Number", + ) + + document_number = fields.Char( + copy=False, + index=True, + ) + + document_key = fields.Char( + string="Key", + copy=False, + index=True, + ) diff --git a/l10n_br_stock_account/models/stock_picking.py b/l10n_br_stock_account/models/stock_picking.py index 9d459d07199b..f13f0f372726 100644 --- a/l10n_br_stock_account/models/stock_picking.py +++ b/l10n_br_stock_account/models/stock_picking.py @@ -87,3 +87,34 @@ def fields_view_get( } return order_view + + def _put_in_pack(self, move_line_ids, create_package_level=True): + package = super()._put_in_pack(move_line_ids, create_package_level) + if ( + package + and self.picking_type_id.pre_generate_fiscal_document_number == "pack" + ): + self._generate_document_number() + return package + + def button_validate(self): + result = super().button_validate() + for record in self: + if ( + record.state == "done" + and record.picking_type_id.pre_generate_fiscal_document_number + == "validate" + ): + record._generate_document_number() + return result + + def _generate_document_number(self): + if self.company_id.document_type_id and self.fiscal_operation_id: + if self.document_serie and self.document_number: + return + self.document_type_id = self.company_id.document_type_id + self.document_serie_id = self.document_type_id.get_document_serie( + self.company_id, self.fiscal_operation_id + ) + self.document_serie = self.document_serie_id.code + self.document_number = self.document_serie_id.next_seq_number() diff --git a/l10n_br_stock_account/models/stock_picking_type.py b/l10n_br_stock_account/models/stock_picking_type.py index 3414dd754ee7..c4fe666d10a3 100644 --- a/l10n_br_stock_account/models/stock_picking_type.py +++ b/l10n_br_stock_account/models/stock_picking_type.py @@ -12,3 +12,15 @@ class StockPickingType(models.Model): string="Default Fiscal Operation", domain="[('state', '=', 'approved')]", ) + + pre_generate_fiscal_document_number = fields.Selection( + selection=[ + ("none", "None"), + ("pack", "Pack"), + ("validate", "Validate"), + ("invoice_wizard", "Invoice Create Wizard"), + ], + default="none", + string="Pré generate Fiscal Document Number", + help="Check this box if you want to generate fiscal document for this operation.", + ) diff --git a/l10n_br_stock_account/tests/test_invoicing_picking.py b/l10n_br_stock_account/tests/test_invoicing_picking.py index 0bdaf3829af4..2bdf4fe484b3 100644 --- a/l10n_br_stock_account/tests/test_invoicing_picking.py +++ b/l10n_br_stock_account/tests/test_invoicing_picking.py @@ -569,3 +569,183 @@ def test_simples_nacional(self): invoice.fiscal_document_id, "Simples Nacional case should has Fiscal Document.", ) + + def test_generate_document_number_on_packing(self): + """Test Invoicing Picking""" + self._change_user_company(self.env.ref("base.main_company")) + picking = self.env.ref("l10n_br_stock_account.main_company-picking_1") + # self._run_fiscal_onchanges(picking) + # Testa os Impostos Dedutiveis + picking.fiscal_operation_id.deductible_taxes = True + nb_invoice_before = self.env["account.move"].search_count([]) + picking.picking_type_id.pre_generate_fiscal_document_number = "pack" + + self._run_fiscal_onchanges(picking) + picking.action_confirm() + picking.action_assign() + for move in picking.move_ids_without_package: + self._run_fiscal_line_onchanges(move) + move.quantity_done = move.product_uom_qty + + picking.action_put_in_pack() + picking.button_validate() + picking.set_to_be_invoiced() + self.assertTrue(picking.document_number) + + invoice = self.create_invoice_wizard(picking) + self.assertTrue(invoice, "Invoice is not created.") + 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, + picking.id, + "Relation between invoice and picking are missing.", + ) + for line in invoice.invoice_line_ids: + self.assertEqual( + line.price_unit, + line.product_id.with_company(line.company_id).standard_price, + ) + # Valida presença dos campos principais para o mapeamento Fiscal + self.assertTrue(line.fiscal_operation_id, "Missing Fiscal Operation.") + self.assertTrue( + line.fiscal_operation_line_id, "Missing Fiscal Operation Line." + ) + + self.assertTrue( + invoice.fiscal_operation_id, + "Mapping fiscal operation on wizard to create invoice fail.", + ) + self.assertTrue( + invoice.fiscal_document_id, + "Mapping Fiscal Documentation_id on wizard to create invoice fail.", + ) + + self.assertEqual(picking.document_number, invoice.document_number) + self.assertEqual( + picking.document_number, invoice.fiscal_document_id.document_number + ) + + def test_generate_document_number_on_validating(self): + """Test Invoicing Picking""" + self._change_user_company(self.env.ref("base.main_company")) + picking = self.env.ref("l10n_br_stock_account.main_company-picking_1") + # self._run_fiscal_onchanges(picking) + # Testa os Impostos Dedutiveis + picking.fiscal_operation_id.deductible_taxes = True + nb_invoice_before = self.env["account.move"].search_count([]) + picking.picking_type_id.pre_generate_fiscal_document_number = "validate" + + self.picking_move_state(picking) + + picking.set_to_be_invoiced() + self.assertTrue(picking.document_number) + + invoice = self.create_invoice_wizard(picking) + self.assertTrue(invoice, "Invoice is not created.") + 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, + picking.id, + "Relation between invoice and picking are missing.", + ) + for line in invoice.invoice_line_ids: + self.assertEqual( + line.price_unit, + line.product_id.with_company(line.company_id).standard_price, + ) + # Valida presença dos campos principais para o mapeamento Fiscal + self.assertTrue(line.fiscal_operation_id, "Missing Fiscal Operation.") + self.assertTrue( + line.fiscal_operation_line_id, "Missing Fiscal Operation Line." + ) + + self.assertTrue( + invoice.fiscal_operation_id, + "Mapping fiscal operation on wizard to create invoice fail.", + ) + self.assertTrue( + invoice.fiscal_document_id, + "Mapping Fiscal Documentation_id on wizard to create invoice fail.", + ) + + self.assertEqual(picking.document_number, invoice.document_number) + self.assertEqual( + picking.document_number, invoice.fiscal_document_id.document_number + ) + + def test_generate_document_number_on_invoice_create_wizard(self): + """Test Invoicing Picking""" + 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 + picking.fiscal_operation_id.deductible_taxes = True + nb_invoice_before = self.env["account.move"].search_count([]) + picking.picking_type_id.pre_generate_fiscal_document_number = "validate" + + self.picking_move_state(picking) + + picking.set_to_be_invoiced() + self.assertTrue(picking.document_number) + + invoice = self.create_invoice_wizard(picking) + self.assertTrue(invoice, "Invoice is not created.") + 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, + picking.id, + "Relation between invoice and picking are missing.", + ) + for line in invoice.invoice_line_ids: + self.assertEqual( + line.price_unit, + line.product_id.with_company(line.company_id).standard_price, + ) + # Valida presença dos campos principais para o mapeamento Fiscal + self.assertTrue(line.fiscal_operation_id, "Missing Fiscal Operation.") + self.assertTrue( + line.fiscal_operation_line_id, "Missing Fiscal Operation Line." + ) + + self.assertTrue( + invoice.fiscal_operation_id, + "Mapping fiscal operation on wizard to create invoice fail.", + ) + self.assertTrue( + invoice.fiscal_document_id, + "Mapping Fiscal Documentation_id on wizard to create invoice fail.", + ) + + self.assertEqual(picking.document_number, invoice.document_number) + self.assertEqual( + picking.document_number, invoice.fiscal_document_id.document_number + ) diff --git a/l10n_br_stock_account/views/stock_picking.xml b/l10n_br_stock_account/views/stock_picking.xml index 8362fd7a4dc6..2db34c735590 100644 --- a/l10n_br_stock_account/views/stock_picking.xml +++ b/l10n_br_stock_account/views/stock_picking.xml @@ -221,6 +221,26 @@ + + + + + + + + + + + + + + + + diff --git a/l10n_br_stock_account/views/stock_picking_type_view.xml b/l10n_br_stock_account/views/stock_picking_type_view.xml index 2cd3a3398da3..abad382d9b75 100644 --- a/l10n_br_stock_account/views/stock_picking_type_view.xml +++ b/l10n_br_stock_account/views/stock_picking_type_view.xml @@ -8,6 +8,7 @@ + diff --git a/l10n_br_stock_account/wizards/stock_invoice_onshipping.py b/l10n_br_stock_account/wizards/stock_invoice_onshipping.py index 3e16530bfbe4..692bb6512df9 100644 --- a/l10n_br_stock_account/wizards/stock_invoice_onshipping.py +++ b/l10n_br_stock_account/wizards/stock_invoice_onshipping.py @@ -68,6 +68,9 @@ def _get_journal(self): return journal def _build_invoice_values_from_pickings(self, pickings): + # Gera o numero do documento fiscal antes de criar a fatura + self._pre_generate_document_number(pickings) + invoice, values = super()._build_invoice_values_from_pickings(pickings) picking = fields.first(pickings) if not picking.fiscal_operation_id: @@ -76,16 +79,18 @@ def _build_invoice_values_from_pickings(self, pickings): fiscal_vals = picking._prepare_br_fiscal_dict() - document_type = picking.company_id.document_type_id - document_type_id = picking.company_id.document_type_id.id + if not fiscal_vals.get("document_type_id"): + # não sobrescreve os dados caso ás informações já tenham sido geradas + # nó método _put_in_pack + document_type_id = picking.company_id.document_type_id - fiscal_vals["document_type_id"] = document_type_id + fiscal_vals["document_type_id"] = document_type_id.id - document_serie = document_type.get_document_serie( - picking.company_id, picking.fiscal_operation_id - ) - if document_serie: - fiscal_vals["document_serie_id"] = document_serie.id + document_serie = document_type_id.get_document_serie( + picking.company_id, picking.fiscal_operation_id + ) + if document_serie: + fiscal_vals["document_serie_id"] = document_serie.id if picking.fiscal_operation_id and picking.fiscal_operation_id.journal_id: fiscal_vals["journal_id"] = picking.fiscal_operation_id.journal_id.id @@ -170,3 +175,11 @@ def _get_move_key(self, move): key = key + (move.fiscal_operation_line_id,) return key + + def _pre_generate_document_number(self, pickings): + for picking in pickings: + if ( + picking.picking_type_id.pre_generate_fiscal_document_number + == "invoice_wizard" + ): + picking._generate_document_number()