odoo-addon-account-move-payroll-import 16.0.1.0.0__py2.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.
Files changed (28) hide show
  1. odoo/addons/account_move_payroll_import/CHANGELOG.md +14 -0
  2. odoo/addons/account_move_payroll_import/README.rst +117 -0
  3. odoo/addons/account_move_payroll_import/__init__.py +4 -0
  4. odoo/addons/account_move_payroll_import/__manifest__.py +39 -0
  5. odoo/addons/account_move_payroll_import/data/payroll_import_defaults.xml +108 -0
  6. odoo/addons/account_move_payroll_import/i18n/ca_ES.po +828 -0
  7. odoo/addons/account_move_payroll_import/i18n/es.po +829 -0
  8. odoo/addons/account_move_payroll_import/models/__init__.py +6 -0
  9. odoo/addons/account_move_payroll_import/models/account_move.py +167 -0
  10. odoo/addons/account_move_payroll_import/models/payroll_custom_concept.py +57 -0
  11. odoo/addons/account_move_payroll_import/models/payroll_import_mapping.py +28 -0
  12. odoo/addons/account_move_payroll_import/models/payroll_import_setup.py +497 -0
  13. odoo/addons/account_move_payroll_import/security/ir.model.access.csv +5 -0
  14. odoo/addons/account_move_payroll_import/static/src/css/styles.css +26 -0
  15. odoo/addons/account_move_payroll_import/static/src/js/payroll_import_button.js +32 -0
  16. odoo/addons/account_move_payroll_import/static/src/xml/payroll_import_templates.xml +24 -0
  17. odoo/addons/account_move_payroll_import/utils/__init__.py +0 -0
  18. odoo/addons/account_move_payroll_import/utils/file_utils.py +31 -0
  19. odoo/addons/account_move_payroll_import/utils/parse_utils.py +34 -0
  20. odoo/addons/account_move_payroll_import/views/assets_template.xml +13 -0
  21. odoo/addons/account_move_payroll_import/views/payroll_import_views.xml +229 -0
  22. odoo/addons/account_move_payroll_import/wizards/__init__.py +3 -0
  23. odoo/addons/account_move_payroll_import/wizards/payroll_import_wizard.py +320 -0
  24. odoo/addons/account_move_payroll_import/wizards/payroll_import_wizard.xml +44 -0
  25. odoo_addon_account_move_payroll_import-16.0.1.0.0.dist-info/METADATA +131 -0
  26. odoo_addon_account_move_payroll_import-16.0.1.0.0.dist-info/RECORD +28 -0
  27. odoo_addon_account_move_payroll_import-16.0.1.0.0.dist-info/WHEEL +6 -0
  28. odoo_addon_account_move_payroll_import-16.0.1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from . import payroll_custom_concept
