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.