diff --git a/l10n_br_account_nfe/__init__.py b/l10n_br_account_nfe/__init__.py index 2cc1876f12df..131bce8ddf5f 100644 --- a/l10n_br_account_nfe/__init__.py +++ b/l10n_br_account_nfe/__init__.py @@ -1,3 +1,4 @@ from .hooks import post_init_hook from . import models +from . import wizards diff --git a/l10n_br_account_nfe/__manifest__.py b/l10n_br_account_nfe/__manifest__.py index e207fb5d8d8f..aa6f5f5005a9 100644 --- a/l10n_br_account_nfe/__manifest__.py +++ b/l10n_br_account_nfe/__manifest__.py @@ -22,6 +22,7 @@ ], "data": [ "views/account_payment_mode.xml", + "wizards/import_document.xml", ], "post_init_hook": "post_init_hook", "installable": True, diff --git a/l10n_br_account_nfe/models/__init__.py b/l10n_br_account_nfe/models/__init__.py index b0e09929a8b1..5d4013cfc6fb 100644 --- a/l10n_br_account_nfe/models/__init__.py +++ b/l10n_br_account_nfe/models/__init__.py @@ -1,4 +1,6 @@ from . import account_payment_mode +from . import account_move from . import account_move_line from . import document +from . import document_line from . import leiauteNFe diff --git a/l10n_br_account_nfe/models/account_move.py b/l10n_br_account_nfe/models/account_move.py new file mode 100644 index 000000000000..9ab16c855608 --- /dev/null +++ b/l10n_br_account_nfe/models/account_move.py @@ -0,0 +1,36 @@ +# Copyright (C) 2023 - TODAY Renan Hiroki Bastos - KMEE +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import models + + +class AccountMove(models.Model): + _inherit = "account.move" + + def _create_financial_lines_from_dups(self): + for invoice in self: + if invoice.nfe40_dup: + invoice.financial_move_line_ids = [ + (2, financial_line, 0) + for financial_line in invoice.financial_move_line_ids.ids + ] + financial_lines = [] + for dup in invoice.nfe40_dup: + financial_lines.append( + { + "move_id": invoice.id, + "name": dup.nfe40_nDup, + "debit": 0.0, + "credit": dup.nfe40_vDup, + "quantity": 1.0, + "amount_currency": -dup.nfe40_vDup, + "date_maturity": dup.nfe40_dVenc, + "currency_id": invoice.currency_id.id, + "account_id": invoice.partner_id.property_account_payable_id.id, + "partner_id": invoice.partner_id.id, + "exclude_from_invoice_tab": True, + } + ) + invoice.financial_move_line_ids = [ + (0, 0, dup) for dup in financial_lines + ] diff --git a/l10n_br_account_nfe/models/account_move_line.py b/l10n_br_account_nfe/models/account_move_line.py index e36606e2b5ac..e201c7cad8b6 100644 --- a/l10n_br_account_nfe/models/account_move_line.py +++ b/l10n_br_account_nfe/models/account_move_line.py @@ -2,7 +2,7 @@ # @author Renato Lima # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models +from odoo import api, models from odoo.addons.l10n_br_fiscal.constants.fiscal import ( DOCUMENT_ISSUER_COMPANY, @@ -31,3 +31,14 @@ def write(self, values): invoice.fiscal_document_id.action_document_confirm() invoice.fiscal_document_id._document_export() return result + + @api.model_create_multi + def create(self, vals_list): + account_move_lines = super().create(vals_list) + # for account_move_line, vals in zip(account_move_lines, vals_list): + # if self._context.get("create_from_document") \ + # and vals.get("fiscal_document_line_id"): + # account_move_line.write({ + # "fiscal_document_line_id": vals.get("fiscal_document_line_id"), + # }) + return account_move_lines diff --git a/l10n_br_account_nfe/models/document.py b/l10n_br_account_nfe/models/document.py index 37c166701d5f..9855eb49e215 100644 --- a/l10n_br_account_nfe/models/document.py +++ b/l10n_br_account_nfe/models/document.py @@ -166,3 +166,86 @@ def _process_document_in_contingency(self): if self.move_ids: copy_invoice = self.move_ids[0].copy() copy_invoice.action_post() + + @api.model_create_multi + def create(self, vals_list): + if self._context.get("create_from_move"): + filtered_vals_list = [] + for values in vals_list: + if not values.get("imported_document", False): + filtered_vals_list.append(values) + documents = super().create(filtered_vals_list) + else: + documents = super().create(vals_list) + if documents and self._context.get("create_from_document"): + invoices = documents._create_account_moves() + invoices._create_financial_lines_from_dups() + return documents + + def _create_account_moves(self): + self.flush() + AccountMove = self.env["account.move"] + invoices_to_create = [] + for document in self: + invoices_to_create.append( + { + "partner_id": document.partner_id.id, + "user_id": self.env.user.id, + "company_id": self.env.company.id, + "currency_id": self.env.company.currency_id.id, + "invoice_date": document.document_date, # TODO: Arrumar datedue + "invoice_line_ids": [ + (0, None, self._prepare_invoice_line(line)) + for line in document.fiscal_line_ids + ], + "move_type": "in_invoice", + "imported_document": document.imported_document, + } + ) + if invoices_to_create: + invoices = AccountMove.create(invoices_to_create) + for document, invoice in zip(self, invoices): + invoice.write({"fiscal_document_id": document.id}) + for invoice_line in invoice.invoice_line_ids: + # TODO: Não vai funcionar para notas com o mesmo produto + # em mais de uma linha + invoice_line.fiscal_document_line_id = ( + document.fiscal_line_ids.filtered( + lambda fl: fl.product_id == invoice_line.product_id + ) + ) + invoice._move_autocomplete_invoice_lines_values() + return invoices + + def _prepare_invoice_line(self, fiscal_line): + fiscal_line.reserve_map_taxes_ids() + fiscal_position = self.env["account.fiscal.position"].browse( + fiscal_line.partner_id.property_account_position_id.id + ) + values = fiscal_line._convert_to_write(fiscal_line.read()[0]) + # TODO: Utilizar lógica parecida com do stock.invoice.onshipping + # para mapear account_id + values.update( + { + "name": fiscal_line.name, + "account_id": fiscal_position.map_account( + fiscal_line.product_id.categ_id.property_account_expense_categ_id + ).id, + "product_id": fiscal_line.product_id.id, + "product_uom_id": fiscal_line.uom_id.id, + "quantity": fiscal_line.quantity, + "discount": fiscal_line.discount_value, + "price_unit": fiscal_line.price_unit, + "tax_ids": [ + ( + 6, + 0, + fiscal_line.fiscal_tax_ids.account_taxes( + user_type="purchase" + ).ids, + ) + ], + "fiscal_document_line_id": fiscal_line.id, + } + ) + return values diff --git a/l10n_br_account_nfe/models/document_line.py b/l10n_br_account_nfe/models/document_line.py new file mode 100644 index 000000000000..7ba6ce2dfc6f --- /dev/null +++ b/l10n_br_account_nfe/models/document_line.py @@ -0,0 +1,52 @@ +# Copyright (C) 2023 - TODAY Renan Hiroki Bastos - Kmee +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import api, models + + +class FiscalDocumentLine(models.Model): + _inherit = "l10n_br_fiscal.document.line" + + def reserve_map_taxes_ids(self): + for line in self: + line.icms_tax_id = self.env["l10n_br_fiscal.tax"].search( + [ + ("tax_group_id.name", "=", "ICMS"), + ("percent_amount", "=", line.icms_percent), + ("cst_in_id", "=", line.icms_cst_id.id), + ], + limit=1, + ) + line.ipi_tax_id = self.env["l10n_br_fiscal.tax"].search( + [ + ("tax_group_id.name", "=", "IPI"), + ("percent_amount", "=", line.ipi_percent), + ], + limit=1, + ) + line.pis_tax_id = self.env["l10n_br_fiscal.tax"].search( + [ + ("tax_group_id.name", "=", "PIS"), + ("percent_amount", "=", line.pis_percent), + ], + limit=1, + ) + line.cofins_tax_id = self.env["l10n_br_fiscal.tax"].search( + [ + ("tax_group_id.name", "=", "COFINS"), + ("percent_amount", "=", line.cofins_percent), + ], + limit=1, + ) + line._update_fiscal_tax_ids(line._get_all_tax_id_fields()) + line._update_taxes() + + @api.model_create_multi + def create(self, vals_list): + if self._context.get("create_from_move_line") and self._context.get( + "create_from_document" + ): + return [] + else: + documents = super().create(vals_list) + return documents diff --git a/l10n_br_account_nfe/wizards/__init__.py b/l10n_br_account_nfe/wizards/__init__.py new file mode 100644 index 000000000000..285f70e22eee --- /dev/null +++ b/l10n_br_account_nfe/wizards/__init__.py @@ -0,0 +1 @@ +from . import import_document diff --git a/l10n_br_account_nfe/wizards/import_document.py b/l10n_br_account_nfe/wizards/import_document.py new file mode 100644 index 000000000000..741fcb7eed92 --- /dev/null +++ b/l10n_br_account_nfe/wizards/import_document.py @@ -0,0 +1,27 @@ +# Copyright (C) 2022 Renan Hiroki Bastos - Kmee +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + + +from odoo import fields, models + +# from datetime import datetime + + +class NfeImport(models.TransientModel): + """Importar XML Nota Fiscal Eletrônica""" + + _inherit = "l10n_br_nfe.import_xml" + + # TODO: Mover isso pro módulo l10n_br_nfe + fiscal_operation_id = fields.Many2one( + comodel_name="l10n_br_fiscal.operation", + string="Fiscal Operation", + ) + + def _create_edoc_from_xml(self): + edoc = super( + NfeImport, self.with_context(create_from_document=True) + )._create_edoc_from_xml() + edoc.fiscal_operation_id = self.fiscal_operation_id + + return edoc diff --git a/l10n_br_account_nfe/wizards/import_document.xml b/l10n_br_account_nfe/wizards/import_document.xml new file mode 100644 index 000000000000..fb1aa5d9c95c --- /dev/null +++ b/l10n_br_account_nfe/wizards/import_document.xml @@ -0,0 +1,17 @@ + + + + + + l10n_br_nfe.import_xml.form.inherit + l10n_br_nfe.import_xml + + + + + + + + + diff --git a/l10n_br_nfe/models/product_product.py b/l10n_br_nfe/models/product_product.py index fff8573fe260..129c8549badc 100644 --- a/l10n_br_nfe/models/product_product.py +++ b/l10n_br_nfe/models/product_product.py @@ -97,4 +97,14 @@ def default_get(self, default_fields): ) ) values["ncm_id"] = ncm.id + + # UOM + if parent_dict.get("nfe40_uCom"): + uom = self.env["uom.uom"].search( + [("code", "ilike", parent_dict.get("nfe40_uCom"))], limit=1 + ) + if uom: + values["uom_id"] = uom.id + values["uom_po_id"] = uom.id + return values