Newer
Older
# © 2021 Le Filament (<http://www.le-filament.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from datetime import datetime
from odoo.exceptions import AccessError
from odoo.addons.base_rest import restapi
from odoo.addons.component.core import Component
class OperationsService(Component):
_inherit = "base.rest.service"
_name = "operation.service"
_usage = "operation"
_description = """
Operation Services
Accès aux opérations
"""
@restapi.method(
[(["/all"], "GET")],
output_param=restapi.CerberusValidator("_validator_return_get_all"),
cors="*",
crsf=False,
)
def get_all(self):
"""
Retourne la liste de toutes les opérations dans lesquelles l'utilisateur
ou sa société sont engagés
"""
# Get partners
partner_id = self.env["res.users"].browse(self.request.uid).partner_id
partner_ids = partner_id + partner_id.parent_id
# Get operations
operations_pmo = self.env["acc.operation"].search(
[("pmo_id", "in", partner_ids.ids)]
)
operations_counter = (
self.env["acc.counter"]
.search([("partner_id", "in", partner_ids.ids)])
.mapped("acc_operation_id")
)
operations = operations_pmo | operations_counter
# Get news
news = self.env["acc.actu"].search([("operation_id", "=", False)], limit=10)
datas = {}
if operations:
# Return datas
datas["operations"] = operations.mapped(
lambda o: {
"id": o.id,
"name": o.name,
"description": o.description,
"date_start": o.date_start_contract
if o.date_start_contract
else None,
"date_end": o.date_end_contract if o.date_end_contract else None,
"distribution_key": o.distribution_key
if o.distribution_key
else None,
"pmo": o.sudo().pmo_id.name,
"image": o.image_256.decode("utf-8") if o.image_256 else None,
}
)
datas["news"] = news.mapped(
lambda n: {
"id": n.id,
"name": n.name,
"date_actu": n.date_actu if n.date_actu else None,
return datas
@restapi.method(
[(["/<int:id>/home"], "GET")],
output_param=restapi.CerberusValidator("_validator_return_get_id"),
cors="*",
crsf=False,
)
def get_id(self, _id):
"""
Retourne les statistiques générales et les actualités liées à une opération
dans laquelle l'utilisateur ou sa société sont engagés
"""
power_install = sum(operation.sudo().acc_injection_ids.mapped("power_instal"))
try:
power_tot = operation.get_power_tot()
cons_rate = round((power_tot[2] / power_tot[1]) * 100, 2)
prod_rate = round((power_tot[2] / power_tot[0]) * 100, 2)
cons_rate = prod_rate = 0
nb_conso = (
self.env["acc.counter"]
.sudo()
.search_count(
[
("acc_operation_id", "=", operation.id),
("is_delivery", "=", True),
]
)
)
nb_prod = (
self.env["acc.counter"]
.sudo()
.search_count(
[
("acc_operation_id", "=", operation.id),
("is_injection", "=", True),
]
)
)
"role": role,
"id": operation.id,
"name": operation.name,
"description": operation.description,
"date_start": operation.date_start_contract
if operation.date_start_contract
else None,
"date_end": operation.date_end_contract
if operation.date_end_contract
else None,
"distribution_key": operation.distribution_key
if operation.distribution_key
else None,
"pmo": operation.sudo().pmo_id.name,
"consumer_nb": nb_conso,
"productor_nb": nb_prod,
"power_install": power_install,
"image": operation.image_256.decode("utf-8")
if operation.image_256
else None,
"conso_tot": power_tot[0],
"prod_tot": power_tot[1],
news = (
self.env["acc.actu"].sudo().search([("operation_id", "=", _id)], limit=10)
)
datas["news"] = news.mapped(
lambda n: {
"id": n.id,
"name": n.name,
"date_actu": n.date_actu,
input_param=restapi.CerberusValidator("_validator_get_doc"),
output_param=restapi.CerberusValidator("_validator_return_get_doc"),
Retourne les documents (Factures) liés à une opération
dans laquelle l'utilisateur ou sa société sont engagés
"""
base_url = self.env["ir.config_parameter"].sudo().get_param("web.base.url")
"role": role,
"id": operation.id,
"name": operation.name,
# Récupération de toutes les factures liées à l'opération spécifiée
acc_account_ids = self.env["acc.account"].search(
[("acc_operation_id", "=", _id), ("state", "=", "published")]
)
# Récupération de toutes les factures externes
# liées à l'opération spécifiée
domain = [("acc_operation_id", "=", _id)]
domain += [
("type", "=", "facture"),
]
acc_contract_ids_f = self.env["acc.contract"].search(domain)
invoice_exist = False
if acc_contract_ids_f or acc_account_ids:
invoice_exist = True
# Récupération de tous les contrats liés à l'opération spécifiée
domain_c = [("acc_operation_id", "=", _id)]
domain_pmo = [("acc_operation_id", "=", _id)]
role = self._get_role(operation)
if role.get("isConsumer") or role.get("isProductor"):
domain_c += [
if role.get("isPmo"):
domain_pmo += [("type", "!=", False)]
acc_contract_ids = self.env["acc.contract"].search(domain_pmo)
else:
acc_contract_all = (
self.env["acc.contract"]
.sudo()
.search([
("acc_operation_id", "=", _id),
("type", "=", "all"),
])
)
acc_contract_ids = self.env["acc.contract"].search(domain_c)
acc_contract_ids += acc_contract_all
acc_contract_pmo = self.env["acc.contract"].search(
[
("acc_operation_id", "=", _id),
("type", "=", "pmo"),
]
)
acc_contract_ids += acc_contract_pmo
contract_exist = False
if acc_contract_ids:
contract_exist = True
if type == "invoice" and invoice_exist:
lambda n: {
"id": n.id,
"name": n.name,
"date": n.date,
"start_date": n.start_date,
"end_date": n.end_date,
"amount_total": n.amount_total,
"consumer": n.consumer_id.name,
"prm_c": n.acc_delivery_id.name,
"url": base_url + n.get_portal_url(report_type="pdf"),
}
)
if acc_account_ids
else []
)
lambda n: {
"id": n.id,
"name": n.name,
"start_date": n.start_date,
"end_date": n.end_date,
"type": n.type,
"url": base_url + n.get_portal_url(),
}
)
elif type == "contract" or (not invoice_exist and contract_exist):
datas["contracts"] = (
acc_contract_ids.mapped(
lambda n: {
"id": n.id,
"name": n.name,
"start_date": n.start_date,
"end_date": n.end_date,
"type": n.type,
"url": base_url + n.get_portal_url(),
}
)
if acc_contract_ids
else []
)
datas["contracts_pmo"] = (
acc_contract_pmo.mapped(
lambda n: {
"id": n.id,
"name": n.name,
"start_date": n.start_date,
"end_date": n.end_date,
"type": n.type,
"url": base_url + n.get_portal_url(),
}
)
if acc_contract_pmo
else []
)
datas["contract_exist"] = contract_exist
datas["invoice_exist"] = invoice_exist
@restapi.method(
[(["/<int:id>/pmo"], "POST")],
input_param=restapi.CerberusValidator("_validator_get_pmo"),
cors="*",
crsf=False,
)
def get_pmo(self, _id, **params):
"""
Retourne les courbes de production et de consommation liées à une opération
dans laquelle l'utilisateur ou sa société ont le rôle de PMO
"""
# Check rights
role = self._get_role(operation)
# Get params
scale = params.get("scale", False)
date_start = params.get("date_start", False)
date_end = params.get("date_end", False)
graph_data = operation.sudo().graph_view_global(scale=scale)
graph_data = operation.sudo().graph_view_global(
date_start=datetime.strptime(date_start, "%Y-%m-%d"),
date_end=datetime.strptime(date_end, "%Y-%m-%d"),
graph_data = operation.sudo().graph_view_global(scale="week")
return datas
@restapi.method(
[(["/<int:id>/consumer"], "POST")],
input_param=restapi.CerberusValidator("_validator_get_prm"),
# output_param=restapi.CerberusValidator("_validator_get_return_consumer"),
cors="*",
crsf=False,
)
def get_consumer(self, _id, **params):
"""
Retourne les courbes de consommation liées à une opération ou à un PRM
dans laquelle l'utilisateur ou sa société ont le rôle de PMO
"""
operation = self.env["acc.operation"].browse(_id).sudo()
partner_id = self.env["res.users"].browse(self.request.uid).partner_id
# Check rights
role = self._get_role(operation)
if not role.get("isConsumer") and not role.get("isPmo"):
raise AccessError(
"User id "
+ str(role.get("id"))
+ " does not have access to ("
+ role.get("name")
+ ") for Consumer role"
)
scale = params.get("scale", False)
date_start = params.get("date_start", False)
date_end = params.get("date_end", False)
prm_id = params.get("prm_id", False)
consumer_id = params.get("partner_id", False)
domain_prm = [("acc_operation_id", "=", _id), ("is_delivery", "=", True)]
if not role.get("isPmo"):
domain_prm.append(
("partner_id", "in", [partner_id.id, partner_id.parent_id.id])
)
prm_ids = (
self.env["acc.counter"].sudo().search(domain_prm, order="partner_id asc")
)
prm_name = prm_ids.mapped(
lambda p: {
"id": p.id,
"name": p.name,
"partner_id": p.partner_id.id,
}
)
consumer_name = prm_ids.mapped("partner_id").mapped(
lambda p: {
"id": p.id,
"name": p.name,
}
)
if role.get("isConsumer") and not role.get("isPmo") and not prm_id:
graph_datas = operation.graph_view_type(
type="cons", scale=scale, prm_id=prm_id, partner_id=consumer_id
)
type="cons",
date_start=datetime.strptime(date_start, "%Y-%m-%d"),
date_end=datetime.strptime(date_end, "%Y-%m-%d"),
type="cons", scale="week", prm_id=prm_id, partner_id=consumer_id
)
graph_datas["name"] = (
"PRM N° " + self.env["acc.counter"].sudo().browse(prm_id).name
)
graph_datas["name"] = (
self.env["res.partner"].sudo().browse(consumer_id).name
)
graph_datas["prm_id"] = prm_id
graph_datas["partner_id"] = consumer_id
else:
graph_datas = None
datas = {
"role": role,
"graph_datas": graph_datas,
"prms": prm_name,
"consumers": consumer_name,
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
@restapi.method(
[(["/<int:id>/consumer-financial"], "POST")],
input_param=restapi.CerberusValidator("_validator_get_prm"),
cors="*",
crsf=False,
)
def get_consumer_financial(self, _id, **params):
"""
Retourne les données financières de consommation liées à une opération ou à un PRM
dans laquelle l'utilisateur ou sa société ont le rôle de PMO
"""
operation = self.env["acc.operation"].browse(_id).sudo()
partner_id = self.env["res.users"].browse(self.request.uid).partner_id
# Check rights
role = self._get_role(operation)
if not role.get("isConsumer") and not role.get("isPmo"):
raise AccessError(
"User id "
+ str(role.get("id"))
+ " does not have access to ("
+ role.get("name")
+ ") for Consumer role"
)
# Get params
prm_id = params.get("prm_id", False)
domain_prm = [("acc_operation_id", "=", _id), ("is_delivery", "=", True)]
if not role.get("isPmo"):
domain_prm.append(
("partner_id", "in", [partner_id.id, partner_id.parent_id.id])
)
prm_ids = self.env["acc.counter"].sudo().search(domain_prm)
prm_name = prm_ids.mapped(
lambda p: {
"id": p.id,
"name": p.name,
"partner_id": p.partner_id.id,
}
)
if operation.is_data_enedis:
graph_datas = operation.get_financial_monitoring(type="cons", prm_id=prm_id)
if prm_id:
graph_datas["name"] = (
"PRM N° " + self.env["acc.counter"].sudo().browse(prm_id).name
)
graph_datas["prm_id"] = prm_id
else:
graph_datas = None
datas = {
"graph_datas": graph_datas,
"role": role,
"prms": prm_name,
}
return datas
@restapi.method(
[(["/<int:id>/productor"], "POST")],
input_param=restapi.CerberusValidator("_validator_get_prm"),
# output_param=restapi.CerberusValidator("_validator_get_return_productor"),
cors="*",
crsf=False,
)
def get_productor(self, _id, **params):
"""
Retourne les courbes de production liées à une opération ou à un PRM
dans laquelle l'utilisateur ou sa société ont le rôle de PMO
"""
operation = self.env["acc.operation"].browse(_id).sudo()
partner_id = self.env["res.users"].browse(self.request.uid).partner_id
# Check rights
role = self._get_role(operation)
if not role.get("isProductor") and not role.get("isPmo"):
raise AccessError(
"User id "
+ str(role.get("id"))
+ " does not have access to "
+ "("
+ role.get("name")
+ ") for Productor role"
)
scale = params.get("scale", False)
date_start = params.get("date_start", False)
date_end = params.get("date_end", False)
prm_id = params.get("prm_id", False)
producer_id = params.get("partner_id", False)
domain_prm = [("acc_operation_id", "=", _id), ("is_injection", "=", True)]
if not role.get("isPmo"):
domain_prm.append(
("partner_id", "in", [partner_id.id, partner_id.parent_id.id])
)
prm_ids = self.env["acc.counter"].sudo().search(domain_prm)
prm_name = prm_ids.mapped(
lambda p: {
"id": p.id,
"name": p.name,
"partner_id": p.partner_id.id,
producer_name = prm_ids.mapped("partner_id").mapped(
lambda p: {
"id": p.id,
"name": p.name,
}
)
graph_datas = operation.graph_view_type(
type="prod", scale=scale, prm_id=prm_id, partner_id=producer_id
)
type="prod",
date_start=datetime.strptime(date_start, "%Y-%m-%d"),
date_end=datetime.strptime(date_end, "%Y-%m-%d"),
type="prod", scale="week", prm_id=prm_id, partner_id=producer_id
)
graph_datas["name"] = (
"PRM n° " + self.env["acc.counter"].sudo().browse(prm_id).name
)
graph_datas["name"] = (
self.env["res.partner"].sudo().browse(producer_id).name
)
graph_datas["prm_id"] = prm_id
graph_datas["partner_id"] = producer_id
else:
graph_datas = None
datas = {
"role": self._get_role(operation),
"graph_datas": graph_datas,
"prms": prm_name,
"producers": producer_name,
@restapi.method(
[(["/<int:id>/contact"], "GET")],
output_param=restapi.CerberusValidator("_validator_return_get_contact"),
cors="*",
crsf=False,
)
def get_contact(self, _id):
"""
Retourne les données de l'opération
dans laquelle l'utilisateur ou sa société sont engagés
"""
operation = self.env["acc.operation"].browse(_id)
role = self._get_role(operation)
if not role.get("isIn"):
return AccessError()
datas = {
"role": role,
"id": operation.id,
"name": operation.name,
"email": operation.sudo().mail_contact or "",
# ------------------------------------------------------
# Validators
# ------------------------------------------------------
def _validator_get_all(self):
return {}
def _validator_return_get_all(self):
return {
"operations": {
"type": "list",
"schema": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"description": {"type": "string", "nullable": True},
"date_start": {"type": "date", "nullable": True},
"date_end": {"type": "date", "nullable": True},
"distribution_key": {"type": "string", "nullable": True},
"pmo": {"type": "string"},
"image": {"type": "string", "nullable": True},
"news": {
"type": "list",
"schema": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"date_actu": {"type": "date"},
},
},
},
}
def _validator_get_id(self):
return {
}
def _validator_return_get_id(self):
return {
"role": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"description": {"type": "string"},
"isIn": {"type": "boolean"},
"isPmo": {"type": "boolean"},
"isConsumer": {"type": "boolean"},
"isProductor": {"type": "boolean"},
"id": {"type": "integer"},
"name": {"type": "string"},
"date_start": {"type": "date"},
"date_end": {"type": "date", "nullable": True},
"distribution_key": {"type": "string", "nullable": True},
"pmo": {"type": "string"},
"consumer_nb": {"type": "integer"},
"productor_nb": {"type": "integer"},
"power_install": {"type": "float"},
"image": {"type": "string", "nullable": True},
"conso_tot": {"type": "float"},
"prod_tot": {"type": "float"},
"conso_rate": {"type": "float"},
"prod_rate": {"type": "float"},
"news": {
"type": "list",
"schema": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"date_actu": {"type": "date", "nullable": True},
def _validator_return_get_contact(self):
return {
"role": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"description": {"type": "string"},
"isIn": {"type": "boolean"},
"isPmo": {"type": "boolean"},
"isConsumer": {"type": "boolean"},
"isProductor": {"type": "boolean"},
},
},
"id": {"type": "integer"},
"name": {"type": "string"},
"email": {"type": "string", "nullable": True},
def _validator_return_get_doc(self):
return {
"role": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"description": {"type": "string"},
"isIn": {"type": "boolean"},
"isPmo": {"type": "boolean"},
"isConsumer": {"type": "boolean"},
"isProductor": {"type": "boolean"},
"invoice_exist": {"type": "boolean"},
"contract_exist": {"type": "boolean"},
"name": {"type": "string"},
"documents": {
"type": "list",
"schema": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"date": {"type": "date", "nullable": True},
"start_date": {"type": "date", "nullable": True},
"end_date": {"type": "date", "nullable": True},
"amount_total": {"type": "float", "nullable": True},
"url": {"type": "string", "nullable": True},
"consumer": {"type": "string", "nullable": True},
"prm_c": {"type": "string", "nullable": True},
},
},
},
"factures_externes": {
"nullable": True,
"type": "list",
"schema": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"type": {"type": "string", "nullable": True},
"url": {"type": "string", "nullable": True},
"seller": {"type": "string", "nullable": True},
"buyer": {"type": "string", "nullable": True},
"type": "list",
"schema": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"type": {"type": "string", "nullable": True},
"url": {"type": "string", "nullable": True},
"seller": {"type": "string", "nullable": True},
"buyer": {"type": "string", "nullable": True},
},
},
},
"contracts_pmo": {
"nullable": True,
"type": "list",
"schema": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"type": {"type": "string", "nullable": True},
"url": {"type": "string", "nullable": True},
"seller": {"type": "string", "nullable": True},
"buyer": {"type": "string", "nullable": True},
},
},
},
"id": {"type": "integer"},
"scale": {"type": "string", "nullable": True},
"date_start": {"type": "string", "nullable": True},
"date_end": {"type": "string", "nullable": True},
def _validator_get_return_pmo(self):
return {
"role": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"description": {"type": "string"},
"isIn": {"type": "boolean"},
"isPmo": {"type": "boolean"},
"isConsumer": {"type": "boolean"},
"isProductor": {"type": "boolean"},
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
},
},
"graph_data": {
"type": "dict",
"schema": {
"line_chart_prod_line": {"type": "string", "nullable": True},
"line_chart_conso_line": {"type": "string", "nullable": True},
"line_chart_prod_prm": {"type": "string", "nullable": True},
"donuts_chart_prod": {"type": "string", "nullable": True},
"donuts_chart_conso": {"type": "string", "nullable": True},
"histo_chart_prod": {"type": "string", "nullable": True},
"histo_chart_conso": {"type": "string", "nullable": True},
"date_start": {"type": "date", "nullable": True},
"date_end": {"type": "date", "nullable": True},
"date_min": {"type": "date", "nullable": True},
"date_max": {"type": "date", "nullable": True},
"scale": {"type": "string", "nullable": True},
},
},
}
def _validator_get_return_consumer(self):
return {
"role": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"description": {"type": "string"},
"isIn": {"type": "boolean"},
"isPmo": {"type": "boolean"},
"isConsumer": {"type": "boolean"},
"isProductor": {"type": "boolean"},
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"partner_id": {"type": "integer"},
},
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
},
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
},
},
"graph_data": {
"type": "dict",
"schema": {
"line_chart_prod_line": {"type": "string", "nullable": True},
"line_chart_conso_line": {"type": "string", "nullable": True},
"line_chart_prod_prm": {"type": "string", "nullable": True},
"donuts_chart_prod": {"type": "string", "nullable": True},
"donuts_chart_conso": {"type": "string", "nullable": True},
"histo_chart_prod": {"type": "string", "nullable": True},
"histo_chart_conso": {"type": "string", "nullable": True},
"date_start": {"type": "date", "nullable": True},
"date_end": {"type": "date", "nullable": True},
"date_min": {"type": "date", "nullable": True},
"date_max": {"type": "date", "nullable": True},
"scale": {"type": "string", "nullable": True},
"name": {"type": "string", "nullable": True},
"prm_id": {"type": "integer", "nullable": True},
"partner_id": {"type": "integer", "nullable": True},
},
},
}
def _validator_get_return_productor(self):
return {
"role": {
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"description": {"type": "string"},
"isIn": {"type": "boolean"},
"isPmo": {"type": "boolean"},
"isConsumer": {"type": "boolean"},
"isProductor": {"type": "boolean"},
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
"partner_id": {"type": "integer"},
},
"type": "dict",
"schema": {
"id": {"type": "integer"},
"name": {"type": "string"},
},
},
},
"graph_data": {
"type": "dict",
"schema": {
"line_chart_prod_line": {"type": "string", "nullable": True},
"line_chart_conso_line": {"type": "string", "nullable": True},
"line_chart_prod_prm": {"type": "string", "nullable": True},
"donuts_chart_prod": {"type": "string", "nullable": True},
"donuts_chart_conso": {"type": "string", "nullable": True},
"histo_chart_prod": {"type": "string", "nullable": True},
"histo_chart_conso": {"type": "string", "nullable": True},
"date_start": {"type": "date", "nullable": True},
"date_end": {"type": "string", "nullable": True},
"date_min": {"type": "date", "nullable": True},
"date_max": {"type": "date", "nullable": True},
"scale": {"type": "string", "nullable": True},
"name": {"type": "string", "nullable": True},
"prm_id": {"type": "integer", "nullable": True},
"partner_id": {"type": "integer", "nullable": True},
},
},
}
"id": {"type": "integer"},
"scale": {"type": "string", "nullable": True},