From 4e3e2f9a36dba93882b5030141dbd7bcf5466556 Mon Sep 17 00:00:00 2001 From: thienan Date: Wed, 16 Jun 2021 10:45:08 +0200 Subject: [PATCH] Ajout graphes CA par clients --- .gitignore | 14 +- mondumas/models/stats.py | 49 ++++- mondumas/routes.py | 168 +++++++++--------- mondumas/templates/stats/ca_clients.pt | 89 ++++++++++ .../{ca_groupes_12m.pt => ca_groupes.pt} | 0 mondumas/templates/stats/stats.pt | 67 +++---- mondumas/views/stats.py | 107 +++++++++-- 7 files changed, 359 insertions(+), 135 deletions(-) create mode 100644 mondumas/templates/stats/ca_clients.pt rename mondumas/templates/stats/{ca_groupes_12m.pt => ca_groupes.pt} (100%) diff --git a/.gitignore b/.gitignore index a1710cc..73d53f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ -# Fichiers temporaires # -######################## -*~ -*.pyc -*.pid -*.log - +# Fichiers temporaires # +######################## +*~ +*.pyc +*.pid +*.log +development.ini diff --git a/mondumas/models/stats.py b/mondumas/models/stats.py index ca51ae5..7a61617 100644 --- a/mondumas/models/stats.py +++ b/mondumas/models/stats.py @@ -59,7 +59,7 @@ def get_ca_groupe_12m(request, societe, datedeb, datefin): SUM(IF(groupe = 'MAIF', 1, 0)) AS MAIF_nb FROM bddevfac.facture WHERE societe=:societe and date >= :datedeb and date <= :datefin GROUP BY yymm;""" - results = request.dbsession.execute(query, {'societe': societe, 'datedeb': datedeb.strftime("%Y%m"), 'datefin': datefin.strftime("%Y%m")}) + results = request.dbsession.execute(query, {'societe': societe, 'datedeb': datedeb.strftime("%Y-%m"), 'datefin': datefin.strftime("%Y-%m")}) return results.fetchall() def get_ca_groupe_3y(request, societe, datedeb): @@ -69,10 +69,53 @@ def get_ca_groupe_3y(request, societe, datedeb): query = """SELECT groupe, SUM(IF (date_format(date, '%Y') = :date_n-2, TOTALHT, 0)) as Annee1, + SUM(IF (date_format(date, '%Y') = :date_n-2, 1, 0)) as Count1, SUM(IF (date_format(date, '%Y') = :date_n-1, TOTALHT, 0)) as Annee2, - SUM(IF (date_format(date, '%Y') = :date_n, TOTALHT, 0)) as Annee3 + SUM(IF (date_format(date, '%Y') = :date_n-1, 1, 0)) as Count2, + SUM(IF (date_format(date, '%Y') = :date_n, TOTALHT, 0)) as Annee3, + SUM(IF (date_format(date, '%Y') = :date_n, 1, 0)) as Count3 FROM bddevfac.facture - WHERE societe=:societe GROUP BY groupe;""" + WHERE societe=:societe AND groupe <> 'X' GROUP BY groupe;""" results = request.dbsession.execute(query, {'societe': societe, 'date_n': date3.strftime("%Y"), 'date_n-1': date2.strftime("%Y"), 'date_n': datedeb.strftime("%Y")}) return results.fetchall() +def get_ca_clients_12m(request, societe, datedeb, datefin): + + query = """SELECT DATE_FORMAT(date, "%Y%m") as yymm, + DATE_FORMAT(date, "%M") as mois, + DATE_FORMAT(date, "%M %Y") as date, + SUM(IF(typecli = 'A', totalht, 0)) AS A_ca, + SUM(IF(typecli = 'A', 1, 0)) AS A_nb, + SUM(IF(typecli = 'E', totalht, 0)) AS E_ca, + SUM(IF(typecli = 'E', 1, 0)) AS E_nb, + SUM(IF(typecli = 'G', totalht, 0)) AS G_ca, + SUM(IF(typecli = 'G', 1, 0)) AS G_nb, + SUM(IF(typecli = 'I', totalht, 0)) AS I_ca, + SUM(IF(typecli = 'I', 1, 0)) AS I_nb, + SUM(IF(typecli = 'P', totalht, 0)) AS P_ca, + SUM(IF(typecli = 'P', 1, 0)) AS P_nb, + SUM(IF(typecli = 'R', totalht, 0)) AS R_ca, + SUM(IF(typecli = 'R', 1, 0)) AS R_nb, + SUM(IF(typecli = 'S', totalht, 0)) AS S_ca, + SUM(IF(typecli = 'S', 1, 0)) AS S_nb + FROM bddevfac.facture + WHERE societe=:societe and date >= :datedeb and date <= :datefin GROUP BY yymm;""" + results = request.dbsession.execute(query, {'societe': societe, 'datedeb': datedeb.strftime("%Y-%m"), 'datefin': datefin.strftime("%Y-%m")}) + return results.fetchall() + +def get_ca_clients_3y(request, societe, datedeb): + + date2 = datedeb + relativedelta(years=-1) + date3 = datedeb + relativedelta(years=-2) + + query = """SELECT typecli, + SUM(IF (date_format(date, '%Y') = :date_n-2, TOTALHT, 0)) as Annee1, + SUM(IF (date_format(date, '%Y') = :date_n-2, 1, 0)) as Count1, + SUM(IF (date_format(date, '%Y') = :date_n-1, TOTALHT, 0)) as Annee2, + SUM(IF (date_format(date, '%Y') = :date_n-1, 1, 0)) as Count2, + SUM(IF (date_format(date, '%Y') = :date_n, TOTALHT, 0)) as Annee3, + SUM(IF (date_format(date, '%Y') = :date_n, 1, 0)) as Count3 + FROM bddevfac.facture + WHERE societe=:societe GROUP BY typecli;""" + results = request.dbsession.execute(query, {'societe': societe, 'date_n': date3.strftime("%Y"), 'date_n-1': date2.strftime("%Y"), 'date_n': datedeb.strftime("%Y")}) + return results.fetchall() diff --git a/mondumas/routes.py b/mondumas/routes.py index aa0e1cf..df2dccc 100644 --- a/mondumas/routes.py +++ b/mondumas/routes.py @@ -1,83 +1,85 @@ -def includeme(config): - config.add_static_view('static', 'static', cache_max_age=3600) - # agenda - config.add_route('agenda', '/agenda/{date}') - config.add_route('planning', '/planning/{date}') - config.add_route('rdv_edit','/rdv_edit/{nodossier}/{nolig}') - # default - config.add_route('home', '/') - config.add_route('affiche_message','/affiche_message/{login}') - config.add_route('ajax_article', '/ajax_article') - config.add_route('ajax_client', '/ajax_client') - config.add_route('ajax_codepostal', '/ajax_codepostal') - config.add_route('ajax_lookup', '/ajax_lookup') - config.add_route('ajax_texte', '/ajax_texte') - config.add_route('changer_mdp', '/changer_mdp') - config.add_route('envoyer_mdp', '/envoyer_mdp') - config.add_route('login', '/login') - config.add_route('login_as', '/login_as/{login}') - config.add_route('logout', '/logout') - config.add_route('redefinir_mdp', '/redefinir_mdp/{lien}') - config.add_route('init_mdp', '/init_mdp/{user}/{lien}') - # devis - config.add_route('devis_ligne', '/devis_ligne/{type_ligne}/{nodevis}/{nolig}') - config.add_route('devis_lig_mv', '/devis_lig_mv/{move}/{nodevis}/{nolig}') - config.add_route('devis_list', '/devis_list') - config.add_route('devis_create', '/devis_create/{nodossier}') - config.add_route('devis_web', '/devis_web/{nodevis}') - config.add_route('devis_view', '/devis_view/{nodevis}') - config.add_route('devis_preview', '/devis_preview/{nodevis}') - # dossier - config.add_route('demandes','/demandes') - config.add_route('demandes_dl','/demandes_dl/{societe}/{email_from}/{email_uid}') - config.add_route('delete_img','/delete_img/{nodossier}/{norapport}/{origine}/{nomfic}') - config.add_route('dossier_edit', '/dossier_edit/{nodossier}') - config.add_route('dossier_lookup', '/dossier_lookup') - config.add_route('dossier_select', '/dossier_select/{date}') - config.add_route('dossier_selected', '/dossier_selected/{goto}/{date}/{nodossier}') - config.add_route('dossier_view', '/dossier_view/{nodossier}') - config.add_route('rdf_bill','/rdf_bill/{no_id}') - config.add_route('rdf_client','/rdf_client/{no_id}') - config.add_route('rdf_edit','/rdf_edit/{nodossier}/{date_inter}') - config.add_route('rdf_list','/rdf_list') - config.add_route('rdf_rapport','/rdf_rapport/{no_id}') - config.add_route('rdf_view','/rdf_view/{no_id}') - config.add_route('rotate_img','/rotate_img/{nodossier}/{norapport}/{origine}/{nomfic}/{angle}') - config.add_route('suivi_edit','/suivi_edit/{nodossier}/{nolig}') - config.add_route('upload_doc', '/upload_doc/{nodossier}/{origine}') - config.add_route('upload_img', '/upload_img/{norapport}/{origine}') - config.add_route('upload_om', '/upload_om') - # parametres - config.add_route('parametres', '/parametres') - config.add_route('article_edit', '/article_edit/{ref}') - config.add_route('articles', '/articles') - config.add_route('cabinet_edit', '/cabinet_edit/{code}') - config.add_route('cabinets', '/cabinets') - config.add_route('connecter_a', '/connecter_a/{login}') - config.add_route('dashboard', '/dashboard') - config.add_route('emails_msg', '/emails_msg/{nolig}') - config.add_route('expert_edit', '/expert_edit/{code_cab}/{code_exp}') - config.add_route('infrastructure', '/infrastructure') - config.add_route('rappels_rdv', '/rappels_rdv') - config.add_route('rdf_cause_edit', '/rdf_cause_edit/{code}') - config.add_route('rdf_causes', '/rdf_causes') - config.add_route('societe_edit', '/societe_edit/{societe}') - config.add_route('societes', '/societes') - config.add_route('text_edit', '/text_edit/{text_id}') - config.add_route('text_list', '/text_list') - config.add_route('text_view', '/text_view/{text_id}') - config.add_route('tarif_edit', '/tarif_edit/{groupe}/{ref}') - config.add_route('tarifs', '/tarifs/{groupe}') - config.add_route('tarifs_import', '/tarifs_import') - config.add_route('user_edit', '/user_edit/{cd_uti}') - config.add_route('users', '/users') - config.add_route('users_ua', '/users_ua') - - # stats - config.add_route('stats', '/stats') - config.add_route('stats_dossiers', '/stats_dossiers/{societe}') - config.add_route('stats_delais', '/stats_delais/{societe}') - config.add_route('ca_groupes_12m', '/ca_groupes_12m/{societe}') - # utils - config.add_route('batch_nuit', '/batch_nuit/{param}') - config.add_route('batch_test', '/batch_test/{param}') +def includeme(config): + config.add_static_view('static', 'static', cache_max_age=3600) + # agenda + config.add_route('agenda', '/agenda/{date}') + config.add_route('planning', '/planning/{date}') + config.add_route('rdv_edit','/rdv_edit/{nodossier}/{nolig}') + # default + config.add_route('home', '/') + config.add_route('affiche_message','/affiche_message/{login}') + config.add_route('ajax_article', '/ajax_article') + config.add_route('ajax_client', '/ajax_client') + config.add_route('ajax_codepostal', '/ajax_codepostal') + config.add_route('ajax_lookup', '/ajax_lookup') + config.add_route('ajax_texte', '/ajax_texte') + config.add_route('changer_mdp', '/changer_mdp') + config.add_route('envoyer_mdp', '/envoyer_mdp') + config.add_route('login', '/login') + config.add_route('login_as', '/login_as/{login}') + config.add_route('logout', '/logout') + config.add_route('redefinir_mdp', '/redefinir_mdp/{lien}') + config.add_route('init_mdp', '/init_mdp/{user}/{lien}') + # devis + config.add_route('devis_ligne', '/devis_ligne/{type_ligne}/{nodevis}/{nolig}') + config.add_route('devis_lig_mv', '/devis_lig_mv/{move}/{nodevis}/{nolig}') + config.add_route('devis_list', '/devis_list') + config.add_route('devis_create', '/devis_create/{nodossier}') + config.add_route('devis_web', '/devis_web/{nodevis}') + config.add_route('devis_view', '/devis_view/{nodevis}') + config.add_route('devis_preview', '/devis_preview/{nodevis}') + # dossier + config.add_route('demandes','/demandes') + config.add_route('demandes_dl','/demandes_dl/{societe}/{email_from}/{email_uid}') + config.add_route('delete_img','/delete_img/{nodossier}/{norapport}/{origine}/{nomfic}') + config.add_route('dossier_edit', '/dossier_edit/{nodossier}') + config.add_route('dossier_lookup', '/dossier_lookup') + config.add_route('dossier_select', '/dossier_select/{date}') + config.add_route('dossier_selected', '/dossier_selected/{goto}/{date}/{nodossier}') + config.add_route('dossier_view', '/dossier_view/{nodossier}') + config.add_route('rdf_bill','/rdf_bill/{no_id}') + config.add_route('rdf_client','/rdf_client/{no_id}') + config.add_route('rdf_edit','/rdf_edit/{nodossier}/{date_inter}') + config.add_route('rdf_list','/rdf_list') + config.add_route('rdf_rapport','/rdf_rapport/{no_id}') + config.add_route('rdf_view','/rdf_view/{no_id}') + config.add_route('rotate_img','/rotate_img/{nodossier}/{norapport}/{origine}/{nomfic}/{angle}') + config.add_route('suivi_edit','/suivi_edit/{nodossier}/{nolig}') + config.add_route('upload_doc', '/upload_doc/{nodossier}/{origine}') + config.add_route('upload_img', '/upload_img/{norapport}/{origine}') + config.add_route('upload_om', '/upload_om') + # parametres + config.add_route('parametres', '/parametres') + config.add_route('article_edit', '/article_edit/{ref}') + config.add_route('articles', '/articles') + config.add_route('cabinet_edit', '/cabinet_edit/{code}') + config.add_route('cabinets', '/cabinets') + config.add_route('connecter_a', '/connecter_a/{login}') + config.add_route('dashboard', '/dashboard') + config.add_route('emails_msg', '/emails_msg/{nolig}') + config.add_route('expert_edit', '/expert_edit/{code_cab}/{code_exp}') + config.add_route('infrastructure', '/infrastructure') + config.add_route('rappels_rdv', '/rappels_rdv') + config.add_route('rdf_cause_edit', '/rdf_cause_edit/{code}') + config.add_route('rdf_causes', '/rdf_causes') + config.add_route('societe_edit', '/societe_edit/{societe}') + config.add_route('societes', '/societes') + config.add_route('text_edit', '/text_edit/{text_id}') + config.add_route('text_list', '/text_list') + config.add_route('text_view', '/text_view/{text_id}') + config.add_route('tarif_edit', '/tarif_edit/{groupe}/{ref}') + config.add_route('tarifs', '/tarifs/{groupe}') + config.add_route('tarifs_import', '/tarifs_import') + config.add_route('user_edit', '/user_edit/{cd_uti}') + config.add_route('users', '/users') + config.add_route('users_ua', '/users_ua') + + # stats + config.add_route('stats', '/stats') + config.add_route('stats_dossiers', '/stats_dossiers/{societe}') + config.add_route('stats_delais', '/stats_delais/{societe}') + config.add_route('ca_groupes', '/ca_groupes/{societe}') + config.add_route('ca_clients', '/ca_clients/{societe}') + + # utils + config.add_route('batch_nuit', '/batch_nuit/{param}') + config.add_route('batch_test', '/batch_test/{param}') diff --git a/mondumas/templates/stats/ca_clients.pt b/mondumas/templates/stats/ca_clients.pt new file mode 100644 index 0000000..f0ec189 --- /dev/null +++ b/mondumas/templates/stats/ca_clients.pt @@ -0,0 +1,89 @@ + +
+ +
+
+
+
+ +
+ +
+
+
+
+ +
+ +
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+ + + + + +
+
+ + diff --git a/mondumas/templates/stats/ca_groupes_12m.pt b/mondumas/templates/stats/ca_groupes.pt similarity index 100% rename from mondumas/templates/stats/ca_groupes_12m.pt rename to mondumas/templates/stats/ca_groupes.pt diff --git a/mondumas/templates/stats/stats.pt b/mondumas/templates/stats/stats.pt index a78062d..afe2a67 100644 --- a/mondumas/templates/stats/stats.pt +++ b/mondumas/templates/stats/stats.pt @@ -1,31 +1,36 @@ - -
- - - -
-
- -
-
- - + +
+ + + +
+
+ +
+
+ + diff --git a/mondumas/views/stats.py b/mondumas/views/stats.py index 4fd457c..dc81cb1 100644 --- a/mondumas/views/stats.py +++ b/mondumas/views/stats.py @@ -155,13 +155,14 @@ def stats_delais(request): 'groupe': groupe, } -@view_config(route_name='ca_groupes_12m', renderer='../templates/stats/ca_groupes_12m.pt', permission='view') -def ca_groupes_12m(request): +@view_config(route_name='ca_groupes', renderer='../templates/stats/ca_groupes.pt', permission='view') +def ca_groupes(request): societe = request.matchdict['societe'] - url = request.route_url('stats_delais', societe = societe) + url = request.route_url('ca_groupes', societe = societe) datefin = date.today() + datefin.replace(day=1) # debut = aujourd'hui - 11 mois datedeb = datefin + relativedelta(months=-11) @@ -172,6 +173,7 @@ def ca_groupes_12m(request): # lire les CA par mois items = get_ca_groupe_12m(request, societe, datedeb, datefin) + print(datedeb) chart_ca_12m = [] # titre des colonnes chart_ca_12m.append(('Mois', 'AXA', { 'type':'string','role': 'tooltip'}, 'MAIF', { 'type':'string','role': 'tooltip'})) @@ -194,22 +196,105 @@ def ca_groupes_12m(request): chart_ca_3y_2 = [] chart_ca_3y_3 = [] # titre des colonnes - chart_ca_3y_1.append(('Groupe', 'CA')) - chart_ca_3y_2.append(('Groupe', 'CA')) - chart_ca_3y_3.append(('Groupe', 'CA')) + chart_ca_3y_1.append(('Groupe', 'CA', { 'type':'string','role': 'tooltip'})) + chart_ca_3y_2.append(('Groupe', 'CA', { 'type':'string','role': 'tooltip'})) + chart_ca_3y_3.append(('Groupe', 'CA', { 'type':'string','role': 'tooltip'})) title1 = 'CA ' + (datedeb + relativedelta(years=-2)).strftime("%Y") title2 = 'CA ' + (datedeb + relativedelta(years=-1)).strftime("%Y") title3 = 'CA ' + datedeb.strftime("%Y") for item in items: # construire la liste pour donut cible - #tooltipMAIF = item.date + ' \nCA: '+str(item.MAIF_ca) + ' €\nDossiers: '+str(round(item.MAIF_nb)) - #tooltipAXA = item.date + ' \nCA: '+str(item.AXA_ca) + ' €\nDossiers: '+str(round(item.AXA_nb)) + tooltip_y1 = item.groupe + ' \nCA: '+str(item.Annee1) + ' €\nDossiers: '+str(round(item.Count1)) + tooltip_y2 = item.groupe + ' \nCA: '+str(item.Annee2) + ' €\nDossiers: '+str(round(item.Count1)) + tooltip_y3 = item.groupe + ' \nCA: '+str(item.Annee3) + ' €\nDossiers: '+str(round(item.Count1)) # ('+str(item.population)+')/n' - d1 = (item.groupe, float(item.Annee1)) + d1 = (item.groupe, float(item.Annee1), tooltip_y1) chart_ca_3y_1.append(d1) - d2 = (item.groupe, float(item.Annee2)) + d2 = (item.groupe, float(item.Annee2), tooltip_y2) chart_ca_3y_2.append(d2) - d3 = (item.groupe, float(item.Annee3)) + d3 = (item.groupe, float(item.Annee3), tooltip_y3) + chart_ca_3y_3.append(d3) + + return { + 'page_title': "CA par groupe", + 'url': url, + 'chart_ca_12m': json.dumps(chart_ca_12m), + 'chart_ca_3y_1': json.dumps(chart_ca_3y_1), + 'chart_ca_3y_2': json.dumps(chart_ca_3y_2), + 'chart_ca_3y_3': json.dumps(chart_ca_3y_3), + 'title': title, + 'title1': title1, + 'title2': title2, + 'title3': title3, + 'societes': societes, + 'societe': societe, + } + +@view_config(route_name='ca_clients', renderer='../templates/stats/ca_clients.pt', permission='view') +def ca_clients(request): + + societe = request.matchdict['societe'] + url = request.route_url('ca_clients', societe = societe) + + datefin = date.today() + # debut = aujourd'hui - 11 mois + datedeb = datefin + relativedelta(months=-11) + + societes = ['PE','ME','PL'] + # si societe a été changé par le user + if 'societe' in request.params: + societe = request.params["societe"] + + # lire les CA par mois + items = get_ca_clients_12m(request, societe, datedeb, datefin) + print(datedeb) + chart_ca_12m = [] + # titre des colonnes + chart_ca_12m.append(('Mois', 'A', { 'type':'string','role': 'tooltip'}, 'E', { 'type':'string','role': 'tooltip'}, + 'G', { 'type':'string','role': 'tooltip'}, 'I', { 'type':'string','role': 'tooltip'}, 'P', { 'type':'string','role': 'tooltip'}, + 'R', { 'type':'string','role': 'tooltip'}, 'S', { 'type':'string','role': 'tooltip'})) + title = 'CA / MOIS' + for item in items: + # construire la liste pour donut cible + tooltipA = item.date + ' \nCA: '+str(item.A_ca) + ' €\nDossiers: '+str(round(item.A_nb)) + tooltipE = item.date + ' \nCA: '+str(item.E_ca) + ' €\nDossiers: '+str(round(item.E_nb)) + tooltipG = item.date + ' \nCA: '+str(item.G_ca) + ' €\nDossiers: '+str(round(item.G_nb)) + tooltipI = item.date + ' \nCA: '+str(item.I_ca) + ' €\nDossiers: '+str(round(item.I_nb)) + tooltipP = item.date + ' \nCA: '+str(item.P_ca) + ' €\nDossiers: '+str(round(item.P_nb)) + tooltipR = item.date + ' \nCA: '+str(item.R_ca) + ' €\nDossiers: '+str(round(item.R_nb)) + tooltipS = item.date + ' \nCA: '+str(item.S_ca) + ' €\nDossiers: '+str(round(item.S_nb)) + # ('+str(item.population)+')/n' + d = (item.mois, float(item.A_ca), tooltipA, float(item.E_ca), tooltipE, float(item.G_ca), tooltipG, + float(item.I_ca), tooltipI, float(item.P_ca), tooltipP, float(item.R_ca), tooltipR, float(item.S_ca), tooltipS) + chart_ca_12m.append(d) + + # debut = aujourd'hui - 11 mois + datedeb = date.today() + datedeb.replace(month=1,day=1) + + # lire les CA par mois + items = get_ca_clients_3y(request, societe, datedeb) + chart_ca_3y_1 = [] + chart_ca_3y_2 = [] + chart_ca_3y_3 = [] + # titre des colonnes + chart_ca_3y_1.append(('Clients', 'CA', { 'type':'string','role': 'tooltip'})) + chart_ca_3y_2.append(('Clients', 'CA', { 'type':'string','role': 'tooltip'})) + chart_ca_3y_3.append(('Clients', 'CA', { 'type':'string','role': 'tooltip'})) + title1 = 'CA ' + (datedeb + relativedelta(years=-2)).strftime("%Y") + title2 = 'CA ' + (datedeb + relativedelta(years=-1)).strftime("%Y") + title3 = 'CA ' + datedeb.strftime("%Y") + for item in items: + # construire la liste pour donut cible + tooltip_y1 = item.typecli + ' \nCA: '+str(item.Annee1) + ' €\nDossiers: '+str(round(item.Count1)) + tooltip_y2 = item.typecli + ' \nCA: '+str(item.Annee2) + ' €\nDossiers: '+str(round(item.Count1)) + tooltip_y3 = item.typecli + ' \nCA: '+str(item.Annee3) + ' €\nDossiers: '+str(round(item.Count1)) + # ('+str(item.population)+')/n' + d1 = (item.typecli, float(item.Annee1), tooltip_y1) + chart_ca_3y_1.append(d1) + d2 = (item.typecli, float(item.Annee2), tooltip_y2) + chart_ca_3y_2.append(d2) + d3 = (item.typecli, float(item.Annee3), tooltip_y3) chart_ca_3y_3.append(d3) return {