4
+ from . import payroll_import_setup
5
+ from . import payroll_import_mapping
6
+ from . import account_move
@@ -0,0 +1,167 @@
1
+ from collections import defaultdict
2
+ from contextlib import contextmanager
3
+
4
+ from odoo import models
5
+
6
+
7
+ class AccountMove(models.Model):
8
+ _inherit = "account.move"
9
+
10
+ @contextmanager
11
+ def _sync_dynamic_line( # noqa: C901
12
+ self,
13
+ existing_key_fname,
14
+ needed_vals_fname,
15
+ needed_dirty_fname,
16
+ line_type,
17
+ container,
18
+ ):
19
+ """
20
+ Overwrite this method to prevent line modifications in payroll import context
21
+ See account/account_move.py for the original method.
22
+ """
23
+ def existing():
24
+ return {
25
+ line: line[existing_key_fname]
26
+ for line in container["records"].line_ids
27
+ if line[existing_key_fname]
28
+ }
29
+
30
+ def needed():
31
+ res = {}
32
+ for computed_needed in container["records"].mapped(needed_vals_fname):
33
+ if computed_needed is False:
34
+ continue # there was an invalidation, let's hope nothing needed to be changed...
35
+ for key, values in computed_needed.items():
36
+ if key not in res:
37
+ res[key] = dict(values)
38
+ else:
39
+ ignore = True
40
+ for fname in res[key]:
41
+ if (
42
+ self.env["account.move.line"]._fields[fname].type
43
+ == "monetary"
44
+ ):
45
+ res[key][fname] += values[fname]
46
+ if res[key][fname]:
47
+ ignore = False
48
+ if ignore:
49
+ del res[key]
50
+
51
+ # Convert float values to their "ORM cache" one to prevent different rounding calculations
52
+ for dict_key in res:
53
+ move_id = dict_key.get("move_id")
54
+ if not move_id:
55
+ continue
56
+ record = self.env["account.move"].browse(move_id)
57
+ for fname, current_value in res[dict_key].items():
58
+ field = self.env["account.move.line"]._fields[fname]
59
+ if isinstance(current_value, float):
60
+ new_value = field.convert_to_cache(current_value, record)
61
+ res[dict_key][fname] = new_value
62
+
63
+ return res
64
+
65
+ def dirty():
66
+ *path, dirty_fname = needed_dirty_fname.split(".")
67
+ eligible_recs = container["records"].mapped(".".join(path))
68
+ if eligible_recs._name == "account.move.line":
69
+ eligible_recs = eligible_recs.filtered(
70
+ lambda l: l.display_type != "cogs"
71
+ )
72
+ dirty_recs = eligible_recs.filtered(dirty_fname)
73
+ return dirty_recs, dirty_fname
74
+
75
+ # don't do anything if we are in a payroll import context
76
+ if self.env.context.get("is_payroll_import"):
77
+ yield
78
+ return
79
+
80
+ inv_existing_before = existing()
81
+ needed_before = needed()
82
+ dirty_recs_before, dirty_fname = dirty()
83
+ dirty_recs_before[dirty_fname] = False
84
+ yield
85
+ dirty_recs_after, dirty_fname = dirty()
86
+ if dirty_recs_before and not dirty_recs_after: # TODO improve filter
87
+ return
88
+ inv_existing_after = existing()
89
+ needed_after = needed()
90
+
91
+ # Filter out deleted lines from `needed_before` to not recompute lines if not necessary or wanted
92
+ line_ids = set(
93
+ self.env["account.move.line"]
94
+ .browse(k["id"] for k in needed_before if "id" in k)
95
+ .exists()
96
+ .ids
97
+ )
98
+ needed_before = {
99
+ k: v
100
+ for k, v in needed_before.items()
101
+ if "id" not in k or k["id"] in line_ids
102
+ }
103
+
104
+ # old key to new key for the same line
105
+ before2after = {
106
+ before: inv_existing_after[bline]
107
+ for bline, before in inv_existing_before.items()
108
+ if bline in inv_existing_after
109
+ }
110
+
111
+ if needed_after == needed_before:
112
+ return
113
+
114
+ existing_after = defaultdict(list)
115
+ for k, v in inv_existing_after.items():
116
+ existing_after[v].append(k)
117
+ to_delete = [
118
+ line.id
119
+ for line, key in inv_existing_before.items()
120
+ if key not in needed_after
121
+ and key in existing_after
122
+ and before2after[key] not in needed_after
123
+ ]
124
+ to_delete_set = set(to_delete)
125
+ to_delete.extend(
126
+ line.id
127
+ for line, key in inv_existing_after.items()
128
+ if key not in needed_after and line.id not in to_delete_set
129
+ )
130
+ to_create = {
131
+ key: values
132
+ for key, values in needed_after.items()
133
+ if key not in existing_after
134
+ }
135
+ to_write = {
136
+ line: values
137
+ for key, values in needed_after.items()
138
+ for line in existing_after[key]
139
+ if any(
140
+ self.env["account.move.line"]
141
+ ._fields[fname]
142
+ .convert_to_write(line[fname], self)
143
+ != values[fname]
144
+ for fname in values
145
+ )
146
+ }
147
+
148
+ while to_delete and to_create:
149
+ key, values = to_create.popitem()
150
+ line_id = to_delete.pop()
151
+ self.env["account.move.line"].browse(line_id).write(
152
+ {**key, **values, "display_type": line_type}
153
+ )
154
+ if to_delete:
155
+ self.env["account.move.line"].browse(to_delete).with_context(
156
+ dynamic_unlink=True
157
+ ).unlink()
158
+ if to_create:
159
+ self.env["account.move.line"].create(
160
+ [
161
+ {**key, **values, "display_type": line_type}
162
+ for key, values in to_create.items()
163
+ ]
164
+ )
165
+ if to_write:
166
+ for line, values in to_write.items():
167
+ line.write(values)
@@ -0,0 +1,57 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from odoo import models, fields, api, _
4
+
5
+
6
+ class PayrollCustomConcept(models.Model):
7
+ _name = "payroll.custom.concept"
8
+ _description = "Payroll Custom Concept"
9
+ _check_company_auto = True
10
+
11
+ @api.model
12
+ def create(self, vals):
13
+ default_account_ext_id = "l10n_es.%s_%s" % (
14
+ self.env.company.id, vals.get("default_account_xml_id", False)
15
+ )
16
+ if default_account_ext_id:
17
+ account = self.env.ref(default_account_ext_id, False)
18
+ vals.update({"account_id": account.id if account else False})
19
+
20
+ return super(PayrollCustomConcept, self).create(vals)
21
+
22
+ def _default_account(self):
23
+ default_account_ext_id = "l10n_es.%s_%s" % (
24
+ self.env.company.id, self.default_account_xml_id
25
+ )
26
+ default_account = self.env.ref(default_account_ext_id, False)
27
+ return default_account.id if default_account else False
28
+
29
+ name = fields.Char(
30
+ string="Tag",
31
+ required=True,
32
+ help=_("Indicate the name of the custom concept.")
33
+ )
34
+ col_index = fields.Integer(
35
+ string="Column Number",
36
+ required=True,
37
+ help=_("Indicate the position in the file.")
38
+ )
39
+ account_id = fields.Many2one(
40
+ comodel_name="account.account",
41
+ string="Account",
42
+ required=True,
43
+ help=_("Indicate the account to post the data.")
44
+ )
45
+ default_account_xml_id = fields.Char("Default Account XML ID")
46
+ payroll_import_setup_id = fields.Many2one(
47
+ comodel_name="payroll.import.setup",
48
+ string="Payroll Import Setup",
49
+ required=True,
50
+ ondelete="cascade",
51
+ )
52
+ company_id = fields.Many2one(
53
+ related="payroll_import_setup_id.company_id",
54
+ string="Company",
55
+ store=True,
56
+ readonly=True,
57
+ )
@@ -0,0 +1,28 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from odoo import models, fields, _
4
+
5
+
6
+ class PayrollImportMapping(models.Model):
7
+ _name = "payroll.import.mapping"
8
+ _description = "Payroll Import Mapping"
9
+
10
+ name = fields.Char(string="Name", required=True, default="payroll.import.setup")
11
+ res_model = fields.Char(string=_("Model"))
12
+ res_field = fields.Char(string=_("Field"))
13
+ column_field = fields.Char(string=_("Column Field"), required=True)
14
+ account_field = fields.Char(string=_("Account Field"))
15
+ tax_field = fields.Char(string=_("Tax Field"))
16
+ aggregate_field = fields.Char(string=_("Aggregate Flag Field"))
17
+ payroll_import_setup_id = fields.Many2many(
18
+ comodel_name="payroll.import.setup",
19
+ string="Payroll Import Setup",
20
+ )
21
+
22
+ _sql_constraints = [
23
+ (
24
+ "unique_mapping",
25
+ "unique(name, res_model, res_field, column_field)",
26
+ "This mapping already exists.",
27
+ )
28
+ ]