Skip to content
Extraits de code Groupes Projets
Valider 912ec4eb rédigé par Juliana's avatar Juliana
Parcourir les fichiers

[UPD]Add load curves + manage popup

parent b874bd23
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
# Copyright 2023 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models from . import models
from . import wizards
...@@ -5,14 +5,15 @@ ...@@ -5,14 +5,15 @@
"website": "https://le-filament.com", "website": "https://le-filament.com",
"version": "16.0.1.0.0", "version": "16.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"depends": ["api_enedis", "oacc"], "depends": ["api_enedis", "oacc", "queue_job"],
"data": [ "data": [
# "security/ir.model.access.csv", "security/ir.model.access.csv",
# datas # datas
# views # views
"views/acc_operation_views.xml", "views/acc_operation_views.xml",
# views menu # views menu
# wizard # wizard
"wizards/acc_operation_wizard_views.xml"
], ],
"assets": { "assets": {
"web._assets_primary_variables": [], "web._assets_primary_variables": [],
......
# Copyright 2023 Le Filament (<http://www.le-filament.com>) # Copyright 2023 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging import logging
from datetime import date import pytz
from datetime import date, datetime
from odoo import _, fields, models from odoo import _, fields, models
from odoo.exceptions import UserError from odoo.exceptions import UserError
...@@ -38,88 +40,38 @@ class AccOperation(models.Model): ...@@ -38,88 +40,38 @@ class AccOperation(models.Model):
# ------------------------------------------------------ # ------------------------------------------------------
# CRUD methods (ORM overrides) # CRUD methods (ORM overrides)
# ------------------------------------------------------ # ------------------------------------------------------
# @api.model
# def _auto_get_enedis_data(self):
# """This method is called from a cron job.
# It is used to get data from Enedis with API.
# """
# day_birthday = date.today() - relativedelta(months=1, days=10)
# records = self.search(
# [
# ("birthday_date", "=", day_birthday.day),
# ("client_id", "!=", False),
# ("secret_id", "!=", False),
# ]
# )
# for rec in records:
# last_date = day_birthday + relativedelta(months=1, days=-1)
# token = self.access_token()
# rec.get_curves(day_birthday, last_date, token)
# ------------------------------------------------------ # ------------------------------------------------------
# Actions # Actions
# ------------------------------------------------------ # ------------------------------------------------------
# def get_curves(self, date_start, date_end, token=None): # def curves(self):
# # Ask token to API # self.ensure_one()
# if not token: # message = self.get_curves()
# token = self.access_token()
#
# # Création du lot
# batch_name = (
# "Courbes du "
# + str(date_start)
# + " au "
# + str(date_end)
# + " - Opération :"
# + str(self.name)
# )
# batch = self.env["queue.job.batch"].get_new_batch(batch_name)
# # Load consommation data by PRM
# for delivery_counter_id in self.acc_delivery_ids:
# # Mise en file d'attente des appels API consommateur
# self.with_context(job_batch=batch).with_delay().definitive_load_curves(
# date_start, date_end, delivery_counter_id, token=token
# )
# #
# # Load production data by PRM # # Logs information
# for injection_counter_id in self.acc_injection_ids: # log_id = self.env["acc.logs"].create(
# # Mise en file d'attente des appels API producteur # {
# self.with_context(job_batch=batch).with_delay().definitive_load_curves( # "name": "Appel API Enedis Courbes du " + str(fields.Date.today()),
# date_start, date_end, injection_counter_id, token=token # "date_launched": fields.Datetime.now(),
# "type_log": "api",
# "message": message,
# "acc_operation_id": self.id,
# }
# ) # )
# # lancement de la file d'attente
# batch.enqueue()
# #
# def get_curves_all(self, date_start): # view_id = self.env.ref("oacc.acc_logs_form").id
# # Calcul du nombre de mois entre la date de début de contrat # return {
# # de l'opération et la date du jour pour lancer la récupération des données # "name": "LOGS",
# num_months = (date.today().year - date_start.year) * 12 + ( # "view_type": "form",
# date.today().month - date_start.month # "view_mode": "form",
# ) # "views": [(view_id, "form")],
# # "res_model": "acc.logs",
# date_start_it = date_start # "view_id": view_id,
# date_end_it = date_start + relativedelta(months=1, days=-1) # "type": "ir.actions.act_window",
# # "res_id": log_id.id,
# token = self.access_token() # "target": "new",
# i = 1 # "flags": {"initial_mode": "view"},
# while i < num_months: # }
# self.get_curves(date_start_it, date_end_it, token)
# date_start_it = date_start_it + relativedelta(months=1)
# date_end_it = date_start_it + relativedelta(months=1, days=-1)
# i += 1
# ------------------------------------------------------
# API functions
# ------------------------------------------------------
def _check_access_api(self):
if not self.client_id and not self.secret_id:
raise UserError(
_(
"L'identifiant et la clé de l'opération pour l'utilisation de "
"l'API Enedis ne sont pas renseignées. "
"Veuillez les renseigner dans l'onglet API Enedis."
)
)
def get_perimeter(self): def get_perimeter(self):
self.ensure_one() self.ensure_one()
...@@ -150,6 +102,134 @@ class AccOperation(models.Model): ...@@ -150,6 +102,134 @@ class AccOperation(models.Model):
"flags": {"initial_mode": "view"}, "flags": {"initial_mode": "view"},
} }
# ------------------------------------------------------
# API functions
# ------------------------------------------------------
def curves(
self,
date_start,
date_end,
usage_point_cons_ids=None,
usage_point_prod_ids=None):
"""
Récupère les données de l'opération concernant le périmètre:
- liste des PRM
- date de début opération
"""
self._check_access_api()
# Si pas de PRM sélectionnés
if not usage_point_cons_ids and not usage_point_prod_ids:
usage_point_cons_ids = self.acc_delivery_ids
usage_point_prod_ids = self.acc_injection_ids
message = str()
message += (
"<h1>API Enedis OACC - Appel Courbes "
+ str(fields.Datetime.now())
+ "</h1>"
"Appel API pour la période "
"" + str(date_start) + " " + str(date_end) + "<br/>"
)
if usage_point_cons_ids:
# Traitement données de cons
message += "<br/><strong>Traitement des données de consommation</strong><br/>"
for usage_point_id in usage_point_cons_ids:
desc = "Opération: " + self.name + " - PRM: " + usage_point_id.name + " - Date: " + str(fields.Datetime.today())
# message += self.with_delay(description=desc).get_definitive_load_curves(
self.with_delay(description=desc).get_definitive_load_curves(
date_end,
date_start,
["cons,autocons,complement"],
usage_point_id)
if usage_point_prod_ids:
# Traitement données de prod
message += "<br/><strong>Traitement des données de production</strong><br/>"
for usage_point_id in usage_point_prod_ids:
desc = "Opération: " + self.name + " - PRM: " + usage_point_id.name + " - Date: " + str(
fields.Datetime.today())
self.with_delay(description=desc).get_definitive_load_curves(
# message += self.with_delay(description=desc).get_definitive_load_curves(
date_end,
date_start,
["surplus,prod"],
usage_point_id)
message += (
"<br/><h1>Fin appel API Courbes: " + str(fields.Datetime.now()) + "</h1>"
)
# Logs information
log_id = self.env["acc.logs"].create(
{
"name": "Appel API Enedis Courbes du " + str(fields.Date.today()) + " - Période " + str(date_start) + " " + str(date_end),
"date_launched": fields.Datetime.now(),
"type_log": "api",
"message": message,
"acc_operation_id": self.id,
}
)
def get_definitive_load_curves(
self, date_end, date_start, type_curve, usage_point_id):
message = str()
message += "PRM " + usage_point_id.name + "\n"
message += "Appel API ...\n"
curves_data = self._get_definitive_load_curves(
self.name, date_end, date_start, type_curve,
usage_point_id.name, self.client_id, self.secret_id)
message += "Appel API terminé. Traitement des données ...\n"
curves = curves_data.get("curves")
if curves:
name = usage_point_id.name + "_" + str(date_start) + "_" + str(date_end)
for curve in curves:
type = curve["type"]
for point in curve["interval_reading"]:
dt = pytz.utc.localize(
datetime.strptime(point["timestamp"], "%Y-%m-%dT%H:%M:%SZ")
)
date_slot = fields.Datetime.to_string(
dt.astimezone(pytz.timezone("Europe/Paris"))
)
date_slot_utc = fields.Datetime.to_string(dt)
self.env["acc.enedis.cdc"].create(
{
"name": name,
"acc_operation_id": self.id,
"acc_counter_id": usage_point_id.id or False,
"comp_data_type": type,
"power": point["value"],
"date_slot": date_slot,
"date_slot_utc": date_slot_utc,
}
)
message += "Fin du traitement des données\n"
return message
def get_curves_all(self, date_start):
# Calcul du nombre de mois entre la date de début de contrat
# de l'opération et la date du jour pour lancer la récupération des données
num_months = (date.today().year - date_start.year) * 12 + (
date.today().month - date_start.month
)
date_start_it = date_start
date_end_it = date_start + relativedelta(months=1, days=-1)
token = self.access_token()
i = 1
while i < num_months:
self.get_curves(date_start_it, date_end_it, token)
date_start_it = date_start_it + relativedelta(months=1)
date_end_it = date_start_it + relativedelta(months=1, days=-1)
i += 1
def perimeter(self): def perimeter(self):
""" """
Récupère les données de l'opération concernant le périmètre: Récupère les données de l'opération concernant le périmètre:
...@@ -230,3 +310,12 @@ class AccOperation(models.Model): ...@@ -230,3 +310,12 @@ class AccOperation(models.Model):
# ------------------------------------------------------ # ------------------------------------------------------
# Business methods # Business methods
# ------------------------------------------------------ # ------------------------------------------------------
def _check_access_api(self):
if not self.client_id and not self.secret_id:
raise UserError(
_(
"L'identifiant et la clé de l'opération pour l'utilisation de "
"l'API Enedis ne sont pas renseignées. "
"Veuillez les renseigner dans l'onglet API Enedis."
)
)
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
"access_acc_operation_wizard_group_partner_manager","acc_operation_wizard group_partner_manager","model_acc_operation_wizard","base.group_partner_manager",1,1,1,1
"access_acc_operation_wizard_group_user","acc_operation_wizard group_user","model_acc_operation_wizard","base.group_user",1,0,0,0
...@@ -16,6 +16,13 @@ ...@@ -16,6 +16,13 @@
name="get_perimeter" name="get_perimeter"
attrs="{'invisible':[('client_id','=', False), ('secret_id','=', False)]}" attrs="{'invisible':[('client_id','=', False), ('secret_id','=', False)]}"
/> />
<button
string="Récupération des courbes"
type="action"
class="btn-primary"
name="%(oacc_enedis_api.acc_operation_wizard_action)d"
attrs="{'invisible':[('client_id','=', False), ('secret_id','=', False)]}"
/>
</header> </header>
<group> <group>
<field name="client_id" /> <field name="client_id" />
......
# Copyright 2023 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import acc_operation_wizard
# Copyright 2023 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import _, fields, models
from odoo.exceptions import UserError
class AccOperationWizard(models.TransientModel):
_name = "acc.operation.wizard"
_description = "Récupération des courbes pour une date donnée"
# ------------------------------------------------------
# Fields declaration
# ------------------------------------------------------
def _default_operation_id(self):
op = self.env['acc.operation'].browse(self.env.context.get('active_ids')[0] if self.env.context.get('active_ids') else [])
return op
operation_id = fields.Many2one(
"acc.operation", default=lambda self: self._default_operation_id())
date_start = fields.Date("Date de début")
date_end = fields.Date("Date de fin")
prm_cons_ids = fields.Many2many(
"acc.counter",
relation="acc_counter_cons_rel",
column1="cons_id",
column2="op_id",
domain=[("is_delivery", "=", True)],
string="PRM de soutirage")
prm_prod_ids = fields.Many2many(
"acc.counter",
relation="acc_counter_prod_rel",
column1="prod_id",
column2="op_id",
domain=[("is_injection", "=", True)],
string="PRM d'injection")
# ------------------------------------------------------
# SQL Constraints
# ------------------------------------------------------
# ------------------------------------------------------
# Default methods
# ------------------------------------------------------
# ------------------------------------------------------
# Computed fields / Search Fields
# ------------------------------------------------------
# ------------------------------------------------------
# Onchange / Constraints
# ------------------------------------------------------
# ------------------------------------------------------
# CRUD methods (ORM overrides)
# ------------------------------------------------------
# ------------------------------------------------------
# Actions
# ------------------------------------------------------
def get_curves(self):
if not self.date_end and not self.date_start:
raise UserError(
_("Les champs Date de début et Date de fin sont obligatoires")
)
if (self.date_end - self.date_start).days > 31:
raise UserError(_("L'intervalle de temps ne doit pas dépasser 31 Jours"))
if (self.date_end <= self.date_start):
raise UserError(_("La date de fin doit être supérieure à la date de début"))
self.operation_id.curves(
self.date_start, self.date_end, self.prm_cons_ids, self.prm_prod_ids
)
return {"type": "ir.actions.act_window_close"}
def get_curves_all(self):
context = dict(self._context or {})
if context.get("active_ids", False):
op = self.env["acc.operation"].browse(context.get("active_ids"))
if not op.date_start_contract:
raise UserError(
_(
"Renseigner une date de début de contrat pour"
" pouvoir récupérer les courbes à partie de cette date."
)
)
date_start = op.date_start_contract
self.env["acc.operation"].browse(context.get("active_ids")).get_curves_all(
date_start
)
return {"type": "ir.actions.act_window_close"}
# ------------------------------------------------------
# Business methods
# ------------------------------------------------------
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- WIZARD FORM -->
<record id="acc_operation_wizard_view_form" model="ir.ui.view">
<field name="name">acc.operation.wizard.form</field>
<field name="model">acc.operation.wizard</field>
<field name="arch" type="xml">
<form>
<group>
<field name="operation_id" invisible="1"/>
<field
name="prm_cons_ids"
widget="many2many_tags"
domain="[('is_delivery', '=', True), ('acc_operation_id', '=', operation_id)]"
options="{'no_create_edit': True, 'no_create': True}"
/>
<field
name="prm_prod_ids"
widget="many2many_tags"
options="{'no_create_edit': True, 'no_create': True}"
domain="[('is_injection', '=', True), ('acc_operation_id', '=', operation_id)]"
/>
</group>
<group name="period" string="Période" col="2">
<field name="date_start" />
<field name="date_end" />
</group>
<footer>
<button
class="btn btn-sm btn-primary"
name="get_curves"
string="Récupérer"
type="object"
/>
<button
class="btn btn-sm btn-primary"
name="get_curves_all"
string="Récupérer depuis le début"
type="object"
/>
<button
class="btn btn-sm btn-default"
special="cancel"
string="Annuler"
/>
</footer>
</form>
</field>
</record>
<record id="acc_operation_wizard_action" model="ir.actions.act_window">
<field name="name">Récupération des courbes</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">acc.operation.wizard</field>
<field name="view_mode">form</field>
<field name="view_id" ref="acc_operation_wizard_view_form" />
<field name="target">new</field>
</record>
</odoo>
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter