forked from OCA/l10n-brazil
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhooks.py
189 lines (168 loc) · 6 KB
/
hooks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# Copyright (C) 2019-TODAY - Raphaël Valyi Akretion
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl-3.0.en.html).
import inspect
import logging
import sys
from odoo import SUPERUSER_ID, api, models
from .models.spec_models import SpecModel, StackedModel
_logger = logging.getLogger(__name__)
def post_init_hook(cr, registry, module_name, spec_module):
"""
Automatically generate access rules for spec models
"""
env = api.Environment(cr, SUPERUSER_ID, {})
remaining_models = get_remaining_spec_models(cr, registry, module_name, spec_module)
fields = [
"id",
"name",
"model_id/id",
"group_id/id",
"perm_read",
"perm_write",
"perm_create",
"perm_unlink",
]
access_data = []
for model in remaining_models:
underline_name = model.replace(".", "_")
model_id = "%s_spec.model_%s" % (
module_name,
underline_name,
)
access_data.append(
[
"access_%s_user" % (underline_name,),
underline_name,
model_id,
"%s.group_user" % (module_name,),
"1",
"0",
"0",
"0",
]
)
access_data.append(
[
"access_%s_manager" % (underline_name,),
underline_name,
model_id,
"%s.group_manager" % (module_name,),
"1",
"1",
"1",
"1",
]
)
env["ir.model.access"].load(fields, access_data)
def get_remaining_spec_models(cr, registry, module_name, spec_module):
"""
Figure out the list of spec models not injected into existing
Odoo models.
"""
cr.execute(
"""select ir_model.model from ir_model_data
join ir_model on res_id=ir_model.id
where ir_model_data.model='ir.model'
and module=%s;""",
(module_name,),
)
module_models = [
i[0]
for i in cr.fetchall()
if registry.get(i[0]) and not registry[i[0]]._abstract
]
injected_models = set()
for model in module_models:
base_class = registry[model]
# 1st classic Odoo classes
if hasattr(base_class, "_inherit"):
injected_models.add(base_class._name)
for cls in base_class.mro():
if hasattr(cls, "_inherit") and cls._inherit:
if isinstance(cls._inherit, list):
inherit_list = cls._inherit
else:
inherit_list = [cls._inherit]
for inherit in inherit_list:
if inherit.startswith("spec.mixin."):
injected_models.add(cls._name)
# visit_stack will now need the associated spec classes
injected_classes = set()
remaining_models = set()
for m in injected_models:
c = SpecModel._odoo_name_to_class(m, spec_module)
if c is not None:
injected_classes.add(c)
for model in module_models:
base_class = registry[model]
# 2nd StackedModel classes, that we will visit
if hasattr(base_class, "_stacked"):
node = SpecModel._odoo_name_to_class(base_class._stacked, spec_module)
env = api.Environment(cr, SUPERUSER_ID, {})
for (
_kind,
klass,
_path,
_field_path,
_child_concrete,
) in base_class._visit_stack(env, node):
injected_classes.add(klass)
all_spec_models = {
c._name
for name, c in inspect.getmembers(sys.modules[spec_module], inspect.isclass)
}
remaining_models = remaining_models.union(
{i for i in all_spec_models if i not in [c._name for c in injected_classes]}
)
return remaining_models
def register_hook(env, module_name, spec_module, force=False):
"""
Called by Model#_register_hook once all modules are loaded.
Here we take all spec models that are not injected in existing concrete
Odoo models and we make them concrete automatically with
their _auto_init method that will create their SQL DDL structure.
"""
load_key = "_%s_loaded" % (spec_module,)
if hasattr(env.registry, load_key) and not force: # already done for registry
return
setattr(env.registry, load_key, True)
remaining_models = get_remaining_spec_models(
env.cr, env.registry, module_name, spec_module
)
for name in remaining_models:
spec_class = StackedModel._odoo_name_to_class(name, spec_module)
spec_class._module = "fiscal" # TODO use python_module ?
fields = env[spec_class._name].fields_get_keys()
rec_name = next(
filter(
lambda x: (
x.startswith(env[spec_class._name]._field_prefix)
and "_choice" not in x
),
fields,
)
)
c = type(
name,
(SpecModel, spec_class),
{
"_name": name,
"_inherit": [spec_class._inherit, "spec.mixin"],
"_original_module": "fiscal",
"_odoo_module": module_name,
"_spec_module": spec_module,
"_rec_name": rec_name,
},
)
models.MetaModel.module_to_models[module_name] += [c]
# now we init these models properly
# a bit like odoo.modules.loading#load_module_graph would do.
c._build_model(env.registry, env.cr)
env[name]._prepare_setup()
env[name]._setup_base()
env[name]._setup_fields()
env[name]._setup_complete()
hook_key = "_%s_need_hook" % (module_name,)
if hasattr(env.registry, hook_key) and getattr(env.registry, hook_key):
env.registry.init_models(env.cr, remaining_models, {"module": module_name})
setattr(env.registry, hook_key, False)