diff --git a/__manifest__.py b/__manifest__.py index 6acd5147f36b7772869334f4a4adacaaa931782b..0803a59de65c7a8ba3ab764d0a32112ba3a8acc1 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -5,7 +5,7 @@ "website": "https://le-filament.com", "version": "16.0.1.0.0", "license": "AGPL-3", - "depends": ["oacc"], + "depends": ["oacc", "api_enedis_acc"], "data": [ "security/ir.model.access.csv", # datas diff --git a/models/__init__.py b/models/__init__.py index 183168978d7da2e5bc4b899455e45738c23fa71c..a07dd7e6871332d819cc1f6dff33d1365c4fb4d4 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -1,2 +1,3 @@ from . import acc_operation from . import acc_repartition_keys +from . import api_enedis_acc diff --git a/models/api_enedis_acc.py b/models/api_enedis_acc.py new file mode 100644 index 0000000000000000000000000000000000000000..6f82cb02197e71d91dddcf7ee78a9cfaf80adc67 --- /dev/null +++ b/models/api_enedis_acc.py @@ -0,0 +1,26 @@ +# Copyright 2021- Le Filament (https://le-filament.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) +from odoo import _, api, models + + +class ApiEnedisAcc(models.AbstractModel): + _inherit = "api.enedis.acc" + + # ------------------------------------------------------ + # Actions + # ------------------------------------------------------ + + # ------------------------------------------------------ + # Business methods + # ------------------------------------------------------ + @api.model + def send_repartition_key(self, key, operation_name): + """ """ + + uri = f"{self.name}{key.get('route')}" + + return self._get_enedis(uri=uri, params=key.get("body")) + + # ------------------------------------------------------ + # Functions to manage route + # ------------------------------------------------------ diff --git a/tools/key_file.py b/tools/key_file.py index 7e8a0a7feff78ea413a4d4eccc9ebf58b88ff50d..5481f6e241b96aa68fd5c3da7bf8c91559229483 100644 --- a/tools/key_file.py +++ b/tools/key_file.py @@ -25,7 +25,11 @@ class RepartitionKeyEntryFile: ◦ Erreur envoyée “Ligne X : la somme dépasse 100%” """ - check_methods = [self._check_counter, self._check_same_month, self._check_max_value] + check_methods = [ + self._check_counter, + self._check_same_month, + self._check_max_value, + ] result = {"check": True, "message": ""} for check in check_methods: check_result = check() @@ -48,6 +52,7 @@ class RepartitionKeyEntryFile: if line_count == 0: line_count += 1 continue + # line[0] is horodatage json[line[0]] = [] line_count += 1 counter_count = 1 @@ -58,8 +63,9 @@ class RepartitionKeyEntryFile: counter_count += 1 return json - def data_to_send(self, agreement_id, send_empty_key=False): + def data_to_send(self, agreement_id, send_empty_key=True): """ + build route and body for api sending return dict {"route", "body} to enedis """ call_list = [] @@ -67,14 +73,15 @@ class RepartitionKeyEntryFile: date = datetime.strptime(horo, "%d-%m-%Y %H:%M") route = f"/agreements/{agreement_id}/repartition_keys/{date.strftime('%Y%m%dT%H%MZ')}" body = [] - for keys in self.json.get(horo): - if send_empty_key: - body.append(keys) - else: - if float(keys.get("key")) > 0: + # specification enedis si la somme des clefs est nulle on envoi un body vide + if self._get_key_sum(self.json.get(horo)) > 0: + for keys in self.json.get(horo): + if send_empty_key: body.append(keys) - if body: - call_list.append({"route": route, "body": body}) + else: + if float(keys.get("key")) > 0: + body.append(keys) + call_list.append({"route": route, "body": body}) return call_list def _check_counter(self): @@ -108,19 +115,10 @@ class RepartitionKeyEntryFile: def _check_max_value(self): """ - check if all value are in the same month + check if sum of all key is not > 100 """ for hour in self.json: - max = 0 - for key in self.json[hour]: - if key["key"] == "0.00000000": - key["key"] = 0.0 - try: - max = max + float(key["key"]) - except ValueError: - pass - - if max > 100: + if self._get_key_sum(self.json.get(hour)) > 100: return { "check": False, "message": f"Ligne {hour} la somme dépasse 100.", @@ -147,3 +145,20 @@ class RepartitionKeyEntryFile: "message": "Les dates doivent être celles d’un seul mois complet.", } return {"check": True, "message": ""} + + def _get_key_sum(self, horo): + """ + return the sum of key for a horodatage + [{ "id":id, "key":key}, ...] + + """ + keys_sum = 0 + for key in horo: + if key["key"] == "0.00000000": + key["key"] = 0.0 + try: + keys_sum = keys_sum + float(key["key"]) + except ValueError: + pass + + return keys_sum diff --git a/views/acc_keys_repartition_views.xml b/views/acc_keys_repartition_views.xml deleted file mode 100644 index 8ed462a234dad8a6430b92078c25cfe1e0c8b6a8..0000000000000000000000000000000000000000 --- a/views/acc_keys_repartition_views.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<odoo> - <data> - <record id="acc_keys_repatition_action" model="ir.actions.act_window"> - <field name="name">Keys</field> - <field name="res_model">acc.repartition.keys</field> - <field name="view_mode">tree,form</field> - </record> - </data> -</odoo> \ No newline at end of file diff --git a/views/acc_operation_views.xml b/views/acc_operation_views.xml index a70536fe13406258983dce017b7891cec2e4f79f..439894516ccf17e00d78e24af121ae392f4c0c6b 100644 --- a/views/acc_operation_views.xml +++ b/views/acc_operation_views.xml @@ -9,17 +9,15 @@ <field name="arch" type="xml"> <xpath expr="//notebook" position="inside"> <page string="Clefs de répartition" name="keys"> - <header> + <tree> + <field name="keys_repartition_ids" /> + </tree> <button string="Importer un fichier" type="action" name="%(oacc_repartition_keys.acc_repartition_keys_wizard_action)d" class="btn-primary" /> - </header> - <tree> - <field name="keys_repartition_ids" /> - </tree> </page> </xpath> </field> diff --git a/views/acc_repartition_keys_views.xml b/views/acc_repartition_keys_views.xml index e247914f5a22123da9b78669b55d7187c16f996f..b14ec0f02561d1545f6a2d56de31a795c63c8b00 100644 --- a/views/acc_repartition_keys_views.xml +++ b/views/acc_repartition_keys_views.xml @@ -10,7 +10,7 @@ <field name="name">acc.repartition.keys.tree</field> <field name="model">acc.repartition.keys</field> <field name="arch" type="xml"> - <tree string="Keys" editable="bottom"> + <tree string="Keys" create="false"> <field name="date_send"/> <field name="csv_file"/> <field name="operation_id"/> diff --git a/wizard/acc_repartition_keys_wizard.py b/wizard/acc_repartition_keys_wizard.py index 1d414ccdb6538b7365d853c5ede80999686d4da5..4a4b263ece84a7e4c1400034936614849307e516 100644 --- a/wizard/acc_repartition_keys_wizard.py +++ b/wizard/acc_repartition_keys_wizard.py @@ -1,7 +1,9 @@ # Copyright 2021- Le Filament (https://le-filament.com) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) import base64 -from odoo import fields, models +import datetime + +from odoo import api, fields, models from odoo.exceptions import UserError from ..tools.key_file import RepartitionKeyEntryFile @@ -41,7 +43,8 @@ class AccRepartitionKeysWizard(models.TransientModel): # ------------------------------------------------------ # CRUD methods (ORM overrides) # ------------------------------------------------------ - + def ignore(self): + return {'type': 'ir.actions.act_window_close'} # ------------------------------------------------------ # Actions # ------------------------------------------------------ @@ -51,12 +54,15 @@ class AccRepartitionKeysWizard(models.TransientModel): :return: """ if self.csv_file: - file = ( - base64.b64decode(self.csv_file) - .decode("utf-8") - .replace("\r", "") - .split("\n") - ) + try: + file = ( + base64.b64decode(self.csv_file) + .decode("utf-8") + .replace("\r", "") + .split("\n") + ) + except UnicodeDecodeError: + raise UserError("Fichier de répartitions au mauvais format") counter_list_from_operation = [ counter.name @@ -64,18 +70,36 @@ class AccRepartitionKeysWizard(models.TransientModel): [("acc_operation_id.id", "=", self.operation_id.id)] ) ] - - entry_file_handler = RepartitionKeyEntryFile( - data=file, operation_counter_list=counter_list_from_operation - ) - - file_check_result = entry_file_handler.check() + try: + entry_file_handler = RepartitionKeyEntryFile( + data=file, operation_counter_list=counter_list_from_operation + ) + file_check_result = entry_file_handler.check() + except (ValueError, IndexError): + raise UserError("Fichier de répartitions au mauvais format") if not file_check_result.get("check"): raise UserError(file_check_result.get("message")) - data_to_send = entry_file_handler.data_to_send(agreement_id=self.operation_id.name) + data_to_send = entry_file_handler.data_to_send( + agreement_id=self.operation_id.name + ) + for key in data_to_send: + response = self.env["api.enedis.acc"].send_repartition_key( + key=key, operation_name=self.operation_id.name + ) + print(response) + + self.env["acc.repartition.keys"].create( + { + "csv_file": self.csv_file, + "date_send": datetime.datetime.today(), + "operation_id": self.operation_id.id, + } + ) + else: + raise UserError("Fichier de répartition non chargé") # ------------------------------------------------------ # Business methods diff --git a/wizard/acc_repartition_keys_wizard_views.xml b/wizard/acc_repartition_keys_wizard_views.xml index 77b21811042851c0ec169d05da5c7384f6f6485c..a2fdfcc0d165c833231644ef7e9fc7918c453816 100644 --- a/wizard/acc_repartition_keys_wizard_views.xml +++ b/wizard/acc_repartition_keys_wizard_views.xml @@ -5,17 +5,21 @@ <field name="model">acc.repartition.keys.wizard</field> <field name="arch" type="xml"> <form string="Création clefs de repartition"> - <header> - <button + <field name="csv_file"/> + <footer> + <button class="btn btn-primary" name="send_imported_file" type="object" string="Envoyer a enedis" /> - </header> - <group name="keys" string="Clefs de repartition" col="2"> - <field name="csv_file"/> - </group> + <button + class="btn btn-primary" + name="ignore" + type="object" + string="Ignorer" + /> + </footer> </form> </field> </record>