Initial commit: OCA Technical packages (595 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:03 +02:00
commit 2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions

View file

@ -0,0 +1,86 @@
========
IoT Rule
========
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8776ccfdb4eda7e7911d811faef3f33474c34c474237b9afd180e4fe5ca1b233
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fiot-lightgray.png?logo=github
:target: https://github.com/OCA/iot/tree/16.0/iot_rule
:alt: OCA/iot
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/iot-16-0/iot-16-0-iot_rule
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/iot&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This addon allows to define IoT Rules.
A Rule specifies which Inputs that can be controlled by a certain Key.
The Key is owned by an Agent (Employee, Partner or anonymous).
The Input is a request from an IoT Device that executes a certain function in Odoo.
This function will check if the Key (= the Agent) is allowed by any Rule to "control" the Device.
If Odoo answers positively the Agent will be allowed the to execute some Function on the Device
(for example open a door or switch on a relay).
**Table of contents**
.. contents::
:local:
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/iot/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/iot/issues/new?body=module:%20iot_rule%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* CreuBlanca
* ForgeFlow
Contributors
~~~~~~~~~~~~
* Enric Tobella <etobella@creublanca.es>
* Luis Burrel <lu.bu.sax@gmail.com>
* Aaron Henriquez <ahforgeflow@forgeflow.com>
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/iot <https://github.com/OCA/iot/tree/16.0/iot_rule>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1,2 @@
from . import models
from . import wizards

View file

@ -0,0 +1,28 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "IoT Rule",
"summary": """
Define IoT Rules (Keys that control Inputs)""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "CreuBlanca,ForgeFlow,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/iot",
"depends": ["iot_input_oca"],
"data": [
"wizards/iot_key_wizard.xml",
"security/ir.model.access.csv",
"views/iot_rule.xml",
"views/iot_key.xml",
"views/iot_key_action.xml",
"views/iot_lock.xml",
"views/res_partner.xml",
"views/iot_device_input.xml",
],
"demo": [
"demo/iot_rule_demo.xml",
"demo/iot_lock_demo.xml",
"demo/iot_key_demo.xml",
],
}

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="key_101" model="iot.key">
<field name="name">Room 101</field>
<field name="rule_ids" eval="[(4, ref('iot_rule.rule_room_101'))]" />
</record>
<record id="key_102" model="iot.key">
<field name="name">Room 102</field>
<field
name="rule_ids"
eval="[(4, ref('iot_rule.rule_room_102')), (4, ref('iot_rule.rule_premium'))]"
/>
</record>
<record id="key_employee_01" model="iot.key">
<field name="name">Admin</field>
<field name="rule_ids" eval="[(4, ref('iot_rule.rule_employees'))]" />
</record>
<record id="key_employee_02" model="iot.key">
<field name="name">Demo</field>
<field name="rule_ids" eval="[(4, ref('iot_rule.rule_employees'))]" />
</record>
</odoo>

View file

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="lock_101" model="iot.lock">
<field name="name">Room 101</field>
<field
name="rule_ids"
eval="[(4, ref('iot_rule.rule_room_101')), (4, ref('iot_rule.rule_employees'))]"
/>
</record>
<record id="lock_102" model="iot.lock">
<field name="name">Room 102</field>
<field
name="rule_ids"
eval="[(4, ref('iot_rule.rule_room_102')), (4, ref('iot_rule.rule_employees'))]"
/>
</record>
<record id="lock_gym" model="iot.lock">
<field name="name">Gym</field>
<field
name="rule_ids"
eval="[(4, ref('iot_rule.rule_standard')), (4, ref('iot_rule.rule_employees'))]"
/>
</record>
<record id="lock_spa" model="iot.lock">
<field name="name">Spa</field>
<field
name="rule_ids"
eval="[(4, ref('iot_rule.rule_premium')), (4, ref('iot_rule.rule_employees'))]"
/>
</record>
<record id="lock_janitor" model="iot.lock">
<field name="name">Janitor</field>
<field name="rule_ids" eval="[(4, ref('iot_rule.rule_employees'))]" />
</record>
</odoo>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="rule_employees" model="iot.rule">
<field name="name">Employees</field>
</record>
<record id="rule_premium" model="iot.rule">
<field name="name">Premium Locks</field>
<field name="parent_ids" eval="[(4, ref('iot_rule.rule_employees'))]" />
</record>
<record id="rule_standard" model="iot.rule">
<field name="name">Standard Locks</field>
<field name="parent_ids" eval="[(4, ref('iot_rule.rule_employees'))]" />
</record>
<record id="rule_room_101" model="iot.rule">
<field name="name">Room 101</field>
<field name="parent_ids" eval="[(4, ref('iot_rule.rule_standard'))]" />
</record>
<record id="rule_room_102" model="iot.rule">
<field name="name">Room 102</field>
<field name="parent_ids" eval="[(4, ref('iot_rule.rule_standard'))]" />
</record>
</odoo>

View file

@ -0,0 +1,355 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * iot_rule
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: iot_rule
#. odoo-python
#: code:addons/iot_rule/models/iot_rule.py:0
#, python-format
msgid "A recurssion was found"
msgstr "Pronađena je rekurzija"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__action_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__action_ids
msgid "Action"
msgstr "Akcija"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__active
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__active
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__active
msgid "Active"
msgstr "Aktivan"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_form_view
msgid "Authorized Lock Groups"
msgstr "Ovlašćene grupe brave"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Cancel"
msgstr "Otkaži"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_res_partner
msgid "Contact"
msgstr "Kontakt"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Create"
msgstr "Kreiraj"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_wizard
msgid "Create a Key"
msgstr "Kreiraj ključ"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__create_uid
msgid "Created by"
msgstr "Kreirao"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__create_date
msgid "Created on"
msgstr "Kreirano"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__description
msgid "Description"
msgstr "Opis"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_device_input
msgid "Device input"
msgstr "Ulaz uređaja"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__display_name
msgid "Display Name"
msgstr "Prikazani naziv"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__expiration_date
msgid "Expiration Date"
msgstr "Datum isteka"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Expired"
msgstr "Istekao"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Expired Keys"
msgstr "Istekli ključevi"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_device_input_form_view
msgid "Generate IoT Lock for this Input"
msgstr "Generiraj IoT bravu za ovaj unos"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__id
msgid "ID"
msgstr "ID"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_device
msgid "IoT Device"
msgstr "IoT uređaj"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key
msgid "IoT Key"
msgstr "IoT ključ"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_action
msgid "IoT Key - Actions Log"
msgstr "IoT ključ - Dnevnik radnji"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_wizard_act_window
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "IoT Key Wizard"
msgstr "Čarobnjak IoT ključa"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_lock
msgid "IoT Lock"
msgstr "IoT brava"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_device_input_form_view
msgid "IoT Lock associated"
msgstr "IoT brava povezana"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_rule
msgid "IoT Rule (Relation Key-Lock)"
msgstr "IoT pravilo (veza ključ-brava)"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_mixin__iot_key_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__iot_key_id
#: model:ir.model.fields,field_description:iot_rule.field_res_partner__iot_key_ids
#: model:ir.model.fields,field_description:iot_rule.field_res_users__iot_key_ids
msgid "Iot Key"
msgstr "IoT ključ"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_mixin__iot_key_count
#: model:ir.model.fields,field_description:iot_rule.field_res_partner__iot_key_count
#: model:ir.model.fields,field_description:iot_rule.field_res_users__iot_key_count
msgid "Iot Key Count"
msgstr "Broj IoT ključa"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__key_id
msgid "Key"
msgstr "Ključ"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__key_type
msgid "Key Type"
msgstr "Tip ključa"
#. module: iot_rule
#: model:ir.model.constraint,message:iot_rule.constraint_iot_key_unique_virtual_key_uniq
msgid "Key must be unique"
msgstr "Ključ mora biti jedinstven"
#. module: iot_rule
#. odoo-python
#: code:addons/iot_rule/wizards/iot_key_wizard.py:0
#: code:addons/iot_rule/wizards/iot_key_wizard.py:0
#, python-format
msgid "Key of %s"
msgstr "Ključ od %s"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__key_name
msgid "Key's Name"
msgstr "Naziv ključa"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.res_partner_form_view
msgid "Keys"
msgstr "Ključevi"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_act_window
#: model:ir.ui.menu,name:iot_rule.iot_key_menu
msgid "Keys (Persons)"
msgstr "Ključevi (osobe)"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule____last_update
msgid "Last Modified on"
msgstr "Zadnje mijenjano"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__write_uid
msgid "Last Updated by"
msgstr "Zadnji ažurirao"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__write_date
msgid "Last Updated on"
msgstr "Zadnje ažurirano"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_device_input__lock_id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__lock_id
msgid "Lock"
msgstr "Zaključaj"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__lock_ids
msgid "Locks"
msgstr "Brave"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_lock_act_window
#: model:ir.ui.menu,name:iot_rule.iot_lock_menu
msgid "Locks (Devices)"
msgstr "Brave (uređaji)"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_lock_form_view
msgid "Member of these Groups of Locks"
msgstr "Član ovih grupa brava"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_mixin
msgid "Mixin for relation between record and Iot Keys"
msgstr "Mixin za vezu između zapisa i IoT ključeva"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__name
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__name
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__name
msgid "Name"
msgstr "Naziv:"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Not Expired"
msgstr "Neisteklo"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Not expired Keys"
msgstr "Neistekli ključevi"
#. module: iot_rule
#. odoo-python
#: code:addons/iot_rule/models/iot_key.py:0
#, python-format
msgid "Only one key can be assigned to this model"
msgstr "Samo jedan ključ se može dodijeliti ovom modelu"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__parent_ids
msgid "Parent"
msgstr "Nasljeđeni"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__res_id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__res_id
msgid "Res"
msgstr "Res"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__res_model
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__res_model
msgid "Res Model"
msgstr "Res model"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__result
msgid "Result"
msgstr "Rezultat"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__rule_ids
msgid "Rule"
msgstr "Pravilo"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_rule_act_window
#: model:ir.actions.act_window,name:iot_rule.iot_rule_action
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__rule_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__rule_ids
#: model:ir.ui.menu,name:iot_rule.iot_define_rules_menu
#: model:ir.ui.menu,name:iot_rule.iot_rule_menu
msgid "Rules"
msgstr "Pravila"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__timestamp
msgid "Time"
msgstr "Vrijeme"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__unique_virtual_key
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__unique_virtual_key
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__unique_virtual_key
msgid "Unique Virtual Key"
msgstr "Jedinstveni virtualni ključ"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Update"
msgstr "Ažuriraj"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_action_act_window
#: model:ir.ui.menu,name:iot_rule.iot_key_action_menu
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_form_view
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_lock_form_view
msgid "Usage Log"
msgstr "Dnevnik korištenja"

View file

@ -0,0 +1,355 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * iot_rule
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-11-15 17:38+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: none\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: iot_rule
#: code:addons/iot_rule/models/iot_rule.py:0
#, python-format
msgid "A recurssion was found"
msgstr "Se ha encontrado una recursión"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__action_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__action_ids
msgid "Action"
msgstr "Acción"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__active
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__active
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__active
msgid "Active"
msgstr "Activo"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_form_view
msgid "Authorized Lock Groups"
msgstr "Grupos de Cierre Autorizados"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Cancel"
msgstr "Cancelar"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_res_partner
msgid "Contact"
msgstr "Contacto"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Create"
msgstr "Crear"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_wizard
msgid "Create a Key"
msgstr "Crear una clave"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__create_date
msgid "Created on"
msgstr "Creado el"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__description
msgid "Description"
msgstr "Descripción"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_device_input
msgid "Device input"
msgstr "Entrada del dispositivo"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__display_name
msgid "Display Name"
msgstr "Mostrar Nombre"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__expiration_date
msgid "Expiration Date"
msgstr "Fecha de Vencimiento"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Expired"
msgstr "Expirado"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Expired Keys"
msgstr "Claves Expiradas"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_device_input_form_view
msgid "Generate IoT Lock for this Input"
msgstr "Generar bloqueo IoT para esta entrada"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__id
msgid "ID"
msgstr "ID (identificación)"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_device
msgid "IoT Device"
msgstr "Dispositivo IoT"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key
msgid "IoT Key"
msgstr "Llave IoT"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_action
msgid "IoT Key - Actions Log"
msgstr "Clave IoT - Registro de Acciones"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_wizard_act_window
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "IoT Key Wizard"
msgstr "Asistente para claves IoT"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_lock
msgid "IoT Lock"
msgstr "Cerradura IoT"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_device_input_form_view
msgid "IoT Lock associated"
msgstr "Bloqueo IoT asociado"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_rule
msgid "IoT Rule (Relation Key-Lock)"
msgstr "Regla IoT (bloqueo de clave de relación)"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_mixin__iot_key_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__iot_key_id
#: model:ir.model.fields,field_description:iot_rule.field_res_partner__iot_key_ids
#: model:ir.model.fields,field_description:iot_rule.field_res_users__iot_key_ids
msgid "Iot Key"
msgstr "Clave Iot"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_mixin__iot_key_count
#: model:ir.model.fields,field_description:iot_rule.field_res_partner__iot_key_count
#: model:ir.model.fields,field_description:iot_rule.field_res_users__iot_key_count
msgid "Iot Key Count"
msgstr "Recuento de claves Iot"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__key_id
msgid "Key"
msgstr "Clave"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__key_type
msgid "Key Type"
msgstr "Tipo de llave"
#. module: iot_rule
#: model:ir.model.constraint,message:iot_rule.constraint_iot_key_unique_virtual_key_uniq
msgid "Key must be unique"
msgstr "La clave debe ser única"
#. module: iot_rule
#: code:addons/iot_rule/wizards/iot_key_wizard.py:0
#: code:addons/iot_rule/wizards/iot_key_wizard.py:0
#, python-format
msgid "Key of %s"
msgstr "Clave de %s"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__key_name
msgid "Key's Name"
msgstr "Nombre de la clave"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.res_partner_form_view
msgid "Keys"
msgstr "Llaves"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_act_window
#: model:ir.ui.menu,name:iot_rule.iot_key_menu
msgid "Keys (Persons)"
msgstr "Llaves (Personas)"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule____last_update
msgid "Last Modified on"
msgstr "Última Modificación el"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__write_uid
msgid "Last Updated by"
msgstr "Última actualización por"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__write_date
msgid "Last Updated on"
msgstr "Última Actualización el"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_device_input__lock_id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__lock_id
msgid "Lock"
msgstr "Bloquear"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__lock_ids
msgid "Locks"
msgstr "Bloqueos"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_lock_act_window
#: model:ir.ui.menu,name:iot_rule.iot_lock_menu
msgid "Locks (Devices)"
msgstr "Cerraduras (dispositivos)"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_lock_form_view
msgid "Member of these Groups of Locks"
msgstr "Miembro de Estos Grupos de Bloqueos"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_mixin
msgid "Mixin for relation between record and Iot Keys"
msgstr "Mezcla para la relación entre registros y claves Iot"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__name
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__name
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__name
msgid "Name"
msgstr "Nombre"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Not Expired"
msgstr "No Expirado"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Not expired Keys"
msgstr "Claves no expiradas"
#. module: iot_rule
#: code:addons/iot_rule/models/iot_key.py:0
#, python-format
msgid "Only one key can be assigned to this model"
msgstr "Sólo se puede asignar una tecla a este modelo"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__parent_ids
msgid "Parent"
msgstr "Parental"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__res_id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__res_id
msgid "Res"
msgstr "Rec"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__res_model
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__res_model
msgid "Res Model"
msgstr "Modelo Rec"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__result
msgid "Result"
msgstr "Resultado"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__rule_ids
msgid "Rule"
msgstr "Regla"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_rule_act_window
#: model:ir.actions.act_window,name:iot_rule.iot_rule_action
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__rule_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__rule_ids
#: model:ir.ui.menu,name:iot_rule.iot_define_rules_menu
#: model:ir.ui.menu,name:iot_rule.iot_rule_menu
msgid "Rules"
msgstr "Reglas"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__timestamp
msgid "Time"
msgstr "Tiempo"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__unique_virtual_key
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__unique_virtual_key
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__unique_virtual_key
msgid "Unique Virtual Key"
msgstr "Clave Virtual Única"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Update"
msgstr "Actualización"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_action_act_window
#: model:ir.ui.menu,name:iot_rule.iot_key_action_menu
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_form_view
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_lock_form_view
msgid "Usage Log"
msgstr "Registro de Utilización"

View file

@ -0,0 +1,355 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * iot_rule
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: iot_rule
#. odoo-python
#: code:addons/iot_rule/models/iot_rule.py:0
#, python-format
msgid "A recurssion was found"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__action_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__action_ids
msgid "Action"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__active
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__active
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__active
msgid "Active"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_form_view
msgid "Authorized Lock Groups"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Cancel"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_res_partner
msgid "Contact"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Create"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_wizard
msgid "Create a Key"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__create_uid
msgid "Created by"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__create_date
msgid "Created on"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__description
msgid "Description"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_device_input
msgid "Device input"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__display_name
msgid "Display Name"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__expiration_date
msgid "Expiration Date"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Expired"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Expired Keys"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_device_input_form_view
msgid "Generate IoT Lock for this Input"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__id
msgid "ID"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_device
msgid "IoT Device"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key
msgid "IoT Key"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_action
msgid "IoT Key - Actions Log"
msgstr ""
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_wizard_act_window
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "IoT Key Wizard"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_lock
msgid "IoT Lock"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_device_input_form_view
msgid "IoT Lock associated"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_rule
msgid "IoT Rule (Relation Key-Lock)"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_mixin__iot_key_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__iot_key_id
#: model:ir.model.fields,field_description:iot_rule.field_res_partner__iot_key_ids
#: model:ir.model.fields,field_description:iot_rule.field_res_users__iot_key_ids
msgid "Iot Key"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_mixin__iot_key_count
#: model:ir.model.fields,field_description:iot_rule.field_res_partner__iot_key_count
#: model:ir.model.fields,field_description:iot_rule.field_res_users__iot_key_count
msgid "Iot Key Count"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__key_id
msgid "Key"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__key_type
msgid "Key Type"
msgstr ""
#. module: iot_rule
#: model:ir.model.constraint,message:iot_rule.constraint_iot_key_unique_virtual_key_uniq
msgid "Key must be unique"
msgstr ""
#. module: iot_rule
#. odoo-python
#: code:addons/iot_rule/wizards/iot_key_wizard.py:0
#: code:addons/iot_rule/wizards/iot_key_wizard.py:0
#, python-format
msgid "Key of %s"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__key_name
msgid "Key's Name"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.res_partner_form_view
msgid "Keys"
msgstr ""
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_act_window
#: model:ir.ui.menu,name:iot_rule.iot_key_menu
msgid "Keys (Persons)"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule____last_update
msgid "Last Modified on"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__write_uid
msgid "Last Updated by"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__write_date
msgid "Last Updated on"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_device_input__lock_id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__lock_id
msgid "Lock"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__lock_ids
msgid "Locks"
msgstr ""
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_lock_act_window
#: model:ir.ui.menu,name:iot_rule.iot_lock_menu
msgid "Locks (Devices)"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_lock_form_view
msgid "Member of these Groups of Locks"
msgstr ""
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_mixin
msgid "Mixin for relation between record and Iot Keys"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__name
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__name
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__name
msgid "Name"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Not Expired"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Not expired Keys"
msgstr ""
#. module: iot_rule
#. odoo-python
#: code:addons/iot_rule/models/iot_key.py:0
#, python-format
msgid "Only one key can be assigned to this model"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__parent_ids
msgid "Parent"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__res_id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__res_id
msgid "Res"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__res_model
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__res_model
msgid "Res Model"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__result
msgid "Result"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__rule_ids
msgid "Rule"
msgstr ""
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_rule_act_window
#: model:ir.actions.act_window,name:iot_rule.iot_rule_action
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__rule_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__rule_ids
#: model:ir.ui.menu,name:iot_rule.iot_define_rules_menu
#: model:ir.ui.menu,name:iot_rule.iot_rule_menu
msgid "Rules"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__timestamp
msgid "Time"
msgstr ""
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__unique_virtual_key
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__unique_virtual_key
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__unique_virtual_key
msgid "Unique Virtual Key"
msgstr ""
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Update"
msgstr ""
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_action_act_window
#: model:ir.ui.menu,name:iot_rule.iot_key_action_menu
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_form_view
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_lock_form_view
msgid "Usage Log"
msgstr ""

View file

@ -0,0 +1,354 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * iot_rule
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2023-07-12 12:13+0000\n"
"Last-Translator: Francesco Foresti <francesco.foresti@ooops404.com>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: iot_rule
#: code:addons/iot_rule/models/iot_rule.py:0
#, python-format
msgid "A recurssion was found"
msgstr "Trovata una ricorsione"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__action_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__action_ids
msgid "Action"
msgstr "Azione"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__active
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__active
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__active
msgid "Active"
msgstr "Attivo"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_form_view
msgid "Authorized Lock Groups"
msgstr "Gruppi blocco autorizzati"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Cancel"
msgstr "Annulla"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_res_partner
msgid "Contact"
msgstr "Contatto"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Create"
msgstr "Crea"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_wizard
msgid "Create a Key"
msgstr "Crea una chiave"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__create_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__create_uid
msgid "Created by"
msgstr "Creato da"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__create_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__create_date
msgid "Created on"
msgstr "Creato il"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__description
msgid "Description"
msgstr "Descrizione"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_device_input
msgid "Device input"
msgstr "Input dispositivo"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__display_name
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__display_name
msgid "Display Name"
msgstr "Nome visualizzato"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__expiration_date
msgid "Expiration Date"
msgstr "Data di scadenza"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Expired"
msgstr "Scaduta"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Expired Keys"
msgstr "Chiavi scadute"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_device_input_form_view
msgid "Generate IoT Lock for this Input"
msgstr "Genera blocco IoT per questo input"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__id
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__id
msgid "ID"
msgstr "ID"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_device
msgid "IoT Device"
msgstr "Dispositivo IoT"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key
msgid "IoT Key"
msgstr "Chiave IoT"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_action
msgid "IoT Key - Actions Log"
msgstr "Chiave IoT - log azioni"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_wizard_act_window
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "IoT Key Wizard"
msgstr "Procedura guidata chiave ioT"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_lock
msgid "IoT Lock"
msgstr "Blocco IoT"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_device_input_form_view
msgid "IoT Lock associated"
msgstr "Blocco IoT associato"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_rule
msgid "IoT Rule (Relation Key-Lock)"
msgstr "Regola IoT (relazione chiave-blocco)"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_mixin__iot_key_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__iot_key_id
#: model:ir.model.fields,field_description:iot_rule.field_res_partner__iot_key_ids
#: model:ir.model.fields,field_description:iot_rule.field_res_users__iot_key_ids
msgid "Iot Key"
msgstr "Chiave IoT"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_mixin__iot_key_count
#: model:ir.model.fields,field_description:iot_rule.field_res_partner__iot_key_count
#: model:ir.model.fields,field_description:iot_rule.field_res_users__iot_key_count
msgid "Iot Key Count"
msgstr "Conteggio chiave IoT"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__key_id
msgid "Key"
msgstr "Chiave"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__key_type
msgid "Key Type"
msgstr "Tipo chiave"
#. module: iot_rule
#: model:ir.model.constraint,message:iot_rule.constraint_iot_key_unique_virtual_key_uniq
msgid "Key must be unique"
msgstr "La chiave deve essere univoca"
#. module: iot_rule
#: code:addons/iot_rule/wizards/iot_key_wizard.py:0
#, python-format
msgid "Key of %s"
msgstr "Chiave di %s"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__key_name
msgid "Key's Name"
msgstr "Nome chiave"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.res_partner_form_view
msgid "Keys"
msgstr "Chiavi"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_act_window
#: model:ir.ui.menu,name:iot_rule.iot_key_menu
msgid "Keys (Persons)"
msgstr "Chiave (persona)"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock____last_update
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule____last_update
msgid "Last Modified on"
msgstr "Ultima modifica il"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__write_uid
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__write_uid
msgid "Last Updated by"
msgstr "Ultimo aggiornamento di"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__write_date
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__write_date
msgid "Last Updated on"
msgstr "Ultimo aggiornamento il"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_device_input__lock_id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__lock_id
msgid "Lock"
msgstr "Blocco"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__lock_ids
msgid "Locks"
msgstr "Blocchi"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_lock_act_window
#: model:ir.ui.menu,name:iot_rule.iot_lock_menu
msgid "Locks (Devices)"
msgstr "Blocchi (dispositivi)"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_lock_form_view
msgid "Member of these Groups of Locks"
msgstr "Componenti di questi gruppi di blocchi"
#. module: iot_rule
#: model:ir.model,name:iot_rule.model_iot_key_mixin
msgid "Mixin for relation between record and Iot Keys"
msgstr "Mixin per la relazione tra record e chiavi lotto"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__name
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__name
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__name
msgid "Name"
msgstr "Nome"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Not Expired"
msgstr "Non scaduto"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_search_view
msgid "Not expired Keys"
msgstr "Chiavi non scadute"
#. module: iot_rule
#: code:addons/iot_rule/models/iot_key.py:0
#, python-format
msgid "Only one key can be assigned to this model"
msgstr "Solo una chiave può essere associata a questo modello"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_rule__parent_ids
msgid "Parent"
msgstr "Padre"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__res_id
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__res_id
msgid "Res"
msgstr "Res"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__res_model
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__res_model
msgid "Res Model"
msgstr "Modello res"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__result
msgid "Result"
msgstr "Risultato"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__rule_ids
msgid "Rule"
msgstr "Regola"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_rule_act_window
#: model:ir.actions.act_window,name:iot_rule.iot_rule_action
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__rule_ids
#: model:ir.model.fields,field_description:iot_rule.field_iot_lock__rule_ids
#: model:ir.ui.menu,name:iot_rule.iot_define_rules_menu
#: model:ir.ui.menu,name:iot_rule.iot_rule_menu
msgid "Rules"
msgstr "Regole"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__timestamp
msgid "Time"
msgstr "Orario"
#. module: iot_rule
#: model:ir.model.fields,field_description:iot_rule.field_iot_key__unique_virtual_key
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_action__unique_virtual_key
#: model:ir.model.fields,field_description:iot_rule.field_iot_key_wizard__unique_virtual_key
msgid "Unique Virtual Key"
msgstr "Chiave virtuale univoca"
#. module: iot_rule
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_wizard_form_view
msgid "Update"
msgstr "Aggiorna"
#. module: iot_rule
#: model:ir.actions.act_window,name:iot_rule.iot_key_action_act_window
#: model:ir.ui.menu,name:iot_rule.iot_key_action_menu
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_key_form_view
#: model_terms:ir.ui.view,arch_db:iot_rule.iot_lock_form_view
msgid "Usage Log"
msgstr "Log utilizzo"

View file

@ -0,0 +1,7 @@
from . import iot_lock
from . import iot_key
from . import iot_rule
from . import iot_key_action
from . import res_partner
from . import iot_device_input
from . import iot_device

View file

@ -0,0 +1,30 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
class IotDevice(models.Model):
_inherit = "iot.device"
def get_iot_keys(self, serial_of_input, type_of_key):
iot_input = self.env["iot.device.input"].search(
[("serial", "=", serial_of_input)], limit=1
)
if iot_input:
if iot_input.lock_id:
domain = []
if type_of_key != "ALL":
domain.append(("key_type", "=", type_of_key))
return {"keys": iot_input.lock_id.get_virtual_keys(domain)}
return {"error": "no input found"}
def write(self, vals):
if vals.get("name", False):
for device in self:
for device_input in device.input_ids:
if device_input.lock_id:
input_name = device_input.name
device_input.lock_id.write(
{"name": vals.get("name") + " / " + input_name}
)
return super().write(vals)

View file

@ -0,0 +1,29 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class IotDeviceInput(models.Model):
_inherit = "iot.device.input"
lock_id = fields.Many2one("iot.lock")
def call_lock(self, value):
result = self.lock_id.check_access_unique_virtual_key(value)
return {"access_granted": result}
def get_iot_keys(self, domain=None):
if domain is None:
domain = []
return {"keys": self.lock_id.get_virtual_keys(domain)}
def generate_iot_lock(self):
self.ensure_one()
if not self.lock_id:
device_name = self.device_id.name
lock = self.env["iot.lock"].create(
{"name": device_name + " / " + self.name}
)
self.lock_id = lock.id
return {}

View file

@ -0,0 +1,122 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import uuid
from datetime import datetime
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class IotKey(models.Model):
_name = "iot.key"
_description = "IoT Key"
_rec_name = "unique_virtual_key"
name = fields.Char()
key_type = fields.Char()
unique_virtual_key = fields.Char(
readonly=True,
default="/",
required=True,
)
expiration_date = fields.Datetime()
rule_ids = fields.Many2many("iot.rule", string="Rules")
action_ids = fields.One2many("iot.key.action", inverse_name="key_id")
active = fields.Boolean(default=True)
res_id = fields.Integer(index=True)
res_model = fields.Char(index=True)
_sql_constraints = [
(
"unique_virtual_key_uniq",
"UNIQUE(unique_virtual_key)",
"Key must be unique",
),
]
def _get_unique_virtual_key(self, vals):
"""Hook that can be used to define the key according to needs"""
return uuid.uuid4()
@api.model_create_multi
def create(self, mvals):
for vals in mvals:
if vals.get("unique_virtual_key", "/") == "/":
vals["unique_virtual_key"] = self._get_unique_virtual_key(vals)
return super().create(mvals)
def view_actions(self):
self.ensure_one()
action = self.env.ref("iot_rule.iot_key_action_act_window").read()[0]
action["domain"] = [("key_id", "=", self.id)]
return action
def get_iot_rule_values(self):
result = []
for key in self:
result.append(key._get_iot_rule_values())
return result
def _get_iot_rule_values(self):
if self.expiration_date:
expiration_timestamp = int(datetime.timestamp(self.expiration_date))
else:
expiration_timestamp = False
return {
"key_type": self.key_type,
"expiration_date": expiration_timestamp,
"unique_virtual_key": self.unique_virtual_key,
"id": self.id,
}
def _get_unique_key_models(self):
return []
@api.constrains("res_model", "res_id")
def _constrain_key_model(self):
unique_models = self._get_unique_key_models()
for record in self:
if record.res_model not in unique_models:
continue
if self.with_context(active_test=False).search(
[
("id", "!=", record.id),
("res_id", "=", record.res_id),
("res_model", "=", record.res_model),
],
limit=1,
):
raise ValidationError(_("Only one key can be assigned to this model"))
class IotKeyMixin(models.AbstractModel):
_name = "iot.key.mixin"
_description = "Mixin for relation between record and Iot Keys"
iot_key_ids = fields.One2many(
"iot.key",
inverse_name="res_id",
domain=lambda r: [("res_model", "=", r._name)],
)
iot_key_count = fields.Integer(compute="_compute_iot_key_count")
@api.depends("iot_key_ids")
def _compute_iot_key_count(self):
for record in self:
record.iot_key_count = len(record.iot_key_ids)
def action_view_iot_key(self):
self.ensure_one()
action = self.env["ir.actions.act_window"]._for_xml_id(
"iot_rule.iot_key_act_window"
)
action["domain"] = [
("res_id", "=", self.id),
("res_model", "=", self._name),
]
action["context"] = {
"default_res_id": self.id,
"default_res_model": self._name,
}
return action

View file

@ -0,0 +1,20 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class IotKeyAction(models.Model):
_name = "iot.key.action"
_description = "IoT Key - Actions Log"
_order = "timestamp DESC"
key_id = fields.Many2one("iot.key")
key_name = fields.Char(related="key_id.name", string="Key's Name")
unique_virtual_key = fields.Char()
lock_id = fields.Many2one("iot.lock", required=True)
result = fields.Char(required=True, default="undefined")
timestamp = fields.Datetime(
string="Time", default=fields.Datetime.now, required=True
)

View file

@ -0,0 +1,66 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class IotLock(models.Model):
_name = "iot.lock"
_description = "IoT Lock"
name = fields.Char(required=True)
description = fields.Text()
rule_ids = fields.Many2many("iot.rule", string="Rules")
action_ids = fields.One2many("iot.key.action", inverse_name="lock_id")
active = fields.Boolean(default=True, required=True)
def check_access_unique_virtual_key(self, unique_virtual_key):
self.ensure_one()
key = self.env["iot.key"].search(
[("unique_virtual_key", "=", unique_virtual_key)], limit=1
)
if not key:
self._missing_key(unique_virtual_key)
return False
return self.check_access(key)
def _missing_key(self, unique_virtual_key):
return self.env["iot.key.action"].create(
self._missing_key_action_vals(unique_virtual_key)
)
def _missing_key_action_vals(self, unique_virtual_key):
return {
"lock_id": self.id,
"unique_virtual_key": unique_virtual_key,
"result": "refused",
}
def check_access(self, key):
result = self.rule_ids._check_access(key)
self.create_action(key, result)
return result
def create_action(self, key, result):
return self.env["iot.key.action"].create(self._create_action_vals(key, result))
def _create_action_vals(self, key, result):
return {
"lock_id": self.id,
"key_id": key.id,
"result": "accepted" if result else "refused",
}
def view_actions(self):
self.ensure_one()
action = self.env.ref("iot_rule.iot_key_action_act_window").read()[0]
action["domain"] = [("lock_id", "=", self.id)]
return action
def get_virtual_keys(self, domain=None):
self.ensure_one()
if domain is None:
domain = []
keys = self.rule_ids._get_virtual_keys(domain)
return keys.get_iot_rule_values()

View file

@ -0,0 +1,55 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class IotRule(models.Model):
_name = "iot.rule"
_description = "IoT Rule (Relation Key-Lock)"
name = fields.Char()
active = fields.Boolean(default=True, required=True)
lock_ids = fields.Many2many("iot.lock", string="Locks")
parent_ids = fields.Many2many(
"iot.rule",
relation="iot_rule_implied_rel",
column1="rule_id",
column2="implied_rule_id",
)
def _check_access(self, key):
if key.expiration_date and key.expiration_date < fields.Datetime.now():
return False
return self._check_access_recursion(key)
def _check_access_recursion(self, key, limit=0):
if not self:
return False
if limit > 50:
return False
if self & key.rule_ids:
return True
return self.mapped("parent_ids")._check_access_recursion(key, limit + 1)
@api.constrains("parent_ids")
def _check_recursion_parent_ids(self):
if not self._check_m2m_recursion("parent_ids"):
raise ValidationError(_("A recurssion was found"))
def _get_virtual_keys(self, domain, limit=0):
if not self or limit > 50:
return self.env["iot.key"]
return self.mapped("parent_ids")._get_virtual_keys(
domain, limit + 1
) | self.env["iot.key"].search(
domain
+ [
("rule_ids", "in", self.ids),
"|",
("expiration_date", "=", False),
("expiration_date", ">=", fields.Datetime.now()),
]
)

View file

@ -0,0 +1,9 @@
# Copyright 2020 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
class ResPartner(models.Model):
_name = "res.partner"
_inherit = ["res.partner", "iot.key.mixin"]

View file

@ -0,0 +1,3 @@
* Enric Tobella <etobella@creublanca.es>
* Luis Burrel <lu.bu.sax@gmail.com>
* Aaron Henriquez <ahforgeflow@forgeflow.com>

View file

@ -0,0 +1,8 @@
This addon allows to define IoT Rules.
A Rule specifies which Inputs that can be controlled by a certain Key.
The Key is owned by an Agent (Employee, Partner or anonymous).
The Input is a request from an IoT Device that executes a certain function in Odoo.
This function will check if the Key (= the Agent) is allowed by any Rule to "control" the Device.
If Odoo answers positively the Agent will be allowed the to execute some Function on the Device
(for example open a door or switch on a relay).

View file

@ -0,0 +1,9 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_iot_key,access Key,model_iot_key,iot_oca.group_iot_user,1,0,0,0
access_iot_lock,access Lock,model_iot_lock,iot_oca.group_iot_user,1,0,0,0
access_iot_rule,access Group,model_iot_rule,iot_oca.group_iot_user,1,0,0,0
access_iot_key_action,access Key Action,model_iot_key_action,iot_oca.group_iot_user,1,1,1,0
manage_iot_key,Manage Key,model_iot_key,iot_oca.group_iot_user,1,1,1,0
manage_iot_lock,Manage Lock,model_iot_lock,iot_oca.group_iot_manager,1,1,1,0
manage_iot_rule,Manage Group,model_iot_rule,iot_oca.group_iot_manager,1,1,1,0
access_iot_key_wizard,access_iot_key_wizard,model_iot_key_wizard,iot_oca.group_iot_user,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_iot_key access Key model_iot_key iot_oca.group_iot_user 1 0 0 0
3 access_iot_lock access Lock model_iot_lock iot_oca.group_iot_user 1 0 0 0
4 access_iot_rule access Group model_iot_rule iot_oca.group_iot_user 1 0 0 0
5 access_iot_key_action access Key Action model_iot_key_action iot_oca.group_iot_user 1 1 1 0
6 manage_iot_key Manage Key model_iot_key iot_oca.group_iot_user 1 1 1 0
7 manage_iot_lock Manage Lock model_iot_lock iot_oca.group_iot_manager 1 1 1 0
8 manage_iot_rule Manage Group model_iot_rule iot_oca.group_iot_manager 1 1 1 0
9 access_iot_key_wizard access_iot_key_wizard model_iot_key_wizard iot_oca.group_iot_user 1 1 1 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="Capa_1"
data-name="Capa 1"
viewBox="0 0 200.33 200"
version="1.1"
sodipodi:docname="icon.svg"
inkscape:version="1.0.1 (1.0.1+r73)"
inkscape:export-filename="/home/REINACB/jaime.arroyo/Escritorio/icon.png"
inkscape:export-xdpi="95.841858"
inkscape:export-ydpi="95.841858">
<metadata
id="metadata24">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>icon</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1848"
inkscape:window-height="1016"
id="namedview22"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-text-baseline="true"
inkscape:zoom="2.36"
inkscape:cx="214.46952"
inkscape:cy="122.86727"
inkscape:window-x="1992"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="layer4"
inkscape:document-rotation="0">
<sodipodi:guide
position="51.271186,126.37712"
orientation="-0.70710678,0.70710678"
id="guide40"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="118.65012,168.08767"
orientation="-0.70710678,0.70710678"
id="guide42"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="138.02966,143.00847"
orientation="-0.70710678,0.70710678"
id="guide46"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="137.92373,118.22034"
orientation="-0.70710678,0.70710678"
id="guide48"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="156.99152,93.008474"
orientation="-0.70710678,0.70710678"
id="guide50"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
<sodipodi:guide
position="139.19491,46.822034"
orientation="-0.70710678,0.70710678"
id="guide52"
inkscape:locked="false"
inkscape:label=""
inkscape:color="rgb(0,0,255)" />
</sodipodi:namedview>
<defs
id="defs4">
<style
id="style2">.cls-1{fill:none;}.cls-2{fill:#3b588f;}.cls-3{fill:#070308;opacity:0.4;}.cls-4{fill:#fff;}</style>
</defs>
<title
id="title6">icon</title>
<rect
id="_Sector_"
data-name="&lt;Sector&gt;"
class="cls-1"
width="200"
height="200" />
<rect
class="cls-2"
x="0.33000001"
width="200"
height="200"
id="rect9"
ry="9.5071955"
y="0"
style="fill:#d40000;fill-opacity:1"
rx="8.9955473" />
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="Layer 1"
style="display:inline">
<path
style="fill:#000000;fill-opacity:0.490826;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 0.049671,83.284331 0.26814214,41.291959 -0.0736993,70.20079 c 0.61125585,1.22897 0.0713539,1.30678 1.83376756,3.6869 1.072577,1.37049 4.2927789,1.58367 4.2780498,1.59104 l 127.7494088,0.31174 40.11322,-34.4134 -2.25413,-17.68905 -24.5097,2.96034 0.22711,-12.78168 1.76901,-98.111999 L 115.9642,37.423483 86.621943,72.659745 C 88.349947,64.714496 104.08849,21.147416 104.08849,21.147416 L 50.570781,37.302119 Z"
id="path56-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccccc" />
</g>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Layer 2">
<path
fill="currentColor"
d="M 171.96443,148.26435 H 153.29768 V 51.697132 c 0,-7.868548 -5.02368,-14.273649 -11.20004,-14.273649 H 115.9642 v 18.473479 h 22.40009 V 166.73783 h 33.60014 c 2.06267,0 3.73334,-2.06672 3.73334,-4.61837 v -9.23674 c 0,-2.55165 -1.67067,-4.61837 -3.73334,-4.61837 z M 99.220138,19.241539 54.419962,33.598898 c -3.325016,1.065113 -5.656024,4.892588 -5.656024,9.285807 V 148.26435 H 30.0972 c -2.062677,0 -3.73335,2.06672 -3.73335,4.61837 v 9.23674 c 0,2.55165 1.670673,4.61837 3.73335,4.61837 h 78.40031 V 28.527354 c 0,-6.229028 -4.56402,-10.798327 -9.277372,-9.285815 z M 87.964093,102.08066 c -3.091678,0 -5.600023,-4.136332 -5.600023,-9.236741 0,-5.100412 2.508345,-9.236739 5.600023,-9.236739 3.09168,0 5.600023,4.136327 5.600023,9.236739 0,5.100409 -2.508343,9.236741 -5.600023,9.236741 z"
id="path2"
style="stroke-width:0.259521;fill:#ffffff" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View file

@ -0,0 +1,432 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>IoT Rule</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="iot-rule">
<h1 class="title">IoT Rule</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:8776ccfdb4eda7e7911d811faef3f33474c34c474237b9afd180e4fe5ca1b233
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/iot/tree/16.0/iot_rule"><img alt="OCA/iot" src="https://img.shields.io/badge/github-OCA%2Fiot-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/iot-16-0/iot-16-0-iot_rule"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/iot&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This addon allows to define IoT Rules.</p>
<p>A Rule specifies which Inputs that can be controlled by a certain Key.
The Key is owned by an Agent (Employee, Partner or anonymous).
The Input is a request from an IoT Device that executes a certain function in Odoo.
This function will check if the Key (= the Agent) is allowed by any Rule to “control” the Device.
If Odoo answers positively the Agent will be allowed the to execute some Function on the Device
(for example open a door or switch on a relay).</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-5">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/iot/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/iot/issues/new?body=module:%20iot_rule%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-2">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
<ul class="simple">
<li>CreuBlanca</li>
<li>ForgeFlow</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
<ul class="simple">
<li>Enric Tobella &lt;<a class="reference external" href="mailto:etobella&#64;creublanca.es">etobella&#64;creublanca.es</a>&gt;</li>
<li>Luis Burrel &lt;<a class="reference external" href="mailto:lu.bu.sax&#64;gmail.com">lu.bu.sax&#64;gmail.com</a>&gt;</li>
<li>Aaron Henriquez &lt;<a class="reference external" href="mailto:ahforgeflow&#64;forgeflow.com">ahforgeflow&#64;forgeflow.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-5">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/iot/tree/16.0/iot_rule">OCA/iot</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1 @@
from . import test_iot_rule

View file

@ -0,0 +1,299 @@
# Copyright 2019 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import timedelta
from unittest.mock import patch
from odoo.exceptions import ValidationError
from odoo.fields import Datetime
from odoo.tests.common import TransactionCase
from ..models.iot_key import IotKey
class TestIotRule(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.rule_1 = cls.env["iot.rule"].create({"name": "rule 1"})
cls.rule_2 = cls.env["iot.rule"].create({"name": "rule 2"})
cls.lock_1 = cls.env["iot.lock"].create(
{"name": "Lock 1", "rule_ids": [(4, cls.rule_1.id)]}
)
cls.type_of_key_1 = "RFID"
cls.key_1 = cls.env["iot.key"].create(
{
"name": "Key 1",
"rule_ids": [(4, cls.rule_1.id)],
"key_type": cls.type_of_key_1,
}
)
cls.type_of_key_2 = "UUID"
cls.key_2 = cls.env["iot.key"].create(
{
"name": "Key 2",
"rule_ids": [(4, cls.rule_2.id)],
"key_type": cls.type_of_key_2,
}
)
cls.partner = cls.env["res.partner"].create({"name": "Demo partner"})
cls.system = cls.env["iot.communication.system"].create({"name": "Testing"})
cls.device_1 = cls.env["iot.device"].create(
{"name": "device 1", "communication_system_id": cls.system.id}
)
cls.serial_of_input_1 = "serial 1"
cls.passphrase_of_input_1 = "password 1"
cls.name_of_input_1 = "name 1"
cls.device_input_1 = cls.env["iot.device.input"].create(
{
"name": cls.name_of_input_1,
"device_id": cls.device_1.id,
"active": True,
"serial": cls.serial_of_input_1,
"passphrase": cls.passphrase_of_input_1,
"call_model_id": cls.env.ref("iot_input_oca.model_iot_device_input").id,
"call_function": "test_input_device",
"lock_id": cls.lock_1.id,
}
)
cls.device_2 = cls.env["iot.device"].create(
{"name": "device 2", "communication_system_id": cls.system.id}
)
cls.serial_of_input_2 = "serial 2"
cls.passphrase_of_input_2 = "password 2"
cls.name_of_input_2 = "name 2"
cls.device_input_2 = cls.env["iot.device.input"].create(
{
"name": cls.name_of_input_2,
"device_id": cls.device_2.id,
"active": True,
"serial": cls.serial_of_input_2,
"passphrase": cls.passphrase_of_input_2,
"call_model_id": cls.env.ref("iot_input_oca.model_iot_device_input").id,
"call_function": "test_input_device",
}
)
cls.serial_of_input_without_device = "foo orphan"
def test_allowed_access(self):
self.assertTrue(
self.lock_1.check_access_unique_virtual_key(self.key_1.unique_virtual_key)
)
def test_not_allowed_access(self):
self.assertFalse(
self.lock_1.check_access_unique_virtual_key(self.key_2.unique_virtual_key)
)
def test_non_existing_key(self):
self.assertFalse(self.lock_1.action_ids)
self.assertFalse(
self.lock_1.check_access_unique_virtual_key(
self.key_1.unique_virtual_key + self.key_2.unique_virtual_key
)
)
self.assertTrue(self.lock_1.action_ids)
self.assertFalse(self.lock_1.action_ids.key_id)
def test_not_unique_key_model(self):
self.key_1.write({"res_model": self.partner._name, "res_id": self.partner.id})
def test_unique_key_models(self):
with patch.object(IotKey, "_get_unique_key_models") as mocked:
mocked.return_value = [self.partner._name]
self.key_1.write(
{"res_model": self.partner._name, "res_id": self.partner.id}
)
with self.assertRaises(ValidationError):
self.key_2.write(
{"res_model": self.partner._name, "res_id": self.partner.id}
)
def test_inheritance(self):
self.rule_1.parent_ids = [(4, self.rule_2.id)]
self.assertTrue(
self.lock_1.check_access_unique_virtual_key(self.key_2.unique_virtual_key)
)
def test_inheritance_loop(self):
rule = self.env["iot.rule"].create({"name": "rule 1 0"})
self.rule_1.parent_ids = [(4, rule.id)]
for i in range(0, 50):
key = self.env["iot.key"].create(
{"name": "Key 2", "rule_ids": [(4, rule.id)]}
)
self.assertTrue(
self.lock_1.check_access_unique_virtual_key(key.unique_virtual_key)
)
new_rule = self.env["iot.rule"].create({"name": "rule 1 %s" % i})
rule.parent_ids = [(4, new_rule.id)]
rule = new_rule
key = self.env["iot.key"].create({"name": "Key 2", "rule_ids": [(4, rule.id)]})
self.assertFalse(
self.lock_1.check_access_unique_virtual_key(key.unique_virtual_key)
)
def test_recursion(self):
self.rule_1.parent_ids = [(4, self.rule_2.id)]
with self.assertRaises(ValidationError):
self.rule_2.parent_ids = [(4, self.rule_1.id)]
def test_actions(self):
self.assertFalse(self.key_1.action_ids)
self.assertFalse(self.lock_1.action_ids)
self.lock_1.check_access_unique_virtual_key(self.key_1.unique_virtual_key)
self.assertTrue(self.key_1.action_ids)
self.assertTrue(self.lock_1.action_ids)
self.assertFalse(self.key_2.action_ids)
self.lock_1.check_access_unique_virtual_key(self.key_2.unique_virtual_key)
self.assertTrue(self.key_2.action_ids)
action = self.lock_1.view_actions()
self.assertEqual(
self.lock_1.action_ids,
self.env[action["res_model"]].search(action["domain"]),
)
action = self.key_1.view_actions()
self.assertEqual(
self.env[action["res_model"]].search(action["domain"]),
self.key_1.action_ids,
)
def test_expiration(self):
self.assertTrue(
self.lock_1.check_access_unique_virtual_key(self.key_1.unique_virtual_key)
)
now = Datetime.from_string(Datetime.now())
self.key_1.expiration_date = Datetime.to_string(now + timedelta(hours=1))
self.assertTrue(
self.lock_1.check_access_unique_virtual_key(self.key_1.unique_virtual_key)
)
self.key_1.expiration_date = Datetime.to_string(now + timedelta(hours=-1))
self.assertFalse(
self.lock_1.check_access_unique_virtual_key(self.key_1.unique_virtual_key)
)
def test_lock_find_keys(self):
result = self.lock_1.get_virtual_keys()
self.assertEqual(len(result), 1)
self.assertEqual(result[0]["id"], self.key_1.id)
key = self.env["iot.key"].create(
{"name": "Key 1", "rule_ids": [(4, self.rule_1.id)]}
)
result = self.lock_1.get_virtual_keys()
self.assertEqual(len(result), 2)
ids = [r["id"] for r in result]
self.assertIn(self.key_1.id, ids)
self.assertIn(key.id, ids)
now = Datetime.from_string(Datetime.now())
key.expiration_date = Datetime.to_string(now + timedelta(hours=-1))
result = self.lock_1.get_virtual_keys()
self.assertEqual(len(result), 1)
self.assertEqual(result[0]["id"], self.key_1.id)
key.expiration_date = Datetime.to_string(now + timedelta(hours=1))
result = self.lock_1.get_virtual_keys()
self.assertEqual(len(result), 2)
ids = [r["id"] for r in result]
self.assertIn(self.key_1.id, ids)
self.assertIn(key.id, ids)
def test_wizard(self):
self.assertEqual(0, self.partner.iot_key_count)
wizard_key = self.env["iot.key.wizard"].create(
{
"res_id": self.partner.id,
"res_model": self.partner._name,
"unique_virtual_key": "Testing Key",
"rule_ids": [(4, self.rule_1.id)],
}
)
wizard_key.create_key()
key = wizard_key.iot_key_id
self.assertEqual(key.unique_virtual_key, "Testing Key")
self.assertEqual(key.rule_ids, self.rule_1)
self.partner.invalidate_model()
self.assertEqual(1, self.partner.iot_key_count)
action = self.partner.action_view_iot_key()
self.assertEqual(key, self.env[action["res_model"]].search(action["domain"]))
original_key = key
wizard_key = self.env["iot.key.wizard"].create(
{
"res_id": self.partner.id,
"res_model": self.partner._name,
"iot_key_id": key.id,
"unique_virtual_key": "Testing Key 2",
"rule_ids": [(4, self.rule_1.id)],
}
)
wizard_key.update_key()
key.invalidate_model()
self.assertEqual(key.unique_virtual_key, "Testing Key 2")
wizard_key = self.env["iot.key.wizard"].create(
{
"res_id": self.partner.id,
"res_model": self.partner._name,
"iot_key_id": key.id,
"unique_virtual_key": "Testing Key",
"rule_ids": [(4, self.rule_1.id)],
}
)
wizard_key.create_key()
key.invalidate_model()
self.assertEqual(key.unique_virtual_key, "Testing Key")
self.assertEqual(key, original_key)
def test_get_iot_keys_from_device_serial_and_type_of_key(self):
result = self.env["iot.device"].get_iot_keys(
self.serial_of_input_2, self.type_of_key_1
)
self.assertTrue(result.get("error", False))
result = self.env["iot.device"].get_iot_keys(
self.serial_of_input_without_device, self.type_of_key_1
)
self.assertTrue(result.get("error", False))
result = self.env["iot.device"].get_iot_keys(
self.serial_of_input_1, self.type_of_key_1
)
self.assertEqual(len(result["keys"]), 1)
self.assertEqual(result["keys"][0].get("key_type"), self.type_of_key_1)
result = self.env["iot.device"].get_iot_keys(
self.serial_of_input_1, self.type_of_key_2
)
self.assertEqual(len(result["keys"]), 0)
result = self.env["iot.device"].get_iot_keys(self.serial_of_input_1, "ALL")
self.assertEqual(len(result["keys"]), 1)
self.rule_1.write({"parent_ids": [(4, self.rule_2.id)]})
result = self.env["iot.device"].get_iot_keys(self.serial_of_input_1, "ALL")
self.assertEqual(len(result["keys"]), 2)
def test_get_iot_keys_from_device_input(self):
result = self.device_input_1.get_iot_keys()
self.assertEqual(len(result["keys"]), 1)
self.assertEqual(result["keys"][0].get("id"), self.key_1.id)
def test_call_lock_of_a_device_input(self):
self.assertTrue(
self.device_input_1.call_lock(self.key_1.unique_virtual_key).get(
"access_granted"
)
)
def test_generate_iot_lock_for_device_input(self):
self.device_2.write({"name": "Changing name"})
self.assertFalse(self.device_input_2.lock_id)
self.device_input_2.generate_iot_lock()
lock = self.env["iot.lock"].search(
[("id", "=", self.device_input_2.lock_id.id)], limit=1
)
self.assertEqual(
lock.name, self.device_2.name + " / " + self.device_input_2.name
)
self.device_input_2.generate_iot_lock()
self.assertEqual(lock, self.device_input_2.lock_id)
def test_change_name_of_lock_if_device_name_changes(self):
self.device_1_new_name = "some funky cool new name"
self.device_1.write({"name": self.device_1_new_name})
self.assertEqual(
self.lock_1.name, self.device_1_new_name + " / " + self.device_input_1.name
)

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 Creu Blanca
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="iot_device_input_form_view">
<field name="name">iot.device.input.form (in iot_rule)</field>
<field name="model">iot.device.input</field>
<field name="inherit_id" ref="iot_input_oca.iot_device_input_form" />
<field name="arch" type="xml">
<field name="call_function" position="after">
<button
name="generate_iot_lock"
groups="iot_oca.group_iot_manager"
string="Generate IoT Lock for this Input"
type="object"
attrs="{'invisible': [('lock_id', '!=', False)]}"
/>
<field
name="lock_id"
groups="iot_oca.group_iot_user"
attrs="{'invisible': [('lock_id', '=', False)]}"
string="IoT Lock associated"
/>
</field>
</field>
</record>
</odoo>

View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 Creu Blanca
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="iot_key_form_view">
<field name="name">iot.key.form (in iot_rule)</field>
<field name="model">iot.key</field>
<field name="arch" type="xml">
<form>
<header />
<sheet>
<widget
name="web_ribbon"
text="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
<field name="active" invisible="1" />
<div class="oe_button_box" name="button_box">
<button
name="view_actions"
type="object"
icon="fa-bars"
groups="iot_oca.group_iot_user"
string="Usage Log"
/>
</div>
<div class="oe_title">
<h1>
<field name="name" />
</h1>
</div>
<group>
<group name="main">
<field name="unique_virtual_key" />
<field name="res_id" invisible="1" />
<field name="res_model" invisible="1" />
<field name="expiration_date" />
</group>
</group>
<group>
<group name="rules">
<field
name="rule_ids"
widget="many2many_tags"
string="Authorized Lock Groups"
/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="iot_key_search_view">
<field name="name">iot.key.search (in iot_rule)</field>
<field name="model">iot.key</field>
<field name="arch" type="xml">
<search>
<field name="name" />
<field name="unique_virtual_key" />
<separator />
<filter
string="Expired"
name="expired"
domain="[('expiration_date', '&lt;', datetime.datetime.now())]"
help="Expired Keys"
/>
<filter
string="Not Expired"
name="not_expired"
domain="['|',('expiration_date', '&gt;', datetime.datetime.now()), ('expiration_date', '=', False)]"
help="Not expired Keys"
/>
</search>
</field>
</record>
<record model="ir.ui.view" id="iot_key_tree_view">
<field name="name">iot.key.tree (in iot_rule)</field>
<field name="model">iot.key</field>
<field name="arch" type="xml">
<tree>
<field name="name" />
<field name="unique_virtual_key" />
<field name="rule_ids" widget="many2many_tags" />
<field name="expiration_date" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="iot_key_act_window">
<field name="name">Keys (Persons)</field>
<field name="res_model">iot.key</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.ui.menu" id="iot_key_menu">
<field name="name">Keys (Persons)</field>
<field name="parent_id" ref="iot_rule.iot_rule_menu" />
<field name="action" ref="iot_key_act_window" />
<field name="sequence" eval="25" />
</record>
</odoo>

View file

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 Creu Blanca
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="iot_key_action_form_view">
<field name="name">iot.key.action.form (in iot_rule)</field>
<field name="model">iot.key.action</field>
<field name="arch" type="xml">
<form delete="0" create="0" edit="0">
<header />
<sheet>
<group>
<field name="lock_id" />
<field name="key_name" />
<field name="key_id" />
<field name="timestamp" />
<field name="result" />
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="iot_key_action_search_view">
<field name="name">iot.key.action.search (in iot_rule)</field>
<field name="model">iot.key.action</field>
<field name="arch" type="xml">
<search>
<field name="timestamp" />
<field name="lock_id" />
<field name="key_name" />
<field name="key_id" />
<field name="result" />
</search>
</field>
</record>
<record model="ir.ui.view" id="iot_key_action_tree_view">
<field name="name">iot.key.action.tree (in iot_rule)</field>
<field name="model">iot.key.action</field>
<field name="arch" type="xml">
<tree delete="0" create="0">
<field name="timestamp" />
<field name="lock_id" />
<field name="key_name" />
<field name="key_id" />
<field name="result" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="iot_key_action_act_window">
<field name="name">Usage Log</field>
<field name="res_model">iot.key.action</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.ui.menu" id="iot_key_action_menu">
<field name="name">Usage Log</field>
<field name="parent_id" ref="iot_rule.iot_rule_menu" />
<field name="action" ref="iot_rule.iot_key_action_act_window" />
<field name="sequence" eval="90" />
</record>
</odoo>

View file

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 Creu Blanca
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="iot_lock_form_view">
<field name="name">iot.lock.form (in iot_rule)</field>
<field name="model">iot.lock</field>
<field name="arch" type="xml">
<form>
<header />
<sheet>
<widget
name="web_ribbon"
text="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
<field name="active" invisible="1" />
<div class="oe_button_box" name="button_box">
<button
name="view_actions"
type="object"
icon="fa-bars"
groups="iot_oca.group_iot_user"
string="Usage Log"
/>
</div>
<group>
<field name="name" />
<field name="description" />
</group>
<group>
<field
name="rule_ids"
widget="many2many_tags"
string="Member of these Groups of Locks"
/>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="iot_lock_search_view">
<field name="name">iot.lock.search (in iot_rule)</field>
<field name="model">iot.lock</field>
<field name="arch" type="xml">
<search>
<field name="name" />
<field name="description" />
</search>
</field>
</record>
<record model="ir.ui.view" id="iot_lock_tree_view">
<field name="name">iot.lock.tree (in iot_rule)</field>
<field name="model">iot.lock</field>
<field name="arch" type="xml">
<tree>
<field name="name" />
<field name="description" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="iot_lock_act_window">
<field name="name">Locks (Devices)</field>
<field name="res_model">iot.lock</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.ui.menu" id="iot_lock_menu">
<field name="name">Locks (Devices)</field>
<field name="parent_id" ref="iot_rule.iot_rule_menu" />
<field name="action" ref="iot_lock_act_window" />
<field name="sequence" eval="16" />
</record>
</odoo>

View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2019 Creu Blanca
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="iot_rule_form_view">
<field name="name">iot.rule.form (in iot_rule)</field>
<field name="model">iot.rule</field>
<field name="arch" type="xml">
<form>
<header />
<sheet>
<widget
name="web_ribbon"
text="Archived"
bg_color="bg-danger"
attrs="{'invisible': [('active', '=', True)]}"
/>
<field name="active" invisible="1" />
<div class="oe_button_box" name="button_box" />
<group>
<field name="name" />
<field name="lock_ids" widget="many2many_tags" />
<field name="parent_ids" widget="many2many_tags" />
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="iot_rule_search_view">
<field name="name">iot.rule.search (in iot_rule)</field>
<field name="model">iot.rule</field>
<field name="arch" type="xml">
<search>
<field name="name" />
</search>
</field>
</record>
<record model="ir.ui.view" id="iot_rule_tree_view">
<field name="name">iot.rule.tree (in iot_rule)</field>
<field name="model">iot.rule</field>
<field name="arch" type="xml">
<tree>
<field name="name" />
</tree>
</field>
</record>
<record model="ir.actions.act_window" id="iot_rule_act_window">
<field name="name">Rules</field>
<field name="res_model">iot.rule</field>
<field name="view_mode">tree,form</field>
<field name="domain">[]</field>
<field name="context">{}</field>
</record>
<record model="ir.actions.act_window" id="iot_rule_action">
<field name="name">Rules</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">iot.rule</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem
name="Rules"
sequence="15"
id="iot_rule_menu"
parent="iot_oca.iot_root_menu"
/>
<menuitem
name="Rules"
sequence="10"
id="iot_define_rules_menu"
action="iot_rule_action"
parent="iot_rule.iot_rule_menu"
/>
</odoo>

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 Creu Blanca
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="res_partner_form_view">
<field name="name">res.partner.form (in iot_rule)</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button
class="oe_stat_button"
name="action_view_iot_key"
type="object"
attrs="{'invisible': [('iot_key_count', '=', 0)]}"
icon="fa-key"
groups="iot_oca.group_iot_user"
>
<field
string="Keys"
name="iot_key_count"
widget="statinfo"
groups="iot_oca.group_iot_user"
/>
<field name="iot_key_ids" invisible="1" />
</button>
</div>
</field>
</record>
</odoo>

View file

@ -0,0 +1 @@
from . import iot_key_wizard

View file

@ -0,0 +1,48 @@
# Copyright 2021 Creu Blanca
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import _, fields, models
class OddoorKeyWizard(models.TransientModel):
_name = "iot.key.wizard"
_description = "Create a Key"
res_id = fields.Integer(required=True)
res_model = fields.Char(required=True)
iot_key_id = fields.Many2one(
"iot.key",
)
unique_virtual_key = fields.Char(required=True)
rule_ids = fields.Many2many("iot.rule")
def _create_iot_key_vals(self):
record = self.env[self.res_model].browse(self.res_id)
return {
"res_id": self.res_id,
"res_model": self.res_model,
"name": _("Key of %s") % record.display_name,
"unique_virtual_key": self.unique_virtual_key,
"rule_ids": [(6, 0, self.rule_ids.ids)],
}
def create_key(self):
self.ensure_one()
if not self.iot_key_id:
self.iot_key_id = self.env["iot.key"].create(self._create_iot_key_vals())
return self.update_key(False)
return self.update_key()
def _update_key_vals(self):
record = self.env[self.res_model].browse(self.res_id)
return {
"unique_virtual_key": self.unique_virtual_key,
"name": _("Key of %s") % record.display_name,
"rule_ids": [(6, 0, self.rule_ids.ids)],
}
def update_key(self, update=True):
if update:
self.iot_key_id.write(self._update_key_vals())
return {}

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2021 Creu Blanca
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="iot_key_wizard_form_view">
<field name="name">iot.key.wizard.form (in iot_rule)</field>
<field name="model">iot.key.wizard</field>
<field name="arch" type="xml">
<form string="IoT Key Wizard">
<field name="res_model" invisible="1" />
<field name="res_id" invisible="1" />
<field name="iot_key_id" invisible="1" />
<group>
<field name="unique_virtual_key" />
<field name="rule_ids" widget="many2many_checkboxes" />
</group>
<footer>
<button
name="create_key"
string="Create"
class="btn-primary"
attrs="{'invisible': [('iot_key_id', '!=', False)]}"
type="object"
/>
<button
name="update_key"
string="Update"
class="btn-primary"
attrs="{'invisible': [('iot_key_id', '=', False)]}"
type="object"
/>
<button string="Cancel" class="btn-default" special="cancel" />
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="iot_key_wizard_act_window">
<field name="name">IoT Key Wizard</field>
<field name="res_model">iot.key.wizard</field>
<field name="view_mode">form</field>
<field name="context">{}</field>
<field name="target">new</field>
</record>
</odoo>