Modele opisujące strukturę systemu (ir)
Tabele/modele o nazwach rozpoczynających się od "ir." zawierają opis struktury systemu Odoo. Można je uzupełniać przy pomocy plików XML w modułach (<record model="ir....>). Oglądać ich zawartość można w funkcji "Ustawienia" po włączeniu trybu deweloperskiego. Poniżej zawarto informacje dotyczące najważniejszych z tych modeli.
Opisy akcji
ir.actions.act_window
Model ten opisuje akcje, które są najczęściej wykorzystywane w modułach: akcje otwarcia okna modelu.
Możemy przeglądać te modele w trybie deweloperskim (Techniczna | Akcje | Akcje okna). Na przykład base.action_partner_form
otwiera okna z danymi partnerów.
Możemy tą akcję uruchomić (powodując otwacie okna "Klienci") z menu:
<menuitem name="demo_act1" id="demo_act_menu" action="base.action_partner_form"/>
Najprostsza struktura:
<record id="demo_akcji" model="ir.actions.act_window">
<field name="name">Demo</field>
<field name="res_model">res.partner</field>
</record>
Akcja o nazwie "demo_akcji" otwiera domyślny widok dla modelu "res.partner". Dodatkowe parametry pozwalają na zmianę widoków, sposobu ich otwarcia etc. Zobacz opis parametrów:
https://www.odoo.com/documentation/11.0/reference/actions.html#window-actions-ir-actions-act-window
ir.actions.server
Akcje serwera można nazwać środkiem hakerskim (o ile słowo "haker" nie oznacza chuligana). Akcje serwera pozwalają na uruchamianie fragmentów kodu w Pythonie (<field name="code">
)
Zobacz też: https://odooforbeginnersblog.wordpress.com/2017/08/10/how-to-create-server-actions-in-odoo-10/.
Kod w akcji serwera może opisywać kolejną akcję. Na przykład otwacia okna z klientami:
<record model="ir.actions.server" id="demo_act.action_server">
<field name="name">demo_act server</field>
<field name="model_id" ref="base.model_res_partner"/> <!-- model_id obowiązkowy -->
<field name="code">
action = {
"type": "ir.actions.act_window",
"view_mode": "tree,form",
"res_model": "res.partner",
}
</field>
</record>
<menuitem name="Akcja serwera" id="demo_act_menu_1"
action="demo_act.action_server" />
Akcje można uruchamiać programowo. Zobaczmy to na trochę bardziej złozonym przykładzie. W poniższym modelu mamy metodę otworz_partnera, która otwiera okno dla modelu res.partner.
# -*- coding: utf-8 -*-
from odoo import models, fields, api
class Demo(models.Model):
_name = "demo.act"
@api.multi
def otworz_partnera(self):
return {
'type': 'ir.actions.act_window',
'res_model': 'res.partner',
'view_type': 'form',
'view_mode': 'form',
'target': 'new',
}
Metoda otworz_okno może być wywoływana w akcji serwera:
<record model="ir.actions.server" id="demo_act.action_server_py">
<field name="name">demo_act server py</field>
<field name="model_id" ref="model_demo_act"/>
<field name="code">
action = env["demo.act"].otworz_partnera()
</field>
</record>
Menu wywołujące powyższą akcję:
<menuitem name="Akcja serwera - py" id="demo_act_menu_2"
action="demo_act.action_server_py" />
ir.actions.todo
Model służy do zapamiętania akcji do wykonania. Można na przykład w ten sposób uruchomić akcję konfigurowania lub rejestracji modułu po jego zainstalowaniu.
Na przykład:
<record id="demo_install_todo_action" model="ir.actions.server">
<field name="name">Demo Todo Action</field>
<field name="model_id" ref="base.model_res_partner"/> <!-- model_id obowiązkowy -->
<field name="code">
# kod w Pythonie
action = {"type": "ir.actions.act_url",
"url": "http://www.localhost/",
"target": "new",}
</field>
</record>
<record id="demo_install_todo" model="ir.actions.todo">
<field name="action_id" ref="demo_install_todo_action"/>
<field name="type">automatic</field>
</record>
Przykład ten pokazuje otwarcie strony http://www.localhost/ po zainstalowaniu modułu.
Pole "type" może zawierać wartość 'automatic', 'manual' (ręcznie), 'once' (tak jak 'manual' - zmienia po uruchomieniu stan na 'done')
Akcje te mogą być wykorzystywane w kreatorach (wizard).
ir.cron
Akcje zdefiniowane w modelu ir.cron są wykonywane okresowo (analogicznie jak cron w systemie operacyjnym). Można zdefiniować ich częstotliwość. Wykaz akcji możemy oglądać w ustawieniach (Techniczne | Automatyzacja | Zaplanowane akcje).
Aby zdefiniować akcję najpierw tworzymy odpowiednią funkcję w modelu (uwaga na dekorator model).:
from odoo import models, fields, api
import logging
_logger = logging.getLogger(__name__)
class Demo(models.Model):
_name = "demo.act"
@api.model
def akcja_cron(self):
_logger.exception("Wywolano akcje Crona - nie zaimplementowane!")
Teraz możemy zdefiniować jej wywołanie:
<record id="moja_unikalna_nazwa_cron" model="ir.cron">
<field name="name">Akcja demo - cron</field>
<field name="active">True</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">hours</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="model" eval="'demo.act'"/>
<field name="function" eval="'akcja_cron'"/>
<field name="args" eval="'()'" />
<!-- alternatywa: field name="model">demo.act</field>
<field name="function">akcja_cron</field>
<field name="args">()</field>
<field name="priority">1</field -->
</record>
Pole interval_type ustanawia jednostki czasu: minutes
, hours
, days
, weeks
, months
. O ilości jednostek decyduje pole interval_number. Domyślny priorytet wynosi 5.
ir.actions.client
Akcje kontrolek (widget) - wykonywane po stronie klienta (frontend). Czyli w praktyce funkcje JavaScript. Sposób ich definiowania wyjaśniono w rozdziale "JavaScript" - punkt "Własne akcje" .
Uprawnienia
ir.model.access
Definiuje dostęp do wszystkich modeli. Przyznawane są uprawnienia na grupę:
- do tworzenia (perm_create),
- do wyszukiwania i czytania (perm_read),
- do aktualizowania (perm_write)
- do usuwania (perm_unlink)
Uprawnienia są addytywne - czyli dla danego modelu użytkownik ma dostęp do wszystkich uprawnień przyznanych dowolnej z grup do której należy. Jeśli nie określono żadnej grupy, uprawnienia dotyczą wszystkich użytkowników.
Zobacz też:
ir.rule <ir.rule>
Pola:
name = fields.Char(required=True, index=True)
active = fields.Boolean(default=True,
help='''If you uncheck the active field, it will disable the ACL without deleting
it (if you delete a native ACL, it will be re-created when you reload the module).''')
model_id = fields.Many2one('ir.model', string='Object', required=True, domain=[('transient', '=', False)],
index=True, ondelete='cascade')
group_id = fields.Many2one('res.groups', string='Group', ondelete='cascade', index=True)
perm_read = fields.Boolean(string='Read Access')
perm_write = fields.Boolean(string='Write Access')
perm_create = fields.Boolean(string='Create Access')
perm_unlink = fields.Boolean(string='Delete Access')
ir.rule
Warunki jakie musi spełniać rekord, aby były dopuszczalne operacje na nim. Podobnie jak dla ir.model.access definiuje się dla grup (brak grupy = wszystkie).
Pole domain określa warunki dla rekordów.
Pola logiczne (read, write, create, delete) mówią, czy ( i jak?) dana reguła stosuje się do danej operacji (odpowiednio: odczyt, zapis, tworzenie, usuwanie) - podobnie jak w przypadku ir.access. Więcej w rozdziale poświęconym zabezpieczeniom.
Przykład (z modułu website_event):
<record id="event_event_public" model="ir.rule">
<field name="name">event: Public</field>
<field name="model_id" ref="event.model_event_event"/>
<field name="domain_force">[('website_published', '=', True)]</field>
<field name="groups" eval="[(4, ref('base.group_public')), (4, ref('base.group_portal'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
</record>
Pola:
name = fields.Char(index=True)
active = fields.Boolean(default=True,
help="""If you uncheck the active field, it will disable the record rule without deleting it
(if you delete a native record rule, it may be re-created when you reload the module).""")
model_id = fields.Many2one('ir.model', string='Object', index=True, required=True, ondelete="cascade")
groups = fields.Many2many('res.groups', 'rule_group_rel', 'rule_group_id', 'group_id')
domain_force = fields.Text(string='Domain')
domain = fields.Binary(compute='_force_domain', string='Domain')
perm_read = fields.Boolean(string='Apply for Read', default=True)
perm_write = fields.Boolean(string='Apply for Write', default=True)
perm_create = fields.Boolean(string='Apply for Create', default=True)
perm_unlink = fields.Boolean(string='Apply for Delete', default=True)
Parametry
ir.config_parameter
Przykład definicji parametru w pliku XML:
<record id="my_id" model="ir.config_parameter">
<field name="key">modul.parametr</field>
<field name="value">True</field>
<field name="group_ids" eval="[(4, ref('base.group_system'))]"/>
</record>
Po wczytaniu modułu z takim ustawieniem, można sprawdzić ustawienia (w trybie deweloperskim): Ustawienia | Techniczne | Parametry | Parametry systemu.
Uwaga! Po odinstalowaniu modułu parametr znika. Jego ręczne ustawienie przed instalacją modułu powoduje błąd.