odoo-addon-l10n-br-fiscal 18.0.2.0.0.10__py3-none-any.whl → 18.0.7.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of odoo-addon-l10n-br-fiscal might be problematic. Click here for more details.

Files changed (78) hide show
  1. odoo/addons/l10n_br_fiscal/README.rst +1 -1
  2. odoo/addons/l10n_br_fiscal/__manifest__.py +7 -3
  3. odoo/addons/l10n_br_fiscal/constants/fiscal.py +64 -18
  4. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cest.csv +1043 -983
  5. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cst.csv +58 -0
  6. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.document.type.csv +1 -0
  7. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.operation.indicator.csv +27 -0
  8. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.classification.csv +163 -0
  9. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.csv +31 -0
  10. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.group.csv +3 -0
  11. odoo/addons/l10n_br_fiscal/data/operation_data.xml +1 -1
  12. odoo/addons/l10n_br_fiscal/demo/fiscal_document_demo.xml +3 -179
  13. odoo/addons/l10n_br_fiscal/demo/fiscal_document_nfse_demo.xml +0 -4
  14. odoo/addons/l10n_br_fiscal/demo/fiscal_operation_demo.xml +2 -2
  15. odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +665 -79
  16. odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +713 -102
  17. odoo/addons/l10n_br_fiscal/migrations/18.0.3.0.0/pre-migration.py +30 -0
  18. odoo/addons/l10n_br_fiscal/models/__init__.py +2 -2
  19. odoo/addons/l10n_br_fiscal/models/comment.py +3 -1
  20. odoo/addons/l10n_br_fiscal/models/data_abstract.py +9 -6
  21. odoo/addons/l10n_br_fiscal/models/document.py +27 -8
  22. odoo/addons/l10n_br_fiscal/models/document_line.py +51 -8
  23. odoo/addons/l10n_br_fiscal/models/document_line_mixin.py +1107 -35
  24. odoo/addons/l10n_br_fiscal/models/document_mixin.py +244 -6
  25. odoo/addons/l10n_br_fiscal/models/document_related.py +1 -1
  26. odoo/addons/l10n_br_fiscal/models/document_serie.py +33 -0
  27. odoo/addons/l10n_br_fiscal/models/icms_regulation.py +1 -1
  28. odoo/addons/l10n_br_fiscal/models/operation_dashboard.py +3 -2
  29. odoo/addons/l10n_br_fiscal/models/operation_indicator.py +58 -0
  30. odoo/addons/l10n_br_fiscal/models/operation_line.py +28 -0
  31. odoo/addons/l10n_br_fiscal/models/partner_profile.py +6 -0
  32. odoo/addons/l10n_br_fiscal/models/product_template.py +4 -0
  33. odoo/addons/l10n_br_fiscal/models/res_company.py +17 -0
  34. odoo/addons/l10n_br_fiscal/models/res_partner.py +17 -0
  35. odoo/addons/l10n_br_fiscal/models/simplified_tax_range.py +8 -0
  36. odoo/addons/l10n_br_fiscal/models/tax.py +7 -3
  37. odoo/addons/l10n_br_fiscal/models/tax_classification.py +81 -0
  38. odoo/addons/l10n_br_fiscal/security/fiscal_security.xml +6 -16
  39. odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +7 -2
  40. odoo/addons/l10n_br_fiscal/static/description/index.html +1 -1
  41. odoo/addons/l10n_br_fiscal/tests/__init__.py +2 -0
  42. odoo/addons/l10n_br_fiscal/tests/test_document_edition.py +175 -10
  43. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +13 -42
  44. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +0 -5
  45. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_serie.py +60 -0
  46. odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +2 -5
  47. odoo/addons/l10n_br_fiscal/tests/test_tax_classification.py +110 -0
  48. odoo/addons/l10n_br_fiscal/views/document_line_mixin_view.xml +107 -4
  49. odoo/addons/l10n_br_fiscal/views/document_line_view.xml +7 -3
  50. odoo/addons/l10n_br_fiscal/views/document_view.xml +34 -15
  51. odoo/addons/l10n_br_fiscal/views/icms_regulation_view.xml +1 -5
  52. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +30 -0
  53. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +16 -9
  54. odoo/addons/l10n_br_fiscal/views/nbs_view.xml +1 -5
  55. odoo/addons/l10n_br_fiscal/views/ncm_view.xml +1 -5
  56. odoo/addons/l10n_br_fiscal/views/operation_dashboard_view.xml +3 -3
  57. odoo/addons/l10n_br_fiscal/views/operation_indicator_view.xml +75 -0
  58. odoo/addons/l10n_br_fiscal/views/operation_line_view.xml +4 -5
  59. odoo/addons/l10n_br_fiscal/views/operation_view.xml +1 -5
  60. odoo/addons/l10n_br_fiscal/views/product_product_view.xml +33 -6
  61. odoo/addons/l10n_br_fiscal/views/product_template_view.xml +22 -4
  62. odoo/addons/l10n_br_fiscal/views/res_company_view.xml +6 -0
  63. odoo/addons/l10n_br_fiscal/views/res_partner_view.xml +10 -0
  64. odoo/addons/l10n_br_fiscal/views/service_type_view.xml +1 -5
  65. odoo/addons/l10n_br_fiscal/views/tax_classification.xml +108 -0
  66. odoo/addons/l10n_br_fiscal/views/tax_definition_view.xml +1 -5
  67. odoo/addons/l10n_br_fiscal/views/tax_view.xml +2 -2
  68. odoo/addons/l10n_br_fiscal/wizards/__init__.py +1 -1
  69. odoo/addons/l10n_br_fiscal/wizards/base_wizard_mixin.py +1 -1
  70. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard.py +234 -0
  71. odoo/addons/l10n_br_fiscal/wizards/{document_import_wizard_mixin.xml → document_import_wizard.xml} +26 -7
  72. {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/METADATA +3 -3
  73. {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/RECORD +75 -68
  74. odoo/addons/l10n_br_fiscal/models/document_line_mixin_methods.py +0 -837
  75. odoo/addons/l10n_br_fiscal/models/document_mixin_methods.py +0 -349
  76. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +0 -129
  77. {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/WHEEL +0 -0
  78. {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/top_level.txt +0 -0
@@ -152,11 +152,7 @@
152
152
  </page>
153
153
  </notebook>
154
154
  </sheet>
155
- <div class="oe_chatter">
156
- <field name="message_follower_ids" groups="base.group_user" />
157
- <field name="activity_ids" />
158
- <field name="message_ids" />
159
- </div>
155
+ <chatter />
160
156
  </form>
161
157
  </field>
162
158
  </record>
@@ -62,13 +62,21 @@
62
62
  <field
63
63
  name="icms_origin"
64
64
  invisible="fiscal_type == '09'"
65
- required="fiscal_type != '09'"
65
+ required="fiscal_type != '09' and (sale_ok or purchase_ok)"
66
+ />
67
+ <field
68
+ name="ncm_id"
69
+ required="sale_ok or purchase_ok"
70
+ options="{'no_create': True, 'no_create_edit': True}"
71
+ />
72
+ <field
73
+ name="tax_icms_or_issqn"
74
+ required="sale_ok or purchase_ok"
66
75
  />
67
- <field name="ncm_id" required="1" />
68
- <field name="tax_icms_or_issqn" required="1" />
69
76
  <field
70
77
  name="service_type_id"
71
78
  invisible="fiscal_type != '09'"
79
+ options="{'no_create': True, 'no_create_edit': True}"
72
80
  />
73
81
  <field
74
82
  name="city_taxation_code_ids"
@@ -85,16 +93,35 @@
85
93
  </field>
86
94
  </group>
87
95
  <group>
88
- <field name="fiscal_genre_id" required="1" />
89
- <field name="cest_id" invisible="fiscal_type == '09'" />
90
- <field name="nbs_id" invisible="fiscal_type != '09'" />
96
+ <field
97
+ name="fiscal_genre_id"
98
+ required="sale_ok"
99
+ options="{'no_create': True, 'no_create_edit': True}"
100
+ />
101
+ <field
102
+ name="cest_id"
103
+ invisible="fiscal_type == '09'"
104
+ options="{'no_create': True, 'no_create_edit': True}"
105
+ />
106
+ <field
107
+ name="nbm_id"
108
+ invisible="fiscal_type == '09'"
109
+ options="{'no_create': True, 'no_create_edit': True}"
110
+ />
111
+ <field
112
+ name="nbs_id"
113
+ invisible="fiscal_type != '09'"
114
+ options="{'no_create': True, 'no_create_edit': True}"
115
+ />
91
116
  <field
92
117
  name="ipi_guideline_class_id"
93
118
  invisible="fiscal_type == '09'"
119
+ options="{'no_create': True, 'no_create_edit': True}"
94
120
  />
95
121
  <field
96
122
  name="ipi_control_seal_id"
97
123
  invisible="fiscal_type == '09'"
124
+ options="{'no_create': True, 'no_create_edit': True}"
98
125
  />
99
126
  </group>
100
127
  <group string="Tax UOM">
@@ -63,14 +63,17 @@
63
63
  <field
64
64
  name="icms_origin"
65
65
  invisible="fiscal_type == '09'"
66
- required="fiscal_type != '09'"
66
+ required="fiscal_type != '09' and (sale_ok or purchase_ok)"
67
67
  />
68
68
  <field
69
69
  name="ncm_id"
70
- required="1"
70
+ required="sale_ok or purchase_ok"
71
71
  options="{'no_create': True, 'no_create_edit': True}"
72
72
  />
73
- <field name="tax_icms_or_issqn" required="1" />
73
+ <field
74
+ name="tax_icms_or_issqn"
75
+ required="sale_ok or purchase_ok"
76
+ />
74
77
  <field
75
78
  name="service_type_id"
76
79
  invisible="fiscal_type != '09'"
@@ -105,7 +108,7 @@
105
108
  <group>
106
109
  <field
107
110
  name="fiscal_genre_id"
108
- required="1"
111
+ required="sale_ok"
109
112
  options="{'no_create': True, 'no_create_edit': True}"
110
113
  />
111
114
  <field
@@ -123,6 +126,21 @@
123
126
  invisible="fiscal_type != '09'"
124
127
  options="{'no_create': True, 'no_create_edit': True}"
125
128
  />
129
+ <field
130
+ name="operation_indicator_id"
131
+ invisible="fiscal_type != '09'"
132
+ options="{'no_create': True, 'no_create_edit': True}"
133
+ />
134
+ <field
135
+ name="ipi_guideline_class_id"
136
+ invisible="fiscal_type == '09'"
137
+ options="{'no_create': True, 'no_create_edit': True}"
138
+ />
139
+ <field
140
+ name="ipi_control_seal_id"
141
+ invisible="fiscal_type == '09'"
142
+ options="{'no_create': True, 'no_create_edit': True}"
143
+ />
126
144
  </group>
127
145
  <group string="Tax UOM">
128
146
  <field
@@ -140,6 +140,12 @@
140
140
  <field name="tax_inss_id" />
141
141
  <field name="tax_inss_wh_id" />
142
142
  </group>
143
+ <group
144
+ name="ibs_cbs_taxes_classification"
145
+ string="IBS/CBS Tax Classification"
146
+ >
147
+ <field name="tax_classification_id" />
148
+ </group>
143
149
  </group>
144
150
  <group name="advanced_taxes" string="Advanced Taxes">
145
151
  <field
@@ -31,6 +31,12 @@
31
31
  force_save="1"
32
32
  readonly="fiscal_profile_id"
33
33
  />
34
+ <field
35
+ name="public_entity_type"
36
+ force_save="1"
37
+ invisible="not is_public_entity"
38
+ readonly="fiscal_profile_id"
39
+ />
34
40
  <field
35
41
  name="legal_nature_id"
36
42
  options="{'no_create': True, 'no_create_edit': True}"
@@ -45,6 +51,10 @@
45
51
  options="{'no_create': True, 'no_create_edit': True}"
46
52
  />
47
53
  <field name="ind_final" />
54
+ <field
55
+ name="nif_motive_absence"
56
+ invisible="country_id == %(base.br)d"
57
+ />
48
58
  </group>
49
59
  </group>
50
60
  </field>
@@ -106,11 +106,7 @@
106
106
  </page>
107
107
  </notebook>
108
108
  </sheet>
109
- <div class="oe_chatter">
110
- <field name="message_follower_ids" groups="base.group_user" />
111
- <field name="activity_ids" />
112
- <field name="message_ids" />
113
- </div>
109
+ <chatter />
114
110
  </form>
115
111
  </field>
116
112
  </record>
@@ -0,0 +1,108 @@
1
+ <?xml version="1.0" encoding="utf-8" ?>
2
+ <!-- Copyright 2025 Marcel Savegnago <https://escodoo.com.br>
3
+ License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
4
+ <odoo>
5
+ <record id="tax_classification_search" model="ir.ui.view">
6
+ <field name="model">l10n_br_fiscal.tax.classification</field>
7
+ <field name="arch" type="xml">
8
+ <search string="Tax Classification">
9
+ <field name="code" />
10
+ <field name="name" />
11
+ <group expand="0" string="Group By...">
12
+ <filter
13
+ string="Rate Type"
14
+ name="rate_type"
15
+ domain="[]"
16
+ context="{'group_by': 'rate_type'}"
17
+ />
18
+ <filter
19
+ string="Regular Taxation"
20
+ name="regular_taxation"
21
+ domain="[('regular_taxation', '=', True)]"
22
+ />
23
+ <filter
24
+ string="Presumed Credit"
25
+ name="presumed_credit"
26
+ domain="[('presumed_credit', '=', True)]"
27
+ />
28
+ </group>
29
+ </search>
30
+ </field>
31
+ </record>
32
+
33
+ <record id="tax_classification_tree" model="ir.ui.view">
34
+ <field name="model">l10n_br_fiscal.tax.classification</field>
35
+ <field name="arch" type="xml">
36
+ <list>
37
+ <field name="code" />
38
+ <field name="name" />
39
+ <field name="cst_code_prefix_like" column_invisible="True" />
40
+ <field name="tax_ibs_id" />
41
+ <field name="tax_cbs_id" />
42
+ <field name="regular_taxation" string="Regular Taxation" />
43
+ <field name="presumed_credit" string="Presumed Credit" />
44
+ <field name="credit_reversal" string="Credit Reversal" />
45
+ <field name="rate_type" string="Rate Type" />
46
+ <field
47
+ name="document_type_ids"
48
+ widget="many2many_tags"
49
+ string="Related DFes"
50
+ />
51
+ </list>
52
+ </field>
53
+ </record>
54
+
55
+ <record id="tax_classification_form" model="ir.ui.view">
56
+ <field name="model">l10n_br_fiscal.tax.classification</field>
57
+ <field name="arch" type="xml">
58
+ <form string="Tax Classification">
59
+ <field name="id" invisible="1" />
60
+ <sheet>
61
+ <group>
62
+ <group>
63
+ <field name="code" />
64
+ <field name="name" />
65
+ <field name="cst_code_prefix_like" invisible="1" />
66
+ <field name="description" />
67
+ <field name="rate_type" />
68
+ </group>
69
+ </group>
70
+ <group string="Taxes">
71
+ <group>
72
+ <field name="tax_ibs_id" />
73
+ </group>
74
+ <group>
75
+ <field name="tax_cbs_id" />
76
+ </group>
77
+ </group>
78
+ <group string="Tax Indicators">
79
+ <group>
80
+ <field name="regular_taxation" />
81
+ </group>
82
+ <group>
83
+ <field name="presumed_credit" />
84
+ </group>
85
+ <group>
86
+ <field name="credit_reversal" />
87
+ </group>
88
+ </group>
89
+ <group string="Related Digital Fiscal Documents">
90
+ <field
91
+ name="document_type_ids"
92
+ widget="many2many_tags"
93
+ options="{'no_create': True, 'no_create_edit': True}"
94
+ />
95
+ </group>
96
+ </sheet>
97
+ </form>
98
+ </field>
99
+ </record>
100
+
101
+ <record id="tax_classification_act_window" model="ir.actions.act_window">
102
+ <field name="name">Tax Classification</field>
103
+ <field name="res_model">l10n_br_fiscal.tax.classification</field>
104
+ <field name="view_mode">list,form</field>
105
+ <field name="domain">[]</field>
106
+ <field name="context">{}</field>
107
+ </record>
108
+ </odoo>
@@ -284,11 +284,7 @@
284
284
  </page>
285
285
  </notebook>
286
286
  </sheet>
287
- <div class="oe_chatter">
288
- <field name="message_follower_ids" groups="base.group_user" />
289
- <field name="activity_ids" />
290
- <field name="message_ids" />
291
- </div>
287
+ <chatter />
292
288
  </form>
293
289
  </field>
294
290
  </record>
@@ -95,12 +95,12 @@
95
95
  />
96
96
  <field
97
97
  name="cst_in_id"
98
- invisible="tax_domain not in ['icms', 'icmssn', 'ipi', 'pis', 'cofins']"
98
+ invisible="tax_domain not in ['icms', 'icmssn', 'ipi', 'pis', 'cofins', 'ibs', 'cbs']"
99
99
  options="{'no_create': True, 'no_create_edit': True}"
100
100
  />
101
101
  <field
102
102
  name="cst_out_id"
103
- invisible="tax_domain not in ['icms', 'icmssn', 'ipi', 'pis', 'cofins']"
103
+ invisible="tax_domain not in ['icms', 'icmssn', 'ipi', 'pis', 'cofins', 'ibs', 'cbs']"
104
104
  options="{'no_create': True, 'no_create_edit': True}"
105
105
  />
106
106
  </group>
@@ -1,3 +1,3 @@
1
1
  from . import base_wizard_mixin
2
2
  from . import document_status_wizard
3
- from . import document_import_wizard_mixin
3
+ from . import document_import_wizard
@@ -5,7 +5,7 @@
5
5
  from odoo import api, fields, models
6
6
 
7
7
 
8
- class BaseWizardMixin(models.TransientModel):
8
+ class BaseWizardMixin(models.AbstractModel):
9
9
  _name = "l10n_br_fiscal.base.wizard.mixin"
10
10
  _description = "Fiscal Base Wizard Mixin"
11
11
 
@@ -0,0 +1,234 @@
1
+ # Copyright (C) 2023 Felipe Zago Rodrigues - Kmee
2
+ # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
3
+
4
+ import base64
5
+ import logging
6
+
7
+ from erpbrasil.base.fiscal.cnpj_cpf import validar_cnpj, validar_cpf
8
+ from erpbrasil.base.fiscal.edoc import detectar_chave_edoc
9
+ from erpbrasil.base.misc import punctuation_rm
10
+
11
+ from odoo import _, api, fields, models
12
+ from odoo.exceptions import UserError
13
+
14
+ from ..constants.fiscal import (
15
+ FISCAL_IN,
16
+ FISCAL_IN_OUT,
17
+ FISCAL_OUT,
18
+ )
19
+
20
+ _logger = logging.getLogger(__name__)
21
+
22
+ try:
23
+ from xsdata.formats.dataclass.parsers import XmlParser
24
+ except ImportError:
25
+ _logger.warning("xsdata Python lib not installed!")
26
+
27
+
28
+ class DocumentImportWizard(models.TransientModel):
29
+ _name = "l10n_br_fiscal.document.import.wizard"
30
+ _description = "Import Document Wizard"
31
+ _inherit = "l10n_br_fiscal.base.wizard.mixin"
32
+
33
+ company_id = fields.Many2one(
34
+ comodel_name="res.company",
35
+ string="Company",
36
+ default=lambda self: self.env.company.id,
37
+ )
38
+
39
+ file = fields.Binary(string="File to Import")
40
+
41
+ fiscal_operation_id = fields.Many2one(
42
+ comodel_name="l10n_br_fiscal.operation",
43
+ string="Fiscal Operation",
44
+ domain="[('fiscal_operation_type', '=', fiscal_operation_type)]",
45
+ )
46
+
47
+ document_type = fields.Char()
48
+
49
+ fiscal_operation_type = fields.Selection(
50
+ selection=FISCAL_IN_OUT,
51
+ compute="_compute_fiscal_operation_type",
52
+ )
53
+
54
+ issuer_cnpj = fields.Char(string="Issuer CNPJ")
55
+ issuer_legal_name = fields.Char()
56
+ issuer_name = fields.Char(string="Fantasia")
57
+ issuer_partner_id = fields.Many2one(
58
+ comodel_name="res.partner",
59
+ )
60
+ issuer_type_in_out = fields.Selection(selection=FISCAL_IN_OUT, string="Issuer Type")
61
+
62
+ destination_cnpj = fields.Char(string="Destination CNPJ")
63
+ destination_name = fields.Char()
64
+ destination_partner_id = fields.Many2one(
65
+ comodel_name="res.partner",
66
+ )
67
+ destination_type_in_out = fields.Selection(
68
+ selection=FISCAL_IN_OUT, string="Destination Type"
69
+ )
70
+
71
+ @api.depends("issuer_cnpj", "company_id.cnpj_cpf")
72
+ def _compute_fiscal_operation_type(self):
73
+ if self.issuer_cnpj == self.company_id.cnpj_cpf:
74
+ self.fiscal_operation_type = "out"
75
+ else:
76
+ self.fiscal_operation_type = "in"
77
+
78
+ def _search_partner(self, cnpj=None, name=None, legal_name=None):
79
+ """
80
+ Search for a partner based on CNPJ, name, or legal name.
81
+
82
+ This method searches for a partner in the `res.partner` model
83
+ based on the provided CNPJ, name, or legal name.
84
+ If a CNPJ is provided, it validates whether it is a
85
+ company or an individual and constructs the search domain accordingly.
86
+
87
+ If a legal name or name is provided, it constructs the
88
+ search domain to match either the legal name or the name.
89
+ If neither CNPJ nor legal name/name is provided, it raises a UserError.
90
+
91
+ Args:
92
+ cnpj (str, optional): The CNPJ or CPF of the partner.
93
+ name (str, optional): The name of the partner.
94
+ legal_name (str, optional): The legal name of the partner.
95
+
96
+ Returns:
97
+ recordset: A recordset of the found partner, limited to one result.
98
+
99
+ Raises:
100
+ UserError: If neither CNPJ nor legal name/name is provided.
101
+ """
102
+ if cnpj:
103
+ if validar_cnpj(cnpj):
104
+ domain = [("is_company", "=", True)]
105
+ elif validar_cpf(cnpj):
106
+ domain = [("is_company", "=", False)]
107
+ domain.append(("cnpj_cpf_stripped", "=", punctuation_rm(cnpj)))
108
+ elif legal_name or name:
109
+ domain = [("is_company", "=", True)]
110
+ domain.append(
111
+ ["|", ("legal_name", "ilike", legal_name), ("name", "ilike", name)]
112
+ )
113
+ else:
114
+ raise UserError(_("No CNPJ or Legal Name to search for a partner!"))
115
+ return self.env["res.partner"].search(domain, limit=1)
116
+
117
+ def _import_edoc(self):
118
+ self._find_existing_document()
119
+ if not self.document_id:
120
+ binding, self.document_id = self._create_edoc_from_file()
121
+ else:
122
+ binding = self._parse_file()
123
+ return binding, self.document_id
124
+
125
+ def action_import_and_open_document(self): # TODO used?
126
+ self._import_edoc()
127
+ return self.action_open_document()
128
+
129
+ def _destination_partner_from_binding(self, binding):
130
+ pass
131
+
132
+ def _create_edoc_from_file(self):
133
+ pass # meant to be overriden
134
+
135
+ def _detect_document_type(self, code):
136
+ self.document_type_id = self.env["l10n_br_fiscal.document.type"].search(
137
+ [("code", "=", code)],
138
+ limit=1,
139
+ )
140
+
141
+ def _find_existing_document(self):
142
+ self.document_id = self.env["l10n_br_fiscal.document"].search(
143
+ [("document_key", "=", self.document_key.replace(" ", ""))],
144
+ limit=1,
145
+ )
146
+
147
+ @api.onchange("file")
148
+ def _onchange_file(self):
149
+ if self.file:
150
+ self._fill_wizard_from_binding()
151
+
152
+ def _fill_wizard_from_binding(self):
153
+ binding = self._parse_file()
154
+ self._detect_binding(binding)
155
+ self._extract_binding_data(binding)
156
+ self._find_existing_document()
157
+ self._destination_partner_from_binding(binding)
158
+ return binding
159
+
160
+ @api.model
161
+ def _detect_binding(self, binding):
162
+ """
163
+ A pluggable method were each specialized fiscal document
164
+ importation wizard can register itself and return a tuple
165
+ with (the_fiscal_document_type_code, the_name_of_the_importation_wizard)
166
+ """
167
+ raise UserError(
168
+ _("Importation not implemented for %s!")
169
+ % (
170
+ type(
171
+ binding,
172
+ )
173
+ )
174
+ )
175
+
176
+ def action_open_document(self):
177
+ return {
178
+ "name": _("Document Imported"),
179
+ "type": "ir.actions.act_window",
180
+ "target": "current",
181
+ "views": [[False, "form"]],
182
+ "res_id": self.document_id.id,
183
+ "res_model": "l10n_br_fiscal.document",
184
+ }
185
+
186
+ def _extract_binding_data(self, binding):
187
+ pass # meant to be overriden
188
+
189
+ def _extract_key_information(self, edoc_key):
190
+ """TODO: Melhorar códifo da chave para não precisar
191
+ remover o tipo de chave do prefixo:
192
+ binding.NFe.infNFe.Id[3:]
193
+ """
194
+ edoc = detectar_chave_edoc(edoc_key)
195
+ self.document_key = " ".join(edoc.partes())
196
+ self.document_number = edoc.numero_documento.strip("0")
197
+ self.document_serie = edoc.numero_serie.strip("0")
198
+ self.issuer_cnpj = edoc.cnpj_cpf_emitente
199
+ self.issuer_partner_id = self._search_partner(edoc.cnpj_cpf_emitente)
200
+ if edoc.forma_emissao == "1":
201
+ self.issuer_type_in_out = FISCAL_OUT
202
+ self.destination_type_in_out = FISCAL_IN
203
+ else:
204
+ self.issuer_type_in_out = FISCAL_IN
205
+ self.destination_type_in_out = FISCAL_OUT
206
+
207
+ def _find_document_type(self, code):
208
+ return self.env["l10n_br_fiscal.document.type"].search(
209
+ [("code", "=", code)],
210
+ limit=1,
211
+ )
212
+
213
+ def _find_fiscal_operation(self, cfop, nat_op, fiscal_operation_type):
214
+ """try to find a matching fiscal operation via an operation line"""
215
+ operation_lines = self.env["l10n_br_fiscal.operation.line"].search(
216
+ [
217
+ ("state", "=", "approved"),
218
+ ("fiscal_type", "=", fiscal_operation_type),
219
+ ("cfop_external_id", "=", cfop),
220
+ ],
221
+ )
222
+ for line in operation_lines:
223
+ if line.fiscal_operation_id.name == nat_op:
224
+ return line.fiscal_operation_id
225
+ if operation_lines:
226
+ return operation_lines[0].fiscal_operation_id
227
+
228
+ def _parse_file(self):
229
+ return self._parse_file_data(self.file)
230
+
231
+ @api.model
232
+ def _parse_file_data(self, file_data):
233
+ # NOTE: no try and a stacktrace does help for debug/support
234
+ return XmlParser().from_bytes(base64.b64decode(file_data))
@@ -2,25 +2,44 @@
2
2
  <!-- Copyright 2023 KMEE
3
3
  License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
4
4
  <odoo>
5
- <record id="l10n_br_fiscal_document_import_wizard_mixin_form" model="ir.ui.view">
6
- <field name="name">l10n_br_fiscal.document.import.wizard.mixin.form</field>
7
- <field name="model">l10n_br_fiscal.document.import.wizard.mixin</field>
5
+ <record id="document_import_wizard_form" model="ir.ui.view">
6
+ <field name="name">document.import.wizard.form</field>
7
+ <field name="model">l10n_br_fiscal.document.import.wizard</field>
8
8
  <field name="arch" type="xml">
9
9
  <form string="Import Document">
10
10
  <group>
11
11
  <field name="file" required="1" />
12
+ <field name="document_key" invisible="file == False" />
12
13
  </group>
13
14
  <separator string="Preview Data" invisible="not file" />
14
15
  <group id="document_info" invisible="not file">
15
16
  <group>
16
17
  <field name="fiscal_operation_id" required="1" />
17
18
  <field name="fiscal_operation_type" invisible="1" />
18
- <field name="document_key" readonly="1" />
19
- <field name="document_number" readonly="1" />
20
- <field name="document_serie" readonly="1" />
19
+ <field name="document_type_id" readonly="1" force_save="1" />
20
+ <field name="document_type" readonly="1" force_save="1" />
21
21
  </group>
22
22
  <group>
23
- <field name="partner_id" readonly="1" />
23
+ <field name="document_number" readonly="1" force_save="1" />
24
+ <field name="document_serie" readonly="1" force_save="1" />
25
+ </group>
26
+ <group string="Emitente">
27
+ <field name="issuer_cnpj" readonly="1" force_save="1" />
28
+ <field name="issuer_partner_id" readonly="1" force_save="1" />
29
+ <field name="issuer_type_in_out" readonly="1" force_save="1" />
30
+ </group>
31
+ <group string="Destinatário">
32
+ <field name="destination_cnpj" readonly="1" force_save="1" />
33
+ <field
34
+ name="destination_partner_id"
35
+ readonly="1"
36
+ force_save="1"
37
+ />
38
+ <field
39
+ name="destination_type_in_out"
40
+ readonly="1"
41
+ force_save="1"
42
+ />
24
43
  </group>
25
44
  </group>
26
45
  <footer>
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: odoo-addon-l10n_br_fiscal
3
- Version: 18.0.2.0.0.10
3
+ Version: 18.0.7.1.0
4
4
  Requires-Python: >=3.10
5
- Requires-Dist: erpbrasil.base>=2.3.0
5
+ Requires-Dist: erpbrasil.base
6
6
  Requires-Dist: odoo-addon-l10n_br_base==18.0.*
7
7
  Requires-Dist: odoo-addon-uom_alias==18.0.*
8
8
  Requires-Dist: odoo==18.0.*
@@ -31,7 +31,7 @@ Módulo fiscal brasileiro
31
31
  !! This file is generated by oca-gen-addon-readme !!
32
32
  !! changes will be overwritten. !!
33
33
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
34
- !! source digest: sha256:b7471fd6bd126d628ba34ff9f474314e408b56c0cde25924e2312b4a1c047a5c
34
+ !! source digest: sha256:5cd8cb0b01f3ea46d8329418b2478d777a70350607e16eee38900f6a08e7e3f2
35
35
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
36
36
 
37
37
  .. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png