diff --git a/README.md b/README.md
index 311ece4..8a2fb97 100644
--- a/README.md
+++ b/README.md
@@ -33,3 +33,17 @@ that explains its license.
----
+
+
+## Keycloak
+
+To integrate Keycloak as a OAuth provider in Odoo, you need to install the following OCA module:
+
+[auth_oidc](https://github.com/OCA/server-auth/tree/18.0/auth_oidc)
+
+
+## Multi Session Odoo
+
+If you wish to enable multiple connections for the same account with an OAuth provider in Odoo, you'll need to install this OCA module:
+
+[auth_oauth_multi_token](https://github.com/OCA/server-auth/tree/18.0/auth_oauth_multi_token)
\ No newline at end of file
diff --git a/openems/__manifest__.py b/openems/__manifest__.py
index 232ebf1..0849898 100644
--- a/openems/__manifest__.py
+++ b/openems/__manifest__.py
@@ -1,7 +1,7 @@
{
"name": "OpenEMS",
"summary": "Everything related to OpenEMS (Open Energy Management System)",
- "version": "16.0.1.0.1",
+ "version": "18.0.1.0.1",
"author": "OpenEMS Association e.V.",
"maintainer": "OpenEMS Association e.V.",
"contributors": [
@@ -11,7 +11,7 @@
"website": "https://openems.io",
"license": "AGPL-3",
"category": "Specific Industry Applications",
- "depends": ["base", "web", "mail", "crm", "resource", "stock", "web_m2x_options", "partner_firstname"],
+ "depends": ["base", "web", "mail", "crm", "resource", "stock", "web_m2x_options", "partner_firstname","auth_oauth"],
"data": [
"data/ir_config_parameter.xml",
"data/res_partner_category.xml",
diff --git a/openems/controllers/alerting.py b/openems/controllers/alerting.py
index 7a848f2..b05bc85 100644
--- a/openems/controllers/alerting.py
+++ b/openems/controllers/alerting.py
@@ -12,51 +12,60 @@ class SumState(Enum):
class Message:
sentAt: datetime
edgeId: str
- userIds: list[int]
+ userLogins: list[str]
- def __init__(self, sentAt: datetime, edgeId: str, userIds: list[int]) -> None:
+ def __init__(self, sentAt: datetime, edgeId: str, userLogins : list[str]) -> None:
self.sentAt = sentAt
self.edgeId = edgeId
- self.userIds = userIds
+ self.userLogins = userLogins
class SumStateMessage(Message):
state: SumState
- def __init__(self, sentAt: datetime, edgeId: str, userIds: list[int], state: SumState) -> None:
- super().__init__(sentAt, edgeId, userIds)
+ def __init__(self, sentAt: datetime, edgeId: str, userLogins: list[str], state: SumState) -> None:
+ super().__init__(sentAt, edgeId, userLogins)
self.state = state
class Alerting(http.Controller):
__logger = logging.getLogger("Alerting")
+ __datetime_format = "%Y-%m-%d %H:%M:%S"
@http.route("/openems_backend/mail/alerting_sum_state", type="json", auth="user")
- def sum_state_alerting(self, sentAt: str, params: list[dict]):
+ def sum_state_alerting(self, sentAt: str, params: list[dict]) -> dict:
msgs = self.__get_sum_state_params(sentAt, params)
update_func = lambda role, at: { role.write({"sum_state_last_notification": at})}
if len(msgs) == 0:
self.__logger.error("Scheduled SumState-Alerting-Mail without any recipients!!!")
+ return {"status": "error", "message": "No recipients for sum state alerting"}
template = request.env.ref('openems.alerting_sum_state')
+ mails_sent = 0
for msg in msgs:
- self.__send_mails(template, msg, update_func)
+ mails_sent += self.__send_mails(template, msg, update_func)
- return {}
+ return {"status": "success", "mails_sent": mails_sent}
@http.route("/openems_backend/mail/alerting_offline", type="json", auth="user")
- def offline_alerting(self, sentAt: str, params: list[dict]):
+ def offline_alerting(self, sentAt: str, params: list[dict]) -> dict:
msgs = self.__get_offline_params(sentAt, params)
update_func = lambda role, at: { role.write({"offline_last_notification": at})}
- template = request.env.ref("openems.alerting_offline")
+ if len(msgs) == 0:
+ self.__logger.error("Scheduled Offline-Alerting-Mail without any recipients!!!")
+ return {"status": "error", "message": "No recipients for offline alerting"}
+
+ mails_sent = 0
+
for msg in msgs:
- self.__send_mails(template, msg, update_func)
+ template = self.__get_template(msg.edgeId)
+ mails_sent += self.__send_mails(template, msg, update_func)
- return {}
+ return {"status": "success", "mails_sent": mails_sent}
def __get_offline_params(self, sentAt, params) -> list[Message]:
msgs = list()
- sent = datetime.strptime(sentAt, "%Y-%m-%d %H:%M:%S")
+ sent = datetime.strptime(sentAt, self.__datetime_format)
for param in params:
edgeId = param["edgeId"]
recipients = param["recipients"]
@@ -65,22 +74,49 @@ def __get_offline_params(self, sentAt, params) -> list[Message]:
def __get_sum_state_params(self, sentAt, params) -> list[SumStateMessage]:
msgs = list()
- sent = datetime.strptime(sentAt, "%Y-%m-%d %H:%M:%S")
+ sent = datetime.strptime(sentAt, self.__datetime_format)
for param in params:
edgeId = param["edgeId"]
recipients = param["recipients"]
state = param["state"]
msgs.append(SumStateMessage(sent, edgeId, recipients, state));
return msgs
+
+ def __get_template(self, device_id):
+ oem, producttype = self.__get_device_data_for(device_id)
+ match (oem.casefold(), producttype.casefold()):
+ case ('openems', _):
+ return request.env.ref("openems.alerting_offline")
- def __send_mails(self, template, msg: Message, update_func):
+ def __get_device_data_for(self, device_id) -> tuple[str, str]:
+ if device_id:
+ found_devices = http.request.env["openems.device"].search_read(
+ [("name", "=", device_id)], ["producttype", "oem"]
+ )
+ if len(found_devices) == 1:
+ device = found_devices[0]
+ oem = device.get('oem') or 'openems'
+ producttype = device.get('producttype') or 'other'
+ return oem, producttype
+
+ self.__logger.warning(f"no device with id '{device_id}' found, using fallback [oem=openems, producttype=other]")
+ return 'openems', 'other'
+
+ def __send_mails(self, template, msg: Message, update_func) -> int:
roles = http.request.env['openems.alerting'].search(
- [('user_id','in',msg.userIds),('device_id','=',msg.edgeId)]
+ [('user_login','in', msg.userLogins),('device_id','=', msg.edgeId)]
)
+ if not roles or len(roles) == 0:
+ self.__logger.error(f"No AlertingSettings found for edgeId[{msg.edgeId}] and userLogins[{msg.userLogins}]!!!")
+ return 0
+
+ mails_sent = 0
for role in roles:
try:
- template.send_mail(res_id=role.id, force_send=True)
+ template.send_mail(res_id=role.id)
update_func(role, msg.sentAt)
+ mails_sent += 1
except Exception as err:
- self.__logger.error("[" + str(err) + "] Unable to send template[" + str(template.name) +"] to edgeUser[user=" + str(role.id) + ", edge=" + str(msg.edgeId)+ "]")
\ No newline at end of file
+ self.__logger.error(f"[{err}] Unable to send template[{template.name}] to edgeUser[user={role.id}, edge={msg.edgeId}]")
+ return mails_sent
\ No newline at end of file
diff --git a/openems/controllers/openems_backend.py b/openems/controllers/openems_backend.py
index d0dcb80..f84b845 100644
--- a/openems/controllers/openems_backend.py
+++ b/openems/controllers/openems_backend.py
@@ -3,15 +3,13 @@
class OpenemsBackend(http.Controller):
@http.route("/openems_backend/info", auth="user", type="json")
- def index(self):
+ def index(self, external_uid):
# Get user
- user_id = http.request.env.context.get("uid")
res_users = http.request.env["res.users"].sudo()
user_rec = res_users.search_read(
- [("id", "=", user_id)],
- ["login", "name", "groups_id", "global_role", "openems_language"],
+ [("oauth_uid", "=", external_uid)],
+ ["login", "name", "groups_id", "global_role", "openems_language", "settings"],
)[0]
- res_users.browse([user_id])
# Get res group model
res_groups_model = http.request.env["res.groups"].sudo()
@@ -23,73 +21,23 @@ def index(self):
manager_group_id = manager_group["id"]
reader_group_id = reader_group["id"]
+ settings = user_rec["settings"] if user_rec.get("settings") else {}
+
# Get user attributes
global_role = user_rec["global_role"]
if manager_group_id in user_rec["groups_id"]:
# Manager group
global_role = "admin"
- # return empty device (use pagination) list if user is manager or reader
+ has_multiple_edges = False
if manager_group_id in user_rec["groups_id"] or reader_group_id in user_rec["groups_id"]:
- return {
- "user": {
- "id": user_rec["id"],
- "login": user_rec["login"],
- "name": user_rec["name"],
- "global_role": global_role,
- "language": user_rec["openems_language"],
- "has_multiple_edges": True
- },
- "devices": [],
- }
-
- # Get specific Device roles
- device_user_role_model = http.request.env["openems.device_user_role"]
- user_role_ids = device_user_role_model.search_read(
- [("user_id", "=", user_id)], ["id", "role"]
- )
-
- # Get Devices
- device_model = http.request.env["openems.device"]
- devices = device_model.search_read(
- [], ["id", "name", "user_role_ids", "comment", "producttype",
- "lastmessage", "first_setup_protocol_date", "openems_sum_state_level"]
- )
-
- devs = []
- for device_rec in devices:
- # Set user role per group
- role = "guest"
- if manager_group_id in user_rec["groups_id"]:
- # Manager group
- role = "admin"
- elif reader_group_id in user_rec["groups_id"]:
- # Reader group
- role = "guest"
-
- # Set specific user role
- for device_role_id in device_rec["user_role_ids"]:
- for user_role_id in user_role_ids:
- if device_role_id == user_role_id["id"]:
- role = user_role_id["role"]
-
- # Prepare result
- dev = {
- "id": device_rec["id"],
- "name": device_rec["name"],
- "comment": device_rec["comment"],
- "producttype": device_rec["producttype"],
- "role": role,
- "lastmessage": device_rec["lastmessage"],
- "openems_sum_state_level": device_rec["openems_sum_state_level"]
- }
-
- if device_rec["first_setup_protocol_date"]:
- dev["first_setup_protocol_date"] = device_rec[
- "first_setup_protocol_date"
- ]
-
- devs.append(dev)
+ has_multiple_edges = True
+ else:
+ device_user_role_model = http.request.env["openems.device_user_role"]
+ user_role_ids = device_user_role_model.search_read(
+ [("user_id", "=", user_rec["id"])], ["id"], limit=2
+ )
+ has_multiple_edges = len(user_role_ids) > 1
return {
"user": {
@@ -98,17 +46,17 @@ def index(self):
"name": user_rec["name"],
"global_role": global_role,
"language": user_rec["openems_language"],
- "has_multiple_edges": len(devs) > 1
+ "has_multiple_edges": has_multiple_edges,
+ "settings": settings
},
- "devices": devs,
+ "devices": [],
}
@http.route("/openems_backend/get_edge_with_role", auth="user", type="json")
- def get_edge_with_role(self, edge_id: str):
- user_id = http.request.env.context.get("uid")
+ def get_edge_with_role(self, external_uid, edge_id: str):
res_users = http.request.env["res.users"].sudo()
user_rec = res_users.search_read(
- [("id", "=", user_id)],
+ [("oauth_uid", "=", external_uid)],
["login", "name", "groups_id"],
)[0]
@@ -124,9 +72,9 @@ def get_edge_with_role(self, edge_id: str):
# get devices for which the user has permissions
device_model = http.request.env["openems.device"]
- devices = device_model.search_read(
+ devices = device_model.with_user(user_rec["id"]).search_read(
[("name", "=", edge_id)],
- ["id", "name", "comment", "producttype", "lastmessage", "first_setup_protocol_date", "openems_sum_state_level"])
+ ["id", "name", "comment", "producttype", "lastmessage", "first_setup_protocol_date", "openems_sum_state_level", "settings"])
if len(devices) != 1:
return {}
@@ -136,7 +84,7 @@ def get_edge_with_role(self, edge_id: str):
# Get specific Device roles
device_user_role_model = http.request.env["openems.device_user_role"]
device_user_roles = device_user_role_model.search_read(
- [("user_id", "=", user_id),
+ [("user_id", "=", user_rec["id"]),
("device_id", "=", device["id"])], ["id", "role"]
)
@@ -162,18 +110,20 @@ def get_edge_with_role(self, edge_id: str):
"lastmessage": device["lastmessage"],
"openems_sum_state_level": device["openems_sum_state_level"]
}
+ if device.get("settings"):
+ dev["settings"] = device["settings"]
+
if device["first_setup_protocol_date"]:
dev["first_setup_protocol_date"] = device["first_setup_protocol_date"]
return dev
@http.route("/openems_backend/get_edges", auth="user", type="json")
- def get_edges(self, limit, page, query=None, searchParams=None):
+ def get_edges(self, external_uid, limit, page, query=None, searchParams=None):
# Get user
- user_id = http.request.env.context.get("uid")
res_users = http.request.env["res.users"].sudo()
user_rec = res_users.search_read(
- [("id", "=", user_id)],
+ [("oauth_uid", "=", external_uid)],
["login", "name", "groups_id", "global_role"],
)[0]
@@ -190,12 +140,13 @@ def get_edges(self, limit, page, query=None, searchParams=None):
# Get specific Device roles
device_user_role_model = http.request.env["openems.device_user_role"]
user_role_ids = device_user_role_model.search_read(
- [("user_id", "=", user_id)], ["id", "role"]
+ [("user_id", "=", user_rec["id"])], ["id", "role"]
)
domains = []
logical_operators = []
additional_domains = []
+ order = ""
if query:
logical_operators.extend(['|', '|'])
domains = [
@@ -213,6 +164,24 @@ def get_edges(self, limit, page, query=None, searchParams=None):
additional_domains.append(
("openems_sum_state_level", "in", sum_states))
+ if searchParams.get("orderState"):
+
+ def map_field(input):
+ lookup = {"id": "name_number", "comment": "comment", "sumState": "openems_sum_state_level"}
+ field = lookup.get(input)
+
+ if not field:
+ raise ValueError("{input} is not supported")
+ return field
+
+ order_state = list(map(lambda s: (map_field(s["field"]), s["sortOrder"]), searchParams.get("orderState")))
+
+ for index, item in enumerate(order_state):
+ order += item[0] + " " + item[1]
+
+ if index < (len(order_state) - 1):
+ order += ","
+
if "isOnline" in searchParams:
additional_domains.append(
("openems_is_connected", "=", searchParams.get("isOnline")))
@@ -230,10 +199,11 @@ def get_edges(self, limit, page, query=None, searchParams=None):
# Get Devices
device_model = http.request.env["openems.device"]
- devices = device_model.search_read(
+ devices = device_model.with_user(user_rec["id"]).search_read(
logical_operators,
["id", "name", "user_role_ids", "comment", "producttype",
- "lastmessage", "first_setup_protocol_date", "openems_sum_state_level"],
+ "lastmessage", "first_setup_protocol_date", "openems_sum_state_level", "settings"],
+ order=order,
limit=limit, offset=(page * limit)
)
devs = []
@@ -263,6 +233,10 @@ def get_edges(self, limit, page, query=None, searchParams=None):
"lastmessage": device_rec["lastmessage"],
"openems_sum_state_level": device_rec["openems_sum_state_level"]
}
+
+ if device_rec.get("settings"):
+ dev["settings"] = device_rec["settings"]
+
if device_rec["first_setup_protocol_date"]:
dev["first_setup_protocol_date"] = device_rec[
diff --git a/openems/controllers/setup_protocol.py b/openems/controllers/setup_protocol.py
index d64b18e..4f73b3c 100644
--- a/openems/controllers/setup_protocol.py
+++ b/openems/controllers/setup_protocol.py
@@ -42,8 +42,8 @@ def index(self, setupProtocolId, edgeId):
templates = self.getTemplates(device_rec[0]['oem'], ibnPdf)
- templates['installer'].send_mail(setupProtocolId, force_send=True)
- templates['customer'].send_mail(setupProtocolId, force_send=True)
+ templates['installer'].send_mail(setupProtocolId)
+ templates['customer'].send_mail(setupProtocolId)
return {}
@@ -65,11 +65,17 @@ def getTemplates(self, oem: str, protocol):
return templates
@http.route('/openems_backend/get_latest_setup_protocol', type='json', auth='user')
- def get_latest_setup_protocol(self, edge_name):
+ def get_latest_setup_protocol(self, external_uid, edge_name):
+ res_users = http.request.env["res.users"].sudo()
+ user_rec = res_users.search_read(
+ [("oauth_uid", "=", external_uid)],
+ ["login"],
+ )[0]
+
# search for device
device_model = request.env['openems.device']
- device = device_model.search([('name', '=', edge_name)])
-
+ device = device_model.with_user(user_rec[0]).search([('name', '=', edge_name)])
+
response = dict()
if not len(device.setup_protocol_ids) > 0:
return response
diff --git a/openems/controllers/user.py b/openems/controllers/user.py
index 75ec137..27df7c4 100644
--- a/openems/controllers/user.py
+++ b/openems/controllers/user.py
@@ -24,7 +24,7 @@ def index(self, userId, password=None, oem: str = ''):
}
# send mail
template.with_context(email_values).send_mail(
- res_id=partner_id[0], force_send=True)
+ res_id=partner_id[0])
return {}
def getTemplate(self, oem: str):
diff --git a/openems/mail/openems/alerting_sum_state.xml b/openems/mail/openems/alerting_sum_state.xml
index 5ac49f6..dee2ccc 100644
--- a/openems/mail/openems/alerting_sum_state.xml
+++ b/openems/mail/openems/alerting_sum_state.xml
@@ -6,6 +6,7 @@
]]>
{{object.user_id.partner_id.id}}
+ {{object.user_id.get_mapped_language()}}
OpenEMS Alert - Edge is in {{object.device_id.openems_sum_state_level}} State
diff --git a/openems/models/device.py b/openems/models/device.py
index bdbda80..488a567 100644
--- a/openems/models/device.py
+++ b/openems/models/device.py
@@ -29,6 +29,7 @@ class Device(models.Model):
"First Setup Protocol Date", compute="_compute_first_setup_protocol"
)
manual_setup_date = fields.Datetime("Manual Setup Date")
+ settings = fields.Json()
@api.depends("setup_protocol_ids", "manual_setup_date")
def _compute_first_setup_protocol(self):
@@ -112,7 +113,7 @@ def _compute_monitoring_url(self):
)
# Helper fields
- name_number = fields.Integer(compute="_compute_name_number", store="True")
+ name_number = fields.Integer(compute="_compute_name_number", store=True, index=True)
@api.depends("name")
def _compute_name_number(self):
@@ -252,7 +253,7 @@ class OpenemsConfigUpdate(models.Model):
_description = "OpenEMS Edge Device Configuration Update"
_order = "create_date desc"
- device_id = fields.Many2one("openems.device", string="OpenEMS Edge")
+ device_id = fields.Many2one("openems.device", string="OpenEMS Edge",index=True)
teaser = fields.Text("Update Details Teaser")
details = fields.Html("Update Details")
@@ -263,7 +264,7 @@ class Systemmessage(models.Model):
_order = "create_date desc"
timestamp = fields.Datetime("Creation date")
- device_id = fields.Many2one("openems.device", string="OpenEMS Edge")
+ device_id = fields.Many2one("openems.device", string="OpenEMS Edge",index=True)
text = fields.Text("Message")
text_teaser = fields.Char(compute="_compute_text_teaser")
@@ -294,19 +295,19 @@ class Alerting(models.Model):
offline_last_notification = fields.Datetime(string="Last Offline notification sent")
sum_state_last_notification = fields.Datetime(string="Last SumState notification sent")
- device_name = fields.Text(compute="_compute_device_name", store="True")
- user_login = fields.Text(compute="_compute_user_login", store="True")
+ device_name = fields.Text(compute="_compute_device_name", store=True)
+ user_login = fields.Text(compute="_compute_user_login", store=True)
user_role = fields.Selection(
[("admin", "Admin"), ("installer", "Installer"), ("owner", "Owner"), ("guest", "Guest"),],
- compute="_compute_user_role", store="False")
+ compute="_compute_user_role", store=False)
@api.depends("device_id")
def _compute_device_name(self):
for rec in self:
rec.device_name = rec.device_id.name;
- @api.depends("user_id")
+ @api.depends("user_id","user_id.login")
def _compute_user_login(self):
for rec in self:
rec.user_login = rec.user_id.login;
diff --git a/openems/models/setup_protocol.py b/openems/models/setup_protocol.py
index 548576e..bdc7cae 100644
--- a/openems/models/setup_protocol.py
+++ b/openems/models/setup_protocol.py
@@ -6,9 +6,9 @@ class SetupProtocol(models.Model):
_description = "OpenEMS Edge Setup Protocols (IBN)"
_order = "create_date desc"
- customer_id = fields.Many2one("res.partner", "Customer", required=True)
+ customer_id = fields.Many2one("res.partner", "Customer")
different_location_id = fields.Many2one("res.partner", "Different Location")
- installer_id = fields.Many2one("res.partner", "Installer", required=True)
+ installer_id = fields.Many2one("res.partner", "Installer")
device_id = fields.Many2one("openems.device", "OpenEMS Edge", required=True)
productionlot_ids = fields.One2many(
"openems.setup_protocol_production_lot", "setup_protocol_id", "Serial Numbers"
@@ -16,6 +16,15 @@ class SetupProtocol(models.Model):
item_ids = fields.One2many(
"openems.setup_protocol_item", "setup_protocol_id", "Entry Items"
)
+ type = fields.Selection(
+ [
+ ("setup-protocol", "Setup protocol"),
+ ("ems-exchange", "EMS exchange"),
+ ("capacity-extension", "Capacity extension"),
+ ],
+ "Type",
+ default="setup-protocol",
+ )
class SetupProtocolProductionLot(models.Model):
diff --git a/openems/models/user.py b/openems/models/user.py
index 321dd87..aef2673 100644
--- a/openems/models/user.py
+++ b/openems/models/user.py
@@ -35,3 +35,12 @@ class ResUsers(models.Model):
default="DE",
required=True,
)
+ oauth_uid = fields.Char(index=True)
+ settings = fields.Text("Custom Settings", readonly=True)
+
+ def get_mapped_language(self):
+ lang = self.env["res.lang"]
+ if self.openems_language == "EN":
+ return lang.search(["code", "=", "en_US"], limit=1)
+ else:
+ return lang.search(["code", "=", "de_DE"], limit=1)
\ No newline at end of file
diff --git a/openems/report/setup_protocol.xml b/openems/report/setup_protocol.xml
index c9db4ec..eb188a3 100644
--- a/openems/report/setup_protocol.xml
+++ b/openems/report/setup_protocol.xml
@@ -26,7 +26,9 @@ th {
- Setup Protocol
+
+ -Protokoll - OpenEMS
+
@@ -39,60 +41,62 @@ th {
-
- | Kontaktdaten Endkunde |
-
-
- | Firmenname |
-
-
- |
-
-
- | Vor- Nachname |
-
-
-
- |
-
-
- | Straße / Hausnummer |
-
-
- |
-
-
- | PLZ |
-
-
- |
-
-
- | Ort |
-
-
- |
-
-
- | Land |
-
-
- |
-
-
- | E-Mail-Adresse |
-
-
- |
-
-
- | Telefonnummer |
-
-
- |
-
+
+
+ | Kontaktdaten Endkunde |
+
+
+ | Firmenname |
+
+
+ |
+
+
+ | Vor- Nachname |
+
+
+
+ |
+
+
+ | Straße / Hausnummer |
+
+
+ |
+
+
+ | PLZ |
+
+
+ |
+
+
+ | Ort |
+
+
+ |
+
+
+ | Land |
+
+
+ |
+
+
+ | E-Mail-Adresse |
+
+
+ |
+
+
+ | Telefonnummer |
+
+
+ |
+
+
@@ -165,60 +169,62 @@ th {
-
- | Installateur |
-
-
- | Firmenname |
-
-
- |
-
-
- | Name Installateur |
-
-
-
- |
-
-
- | Straße / Hausnummer |
-
-
- |
-
-
- | PLZ |
-
-
- |
-
-
- | Ort |
-
-
- |
-
-
- | Land |
-
-
- |
-
-
- | E-Mail-Adresse |
-
-
- |
-
-
- | Telefonnummer |
-
-
- |
-
+
+
+ | Installateur |
+
+
+ | Firmenname |
+
+
+ |
+
+
+ | Name Installateur |
+
+
+
+ |
+
+
+ | Straße / Hausnummer |
+
+
+ |
+
+
+ | PLZ |
+
+
+ |
+
+
+ | Ort |
+
+
+ |
+
+
+ | Land |
+
+
+ |
+
+
+ | E-Mail-Adresse |
+
+
+ |
+
+
+ | Telefonnummer |
+
+
+ |
+
+
diff --git a/openems/views/device.xml b/openems/views/device.xml
index e74b1cb..ffb8adf 100644
--- a/openems/views/device.xml
+++ b/openems/views/device.xml
@@ -5,7 +5,7 @@
Device: Tree
openems.device
-
-
+
@@ -50,6 +50,15 @@
string="OpenEMS Version"
context="{'group_by': 'openems_version'}"
/>
+
+
+
@@ -132,10 +141,10 @@
name="user_role_ids"
string="Access Role in Online-Monitoring"
>
-
+
-
+
@@ -149,12 +158,13 @@
name="setup_protocol_ids"
string="Installation Log"
>
-
+
-
+
+
@@ -183,25 +193,27 @@
name="alerting_settings"
string="Alerting Settings"
>
-
+
+
+
-
+
-
+
-
+
@@ -210,10 +222,10 @@
Device DeviceUserRole: Tree
openems.device_user_role
-
+
-
+
@@ -221,7 +233,7 @@
Devices
ir.actions.act_window
openems.device
- tree,form
+ list,form
@@ -235,11 +247,11 @@
Device Configuration Updates: Tree
openems.openemsconfigupdate
-
+
-
+
@@ -269,11 +281,11 @@
Device Systemmessage: Tree
openems.systemmessage
-
+
-
+
diff --git a/openems/views/partner.xml b/openems/views/partner.xml
index 874530e..bb843b1 100644
--- a/openems/views/partner.xml
+++ b/openems/views/partner.xml
@@ -9,16 +9,16 @@
-
+
-
+
-
+
-
+
diff --git a/openems/views/setup_protocol.xml b/openems/views/setup_protocol.xml
index bf2eee2..45c9d50 100644
--- a/openems/views/setup_protocol.xml
+++ b/openems/views/setup_protocol.xml
@@ -20,6 +20,7 @@
+
@@ -32,12 +33,12 @@
SetupProtocolProductionLot: Tree
openems.setup_protocol_production_lot
-
+
-
+
@@ -45,14 +46,14 @@
SetupProtocolItem: Tree
openems.setup_protocol_item
-
+
-
+
@@ -60,12 +61,12 @@
SetupProtocol: Tree
openems.setup_protocol
-
+
-
+
diff --git a/openems/views/user.xml b/openems/views/user.xml
index 445eb4f..7a57e4c 100644
--- a/openems/views/user.xml
+++ b/openems/views/user.xml
@@ -12,10 +12,10 @@
-
+
-
+