From 25220de3fad12098c4c83f830f0adb0fb35accbf Mon Sep 17 00:00:00 2001 From: Juliana <juliana@le-filament.com> Date: Thu, 27 May 2021 17:11:46 +0200 Subject: [PATCH] Change display curve date + add calendar picker --- models/enercoop_operation.py | 218 +++++++++++++++++++++---- models/enercoop_operation_graph.py | 7 +- static/src/js/operation_graph.js | 105 +++++++++++- views/enercoop_operation_templates.xml | 10 +- views/enercoop_operation_views.xml | 7 +- 5 files changed, 299 insertions(+), 48 deletions(-) diff --git a/models/enercoop_operation.py b/models/enercoop_operation.py index 48c6489..c149428 100644 --- a/models/enercoop_operation.py +++ b/models/enercoop_operation.py @@ -3,6 +3,7 @@ from odoo import fields, models, api from datetime import datetime, timedelta +import dateutil.parser as parser from dateutil.relativedelta import relativedelta @@ -57,6 +58,15 @@ class EnercoopOperation(models.Model): result_graph = operation_ids.chart_data_cons(chart_data) result_graph_prod = operation_ids.chart_data_prod(chart_data) result_graph.update(result_graph_prod) + result_graph.update({'scale': scale}) + + date_end = date_end.strftime("%d/%m/%Y") + date_min = operation_ids.get_first_day() + date_min = date_min.strftime("%d/%m/%Y") + result_graph.update({ + 'date_end': date_end, + 'date_min': date_min + }) return result_graph @@ -134,6 +144,43 @@ class EnercoopOperation(models.Model): return date_start, date_end + def get_first_day(self): + """ + Fonction retournant la première date où des données ont été enregistrées. + :return: une date + """ + + # Get last date slot recorded + first_record = self.env['enercoop.enedis.cdc'].search([ + ('enercoop_operation_id', '=', self.ids), + ], limit=1, order='date_slot ASC') + + date_min = first_record.date_slot + return date_min + + def get_scale(self, date_start, date_end): + """ + Fonction retournant l'échelle à appliquer en fonction d'une date de début et une date de fin. + :return: scale: day/week/month/semestre/year + """ + + # Calculate delta between 2 dates + if date_start == date_end: + scale = 'day' + return scale + else: + delta = date_end - date_start + if delta <= 7: + scale = 'week' + elif delta <= 31: + scale = 'month' + elif delta <= 180: + scale = 'semestre' + else: + scale = 'year' + + return scale + def chart_data_cons(self, chart_data): """ Fonction retournant le dictionnaire permettant la construiction @@ -151,20 +198,46 @@ class EnercoopOperation(models.Model): { 'label': 'Allo Conso', 'data': chart_data['cons'], - 'backgroundColor': 'rgba(79, 129, 189, 0.7)', - 'borderColor': 'rgba(79, 129, 189, 1)', + 'backgroundColor': 'rgba(57, 120, 187, 0.7)', + 'borderColor': 'rgba(57, 120, 187, 1)', }, { 'label': 'Production solaire', 'data': chart_data['prod'], - 'backgroundColor': 'rgba(255, 255, 0, 0)', - 'borderColor': 'rgba(255, 255, 0, 1)', + 'backgroundColor': 'rgba(244, 165, 25, 0)', + 'borderColor': 'rgba(244, 165, 25, 1)', }, { 'label': 'Autoconso', 'data': chart_data['autocons'], - 'backgroundColor': 'rgba(155, 187, 89, 0.7)', - 'borderColor': 'rgba(155, 187, 89, 1)', + 'backgroundColor': 'rgba(91, 154, 81, 0.7)', + 'borderColor': 'rgba(91, 154, 81, 1)', + }, + ], + }, + } + result['line_chart_conso_line'] = { + 'type': 'line', + 'data': { + 'labels': chart_data['label'], + 'datasets': [ + { + 'label': 'Allo Conso', + 'data': chart_data['cons_line'], + 'backgroundColor': 'rgba(57, 120, 187, 0.7)', + 'borderColor': 'rgba(57, 120, 187, 1)', + }, + { + 'label': 'Production solaire', + 'data': chart_data['prod_line'], + 'backgroundColor': 'rgba(244, 165, 25, 0)', + 'borderColor': 'rgba(244, 165, 25, 1)', + }, + { + 'label': 'Autoconso', + 'data': chart_data['autocons_line'], + 'backgroundColor': 'rgba(91, 154, 81, 0.7)', + 'borderColor': 'rgba(91, 154, 81, 1)', }, ], }, @@ -177,8 +250,8 @@ class EnercoopOperation(models.Model): 'label': 'Inférieur à 3', 'data': chart_data['doughnut_cons'], 'backgroundColor': [ - 'rgb(155, 187, 89)', - 'rgb(79, 129, 189)', + 'rgb(91, 154, 81)', + 'rgb(57, 120, 187)', ], 'borderWidth': 1 }], @@ -192,14 +265,14 @@ class EnercoopOperation(models.Model): { 'label': 'AutoConso', 'data': chart_data['autocons'], - 'backgroundColor': 'rgba(155, 187, 89, 0.7)', - 'borderColor': 'rgba(155, 187, 89, 1)', + 'backgroundColor': 'rgba(91, 154, 81, 0.7)', + 'borderColor': 'rgba(91, 154, 81, 1)', }, { 'label': 'AlloConso', 'data': chart_data['cons'], - 'backgroundColor': 'rgba(79, 129, 189, 0.7)', - 'borderColor': 'rgba(79, 129, 189, 1)', + 'backgroundColor': 'rgba(57, 120, 187, 0.7)', + 'borderColor': 'rgba(57, 120, 187, 1)', }] } } @@ -222,14 +295,34 @@ class EnercoopOperation(models.Model): { 'label': 'Surplus', 'data': chart_data['surplus'], - 'backgroundColor': 'rgba(192, 80, 77, 0.7)', - 'borderColor': 'rgba(192, 80, 77, 1)', + 'backgroundColor': 'rgba(225, 80, 96, 0.7)', + 'borderColor': 'rgba(225, 80, 96, 1)', }, { 'label': 'Autoconso', 'data': chart_data['autocons'], - 'backgroundColor': 'rgba(155, 187, 89, 0.7)', - 'borderColor': 'rgba(155, 187, 89, 1)', + 'backgroundColor': 'rgba(91, 154, 81, 0.7)', + 'borderColor': 'rgba(91, 154, 81, 1)', + }, + ], + }, + } + result['line_chart_prod_line'] = { + 'type': 'line', + 'data': { + 'labels': chart_data['label'], + 'datasets': [ + { + 'label': 'Surplus', + 'data': chart_data['surplus_line'], + 'backgroundColor': 'rgba(225, 80, 96, 0.7)', + 'borderColor': 'rgba(225, 80, 96, 1)', + }, + { + 'label': 'Autoconso', + 'data': chart_data['autocons_line'], + 'backgroundColor': 'rgba(91, 154, 81, 0.7)', + 'borderColor': 'rgba(91, 154, 81, 1)', }, ], }, @@ -242,8 +335,8 @@ class EnercoopOperation(models.Model): 'label': 'Inférieur à 3', 'data': chart_data['doughnut_prod'], 'backgroundColor': [ - 'rgb(155, 187, 89)', - 'rgb(192, 80, 77)', + 'rgb(91, 154, 81)', + 'rgb(225, 80, 96)', ], 'borderWidth': 1 }], @@ -257,14 +350,15 @@ class EnercoopOperation(models.Model): { 'label': 'AutoConso', 'data': chart_data['autocons'], - 'backgroundColor': 'rgba(155, 187, 89, 0.7)', - 'borderColor': 'rgba(155, 187, 89, 1)', + 'backgroundColor': 'rgba(91, 154, 81, 0.7)', + 'borderColor': 'rgba(91, 154, 81, 1)', }, { 'label': 'Surplus', 'data': chart_data['surplus'], - 'backgroundColor': 'rgba(192, 80, 77, 0.7)', - 'borderColor': 'rgba(192, 80, 77, 1)', + # 'backgroundColor': 'rgba(192, 80, 77, 0.7)', + 'backgroundColor': 'rgba(225, 80, 96, 0.7)', + 'borderColor': 'rgba(225, 80, 96, 1)', }] } } @@ -286,9 +380,13 @@ class EnercoopOperation(models.Model): label_line_cons = [] data_autocons = [] + data_autocons_line = [] data_cons = [] + data_cons_line = [] data_prod = [] + data_prod_line = [] data_surplus = [] + data_surplus_line = [] # Depending on type scale, define the date slot type # Data by day / hour for type = day @@ -297,17 +395,22 @@ class EnercoopOperation(models.Model): # Data by year / months for type = year if type == 'day': type_date = 'date_slot:hour' + type_date_abs = 'date_slot:day' elif type == 'year': type_date = 'date_slot:month' + type_date_abs = 'date_slot:month' else: type_date = 'date_slot:day' + type_date_abs = 'date_slot:day' + if type == 'week': + type_date = 'date_slot:hour' # Get all data group by curves type and date cdc_ids = self.env['enercoop.enedis.cdc'].sudo().read_group( [('enercoop_operation_id', '=', self.ids), ('date_slot', '>=', date_start), ('date_slot', '<', date_end)], - ['power', 'enercoop_operation_id', 'date_slot'], + ['power', 'enercoop_operation_id', 'date_slot', 'year'], ['comp_data_type', type_date], orderby='comp_data_type, date_slot ASC', lazy=False) # Get the date for the abscissa axis @@ -316,16 +419,16 @@ class EnercoopOperation(models.Model): ('date_slot', '>=', date_start), ('date_slot', '<', date_end)], ['enercoop_operation_id', 'date_slot'], - [type_date], orderby='date_slot ASC', lazy=False) + [type_date_abs], orderby='date_slot ASC', lazy=False) # Build the abscissa axis with the right format date for cdc in cdc_date_ids: - value_hour = cdc[type_date] + value_hour = cdc[type_date_abs] label_line_cons.append(value_hour) # Build the ordinate axis for each data type (autoconso/conso/prod/surplus) for cdc in cdc_ids: - if type == 'day': + if type == 'day' or type == 'week': value_power = round((cdc['power'] / 2), 2) else: value_power = round((cdc['power'] / 1000 / 2), 2) @@ -339,6 +442,39 @@ class EnercoopOperation(models.Model): if cdc['comp_data_type'] == 'surplus': data_surplus.append(value_power) + if type == 'day' or type == 'week': + query = """ + SELECT + A.comp_data_type AS comp_data_type, + A.date_slot AS date_slot, + SUM(A.power) AS power + FROM enercoop_enedis_cdc A + JOIN enercoop_operation E ON E.id = A.enercoop_operation_id + WHERE A.enercoop_operation_id IS NOT NULL + AND A.enercoop_operation_id IN %s + AND A.date_slot >= %s + AND A.date_slot < %s + GROUP BY A.comp_data_type, A.date_slot + ORDER BY A.comp_data_type, A.date_slot ASC; + """ + query_params = (tuple(self.ids), date_start, date_end) + self.env.cr.execute(query, query_params) + raw_data = self.env.cr.dictfetchall() + + for cdc in raw_data: + if type == 'week' or type == 'day': + value_power = round((cdc['power']), 2) + value_hour = cdc['date_slot'] + + if cdc['comp_data_type'] == 'autocons': + data_autocons_line.append({'t': value_hour, 'y': value_power}) + if cdc['comp_data_type'] == 'cons': + data_cons_line.append({'t': value_hour, 'y': value_power}) + if cdc['comp_data_type'] == 'prod': + data_prod_line.append({'t': value_hour, 'y': value_power}) + if cdc['comp_data_type'] == 'surplus': + data_surplus_line.append({'t': value_hour, 'y': value_power}) + # Get the data to build the chart Bilan bilan_cdc = self.env['enercoop.enedis.cdc'].sudo().read_group( [('enercoop_operation_id', '=', self.ids), @@ -377,9 +513,13 @@ class EnercoopOperation(models.Model): cdc_jour = { 'autocons': data_autocons, + 'autocons_line': data_autocons_line, 'cons': data_cons, + 'cons_line': data_cons_line, 'prod': data_prod, + 'prod_line': data_prod_line, 'surplus': data_surplus, + 'surplus_line': data_surplus_line, 'label': label_line_cons, 'label_doughnut': ['Autoconso', 'Alloconso'], 'doughnut_cons': [percent_autocons, percent_cons], @@ -392,9 +532,9 @@ class EnercoopOperation(models.Model): # ------------------------------------------------------ # Functions to manage route # ------------------------------------------------------ - def graph_view_conso(self, scale): + def graph_view_conso(self, scale=None, date_start=None, date_end=None): """ - Fonction appelée pour l'affcihage des courbes consommation + Fonction appelée pour l'affichage des courbes consommation sur le portail :param scale: type d'affichage des graphes (day/week/month/semestre/year) @@ -404,8 +544,13 @@ class EnercoopOperation(models.Model): result_graph = {} - # Get date start and date end depending on type of scale - date_start, date_end = self.get_last_day(scale) + # Get date start and date end depending on type of scale if scale fill + if scale: + date_start, date_end = self.get_last_day(scale) + + # Get scale depending on the date start and date end + if date_start and date_end: + scale = self.get_scale(date_start, date_end) # Get the data to display in chart chart_data = self.get_cdc(scale, date_start, date_end) @@ -415,9 +560,9 @@ class EnercoopOperation(models.Model): return result_graph - def graph_view_prod(self, scale): + def graph_view_prod(self, scale=None, date_start=None, date_end=None): """ - Fonction appelée pour l'affcihage des courbes production + Fonction appelée pour l'affichage des courbes production sur le portail :param scale: type d'affichage des graphes (day/week/month/semestre/year) @@ -426,8 +571,13 @@ class EnercoopOperation(models.Model): """ result_graph = {} - # Get date start and date end depending on type of scale - date_start, date_end = self.get_last_day(scale) + # Get date start and date end depending on type of scale if scale fill + if scale: + date_start, date_end = self.get_last_day(scale) + + # Get scale depending on the date start and date end + if date_start and date_end: + scale = self.get_scale(date_start, date_end) # Get the data to display in chart chart_data = self.get_cdc(scale, date_start, date_end) diff --git a/models/enercoop_operation_graph.py b/models/enercoop_operation_graph.py index 8fe5ad7..5e1155c 100644 --- a/models/enercoop_operation_graph.py +++ b/models/enercoop_operation_graph.py @@ -30,18 +30,21 @@ class EnercoopOperation(models.Model): date_start, date_end = self.get_last_day('month') last_month = date_start.strftime("%d %B %Y") + '-' + date_end.strftime("%d %B %Y") + range_date = date_start.strftime("%d/%m/%Y") + ' - ' + date_end.strftime("%d/%m/%Y") + date_start, date_end = self.get_last_day('semestre') last_semester = date_start.strftime("%d %B %Y") + '-' + date_end.strftime("%d %B %Y") date_start, date_end = self.get_last_day('year') - last_year = date_start.strftime("%d %B %Y") + '-' + date_end.strftime("%d %B %Y") + last_year = date_start.strftime("%d %B %Y") + '- ' + date_end.strftime("%d %B %Y") data_values = { 'last_day': last_day, 'last_week': last_week, 'last_month': last_month, 'last_semestre': last_semester, - 'last_year': last_year + 'last_year': last_year, + 'range_date': range_date, } values['data_values'] = data_values diff --git a/static/src/js/operation_graph.js b/static/src/js/operation_graph.js index 9ae7002..67fedc5 100644 --- a/static/src/js/operation_graph.js +++ b/static/src/js/operation_graph.js @@ -17,9 +17,32 @@ odoo.define('enercoop_cdc.operation_graph', function (require) { await this._super(...arguments); var result = self.state.chartValues; + if (result.scale == 'week'){ + var unit = 'day'; + } + if (result.scale == 'day'){ + var unit = 'hour'; + } + if (result.scale == 'week' || result.scale == 'day'){ + var options_line = { options: { + scales: { + xAxes: [{ + type: 'time', + time: { + // Luxon format string + unit: unit + }, + title: { + display: true, + text: 'Date' + } + }] + } + }}; + } var options = { options: { scales: { - y: { + yAxes: { beginAtZero: true, } } @@ -41,6 +64,7 @@ odoo.define('enercoop_cdc.operation_graph', function (require) { }] } }}; + var line_conso = self.$el.find('#line_chart_conso'); var donuts_conso = self.$el.find('#donuts_chart_conso'); var histo_conso = self.$el.find('#histo_chart_conso'); @@ -48,10 +72,24 @@ odoo.define('enercoop_cdc.operation_graph', function (require) { var donuts_prod = self.$el.find('#donuts_chart_prod'); var histo_prod = self.$el.find('#histo_chart_prod'); - var chart = new Chart( - line_conso, - Object.assign({}, result.line_chart_conso, options) - ); + if (result.scale != 'week' && result.scale != 'day'){ + line_conso.hide(); + line_prod.hide(); + } + + if (result.scale == 'week' || result.scale == 'day'){ + var chart = new Chart( + line_conso, + Object.assign({}, result.line_chart_conso_line, options_line) + ); + } +// else { +// var chart = new Chart( +// line_conso, +// Object.assign({}, result.line_chart_conso, options) +// ); +// } + console.log(chart); var chart = new Chart( donuts_conso, @@ -63,10 +101,12 @@ odoo.define('enercoop_cdc.operation_graph', function (require) { Object.assign({}, result.histo_chart_conso, options_stacked) ); - var chart = new Chart( - line_prod, - Object.assign({}, result.line_chart_prod, options) - ); + if (result.scale == 'week' || result.scale == 'day'){ + var chart = new Chart( + line_prod, + Object.assign({}, result.line_chart_prod_line, options_line) + ); + } var chart = new Chart( donuts_prod, @@ -85,6 +125,37 @@ odoo.define('enercoop_cdc.operation_graph', function (require) { var $but = this.$el.find('.o_enercoop_button[data-mode="month"]') } $but.addClass('active'); + + var pickerLocale = { + applyLabel: 'OK', + cancelLabel: 'Annuler', + fromLabel: 'Entre', + toLabel: 'et', + customRangeLabel: 'Période personnalisée', + daysOfWeek: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"], + monthNames: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Decembre"], + monthNamesShort: ["Jan", "Fev", "Mar", "Avr", "Mai", "Juin", "Juil", "Aoû", "Sep", "Oct", "Nov", "Dec"], + firstDay: 0, + format: 'DD/MM/YYYY', + }; + var cal = self.$el.find('#periode'); + cal.daterangepicker({ + showDropdowns: false, + format: 'DD/MM/YYYY', + separator: ' à ', + locale: pickerLocale, + maxDate: result.date_end, + minDate: result.date_min, + }, + + function(start, end, label) { +// this.trigger_up('cal_open_action', { +// date_start: start.format('DD/MM/YYYY'), +// date_end: end.format('DD/MM/YYYY'), +// }); + console.log('New date range selected: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD') + ' (predefined range: ' + label + ')'); + }); + }, _onChartClicked: function (e) { @@ -173,6 +244,7 @@ odoo.define('enercoop_cdc.operation_graph', function (require) { const Controller = qweb.Controller.extend({ custom_events: _.extend({}, qweb.Controller.prototype.custom_events, { chart_open_action: '_onChartClicked', + cal_open_action: '_onCalClicked', }), init: function (parent, model, renderer, params) { @@ -190,6 +262,16 @@ odoo.define('enercoop_cdc.operation_graph', function (require) { state.scale = e.data.action_name this.reload(); }, + + /** + * @private + * @param {OdooEvent} e + */ + _onCalClicked: function (e) { + state.date_start = e.data.date_start + state.date_end = e.data.date_end + this.reload(); + }, }); var OperationGraph = qweb.View.extend({ @@ -197,6 +279,11 @@ odoo.define('enercoop_cdc.operation_graph', function (require) { searchMenuTypes: ['filter', 'favorite'], jsLibs: [ '/web/static/lib/Chart/Chart.js', + '/web/static/lib/moment/moment.js', + '/web/static/lib/daterangepicker/daterangepicker.js', + ], + cssLibs: [ + '/web/static/lib/daterangepicker/daterangepicker.css', ], config: _.extend({}, qweb.View.prototype.config, { Model: Model, diff --git a/views/enercoop_operation_templates.xml b/views/enercoop_operation_templates.xml index cb8ee7c..dc32ff2 100644 --- a/views/enercoop_operation_templates.xml +++ b/views/enercoop_operation_templates.xml @@ -26,13 +26,19 @@ <button name="semestre" class="btn btn-secondary o_enercoop_button" title="6 derniers mois" aria-label="6 derniers mois" data-mode="semestre"><strong>6 derniers mois</strong><br/><t t-esc="data_values['last_semestre']"/></button> <button name="year" class="btn btn-secondary o_enercoop_button" title="12 derniers mois" aria-label="12 derniers mois" data-mode="year"><strong>12 derniers mois</strong><br/><t t-esc="data_values['last_year']"/></button> </div> + <div class="container text-center mt32 mb32"> + <input id="periode" type="text" name="daterange" t-att-value="data_values['range_date']" /> + <script> + + </script> + </div> <div class="text-center o_title mt32"> <h2>Vues Consommateurs</h2> </div> <div> <div class="container"> <div class="row mb32"> - <div class="col-md-6 col-12 p-5"> + <div class="col-12 p-5"> <canvas id="line_chart_conso" width="auto" height="200"></canvas> </div> <div class="col-md-6 col-12 p-5"> @@ -52,7 +58,7 @@ <div> <div class="container"> <div class="row mb32"> - <div class="col-md-6 col-12 p-5"> + <div class="col-12 p-5"> <canvas id="line_chart_prod" width="auto" height="200"></canvas> </div> <div class="col-md-6 col-12 p-5"> diff --git a/views/enercoop_operation_views.xml b/views/enercoop_operation_views.xml index fea4d82..170cb9a 100644 --- a/views/enercoop_operation_views.xml +++ b/views/enercoop_operation_views.xml @@ -8,7 +8,12 @@ <field name="inherit_id" ref="enercoop_enedis_api.enercoop_operation_form_view"/> <field name="arch" type="xml"> <header position="inside"> - <button string="Voir les courbes" type="object" class="btn-primary" name="action_view_courbes"/> + <button + string="Voir les courbes" + type="object" + class="btn-primary" + name="action_view_courbes" + attrs="{'invisible':[('date_start_contract', '=', False)]}"/> </header> </field> </record> -- GitLab