diff --git a/README.md b/README.md index 8596bb5c..954c0364 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,23 @@ Během marné snahy zajistit očkovací místa pro příbuzné jsme si všimli t Web: https://ockovani.opendatalab.cz ## Napsali o nás -* https://denikn.cz/569269/kde-maji-volna-mista-programatori-po-nocich-vymysleli-aplikaci-ktera-muze-zkratit-cekani-na-vakcinu -* https://www.zive.cz/clanky/kdyz-to-neudelal-stat-poradili-si-programatori-sami-vytvorili-aplikaci-s-prehledem-volnych-mist-pro-ockovani/sc-3-a-208719/default.aspx -* https://domaci.ihned.cz/c1-66889710-programator-rozjel-web-ktery-ukaze-kde-je-volno-na-ockovani-ve-skladech-lezi-250-tisic-davek-vakcin-rika -* https://forbes.cz/kde-se-nechat-naockovat-platforma-z-cvut-ukazuje-dostupne-ockovaci-kapacity/ -* https://www.echo24.cz/a/Sqbj5/kde-je-volna-vakcina-web-ukazuje-stav-na-ockovacich-mistech -* https://zpravy.aktualne.cz/domaci/mladici-marne-hledali-ockovaci-termin-pro-prarodice-vytvoril/r~c7975d9c802511eb9cafac1f6b220ee8/ -* https://prazsky.denik.cz/zpravy_region/ockovani-termin-vakcina-senior-covid-nemocnice-poradi.html -* https://www.ceskenoviny.cz/zpravy/2007015 -* https://radiozurnal.rozhlas.cz/kde-maji-dostatek-vakcin-vedci-z-cvut-vytvorili-web-ktery-porovnava-jednotliva-8446956 -* https://www.vitalia.cz/clanky/jak-si-ne-vybrat-nejpomalejsi-misto-na-ockovani-proti-covidu/ +* [Deník N: Kde mají volná místa? Programátoři po nocích vymysleli aplikaci, která může zkrátit čekání na vakcínu](https://denikn.cz/569269/kde-maji-volna-mista-programatori-po-nocich-vymysleli-aplikaci-ktera-muze-zkratit-cekani-na-vakcinu) +* [Živě: Když to neudělal stát, poradili si programátoři sami. Vytvořili aplikaci s přehledem volných míst pro očkování](https://www.zive.cz/clanky/kdyz-to-neudelal-stat-poradili-si-programatori-sami-vytvorili-aplikaci-s-prehledem-volnych-mist-pro-ockovani/sc-3-a-208719/default.aspx) +* [Hospodářské noviny: Programátor rozjel web, který ukáže, kde je volno na očkování. Ve skladech leží 250 tisíc dávek vakcín, říká](https://domaci.ihned.cz/c1-66889710-programator-rozjel-web-ktery-ukaze-kde-je-volno-na-ockovani-ve-skladech-lezi-250-tisic-davek-vakcin-rika) +* [Forbes: Kde se nechat naočkovat. Platforma z ČVUT ukazuje dostupné očkovací kapacity](https://forbes.cz/kde-se-nechat-naockovat-platforma-z-cvut-ukazuje-dostupne-ockovaci-kapacity/) +* [Echo24: Kde je volná vakcína? Web ukazuje stav na očkovacích místech](https://www.echo24.cz/a/Sqbj5/kde-je-volna-vakcina-web-ukazuje-stav-na-ockovacich-mistech) +* [Aktuálně: Mladí muži marně hledali očkovací termín pro prarodiče. Vytvořili web s volnými místy](https://zpravy.aktualne.cz/domaci/mladici-marne-hledali-ockovaci-termin-pro-prarodice-vytvoril/r~c7975d9c802511eb9cafac1f6b220ee8/) +* [inSmart: Kde je pro mě vakcína? ČVUT vyvinulo aplikaci s přehledem volných míst na očkování proti Covidu](https://insmart.cz/volna-mista-vakciny-covid/) +* [Česká věda do světa: Odborníci z ČVUT vytvořili aplikaci pro očkování proti koronaviru](http://ceskavedadosveta.cz/odbornici-z-cvut-vytvorili-aplikaci-pro-ockovani-proti-koronaviru/) +* [Deník: Vyberte si nejmenší frontu. Pomůže aplikace s vytížeností očkovacích míst](https://www.denik.cz/z_domova/ockovani-termin-vakcina-senior-covid-nemocnice-poradi.html) +* [ČTK: Počet čekajících na vakcínu na covid je možné si ověřit na webu](https://www.ceskenoviny.cz/zpravy/2007015) +* [pribram.cz: Počet čekajících na vakcínu na covid je možné si ověřit na webu](https://www.pribram.cz/clanek/pocet-cekajicich-na-vakcinu-na-covid-je-mozne-si-overit-na-webu/18978/) +* [MoneyMAG: Počet čekajících na vakcínu je možné si ověřit na webu](https://moneymag.cz/aktuality/pocet-cekajicich-na-vakcinu-je-mozne-si-overit-na-webu.f69bad14) +* [EuroZprávy: Počet čekajících na vakcínu je možné si ověřit na webu](https://eurozpravy.cz/domaci/zdravotnictvi/pocet-cekajicich-na-vakcinu-je-mozne-si-overit-na-webu.a09f5308/) +* [Český rozhlas: Kde mají dostatek vakcín? Vědci z ČVUT vytvořili web, který porovnává jednotlivá očkovací místa](https://radiozurnal.rozhlas.cz/kde-maji-dostatek-vakcin-vedci-z-cvut-vytvorili-web-ktery-porovnava-jednotliva-8446956) +* [Vitalia: Jak si (ne)vybrat nejpomalejší místo na očkování proti covidu](https://www.vitalia.cz/clanky/jak-si-ne-vybrat-nejpomalejsi-misto-na-ockovani-proti-covidu/) +* [Televize Seznam: Večerní zprávy (15. 3.)](https://www.televizeseznam.cz/video/vecerni-zpravy-porad/kteri-ministri-uz-jsou-naockovani-opatreni-do-velikonoc-a-opakovani-rocniku-64143662) +* [TV9P: Marta Kloučková Quintet a webová aplikace z FIT](https://www.youtube.com/watch?v=_DcoB_fXfe4) ## Poznámky k fungování Pro získávání dat využívala metody scrapingu. Nyní využíváme oficiálních dat od UZIS. @@ -68,6 +75,14 @@ If you want to fetch recent data please set the FETCH_DATA environment variable: `flask db upgrade` +1. fetch data + + `flask fetch-opendata` + +1. compute metrics + + `flask compute-metrics` + 1. start Flask webserver `flask run` diff --git a/app/__init__.py b/app/__init__.py index 8d6b0e07..3ee2e77e 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -2,8 +2,9 @@ import logging from flask import Flask, Blueprint -from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate +from flask_sqlalchemy import SQLAlchemy + from config import Config app = Flask(__name__) @@ -20,4 +21,4 @@ from app import filters, views, models, commands -app.register_blueprint(bp) \ No newline at end of file +app.register_blueprint(bp) diff --git a/app/commands.py b/app/commands.py index 0f5bd369..ca10f6b3 100644 --- a/app/commands.py +++ b/app/commands.py @@ -4,7 +4,7 @@ import click from app import app -from app.etl import Etl +from app.etl import MetricsEtl from app.opendata_fetcher import OpenDataFetcher from app.twitter_bot import TwitterBot @@ -46,7 +46,7 @@ def compute_metrics_command(datum): while start_date <= end_date: app.logger.info("Computing metrics for date: '{}'.".format(start_date)) - etl = Etl(start_date) + etl = MetricsEtl(start_date) result = etl.compute_all() if not result: break diff --git a/app/context.py b/app/context.py new file mode 100644 index 00000000..b4f34bd4 --- /dev/null +++ b/app/context.py @@ -0,0 +1,31 @@ +from datetime import date + +from flask import g +from sqlalchemy import func + +from app import db +from app.models import Import + +STATUS_FINISHED = 'FINISHED' + + +def get_import_date(): + """ + Returns date of the last successful import. + """ + if 'import_date' not in g: + last_date = db.session.query(func.max(Import.date)).filter(Import.status == STATUS_FINISHED).first()[0] + g.import_date = date.today() if last_date is None else last_date + + return g.import_date + + +def get_import_id(): + """ + Returns id of the last successful import. + """ + if 'import_id' not in g: + last_id = db.session.query(func.max(Import.id)).filter(Import.status == STATUS_FINISHED).first()[0] + g.import_id = -1 if last_id is None else last_id + + return g.import_id \ No newline at end of file diff --git a/app/etl.py b/app/etl.py deleted file mode 100644 index 656383bb..00000000 --- a/app/etl.py +++ /dev/null @@ -1,870 +0,0 @@ -from datetime import timedelta, date - -from sqlalchemy import func, case, text, or_, and_ - -from app import db, app, queries -from app.models import OckovaciMisto, OckovaciMistoMetriky, OckovaniRegistrace, OckovaniRezervace, Import, \ - OckovaniLide, OckovaniDistribuce, OckovaniSpotreba, Okres, OkresMetriky, Kraj, KrajMetriky, Populace - - -class Etl: - def __init__(self, date_): - self._date = date_ - self._import_id = self._find_import_id() - - def compute_all(self): - try: - self.compute_center() - self.compute_okres() - self.compute_regions() - except Exception as e: - app.logger.error(e) - db.session.rollback() - return False - - db.session.commit() - return True - - def compute_center(self): - self._compute_center_registrations() - self._compute_center_reservations() - self._compute_center_vaccinated() - self._compute_center_distributed() - self._compute_center_used() - self._compute_center_derived() - self._compute_center_deltas() - - def compute_okres(self): - self._compute_okres_population() - self._compute_okres_registrations() - self._compute_okres_reservations() - # # self._compute_okres_vaccinated() # todo - self._compute_okres_distributed() - self._compute_okres_used() - self._compute_okres_derived() - self._compute_okres_deltas() - - def compute_regions(self): - self._compute_kraj_population() - self._compute_kraj_registrations() - self._compute_kraj_reservations() - self._compute_kraj_vaccinated() - self._compute_kraj_distributed() - self._compute_kraj_used() - self._compute_kraj_derived() - self._compute_kraj_deltas() - - def _compute_center_registrations(self): - """Computes metrics based on registrations dataset for each vaccination center.""" - registrations = db.session.query( - OckovaciMisto.id, func.coalesce(func.sum(OckovaniRegistrace.pocet), 0).label('registrace_celkem'), - func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == False, OckovaniRegistrace.pocet)], else_=0)), 0).label("registrace_fronta") - ).outerjoin(OckovaniRegistrace, and_(OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id, OckovaniRegistrace.import_id == self._import_id)) \ - .group_by(OckovaciMisto.id) \ - .all() - - for registration in registrations: - db.session.merge(OckovaciMistoMetriky( - misto_id=registration.id, - datum=self._date, - registrace_celkem=registration.registrace_celkem, - registrace_fronta=registration.registrace_fronta - )) - - app.logger.info('Computing vaccination centers metrics - registrations finished.') - - def _compute_center_reservations(self): - """Computes metrics based on reservations dataset for each vaccination center.""" - reservations = db.session.query( - OckovaciMisto.id, - func.coalesce(func.sum(OckovaniRezervace.maximalni_kapacita - OckovaniRezervace.volna_kapacita), 0).label('rezervace_celkem'), - func.coalesce(func.sum(case([(OckovaniRezervace.datum >= self._date, OckovaniRezervace.maximalni_kapacita - OckovaniRezervace.volna_kapacita)], else_=0)), 0).label("rezervace_cekajici"), - func.coalesce(func.sum(case([(and_(OckovaniRezervace.datum == self._date, OckovaniRezervace.kalendar_ockovani == 'V1'), OckovaniRezervace.maximalni_kapacita)], else_=0)), 0).label("rezervace_kapacita") - - ).outerjoin(OckovaniRezervace, and_(OckovaciMisto.id == OckovaniRezervace.ockovaci_misto_id, OckovaniRezervace.import_id == self._import_id)) \ - .group_by(OckovaciMisto.id) \ - .all() - - for reservation in reservations: - db.session.merge(OckovaciMistoMetriky( - misto_id=reservation.id, - datum=self._date, - rezervace_celkem=reservation.rezervace_celkem, - rezervace_cekajici=reservation.rezervace_cekajici, - rezervace_kapacita=reservation.rezervace_kapacita - )) - - app.logger.info('Computing vaccination centers metrics - reservations finished.') - - def _compute_center_vaccinated(self): - """Computes metrics based on vaccinated people dataset for each vaccination center.""" - vaccinated = db.session.query(OckovaciMisto.id, func.coalesce(func.sum(OckovaniLide.pocet), 0).label('ockovani_pocet'), - func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 1, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_1'), - func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 2, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_2')) \ - .outerjoin(OckovaniLide, and_(OckovaciMisto.nrpzs_kod == OckovaniLide.zarizeni_kod, OckovaniLide.datum < self._date)) \ - .filter(OckovaciMisto.nrpzs_kod.in_(queries.unique_nrpzs_subquery())) \ - .group_by(OckovaciMisto.id) \ - .all() - - for vacc in vaccinated: - db.session.merge(OckovaciMistoMetriky( - misto_id=vacc.id, - datum=self._date, - ockovani_pocet=vacc.ockovani_pocet, - ockovani_pocet_1=vacc.ockovani_pocet_1, - ockovani_pocet_2=vacc.ockovani_pocet_2 - )) - - app.logger.info('Computing vaccination centers metrics - vaccinated people finished.') - - def _compute_center_distributed(self): - """Computes metrics based on distributed vaccines dataset for each vaccination center.""" - distributed = db.session.query( - OckovaciMisto.id, - func.coalesce(func.sum(case([(and_(OckovaciMisto.id == OckovaniDistribuce.ockovaci_misto_id, OckovaniDistribuce.akce == 'Výdej'), 0)], else_=OckovaniDistribuce.pocet_davek)), 0).label('vakciny_prijate_pocet'), - func.coalesce(func.sum(case([(and_(OckovaciMisto.id == OckovaniDistribuce.ockovaci_misto_id, OckovaniDistribuce.akce == 'Výdej'), OckovaniDistribuce.pocet_davek)], else_=0)), 0).label('vakciny_vydane_pocet') - ).outerjoin(OckovaniDistribuce, - and_( - or_( - and_(OckovaciMisto.id == OckovaniDistribuce.ockovaci_misto_id, or_(OckovaniDistribuce.akce == 'Příjem', OckovaniDistribuce.akce == 'Výdej')), - and_(OckovaciMisto.id == OckovaniDistribuce.cilove_ockovaci_misto_id, OckovaniDistribuce.akce == 'Výdej') - ), - OckovaniDistribuce.datum < self._date - )) \ - .group_by(OckovaciMisto.id) \ - .all() - - for dist in distributed: - db.session.merge(OckovaciMistoMetriky( - misto_id=dist.id, - datum=self._date, - vakciny_prijate_pocet=dist.vakciny_prijate_pocet-dist.vakciny_vydane_pocet - )) - - app.logger.info('Computing vaccination centers metrics - distributed vaccines finished.') - - def _compute_center_used(self): - """Computes metrics based on used vaccines dataset for each vaccination center.""" - used = db.session.query( - OckovaciMisto.id, - func.coalesce(func.sum(OckovaniSpotreba.pouzite_davky), 0).label('vakciny_ockovane_pocet'), - func.coalesce(func.sum(OckovaniSpotreba.znehodnocene_davky), 0).label('vakciny_znicene_pocet') - ).outerjoin(OckovaniSpotreba, and_(OckovaciMisto.id == OckovaniSpotreba.ockovaci_misto_id, OckovaniSpotreba.datum < self._date)) \ - .group_by(OckovaciMisto.id) \ - .all() - - for use in used: - db.session.merge(OckovaciMistoMetriky( - misto_id=use.id, - datum=self._date, - vakciny_ockovane_pocet=use.vakciny_ockovane_pocet, - vakciny_znicene_pocet=use.vakciny_znicene_pocet - )) - - app.logger.info('Computing vaccination centers metrics - used vaccines finished.') - - def _compute_center_derived(self): - """Computes metrics derived from the previous metrics for each vaccination center.""" - avg_waiting = db.session.query( - OckovaciMisto.id, - (func.sum((OckovaniRegistrace.datum_rezervace - OckovaniRegistrace.datum)*OckovaniRegistrace.pocet)/func.sum(OckovaniRegistrace.pocet)).label('registrace_prumer_cekani'), - ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum_rezervace >= self._date - timedelta(7)) \ - .group_by(OckovaciMisto.id) \ - .all() - - for wait in avg_waiting: - db.session.merge(OckovaciMistoMetriky( - misto_id=wait.id, - datum=self._date, - registrace_prumer_cekani=wait.registrace_prumer_cekani - )) - - est_waiting = db.session.query("id", "registrace_odhad_cekani").from_statement(text( - """ - select id, 7.0 * sum(case when rezervace = false then pocet else 0 end) - / nullif(sum(case when rezervace = true and datum_rezervace >= :datum_7 then pocet else 0 end), 0) - registrace_odhad_cekani - from ockovaci_mista - join ockovani_registrace on id = ockovaci_misto_id - where import_id = :import_id - group by (id) - """ - )).params(datum_7=self._date - timedelta(7), import_id=self._import_id) \ - .all() - - for wait in est_waiting: - db.session.merge(OckovaciMistoMetriky( - misto_id=wait.id, - datum=self._date, - registrace_odhad_cekani=wait.registrace_odhad_cekani - )) - - success_ratio_7 = db.session.query( - OckovaciMisto.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_tydenni_uspesnost') - ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(7)) \ - .group_by(OckovaciMisto.id) \ - .all() - - for ratio in success_ratio_7: - db.session.merge(OckovaciMistoMetriky( - misto_id=ratio.id, - datum=self._date, - registrace_tydenni_uspesnost=ratio.registrace_tydenni_uspesnost - )) - - success_ratio_14 = db.session.query( - OckovaciMisto.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_14denni_uspesnost') - ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(14)) \ - .group_by(OckovaciMisto.id) \ - .all() - - for ratio in success_ratio_14: - db.session.merge(OckovaciMistoMetriky( - misto_id=ratio.id, - datum=self._date, - registrace_14denni_uspesnost=ratio.registrace_14denni_uspesnost - )) - - success_ratio_30 = db.session.query( - OckovaciMisto.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_30denni_uspesnost') - ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(30)) \ - .group_by(OckovaciMisto.id) \ - .all() - - for ratio in success_ratio_30: - db.session.merge(OckovaciMistoMetriky( - misto_id=ratio.id, - datum=self._date, - registrace_30denni_uspesnost=ratio.registrace_30denni_uspesnost - )) - - vacc_est_waiting = db.session.query( - OckovaciMisto.id, - (7.0 * (OckovaciMistoMetriky.registrace_fronta + OckovaciMistoMetriky.rezervace_cekajici) - / case([(func.sum(OckovaniLide.pocet) > 0, func.sum(OckovaniLide.pocet))], else_=None)).label('ockovani_odhad_cekani') - ).join(OckovaciMistoMetriky, OckovaciMisto.id == OckovaciMistoMetriky.misto_id) \ - .join(OckovaniLide, OckovaciMisto.nrpzs_kod == OckovaniLide.zarizeni_kod) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .filter(OckovaciMisto.nrpzs_kod.in_(queries.unique_nrpzs_subquery())) \ - .filter(OckovaniLide.datum < self._date, OckovaniLide.datum >= self._date - timedelta(7)) \ - .group_by(OckovaciMisto.id, OckovaciMistoMetriky.registrace_fronta, OckovaciMistoMetriky.rezervace_cekajici) \ - .all() - - for wait in vacc_est_waiting: - db.session.merge(OckovaciMistoMetriky( - misto_id=wait.id, - datum=self._date, - ockovani_odhad_cekani=wait.ockovani_odhad_cekani - )) - - vacc_skladem = db.session.query( - OckovaciMisto.id, (OckovaciMistoMetriky.vakciny_prijate_pocet - OckovaciMistoMetriky.ockovani_pocet - - OckovaciMistoMetriky.vakciny_znicene_pocet).label('vakciny_skladem_pocet') - ).join(OckovaciMistoMetriky, OckovaciMisto.id == OckovaciMistoMetriky.misto_id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(OckovaciMisto.id, OckovaciMistoMetriky.vakciny_prijate_pocet, OckovaciMistoMetriky.ockovani_pocet, - OckovaciMistoMetriky.vakciny_znicene_pocet) \ - .all() - - for vacc in vacc_skladem: - db.session.merge(OckovaciMistoMetriky( - misto_id=vacc.id, - datum=self._date, - vakciny_skladem_pocet=vacc.vakciny_skladem_pocet - )) - - app.logger.info('Computing vaccination centers metrics - derived metrics finished.') - - def _compute_center_deltas(self): - """Computes deltas for previous metrics for each vaccination center.""" - db.session.execute(text( - """ - update ockovaci_mista_metriky t - set rezervace_celkem_zmena_den = t0.rezervace_celkem - t1.rezervace_celkem, - rezervace_cekajici_zmena_den = t0.rezervace_cekajici - t1.rezervace_cekajici, - rezervace_kapacita_zmena_den = t0.rezervace_kapacita - t1.rezervace_kapacita, - registrace_celkem_zmena_den = t0.registrace_celkem - t1.registrace_celkem, - registrace_fronta_zmena_den = t0.registrace_fronta - t1.registrace_fronta, - registrace_tydenni_uspesnost_zmena_den = t0.registrace_tydenni_uspesnost - t1.registrace_tydenni_uspesnost, - registrace_14denni_uspesnost_zmena_den = t0.registrace_14denni_uspesnost - t1.registrace_14denni_uspesnost, - registrace_30denni_uspesnost_zmena_den = t0.registrace_30denni_uspesnost - t1.registrace_30denni_uspesnost, - registrace_prumer_cekani_zmena_den = t0.registrace_prumer_cekani - t1.registrace_prumer_cekani, - registrace_odhad_cekani_zmena_den = t0.registrace_odhad_cekani - t1.registrace_odhad_cekani, - ockovani_pocet_zmena_den = t0.ockovani_pocet - t1.ockovani_pocet, - ockovani_pocet_1_zmena_den = t0.ockovani_pocet_1 - t1.ockovani_pocet_1, - ockovani_pocet_2_zmena_den = t0.ockovani_pocet_2 - t1.ockovani_pocet_2, - ockovani_odhad_cekani_zmena_den = t0.ockovani_odhad_cekani - t1.ockovani_odhad_cekani, - vakciny_prijate_pocet_zmena_den = t0.vakciny_prijate_pocet - t1.vakciny_prijate_pocet, - vakciny_ockovane_pocet_zmena_den = t0.vakciny_ockovane_pocet - t1.vakciny_ockovane_pocet, - vakciny_znicene_pocet_zmena_den = t0.vakciny_znicene_pocet - t1.vakciny_znicene_pocet, - vakciny_skladem_pocet_zmena_den = t0.vakciny_skladem_pocet - t1.vakciny_skladem_pocet - from ockovaci_mista_metriky t0 - join ockovaci_mista_metriky t1 - on t0.misto_id = t1.misto_id - where t.misto_id = t0.misto_id and t.datum = :datum and t0.datum = :datum and t1.datum = :datum_1 - """ - ), {'datum': self._date, 'datum_1': self._date - timedelta(1)}) - - db.session.execute(text( - """ - update ockovaci_mista_metriky t - set rezervace_celkem_zmena_tyden = t0.rezervace_celkem - t7.rezervace_celkem, - rezervace_cekajici_zmena_tyden = t0.rezervace_cekajici - t7.rezervace_cekajici, - rezervace_kapacita_zmena_tyden = t0.rezervace_kapacita - t7.rezervace_kapacita, - registrace_celkem_zmena_tyden = t0.registrace_celkem - t7.registrace_celkem, - registrace_fronta_zmena_tyden = t0.registrace_fronta - t7.registrace_fronta, - registrace_tydenni_uspesnost_zmena_tyden = t0.registrace_tydenni_uspesnost - t7.registrace_tydenni_uspesnost, - registrace_14denni_uspesnost_zmena_tyden = t0.registrace_14denni_uspesnost - t7.registrace_14denni_uspesnost, - registrace_30denni_uspesnost_zmena_tyden = t0.registrace_30denni_uspesnost - t7.registrace_30denni_uspesnost, - registrace_prumer_cekani_zmena_tyden = t0.registrace_prumer_cekani - t7.registrace_prumer_cekani, - registrace_odhad_cekani_zmena_tyden = t0.registrace_odhad_cekani - t7.registrace_odhad_cekani, - ockovani_pocet_zmena_tyden = t0.ockovani_pocet - t7.ockovani_pocet, - ockovani_pocet_1_zmena_tyden = t0.ockovani_pocet_1 - t7.ockovani_pocet_1, - ockovani_pocet_2_zmena_tyden = t0.ockovani_pocet_2 - t7.ockovani_pocet_2, - ockovani_odhad_cekani_zmena_tyden = t0.ockovani_odhad_cekani - t7.ockovani_odhad_cekani, - vakciny_prijate_pocet_zmena_tyden = t0.vakciny_prijate_pocet - t7.vakciny_prijate_pocet, - vakciny_ockovane_pocet_zmena_tyden = t0.vakciny_ockovane_pocet - t7.vakciny_ockovane_pocet, - vakciny_znicene_pocet_zmena_tyden = t0.vakciny_znicene_pocet - t7.vakciny_znicene_pocet, - vakciny_skladem_pocet_zmena_tyden = t0.vakciny_skladem_pocet - t7.vakciny_skladem_pocet - from ockovaci_mista_metriky t0 - join ockovaci_mista_metriky t7 - on t0.misto_id = t7.misto_id - where t.misto_id = t0.misto_id and t.datum = :datum and t0.datum = :datum and t7.datum = :datum_7 - """ - ), {'datum': self._date, 'datum_7': self._date - timedelta(7)}) - - app.logger.info('Computing vaccination centers metrics - deltas finished.') - - def _compute_okres_population(self): - """Computes metrics based on population for each okres.""" - population = db.session.query( - Okres.id, func.sum(Populace.pocet).label('pocet_obyvatel_celkem'), - func.sum(case([(Populace.vek >= 18, Populace.pocet)], else_=0)).label('pocet_obyvatel_dospeli') - ).join(Populace, Populace.orp_kod == Okres.id) \ - .group_by(Okres.id) - - for pop in population: - db.session.merge(OkresMetriky( - okres_id=pop.id, - datum=self._date, - pocet_obyvatel_celkem=pop.pocet_obyvatel_celkem, - pocet_obyvatel_dospeli=pop.pocet_obyvatel_dospeli - )) - - app.logger.info('Computing okres metrics - population finished.') - - def _compute_okres_registrations(self): - """Computes metrics based on registrations dataset for each okres.""" - registrations = db.session.query( - Okres.id, func.sum(OckovaciMistoMetriky.registrace_celkem).label('registrace_celkem'), - func.sum(OckovaciMistoMetriky.registrace_fronta).label("registrace_fronta") - ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(Okres.id) \ - .all() - - for registration in registrations: - db.session.merge(OkresMetriky( - okres_id=registration.id, - datum=self._date, - registrace_celkem=registration.registrace_celkem, - registrace_fronta=registration.registrace_fronta - )) - - app.logger.info('Computing okres metrics - registrations finished.') - - def _compute_okres_reservations(self): - """Computes metrics based on reservations dataset for each okres.""" - reservations = db.session.query( - Okres.id, func.sum(OckovaciMistoMetriky.rezervace_celkem).label('rezervace_celkem'), - func.sum(OckovaciMistoMetriky.rezervace_cekajici).label("rezervace_cekajici"), - func.sum(OckovaciMistoMetriky.rezervace_kapacita).label("rezervace_kapacita") - ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(Okres.id) \ - .all() - - for reservation in reservations: - db.session.merge(OkresMetriky( - okres_id=reservation.id, - datum=self._date, - rezervace_celkem=reservation.rezervace_celkem, - rezervace_cekajici=reservation.rezervace_cekajici, - rezervace_kapacita=reservation.rezervace_kapacita - )) - - app.logger.info('Computing okres metrics - reservations finished.') - - def _compute_okres_distributed(self): - """Computes metrics based on distributed vaccines dataset for each okres.""" - distributed = db.session.query( - Okres.id, func.sum(OckovaciMistoMetriky.vakciny_prijate_pocet).label('vakciny_prijate_pocet') - ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(Okres.id) \ - .all() - - for dist in distributed: - db.session.merge(OkresMetriky( - okres_id=dist.id, - datum=self._date, - vakciny_prijate_pocet=dist.vakciny_prijate_pocet - )) - - app.logger.info('Computing okres metrics - distributed vaccines finished.') - - def _compute_okres_used(self): - """Computes metrics based on used vaccines dataset for each okres.""" - used = db.session.query( - Okres.id, func.sum(OckovaciMistoMetriky.vakciny_ockovane_pocet).label('vakciny_ockovane_pocet'), - func.sum(OckovaciMistoMetriky.vakciny_znicene_pocet).label("vakciny_znicene_pocet") - ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(Okres.id) \ - .all() - - for use in used: - db.session.merge(OkresMetriky( - okres_id=use.id, - datum=self._date, - vakciny_ockovane_pocet=use.vakciny_ockovane_pocet, - vakciny_znicene_pocet=use.vakciny_znicene_pocet - )) - - app.logger.info('Computing okres metrics - used vaccines finished.') - - def _compute_okres_derived(self): - """Computes metrics derived from the previous metrics for each okres.""" - avg_waiting = db.session.query( - Okres.id, - (func.sum((OckovaniRegistrace.datum_rezervace - OckovaniRegistrace.datum)*OckovaniRegistrace.pocet)/func.sum(OckovaniRegistrace.pocet)).label('registrace_prumer_cekani'), - ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum_rezervace >= self._date - timedelta(7)) \ - .group_by(Okres.id) \ - .all() - - for wait in avg_waiting: - db.session.merge(OkresMetriky( - okres_id=wait.id, - datum=self._date, - registrace_prumer_cekani=wait.registrace_prumer_cekani - )) - - success_ratio_7 = db.session.query( - Okres.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_tydenni_uspesnost') - ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(7)) \ - .group_by(Okres.id) \ - .all() - - for ratio in success_ratio_7: - db.session.merge(OkresMetriky( - okres_id=ratio.id, - datum=self._date, - registrace_tydenni_uspesnost=ratio.registrace_tydenni_uspesnost - )) - - success_ratio_14 = db.session.query( - Okres.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_14denni_uspesnost') - ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(14)) \ - .group_by(Okres.id) \ - .all() - - for ratio in success_ratio_14: - db.session.merge(OkresMetriky( - okres_id=ratio.id, - datum=self._date, - registrace_14denni_uspesnost=ratio.registrace_14denni_uspesnost - )) - - success_ratio_30 = db.session.query( - Okres.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_30denni_uspesnost') - ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(30)) \ - .group_by(Okres.id) \ - .all() - - for ratio in success_ratio_30: - db.session.merge(OkresMetriky( - okres_id=ratio.id, - datum=self._date, - registrace_30denni_uspesnost=ratio.registrace_30denni_uspesnost - )) - - app.logger.info('Computing okres metrics - derived metrics finished.') - - def _compute_okres_deltas(self): - """Computes deltas for previous metrics for each okres.""" - db.session.execute(text( - """ - update okresy_metriky t - set rezervace_celkem_zmena_den = t0.rezervace_celkem - t1.rezervace_celkem, - rezervace_cekajici_zmena_den = t0.rezervace_cekajici - t1.rezervace_cekajici, - rezervace_kapacita_zmena_den = t0.rezervace_kapacita - t1.rezervace_kapacita, - registrace_celkem_zmena_den = t0.registrace_celkem - t1.registrace_celkem, - registrace_fronta_zmena_den = t0.registrace_fronta - t1.registrace_fronta, - registrace_tydenni_uspesnost_zmena_den = t0.registrace_tydenni_uspesnost - t1.registrace_tydenni_uspesnost, - registrace_14denni_uspesnost_zmena_den = t0.registrace_14denni_uspesnost - t1.registrace_14denni_uspesnost, - registrace_30denni_uspesnost_zmena_den = t0.registrace_30denni_uspesnost - t1.registrace_30denni_uspesnost, - registrace_prumer_cekani_zmena_den = t0.registrace_prumer_cekani - t1.registrace_prumer_cekani, - vakciny_prijate_pocet_zmena_den = t0.vakciny_prijate_pocet - t1.vakciny_prijate_pocet, - vakciny_ockovane_pocet_zmena_den = t0.vakciny_ockovane_pocet - t1.vakciny_ockovane_pocet, - vakciny_znicene_pocet_zmena_den = t0.vakciny_znicene_pocet - t1.vakciny_znicene_pocet - from okresy_metriky t0 - join okresy_metriky t1 - on t0.okres_id = t1.okres_id - where t.okres_id = t0.okres_id and t.datum = :datum and t0.datum = :datum and t1.datum = :datum_1 - """ - ), {'datum': self._date, 'datum_1': self._date - timedelta(1)}) - - db.session.execute(text( - """ - update okresy_metriky t - set rezervace_celkem_zmena_tyden = t0.rezervace_celkem - t7.rezervace_celkem, - rezervace_cekajici_zmena_tyden = t0.rezervace_cekajici - t7.rezervace_cekajici, - rezervace_kapacita_zmena_tyden = t0.rezervace_kapacita - t7.rezervace_kapacita, - registrace_celkem_zmena_tyden = t0.registrace_celkem - t7.registrace_celkem, - registrace_fronta_zmena_tyden = t0.registrace_fronta - t7.registrace_fronta, - registrace_tydenni_uspesnost_zmena_tyden = t0.registrace_tydenni_uspesnost - t7.registrace_tydenni_uspesnost, - registrace_14denni_uspesnost_zmena_tyden = t0.registrace_14denni_uspesnost - t7.registrace_14denni_uspesnost, - registrace_30denni_uspesnost_zmena_tyden = t0.registrace_30denni_uspesnost - t7.registrace_30denni_uspesnost, - registrace_prumer_cekani_zmena_tyden = t0.registrace_prumer_cekani - t7.registrace_prumer_cekani, - vakciny_prijate_pocet_zmena_tyden = t0.vakciny_prijate_pocet - t7.vakciny_prijate_pocet, - vakciny_ockovane_pocet_zmena_tyden = t0.vakciny_ockovane_pocet - t7.vakciny_ockovane_pocet, - vakciny_znicene_pocet_zmena_tyden = t0.vakciny_znicene_pocet - t7.vakciny_znicene_pocet - from okresy_metriky t0 - join okresy_metriky t7 - on t0.okres_id = t7.okres_id - where t.okres_id = t0.okres_id and t.datum = :datum and t0.datum = :datum and t7.datum = :datum_7 - """ - ), {'datum': self._date, 'datum_7': self._date - timedelta(7)}) - - app.logger.info('Computing okres metrics - deltas finished.') - - def _compute_kraj_population(self): - """Computes metrics based on population for each okres.""" - population = db.session.query( - Kraj.id, func.sum(Populace.pocet).label('pocet_obyvatel_celkem'), - func.sum(case([(Populace.vek >= 18, Populace.pocet)], else_=0)).label('pocet_obyvatel_dospeli') - ).join(Populace, Populace.orp_kod == Kraj.id) \ - .group_by(Kraj.id) - - for pop in population: - db.session.merge(KrajMetriky( - kraj_id=pop.id, - datum=self._date, - pocet_obyvatel_celkem=pop.pocet_obyvatel_celkem, - pocet_obyvatel_dospeli=pop.pocet_obyvatel_dospeli - )) - - app.logger.info('Computing kraj metrics - population finished.') - - def _compute_kraj_registrations(self): - """Computes metrics based on registrations dataset for each kraj.""" - registrations = db.session.query( - Kraj.id, func.sum(OckovaciMistoMetriky.registrace_celkem).label('registrace_celkem'), - func.sum(OckovaciMistoMetriky.registrace_fronta).label("registrace_fronta") - ).join(Okres, Okres.kraj_id == Kraj.id) \ - .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(Kraj.id) \ - .all() - - for registration in registrations: - db.session.merge(KrajMetriky( - kraj_id=registration.id, - datum=self._date, - registrace_celkem=registration.registrace_celkem, - registrace_fronta=registration.registrace_fronta - )) - - app.logger.info('Computing kraj metrics - registrations finished.') - - def _compute_kraj_reservations(self): - """Computes metrics based on reservations dataset for each kraj.""" - reservations = db.session.query( - Kraj.id, func.sum(OckovaciMistoMetriky.rezervace_celkem).label('rezervace_celkem'), - func.sum(OckovaciMistoMetriky.rezervace_cekajici).label("rezervace_cekajici"), - func.sum(OckovaciMistoMetriky.rezervace_kapacita).label("rezervace_kapacita") - ).join(Okres, Okres.kraj_id == Kraj.id) \ - .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(Kraj.id) \ - .all() - - for reservation in reservations: - db.session.merge(KrajMetriky( - kraj_id=reservation.id, - datum=self._date, - rezervace_celkem=reservation.rezervace_celkem, - rezervace_cekajici=reservation.rezervace_cekajici, - rezervace_kapacita=reservation.rezervace_kapacita - )) - - app.logger.info('Computing kraj metrics - reservations finished.') - - def _compute_kraj_vaccinated(self): - """Computes metrics based on vaccinated people dataset for each kraj.""" - vaccinated = db.session.query( - Kraj.id, func.coalesce(func.sum(OckovaniLide.pocet), 0).label('ockovani_pocet'), - func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 1, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_1'), - func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 2, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_2') - ).outerjoin(OckovaniLide, and_(OckovaniLide.kraj_nuts_kod == Kraj.id, OckovaniLide.datum < self._date)) \ - .group_by(Kraj.id) \ - .all() - - for vacc in vaccinated: - db.session.merge(KrajMetriky( - kraj_id=vacc.id, - datum=self._date, - ockovani_pocet=vacc.ockovani_pocet, - ockovani_pocet_1=vacc.ockovani_pocet_1, - ockovani_pocet_2=vacc.ockovani_pocet_2 - )) - - app.logger.info('Computing kraj metrics - vaccinated people finished.') - - def _compute_kraj_distributed(self): - """Computes metrics based on distributed vaccines dataset for each kraj.""" - distributed = db.session.query( - Kraj.id, func.sum(OckovaciMistoMetriky.vakciny_prijate_pocet).label('vakciny_prijate_pocet') - ).join(Okres, Okres.kraj_id == Kraj.id) \ - .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(Kraj.id) \ - .all() - - for dist in distributed: - db.session.merge(KrajMetriky( - kraj_id=dist.id, - datum=self._date, - vakciny_prijate_pocet=dist.vakciny_prijate_pocet - )) - - app.logger.info('Computing kraj metrics - distributed vaccines finished.') - - def _compute_kraj_used(self): - """Computes metrics based on used vaccines dataset for each kraj.""" - used = db.session.query( - Kraj.id, func.sum(OckovaciMistoMetriky.vakciny_ockovane_pocet).label('vakciny_ockovane_pocet'), - func.sum(OckovaciMistoMetriky.vakciny_znicene_pocet).label("vakciny_znicene_pocet") - ).join(Okres, Okres.kraj_id == Kraj.id) \ - .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ - .filter(OckovaciMistoMetriky.datum == self._date) \ - .group_by(Kraj.id) \ - .all() - - for use in used: - db.session.merge(KrajMetriky( - kraj_id=use.id, - datum=self._date, - vakciny_ockovane_pocet=use.vakciny_ockovane_pocet, - vakciny_znicene_pocet=use.vakciny_znicene_pocet - )) - - app.logger.info('Computing kraj metrics - used vaccines finished.') - - def _compute_kraj_derived(self): - """Computes metrics derived from the previous metrics for each kraj.""" - avg_waiting = db.session.query( - Kraj.id, - (func.sum( - (OckovaniRegistrace.datum_rezervace - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) / func.sum( - OckovaniRegistrace.pocet)).label('registrace_prumer_cekani'), - ).join(Okres, Okres.kraj_id == Kraj.id) \ - .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum_rezervace >= self._date - timedelta(7)) \ - .group_by(Kraj.id) \ - .all() - - for wait in avg_waiting: - db.session.merge(KrajMetriky( - kraj_id=wait.id, - datum=self._date, - registrace_prumer_cekani=wait.registrace_prumer_cekani - )) - - success_ratio_7 = db.session.query( - Kraj.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_tydenni_uspesnost') - ).join(Okres, Okres.kraj_id == Kraj.id) \ - .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(7)) \ - .group_by(Kraj.id) \ - .all() - - for ratio in success_ratio_7: - db.session.merge(KrajMetriky( - kraj_id=ratio.id, - datum=self._date, - registrace_tydenni_uspesnost=ratio.registrace_tydenni_uspesnost - )) - - success_ratio_14 = db.session.query( - Kraj.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_14denni_uspesnost') - ).join(Okres, Okres.kraj_id == Kraj.id) \ - .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(14)) \ - .group_by(Kraj.id) \ - .all() - - for ratio in success_ratio_14: - db.session.merge(KrajMetriky( - kraj_id=ratio.id, - datum=self._date, - registrace_14denni_uspesnost=ratio.registrace_14denni_uspesnost - )) - - success_ratio_30 = db.session.query( - Kraj.id, - (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) - / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_30denni_uspesnost') - ).join(Okres, Okres.kraj_id == Kraj.id) \ - .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ - .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ - .filter(OckovaniRegistrace.import_id == self._import_id) \ - .filter(OckovaniRegistrace.datum >= self._date - timedelta(30)) \ - .group_by(Kraj.id) \ - .all() - - for ratio in success_ratio_30: - db.session.merge(KrajMetriky( - kraj_id=ratio.id, - datum=self._date, - registrace_30denni_uspesnost=ratio.registrace_30denni_uspesnost - )) - - vacc_skladem = db.session.query( - Kraj.id, (KrajMetriky.vakciny_prijate_pocet - KrajMetriky.ockovani_pocet - - KrajMetriky.vakciny_znicene_pocet).label('vakciny_skladem_pocet') - ).join(KrajMetriky, Kraj.id == KrajMetriky.kraj_id) \ - .filter(KrajMetriky.datum == self._date) \ - .group_by(Kraj.id, KrajMetriky.vakciny_prijate_pocet, KrajMetriky.ockovani_pocet, - KrajMetriky.vakciny_znicene_pocet) \ - .all() - - for vacc in vacc_skladem: - db.session.merge(KrajMetriky( - kraj_id=vacc.id, - datum=self._date, - vakciny_skladem_pocet=vacc.vakciny_skladem_pocet - )) - - app.logger.info('Computing kraj metrics - derived metrics finished.') - - def _compute_kraj_deltas(self): - """Computes deltas for previous metrics for each kraj.""" - db.session.execute(text( - """ - update kraje_metriky t - set rezervace_celkem_zmena_den = t0.rezervace_celkem - t1.rezervace_celkem, - rezervace_cekajici_zmena_den = t0.rezervace_cekajici - t1.rezervace_cekajici, - rezervace_kapacita_zmena_den = t0.rezervace_kapacita - t1.rezervace_kapacita, - registrace_celkem_zmena_den = t0.registrace_celkem - t1.registrace_celkem, - registrace_fronta_zmena_den = t0.registrace_fronta - t1.registrace_fronta, - registrace_tydenni_uspesnost_zmena_den = t0.registrace_tydenni_uspesnost - t1.registrace_tydenni_uspesnost, - registrace_14denni_uspesnost_zmena_den = t0.registrace_14denni_uspesnost - t1.registrace_14denni_uspesnost, - registrace_30denni_uspesnost_zmena_den = t0.registrace_30denni_uspesnost - t1.registrace_30denni_uspesnost, - registrace_prumer_cekani_zmena_den = t0.registrace_prumer_cekani - t1.registrace_prumer_cekani, - ockovani_pocet_zmena_den = t0.ockovani_pocet - t1.ockovani_pocet, - ockovani_pocet_1_zmena_den = t0.ockovani_pocet_1 - t1.ockovani_pocet_1, - ockovani_pocet_2_zmena_den = t0.ockovani_pocet_2 - t1.ockovani_pocet_2, - vakciny_prijate_pocet_zmena_den = t0.vakciny_prijate_pocet - t1.vakciny_prijate_pocet, - vakciny_ockovane_pocet_zmena_den = t0.vakciny_ockovane_pocet - t1.vakciny_ockovane_pocet, - vakciny_znicene_pocet_zmena_den = t0.vakciny_znicene_pocet - t1.vakciny_znicene_pocet, - vakciny_skladem_pocet_zmena_den = t0.vakciny_skladem_pocet - t1.vakciny_skladem_pocet - from kraje_metriky t0 - join kraje_metriky t1 - on t0.kraj_id = t1.kraj_id - where t.kraj_id = t0.kraj_id and t.datum = :datum and t0.datum = :datum and t1.datum = :datum_1 - """ - ), {'datum': self._date, 'datum_1': self._date - timedelta(1)}) - - db.session.execute(text( - """ - update kraje_metriky t - set rezervace_celkem_zmena_tyden = t0.rezervace_celkem - t7.rezervace_celkem, - rezervace_cekajici_zmena_tyden = t0.rezervace_cekajici - t7.rezervace_cekajici, - rezervace_kapacita_zmena_tyden = t0.rezervace_kapacita - t7.rezervace_kapacita, - registrace_celkem_zmena_tyden = t0.registrace_celkem - t7.registrace_celkem, - registrace_fronta_zmena_tyden = t0.registrace_fronta - t7.registrace_fronta, - registrace_tydenni_uspesnost_zmena_tyden = t0.registrace_tydenni_uspesnost - t7.registrace_tydenni_uspesnost, - registrace_14denni_uspesnost_zmena_tyden = t0.registrace_14denni_uspesnost - t7.registrace_14denni_uspesnost, - registrace_30denni_uspesnost_zmena_tyden = t0.registrace_30denni_uspesnost - t7.registrace_30denni_uspesnost, - registrace_prumer_cekani_zmena_tyden = t0.registrace_prumer_cekani - t7.registrace_prumer_cekani, - ockovani_pocet_zmena_tyden = t0.ockovani_pocet - t7.ockovani_pocet, - ockovani_pocet_1_zmena_tyden = t0.ockovani_pocet_1 - t7.ockovani_pocet_1, - ockovani_pocet_2_zmena_tyden = t0.ockovani_pocet_2 - t7.ockovani_pocet_2, - vakciny_prijate_pocet_zmena_tyden = t0.vakciny_prijate_pocet - t7.vakciny_prijate_pocet, - vakciny_ockovane_pocet_zmena_tyden = t0.vakciny_ockovane_pocet - t7.vakciny_ockovane_pocet, - vakciny_znicene_pocet_zmena_tyden = t0.vakciny_znicene_pocet - t7.vakciny_znicene_pocet, - vakciny_skladem_pocet_zmena_tyden = t0.vakciny_skladem_pocet - t7.vakciny_skladem_pocet - from kraje_metriky t0 - join kraje_metriky t7 - on t0.kraj_id = t7.kraj_id - where t.kraj_id = t0.kraj_id and t.datum = :datum and t0.datum = :datum and t7.datum = :datum_7 - """ - ), {'datum': self._date, 'datum_7': self._date - timedelta(7)}) - - app.logger.info('Computing kraj metrics - deltas finished.') - - def _find_import_id(self): - id_ = db.session.query(Import.id) \ - .filter(Import.date == self._date, Import.status == queries.STATUS_FINISHED) \ - .first() - - if id_ is None: - raise Exception("No data for date: '{0}'.".format(self._date)) - - return id_[0] - - -if __name__ == '__main__': - etl = Etl(date.today()) - etl.compute_all() \ No newline at end of file diff --git a/app/etl/__init__.py b/app/etl/__init__.py new file mode 100644 index 00000000..b2a7b79a --- /dev/null +++ b/app/etl/__init__.py @@ -0,0 +1 @@ +from app.etl.metrics_etl import MetricsEtl diff --git a/app/etl/center_metrics_etl.py b/app/etl/center_metrics_etl.py new file mode 100644 index 00000000..4ac6fd5b --- /dev/null +++ b/app/etl/center_metrics_etl.py @@ -0,0 +1,342 @@ +from datetime import timedelta + +from sqlalchemy import func, case, text, or_, and_ + +from app import db, app, queries +from app.models import OckovaciMisto, OckovaciMistoMetriky, OckovaniRegistrace, OckovaniRezervace, OckovaniLide, \ + OckovaniDistribuce, OckovaniSpotreba + + +class CenterMetricsEtl: + """Class for computing metrics for vaccination centers.""" + + def __init__(self, date_, import_id): + self._date = date_ + self._import_id = import_id + + def compute_all(self): + self._compute_center_registrations() + self._compute_center_reservations() + self._compute_center_vaccinated() + self._compute_center_distributed() + self._compute_center_used() + self._compute_center_derived() + self._compute_center_deltas() + + def _compute_center_registrations(self): + """Computes metrics based on registrations dataset for each vaccination center.""" + registrations = db.session.query( + OckovaciMisto.id, func.coalesce(func.sum(OckovaniRegistrace.pocet), 0).label('registrace_celkem'), + func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == False, OckovaniRegistrace.pocet)], else_=0)), 0).label("registrace_fronta") + ).outerjoin(OckovaniRegistrace, and_(OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id, OckovaniRegistrace.import_id == self._import_id)) \ + .group_by(OckovaciMisto.id) \ + .all() + + for registration in registrations: + db.session.merge(OckovaciMistoMetriky( + misto_id=registration.id, + datum=self._date, + registrace_celkem=registration.registrace_celkem, + registrace_fronta=registration.registrace_fronta + )) + + app.logger.info('Computing vaccination centers metrics - registrations finished.') + + def _compute_center_reservations(self): + """Computes metrics based on reservations dataset for each vaccination center.""" + reservations = db.session.query( + OckovaciMisto.id, + func.coalesce(func.sum(OckovaniRezervace.maximalni_kapacita - OckovaniRezervace.volna_kapacita), 0).label('rezervace_celkem'), + func.coalesce(func.sum(case([(OckovaniRezervace.datum >= self._date, OckovaniRezervace.maximalni_kapacita - OckovaniRezervace.volna_kapacita)], else_=0)), 0).label("rezervace_cekajici"), + func.coalesce(func.sum(case([(OckovaniRezervace.datum == self._date, OckovaniRezervace.maximalni_kapacita)], else_=0)), 0).label("rezervace_kapacita"), + func.coalesce(func.sum(case([(and_(OckovaniRezervace.datum == self._date, OckovaniRezervace.kalendar_ockovani == 'V1'), OckovaniRezervace.maximalni_kapacita)], else_=0)), 0).label("rezervace_kapacita_1"), + func.min(case([(and_(OckovaniRezervace.datum >= self._date, OckovaniRezervace.kalendar_ockovani == 'V1', OckovaniRezervace.volna_kapacita > 0), OckovaniRezervace.datum)], else_=None)).label("rezervace_nejblizsi_volno") + ).outerjoin(OckovaniRezervace, and_(OckovaciMisto.id == OckovaniRezervace.ockovaci_misto_id, OckovaniRezervace.import_id == self._import_id)) \ + .group_by(OckovaciMisto.id) \ + .all() + + for reservation in reservations: + db.session.merge(OckovaciMistoMetriky( + misto_id=reservation.id, + datum=self._date, + rezervace_celkem=reservation.rezervace_celkem, + rezervace_cekajici=reservation.rezervace_cekajici, + rezervace_kapacita=reservation.rezervace_kapacita, + rezervace_kapacita_1=reservation.rezervace_kapacita_1, + rezervace_nejblizsi_volno=reservation.rezervace_nejblizsi_volno + )) + + app.logger.info('Computing vaccination centers metrics - reservations finished.') + + def _compute_center_vaccinated(self): + """Computes metrics based on vaccinated people dataset for each vaccination center.""" + vaccinated = db.session.query(OckovaciMisto.id, func.coalesce(func.sum(OckovaniLide.pocet), 0).label('ockovani_pocet_davek'), + func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 1, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_castecne'), + func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 2, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_plne')) \ + .outerjoin(OckovaniLide, and_(OckovaciMisto.nrpzs_kod == OckovaniLide.zarizeni_kod, OckovaniLide.datum < self._date)) \ + .filter(OckovaciMisto.nrpzs_kod.in_(queries.unique_nrpzs_subquery())) \ + .group_by(OckovaciMisto.id) \ + .all() + + for vacc in vaccinated: + db.session.merge(OckovaciMistoMetriky( + misto_id=vacc.id, + datum=self._date, + ockovani_pocet_davek=vacc.ockovani_pocet_davek, + ockovani_pocet_castecne=vacc.ockovani_pocet_castecne, + ockovani_pocet_plne=vacc.ockovani_pocet_plne + )) + + app.logger.info('Computing vaccination centers metrics - vaccinated people finished.') + + def _compute_center_distributed(self): + """Computes metrics based on distributed vaccines dataset for each vaccination center.""" + distributed = db.session.query( + OckovaciMisto.id, ( + func.coalesce(func.sum(case([(and_(OckovaciMisto.id == OckovaniDistribuce.ockovaci_misto_id, OckovaniDistribuce.akce == 'Příjem'), OckovaniDistribuce.pocet_davek)], else_=0)), 0) + + func.coalesce(func.sum(case([(and_(OckovaciMisto.id == OckovaniDistribuce.cilove_ockovaci_misto_id, OckovaniDistribuce.akce == 'Výdej'), OckovaniDistribuce.pocet_davek)], else_=0)), 0) + - func.coalesce(func.sum(case([(and_(OckovaciMisto.id == OckovaniDistribuce.ockovaci_misto_id, OckovaniDistribuce.akce == 'Výdej'), OckovaniDistribuce.pocet_davek)], else_=0)), 0)) + .label('vakciny_prijate_pocet') + ).outerjoin(OckovaniDistribuce, and_( + or_(OckovaciMisto.id == OckovaniDistribuce.ockovaci_misto_id, OckovaciMisto.id == OckovaniDistribuce.cilove_ockovaci_misto_id), + OckovaniDistribuce.datum < self._date + )) \ + .group_by(OckovaciMisto.id) \ + .all() + + for dist in distributed: + db.session.merge(OckovaciMistoMetriky( + misto_id=dist.id, + datum=self._date, + vakciny_prijate_pocet=dist.vakciny_prijate_pocet + )) + + app.logger.info('Computing vaccination centers metrics - distributed vaccines finished.') + + def _compute_center_used(self): + """Computes metrics based on used vaccines dataset for each vaccination center.""" + used = db.session.query( + OckovaciMisto.id, + func.coalesce(func.sum(OckovaniSpotreba.pouzite_davky), 0).label('vakciny_ockovane_pocet'), + func.coalesce(func.sum(OckovaniSpotreba.znehodnocene_davky), 0).label('vakciny_znicene_pocet') + ).outerjoin(OckovaniSpotreba, and_(OckovaciMisto.id == OckovaniSpotreba.ockovaci_misto_id, OckovaniSpotreba.datum < self._date)) \ + .group_by(OckovaciMisto.id) \ + .all() + + for use in used: + db.session.merge(OckovaciMistoMetriky( + misto_id=use.id, + datum=self._date, + vakciny_ockovane_pocet=use.vakciny_ockovane_pocet, + vakciny_znicene_pocet=use.vakciny_znicene_pocet + )) + + app.logger.info('Computing vaccination centers metrics - used vaccines finished.') + + def _compute_center_derived(self): + """Computes metrics derived from the previous metrics for each vaccination center.""" + avg_waiting = db.session.query( + OckovaciMisto.id, + (func.sum((OckovaniRegistrace.datum_rezervace - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) + / func.sum(OckovaniRegistrace.pocet)).label('registrace_prumer_cekani'), + ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum_rezervace >= self._date - timedelta(7)) \ + .group_by(OckovaciMisto.id) \ + .all() + + for wait in avg_waiting: + db.session.merge(OckovaciMistoMetriky( + misto_id=wait.id, + datum=self._date, + registrace_prumer_cekani=wait.registrace_prumer_cekani + )) + + avg_queue_waiting = db.session.query( + OckovaciMisto.id, + (func.sum((self._date - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) + / func.sum(OckovaniRegistrace.pocet)).label('registrace_fronta_prumer_cekani'), + ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.rezervace == False) \ + .group_by(OckovaciMisto.id) \ + .all() + + for queue_wait in avg_queue_waiting: + db.session.merge(OckovaciMistoMetriky( + misto_id=queue_wait.id, + datum=self._date, + registrace_fronta_prumer_cekani=queue_wait.registrace_fronta_prumer_cekani + )) + + est_waiting = db.session.query("id", "registrace_odhad_cekani").from_statement(text( + """ + select id, 7.0 * sum(case when rezervace = false then pocet else 0 end) + / nullif(sum(case when rezervace = true and datum_rezervace >= :datum_7 then pocet else 0 end), 0) + registrace_odhad_cekani + from ockovaci_mista + join ockovani_registrace on id = ockovaci_misto_id + where import_id = :import_id + group by (id) + """ + )).params(datum_7=self._date - timedelta(7), import_id=self._import_id) \ + .all() + + for wait in est_waiting: + db.session.merge(OckovaciMistoMetriky( + misto_id=wait.id, + datum=self._date, + registrace_odhad_cekani=wait.registrace_odhad_cekani + )) + + success_ratio_7 = db.session.query( + OckovaciMisto.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_tydenni_uspesnost') + ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(7)) \ + .group_by(OckovaciMisto.id) \ + .all() + + for ratio in success_ratio_7: + db.session.merge(OckovaciMistoMetriky( + misto_id=ratio.id, + datum=self._date, + registrace_tydenni_uspesnost=ratio.registrace_tydenni_uspesnost + )) + + success_ratio_14 = db.session.query( + OckovaciMisto.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_14denni_uspesnost') + ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(14)) \ + .group_by(OckovaciMisto.id) \ + .all() + + for ratio in success_ratio_14: + db.session.merge(OckovaciMistoMetriky( + misto_id=ratio.id, + datum=self._date, + registrace_14denni_uspesnost=ratio.registrace_14denni_uspesnost + )) + + success_ratio_30 = db.session.query( + OckovaciMisto.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_30denni_uspesnost') + ).join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(30)) \ + .group_by(OckovaciMisto.id) \ + .all() + + for ratio in success_ratio_30: + db.session.merge(OckovaciMistoMetriky( + misto_id=ratio.id, + datum=self._date, + registrace_30denni_uspesnost=ratio.registrace_30denni_uspesnost + )) + + vacc_est_waiting = db.session.query( + OckovaciMisto.id, + (7.0 * (OckovaciMistoMetriky.registrace_fronta + OckovaciMistoMetriky.rezervace_cekajici) + / case([(func.sum(OckovaniLide.pocet) > 0, func.sum(OckovaniLide.pocet))], else_=None)).label('ockovani_odhad_cekani') + ).join(OckovaciMistoMetriky, OckovaciMisto.id == OckovaciMistoMetriky.misto_id) \ + .join(OckovaniLide, OckovaciMisto.nrpzs_kod == OckovaniLide.zarizeni_kod) \ + .filter(OckovaciMistoMetriky.datum == self._date) \ + .filter(OckovaciMisto.nrpzs_kod.in_(queries.unique_nrpzs_subquery())) \ + .filter(OckovaniLide.datum < self._date, OckovaniLide.datum >= self._date - timedelta(7)) \ + .group_by(OckovaciMisto.id, OckovaciMistoMetriky.registrace_fronta, OckovaciMistoMetriky.rezervace_cekajici) \ + .all() + + for wait in vacc_est_waiting: + db.session.merge(OckovaciMistoMetriky( + misto_id=wait.id, + datum=self._date, + ockovani_odhad_cekani=wait.ockovani_odhad_cekani + )) + + vacc_skladem = db.session.query( + OckovaciMisto.id, (OckovaciMistoMetriky.vakciny_prijate_pocet - OckovaciMistoMetriky.vakciny_ockovane_pocet + - OckovaciMistoMetriky.vakciny_znicene_pocet).label('vakciny_skladem_pocet') + ).join(OckovaciMistoMetriky, OckovaciMisto.id == OckovaciMistoMetriky.misto_id) \ + .filter(OckovaciMistoMetriky.datum == self._date) \ + .group_by(OckovaciMisto.id, OckovaciMistoMetriky.vakciny_prijate_pocet, OckovaciMistoMetriky.vakciny_ockovane_pocet, + OckovaciMistoMetriky.vakciny_znicene_pocet) \ + .all() + + for vacc in vacc_skladem: + db.session.merge(OckovaciMistoMetriky( + misto_id=vacc.id, + datum=self._date, + vakciny_skladem_pocet=vacc.vakciny_skladem_pocet + )) + + app.logger.info('Computing vaccination centers metrics - derived metrics finished.') + + def _compute_center_deltas(self): + """Computes deltas for previous metrics for each vaccination center.""" + db.session.execute(text( + """ + update ockovaci_mista_metriky t + set rezervace_celkem_zmena_den = t0.rezervace_celkem - t1.rezervace_celkem, + rezervace_cekajici_zmena_den = t0.rezervace_cekajici - t1.rezervace_cekajici, + rezervace_kapacita_zmena_den = t0.rezervace_kapacita - t1.rezervace_kapacita, + rezervace_kapacita_1_zmena_den = t0.rezervace_kapacita_1 - t1.rezervace_kapacita_1, + registrace_celkem_zmena_den = t0.registrace_celkem - t1.registrace_celkem, + registrace_fronta_zmena_den = t0.registrace_fronta - t1.registrace_fronta, + registrace_tydenni_uspesnost_zmena_den = t0.registrace_tydenni_uspesnost - t1.registrace_tydenni_uspesnost, + registrace_14denni_uspesnost_zmena_den = t0.registrace_14denni_uspesnost - t1.registrace_14denni_uspesnost, + registrace_30denni_uspesnost_zmena_den = t0.registrace_30denni_uspesnost - t1.registrace_30denni_uspesnost, + registrace_prumer_cekani_zmena_den = t0.registrace_prumer_cekani - t1.registrace_prumer_cekani, + registrace_odhad_cekani_zmena_den = t0.registrace_odhad_cekani - t1.registrace_odhad_cekani, + registrace_fronta_prumer_cekani_zmena_den = t0.registrace_fronta_prumer_cekani - t1.registrace_fronta_prumer_cekani, + ockovani_pocet_davek_zmena_den = t0.ockovani_pocet_davek - t1.ockovani_pocet_davek, + ockovani_pocet_castecne_zmena_den = t0.ockovani_pocet_castecne - t1.ockovani_pocet_castecne, + ockovani_pocet_plne_zmena_den = t0.ockovani_pocet_plne - t1.ockovani_pocet_plne, + ockovani_odhad_cekani_zmena_den = t0.ockovani_odhad_cekani - t1.ockovani_odhad_cekani, + vakciny_prijate_pocet_zmena_den = t0.vakciny_prijate_pocet - t1.vakciny_prijate_pocet, + vakciny_ockovane_pocet_zmena_den = t0.vakciny_ockovane_pocet - t1.vakciny_ockovane_pocet, + vakciny_znicene_pocet_zmena_den = t0.vakciny_znicene_pocet - t1.vakciny_znicene_pocet, + vakciny_skladem_pocet_zmena_den = t0.vakciny_skladem_pocet - t1.vakciny_skladem_pocet + from ockovaci_mista_metriky t0 + join ockovaci_mista_metriky t1 + on t0.misto_id = t1.misto_id + where t.misto_id = t0.misto_id and t.datum = :datum and t0.datum = :datum and t1.datum = :datum_1 + """ + ), {'datum': self._date, 'datum_1': self._date - timedelta(1)}) + + db.session.execute(text( + """ + update ockovaci_mista_metriky t + set rezervace_celkem_zmena_tyden = t0.rezervace_celkem - t7.rezervace_celkem, + rezervace_cekajici_zmena_tyden = t0.rezervace_cekajici - t7.rezervace_cekajici, + rezervace_kapacita_zmena_tyden = t0.rezervace_kapacita - t7.rezervace_kapacita, + rezervace_kapacita_1_zmena_tyden = t0.rezervace_kapacita_1 - t7.rezervace_kapacita_1, + registrace_celkem_zmena_tyden = t0.registrace_celkem - t7.registrace_celkem, + registrace_fronta_zmena_tyden = t0.registrace_fronta - t7.registrace_fronta, + registrace_tydenni_uspesnost_zmena_tyden = t0.registrace_tydenni_uspesnost - t7.registrace_tydenni_uspesnost, + registrace_14denni_uspesnost_zmena_tyden = t0.registrace_14denni_uspesnost - t7.registrace_14denni_uspesnost, + registrace_30denni_uspesnost_zmena_tyden = t0.registrace_30denni_uspesnost - t7.registrace_30denni_uspesnost, + registrace_prumer_cekani_zmena_tyden = t0.registrace_prumer_cekani - t7.registrace_prumer_cekani, + registrace_odhad_cekani_zmena_tyden = t0.registrace_odhad_cekani - t7.registrace_odhad_cekani, + registrace_fronta_prumer_cekani_zmena_tyden = t0.registrace_fronta_prumer_cekani - t7.registrace_fronta_prumer_cekani, + ockovani_pocet_davek_zmena_tyden = t0.ockovani_pocet_davek - t7.ockovani_pocet_davek, + ockovani_pocet_castecne_zmena_tyden = t0.ockovani_pocet_castecne - t7.ockovani_pocet_castecne, + ockovani_pocet_plne_zmena_tyden = t0.ockovani_pocet_plne - t7.ockovani_pocet_plne, + ockovani_odhad_cekani_zmena_tyden = t0.ockovani_odhad_cekani - t7.ockovani_odhad_cekani, + vakciny_prijate_pocet_zmena_tyden = t0.vakciny_prijate_pocet - t7.vakciny_prijate_pocet, + vakciny_ockovane_pocet_zmena_tyden = t0.vakciny_ockovane_pocet - t7.vakciny_ockovane_pocet, + vakciny_znicene_pocet_zmena_tyden = t0.vakciny_znicene_pocet - t7.vakciny_znicene_pocet, + vakciny_skladem_pocet_zmena_tyden = t0.vakciny_skladem_pocet - t7.vakciny_skladem_pocet + from ockovaci_mista_metriky t0 + join ockovaci_mista_metriky t7 + on t0.misto_id = t7.misto_id + where t.misto_id = t0.misto_id and t.datum = :datum and t0.datum = :datum and t7.datum = :datum_7 + """ + ), {'datum': self._date, 'datum_7': self._date - timedelta(7)}) + + app.logger.info('Computing vaccination centers metrics - deltas finished.') diff --git a/app/etl/cr_metrics_etl.py b/app/etl/cr_metrics_etl.py new file mode 100644 index 00000000..0902fc5a --- /dev/null +++ b/app/etl/cr_metrics_etl.py @@ -0,0 +1,256 @@ +from datetime import timedelta + +from sqlalchemy import func, case, text + +from app import db, app +from app.models import OckovaciMistoMetriky, OckovaniRegistrace, OckovaniLide, Populace, CrMetriky, OckovaniDistribuce + + +class CrMetricsEtl: + """Class for computing metrics for whole Czech republic.""" + + def __init__(self, date_, import_id): + self._date = date_ + self._import_id = import_id + + def compute_all(self): + self._compute_cr_population() + self._compute_cr_registrations() + self._compute_cr_reservations() + self._compute_cr_vaccinated() + self._compute_cr_distributed() + self._compute_cr_used() + self._compute_cr_derived() + self._compute_cr_deltas() + + def _compute_cr_population(self): + """Computes metrics based on population for cr.""" + population = db.session.query( + func.sum(Populace.pocet).label('pocet_obyvatel_celkem'), + func.sum(case([(Populace.vek >= 18, Populace.pocet)], else_=0)).label('pocet_obyvatel_dospeli') + ).filter(Populace.orp_kod == 'CZ0') \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + pocet_obyvatel_celkem=population.pocet_obyvatel_celkem, + pocet_obyvatel_dospeli=population.pocet_obyvatel_dospeli + )) + + app.logger.info('Computing cr metrics - population finished.') + + def _compute_cr_registrations(self): + """Computes metrics based on registrations dataset for cr.""" + registrations = db.session.query( + func.sum(OckovaciMistoMetriky.registrace_celkem).label('registrace_celkem'), + func.sum(OckovaciMistoMetriky.registrace_fronta).label("registrace_fronta") + ).filter(OckovaciMistoMetriky.datum == self._date) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + registrace_celkem=registrations.registrace_celkem, + registrace_fronta=registrations.registrace_fronta + )) + + app.logger.info('Computing cr metrics - registrations finished.') + + def _compute_cr_reservations(self): + """Computes metrics based on reservations dataset for cr.""" + reservations = db.session.query( + func.sum(OckovaciMistoMetriky.rezervace_celkem).label('rezervace_celkem'), + func.sum(OckovaciMistoMetriky.rezervace_cekajici).label("rezervace_cekajici"), + func.sum(OckovaciMistoMetriky.rezervace_kapacita).label("rezervace_kapacita"), + func.sum(OckovaciMistoMetriky.rezervace_kapacita_1).label("rezervace_kapacita_1") + ).filter(OckovaciMistoMetriky.datum == self._date) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + rezervace_celkem=reservations.rezervace_celkem, + rezervace_cekajici=reservations.rezervace_cekajici, + rezervace_kapacita=reservations.rezervace_kapacita, + rezervace_kapacita_1=reservations.rezervace_kapacita_1 + )) + + app.logger.info('Computing cr metrics - reservations finished.') + + def _compute_cr_vaccinated(self): + """Computes metrics based on vaccinated people dataset for cr.""" + vaccinated = db.session.query( + func.coalesce(func.sum(OckovaniLide.pocet), 0).label('ockovani_pocet_davek'), + func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 1, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_castecne'), + func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 2, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_plne') + ).filter(OckovaniLide.datum < self._date) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + ockovani_pocet_davek=vaccinated.ockovani_pocet_davek, + ockovani_pocet_castecne=vaccinated.ockovani_pocet_castecne, + ockovani_pocet_plne=vaccinated.ockovani_pocet_plne + )) + + app.logger.info('Computing cr metrics - vaccinated people finished.') + + def _compute_cr_distributed(self): + """Computes metrics based on distributed vaccines dataset for cr.""" + distributed = db.session.query( + func.sum(case([(OckovaniDistribuce.akce == 'Příjem', OckovaniDistribuce.pocet_davek)], else_=0)).label('vakciny_prijate_pocet') + ).filter(OckovaniDistribuce.datum < self._date) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + vakciny_prijate_pocet=distributed.vakciny_prijate_pocet + )) + + app.logger.info('Computing cr metrics - distributed vaccines finished.') + + def _compute_cr_used(self): + """Computes metrics based on used vaccines dataset for cr.""" + used = db.session.query( + func.sum(OckovaciMistoMetriky.vakciny_ockovane_pocet).label('vakciny_ockovane_pocet'), + func.sum(OckovaciMistoMetriky.vakciny_znicene_pocet).label("vakciny_znicene_pocet") + ).filter(OckovaciMistoMetriky.datum == self._date) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + vakciny_ockovane_pocet=used.vakciny_ockovane_pocet, + vakciny_znicene_pocet=used.vakciny_znicene_pocet + )) + + app.logger.info('Computing cr metrics - used vaccines finished.') + + def _compute_cr_derived(self): + """Computes metrics derived from the previous metrics for cr.""" + avg_waiting = db.session.query( + (func.sum((OckovaniRegistrace.datum_rezervace - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) + / func.sum(OckovaniRegistrace.pocet)).label('registrace_prumer_cekani'), + ).filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum_rezervace >= self._date - timedelta(7)) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + registrace_prumer_cekani=avg_waiting.registrace_prumer_cekani + )) + + avg_queue_waiting = db.session.query( + (func.sum((self._date - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) + / func.sum(OckovaniRegistrace.pocet)).label('registrace_fronta_prumer_cekani'), + ).filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.rezervace == False) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + registrace_fronta_prumer_cekani=avg_queue_waiting.registrace_fronta_prumer_cekani + )) + + success_ratio_7 = db.session.query( + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_tydenni_uspesnost') + ).filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(7)) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + registrace_tydenni_uspesnost=success_ratio_7.registrace_tydenni_uspesnost + )) + + success_ratio_14 = db.session.query( + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_14denni_uspesnost') + ).filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(14)) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + registrace_14denni_uspesnost=success_ratio_14.registrace_14denni_uspesnost + )) + + success_ratio_30 = db.session.query( + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_30denni_uspesnost') + ).filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(30)) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + registrace_30denni_uspesnost=success_ratio_30.registrace_30denni_uspesnost + )) + + vacc_skladem = db.session.query( + (CrMetriky.vakciny_prijate_pocet - CrMetriky.ockovani_pocet_davek - CrMetriky.vakciny_znicene_pocet).label('vakciny_skladem_pocet') + ).filter(CrMetriky.datum == self._date) \ + .one() + + db.session.merge(CrMetriky( + datum=self._date, + vakciny_skladem_pocet=vacc_skladem.vakciny_skladem_pocet + )) + + app.logger.info('Computing cr metrics - derived metrics finished.') + + def _compute_cr_deltas(self): + """Computes deltas for previous metrics for cr.""" + db.session.execute(text( + """ + update cr_metriky t + set rezervace_celkem_zmena_den = t0.rezervace_celkem - t1.rezervace_celkem, + rezervace_cekajici_zmena_den = t0.rezervace_cekajici - t1.rezervace_cekajici, + rezervace_kapacita_zmena_den = t0.rezervace_kapacita - t1.rezervace_kapacita, + rezervace_kapacita_1_zmena_den = t0.rezervace_kapacita_1 - t1.rezervace_kapacita_1, + registrace_celkem_zmena_den = t0.registrace_celkem - t1.registrace_celkem, + registrace_fronta_zmena_den = t0.registrace_fronta - t1.registrace_fronta, + registrace_tydenni_uspesnost_zmena_den = t0.registrace_tydenni_uspesnost - t1.registrace_tydenni_uspesnost, + registrace_14denni_uspesnost_zmena_den = t0.registrace_14denni_uspesnost - t1.registrace_14denni_uspesnost, + registrace_30denni_uspesnost_zmena_den = t0.registrace_30denni_uspesnost - t1.registrace_30denni_uspesnost, + registrace_prumer_cekani_zmena_den = t0.registrace_prumer_cekani - t1.registrace_prumer_cekani, + registrace_fronta_prumer_cekani_zmena_den = t0.registrace_fronta_prumer_cekani - t1.registrace_fronta_prumer_cekani, + ockovani_pocet_davek_zmena_den = t0.ockovani_pocet_davek - t1.ockovani_pocet_davek, + ockovani_pocet_castecne_zmena_den = t0.ockovani_pocet_castecne - t1.ockovani_pocet_castecne, + ockovani_pocet_plne_zmena_den = t0.ockovani_pocet_plne - t1.ockovani_pocet_plne, + vakciny_prijate_pocet_zmena_den = t0.vakciny_prijate_pocet - t1.vakciny_prijate_pocet, + vakciny_ockovane_pocet_zmena_den = t0.vakciny_ockovane_pocet - t1.vakciny_ockovane_pocet, + vakciny_znicene_pocet_zmena_den = t0.vakciny_znicene_pocet - t1.vakciny_znicene_pocet, + vakciny_skladem_pocet_zmena_den = t0.vakciny_skladem_pocet - t1.vakciny_skladem_pocet + from cr_metriky t0 + cross join cr_metriky t1 + where t.datum = :datum and t0.datum = :datum and t1.datum = :datum_1 + """ + ), {'datum': self._date, 'datum_1': self._date - timedelta(1)}) + + db.session.execute(text( + """ + update cr_metriky t + set rezervace_celkem_zmena_tyden = t0.rezervace_celkem - t7.rezervace_celkem, + rezervace_cekajici_zmena_tyden = t0.rezervace_cekajici - t7.rezervace_cekajici, + rezervace_kapacita_zmena_tyden = t0.rezervace_kapacita - t7.rezervace_kapacita, + rezervace_kapacita_1_zmena_tyden = t0.rezervace_kapacita_1 - t7.rezervace_kapacita_1, + registrace_celkem_zmena_tyden = t0.registrace_celkem - t7.registrace_celkem, + registrace_fronta_zmena_tyden = t0.registrace_fronta - t7.registrace_fronta, + registrace_tydenni_uspesnost_zmena_tyden = t0.registrace_tydenni_uspesnost - t7.registrace_tydenni_uspesnost, + registrace_14denni_uspesnost_zmena_tyden = t0.registrace_14denni_uspesnost - t7.registrace_14denni_uspesnost, + registrace_30denni_uspesnost_zmena_tyden = t0.registrace_30denni_uspesnost - t7.registrace_30denni_uspesnost, + registrace_prumer_cekani_zmena_tyden = t0.registrace_prumer_cekani - t7.registrace_prumer_cekani, + registrace_fronta_prumer_cekani_zmena_tyden = t0.registrace_fronta_prumer_cekani - t7.registrace_fronta_prumer_cekani, + ockovani_pocet_davek_zmena_tyden = t0.ockovani_pocet_davek - t7.ockovani_pocet_davek, + ockovani_pocet_castecne_zmena_tyden = t0.ockovani_pocet_castecne - t7.ockovani_pocet_castecne, + ockovani_pocet_plne_zmena_tyden = t0.ockovani_pocet_plne - t7.ockovani_pocet_plne, + vakciny_prijate_pocet_zmena_tyden = t0.vakciny_prijate_pocet - t7.vakciny_prijate_pocet, + vakciny_ockovane_pocet_zmena_tyden = t0.vakciny_ockovane_pocet - t7.vakciny_ockovane_pocet, + vakciny_znicene_pocet_zmena_tyden = t0.vakciny_znicene_pocet - t7.vakciny_znicene_pocet, + vakciny_skladem_pocet_zmena_tyden = t0.vakciny_skladem_pocet - t7.vakciny_skladem_pocet + from cr_metriky t0 + cross join cr_metriky t7 + where t.datum = :datum and t0.datum = :datum and t7.datum = :datum_7 + """ + ), {'datum': self._date, 'datum_7': self._date - timedelta(7)}) + + app.logger.info('Computing cr metrics - deltas finished.') diff --git a/app/etl/kraj_metrics_etl.py b/app/etl/kraj_metrics_etl.py new file mode 100644 index 00000000..4125f79a --- /dev/null +++ b/app/etl/kraj_metrics_etl.py @@ -0,0 +1,353 @@ +from datetime import timedelta + +from sqlalchemy import func, case, text, and_ + +from app import db, app +from app.models import OckovaciMisto, OckovaciMistoMetriky, OckovaniRegistrace, OckovaniLide, Okres, Kraj, KrajMetriky, \ + Populace + + +class KrajMetricsEtl: + """Class for computing metrics for kraj.""" + + def __init__(self, date_, import_id): + self._date = date_ + self._import_id = import_id + + def compute_all(self): + self._compute_kraj_population() + self._compute_kraj_registrations() + self._compute_kraj_reservations() + self._compute_kraj_vaccinated() + self._compute_kraj_distributed() + self._compute_kraj_used() + self._compute_kraj_derived() + self._compute_kraj_deltas() + + def _compute_kraj_population(self): + """Computes metrics based on population for each kraj.""" + population = db.session.query( + Kraj.id, func.sum(Populace.pocet).label('pocet_obyvatel_celkem'), + func.sum(case([(Populace.vek >= 18, Populace.pocet)], else_=0)).label('pocet_obyvatel_dospeli') + ).join(Populace, Populace.orp_kod == Kraj.id) \ + .group_by(Kraj.id) + + for pop in population: + db.session.merge(KrajMetriky( + kraj_id=pop.id, + datum=self._date, + pocet_obyvatel_celkem=pop.pocet_obyvatel_celkem, + pocet_obyvatel_dospeli=pop.pocet_obyvatel_dospeli + )) + + app.logger.info('Computing kraj metrics - population finished.') + + def _compute_kraj_registrations(self): + """Computes metrics based on registrations dataset for each kraj.""" + registrations = db.session.query( + Kraj.id, func.sum(OckovaciMistoMetriky.registrace_celkem).label('registrace_celkem'), + func.sum(OckovaciMistoMetriky.registrace_fronta).label("registrace_fronta") + ).join(Okres, Okres.kraj_id == Kraj.id) \ + .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ + .filter(OckovaciMistoMetriky.datum == self._date) \ + .group_by(Kraj.id) \ + .all() + + for registration in registrations: + db.session.merge(KrajMetriky( + kraj_id=registration.id, + datum=self._date, + registrace_celkem=registration.registrace_celkem, + registrace_fronta=registration.registrace_fronta + )) + + app.logger.info('Computing kraj metrics - registrations finished.') + + def _compute_kraj_reservations(self): + """Computes metrics based on reservations dataset for each kraj.""" + reservations = db.session.query( + Kraj.id, func.sum(OckovaciMistoMetriky.rezervace_celkem).label('rezervace_celkem'), + func.sum(OckovaciMistoMetriky.rezervace_cekajici).label("rezervace_cekajici"), + func.sum(OckovaciMistoMetriky.rezervace_kapacita).label("rezervace_kapacita"), + func.sum(OckovaciMistoMetriky.rezervace_kapacita_1).label("rezervace_kapacita_1"), + func.min(OckovaciMistoMetriky.rezervace_nejblizsi_volno).label('rezervace_nejblizsi_volno') + ).join(Okres, Okres.kraj_id == Kraj.id) \ + .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ + .filter(OckovaciMistoMetriky.datum == self._date) \ + .group_by(Kraj.id) \ + .all() + + for reservation in reservations: + db.session.merge(KrajMetriky( + kraj_id=reservation.id, + datum=self._date, + rezervace_celkem=reservation.rezervace_celkem, + rezervace_cekajici=reservation.rezervace_cekajici, + rezervace_kapacita=reservation.rezervace_kapacita, + rezervace_kapacita_1=reservation.rezervace_kapacita_1, + rezervace_nejblizsi_volno=reservation.rezervace_nejblizsi_volno + )) + + app.logger.info('Computing kraj metrics - reservations finished.') + + def _compute_kraj_vaccinated(self): + """Computes metrics based on vaccinated people dataset for each kraj.""" + vaccinated = db.session.query( + Kraj.id, func.coalesce(func.sum(OckovaniLide.pocet), 0).label('ockovani_pocet_davek'), + func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 1, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_castecne'), + func.coalesce(func.sum(case([(OckovaniLide.poradi_davky == 2, OckovaniLide.pocet)], else_=0)), 0).label('ockovani_pocet_plne') + ).outerjoin(OckovaniLide, and_(OckovaniLide.kraj_nuts_kod == Kraj.id, OckovaniLide.datum < self._date)) \ + .group_by(Kraj.id) \ + .all() + + for vacc in vaccinated: + db.session.merge(KrajMetriky( + kraj_id=vacc.id, + datum=self._date, + ockovani_pocet_davek=vacc.ockovani_pocet_davek, + ockovani_pocet_castecne=vacc.ockovani_pocet_castecne, + ockovani_pocet_plne=vacc.ockovani_pocet_plne + )) + + app.logger.info('Computing kraj metrics - vaccinated people finished.') + + def _compute_kraj_distributed(self): + """Computes metrics based on distributed vaccines dataset for each kraj.""" + distributed = db.session.query("kraj_id", "vakciny_prijate_pocet").from_statement(text( + """ + select o.kraj_id kraj_id, ( + coalesce(sum(case + when akce = 'Příjem' + and d.ockovaci_misto_id in (select m1.id from ockovaci_mista m1 join okresy o1 on m1.okres_id = o1.id where o1.kraj_id = o.kraj_id) + then pocet_davek + else 0 end + ), 0) + + coalesce(sum(case + when akce = 'Výdej' + and d.cilove_ockovaci_misto_id in (select m2.id from ockovaci_mista m2 join okresy o2 on m2.okres_id = o2.id where o2.kraj_id = o.kraj_id) + then pocet_davek + else 0 end + ), 0) + - coalesce(sum(case + when akce = 'Výdej' + and d.ockovaci_misto_id in (select m3.id from ockovaci_mista m3 join okresy o3 on m3.okres_id = o3.id where o3.kraj_id = o.kraj_id) + and d.cilove_ockovaci_misto_id != '' + then pocet_davek + else 0 end + ), 0) + ) vakciny_prijate_pocet + from okresy o + join ockovaci_mista m on (m.okres_id = o.id) + left join ockovani_distribuce d on ((d.ockovaci_misto_id = m.id or d.cilove_ockovaci_misto_id = m.id) and d.datum < :datum) + group by (o.kraj_id) + """ + )).params(datum=self._date) \ + .all() + + for dist in distributed: + db.session.merge(KrajMetriky( + kraj_id=dist.kraj_id, + datum=self._date, + vakciny_prijate_pocet=dist.vakciny_prijate_pocet + )) + + app.logger.info('Computing kraj metrics - distributed vaccines finished.') + + def _compute_kraj_used(self): + """Computes metrics based on used vaccines dataset for each kraj.""" + used = db.session.query( + Kraj.id, func.sum(OckovaciMistoMetriky.vakciny_ockovane_pocet).label('vakciny_ockovane_pocet'), + func.sum(OckovaciMistoMetriky.vakciny_znicene_pocet).label("vakciny_znicene_pocet") + ).join(Okres, Okres.kraj_id == Kraj.id) \ + .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ + .filter(OckovaciMistoMetriky.datum == self._date) \ + .group_by(Kraj.id) \ + .all() + + for use in used: + db.session.merge(KrajMetriky( + kraj_id=use.id, + datum=self._date, + vakciny_ockovane_pocet=use.vakciny_ockovane_pocet, + vakciny_znicene_pocet=use.vakciny_znicene_pocet + )) + + app.logger.info('Computing kraj metrics - used vaccines finished.') + + def _compute_kraj_derived(self): + """Computes metrics derived from the previous metrics for each kraj.""" + avg_waiting = db.session.query( + Kraj.id, + (func.sum((OckovaniRegistrace.datum_rezervace - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) + / func.sum(OckovaniRegistrace.pocet)).label('registrace_prumer_cekani'), + ).join(Okres, Okres.kraj_id == Kraj.id) \ + .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum_rezervace >= self._date - timedelta(7)) \ + .group_by(Kraj.id) \ + .all() + + for wait in avg_waiting: + db.session.merge(KrajMetriky( + kraj_id=wait.id, + datum=self._date, + registrace_prumer_cekani=wait.registrace_prumer_cekani + )) + + avg_queue_waiting = db.session.query( + Kraj.id, + (func.sum((self._date - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) + / func.sum(OckovaniRegistrace.pocet)).label('registrace_fronta_prumer_cekani'), + ).join(Okres, Okres.kraj_id == Kraj.id) \ + .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.rezervace == False) \ + .group_by(Kraj.id,) \ + .all() + + for queue_wait in avg_queue_waiting: + db.session.merge(KrajMetriky( + kraj_id=queue_wait.id, + datum=self._date, + registrace_fronta_prumer_cekani=queue_wait.registrace_fronta_prumer_cekani + )) + + success_ratio_7 = db.session.query( + Kraj.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_tydenni_uspesnost') + ).join(Okres, Okres.kraj_id == Kraj.id) \ + .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(7)) \ + .group_by(Kraj.id) \ + .all() + + for ratio in success_ratio_7: + db.session.merge(KrajMetriky( + kraj_id=ratio.id, + datum=self._date, + registrace_tydenni_uspesnost=ratio.registrace_tydenni_uspesnost + )) + + success_ratio_14 = db.session.query( + Kraj.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_14denni_uspesnost') + ).join(Okres, Okres.kraj_id == Kraj.id) \ + .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(14)) \ + .group_by(Kraj.id) \ + .all() + + for ratio in success_ratio_14: + db.session.merge(KrajMetriky( + kraj_id=ratio.id, + datum=self._date, + registrace_14denni_uspesnost=ratio.registrace_14denni_uspesnost + )) + + success_ratio_30 = db.session.query( + Kraj.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_30denni_uspesnost') + ).join(Okres, Okres.kraj_id == Kraj.id) \ + .join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(30)) \ + .group_by(Kraj.id) \ + .all() + + for ratio in success_ratio_30: + db.session.merge(KrajMetriky( + kraj_id=ratio.id, + datum=self._date, + registrace_30denni_uspesnost=ratio.registrace_30denni_uspesnost + )) + + vacc_skladem = db.session.query( + Kraj.id, (KrajMetriky.vakciny_prijate_pocet - KrajMetriky.ockovani_pocet_davek + - KrajMetriky.vakciny_znicene_pocet).label('vakciny_skladem_pocet') + ).join(KrajMetriky, Kraj.id == KrajMetriky.kraj_id) \ + .filter(KrajMetriky.datum == self._date) \ + .group_by(Kraj.id, KrajMetriky.vakciny_prijate_pocet, KrajMetriky.ockovani_pocet_davek, + KrajMetriky.vakciny_znicene_pocet) \ + .all() + + for vacc in vacc_skladem: + db.session.merge(KrajMetriky( + kraj_id=vacc.id, + datum=self._date, + vakciny_skladem_pocet=vacc.vakciny_skladem_pocet + )) + + app.logger.info('Computing kraj metrics - derived metrics finished.') + + def _compute_kraj_deltas(self): + """Computes deltas for previous metrics for each kraj.""" + db.session.execute(text( + """ + update kraje_metriky t + set rezervace_celkem_zmena_den = t0.rezervace_celkem - t1.rezervace_celkem, + rezervace_cekajici_zmena_den = t0.rezervace_cekajici - t1.rezervace_cekajici, + rezervace_kapacita_zmena_den = t0.rezervace_kapacita - t1.rezervace_kapacita, + rezervace_kapacita_1_zmena_den = t0.rezervace_kapacita_1 - t1.rezervace_kapacita_1, + registrace_celkem_zmena_den = t0.registrace_celkem - t1.registrace_celkem, + registrace_fronta_zmena_den = t0.registrace_fronta - t1.registrace_fronta, + registrace_tydenni_uspesnost_zmena_den = t0.registrace_tydenni_uspesnost - t1.registrace_tydenni_uspesnost, + registrace_14denni_uspesnost_zmena_den = t0.registrace_14denni_uspesnost - t1.registrace_14denni_uspesnost, + registrace_30denni_uspesnost_zmena_den = t0.registrace_30denni_uspesnost - t1.registrace_30denni_uspesnost, + registrace_prumer_cekani_zmena_den = t0.registrace_prumer_cekani - t1.registrace_prumer_cekani, + registrace_fronta_prumer_cekani_zmena_den = t0.registrace_fronta_prumer_cekani - t1.registrace_fronta_prumer_cekani, + ockovani_pocet_davek_zmena_den = t0.ockovani_pocet_davek - t1.ockovani_pocet_davek, + ockovani_pocet_castecne_zmena_den = t0.ockovani_pocet_castecne - t1.ockovani_pocet_castecne, + ockovani_pocet_plne_zmena_den = t0.ockovani_pocet_plne - t1.ockovani_pocet_plne, + vakciny_prijate_pocet_zmena_den = t0.vakciny_prijate_pocet - t1.vakciny_prijate_pocet, + vakciny_ockovane_pocet_zmena_den = t0.vakciny_ockovane_pocet - t1.vakciny_ockovane_pocet, + vakciny_znicene_pocet_zmena_den = t0.vakciny_znicene_pocet - t1.vakciny_znicene_pocet, + vakciny_skladem_pocet_zmena_den = t0.vakciny_skladem_pocet - t1.vakciny_skladem_pocet + from kraje_metriky t0 + join kraje_metriky t1 + on t0.kraj_id = t1.kraj_id + where t.kraj_id = t0.kraj_id and t.datum = :datum and t0.datum = :datum and t1.datum = :datum_1 + """ + ), {'datum': self._date, 'datum_1': self._date - timedelta(1)}) + + db.session.execute(text( + """ + update kraje_metriky t + set rezervace_celkem_zmena_tyden = t0.rezervace_celkem - t7.rezervace_celkem, + rezervace_cekajici_zmena_tyden = t0.rezervace_cekajici - t7.rezervace_cekajici, + rezervace_kapacita_zmena_tyden = t0.rezervace_kapacita - t7.rezervace_kapacita, + rezervace_kapacita_1_zmena_tyden = t0.rezervace_kapacita_1 - t7.rezervace_kapacita_1, + registrace_celkem_zmena_tyden = t0.registrace_celkem - t7.registrace_celkem, + registrace_fronta_zmena_tyden = t0.registrace_fronta - t7.registrace_fronta, + registrace_tydenni_uspesnost_zmena_tyden = t0.registrace_tydenni_uspesnost - t7.registrace_tydenni_uspesnost, + registrace_14denni_uspesnost_zmena_tyden = t0.registrace_14denni_uspesnost - t7.registrace_14denni_uspesnost, + registrace_30denni_uspesnost_zmena_tyden = t0.registrace_30denni_uspesnost - t7.registrace_30denni_uspesnost, + registrace_prumer_cekani_zmena_tyden = t0.registrace_prumer_cekani - t7.registrace_prumer_cekani, + registrace_fronta_prumer_cekani_zmena_tyden = t0.registrace_fronta_prumer_cekani - t7.registrace_fronta_prumer_cekani, + ockovani_pocet_davek_zmena_tyden = t0.ockovani_pocet_davek - t7.ockovani_pocet_davek, + ockovani_pocet_castecne_zmena_tyden = t0.ockovani_pocet_castecne - t7.ockovani_pocet_castecne, + ockovani_pocet_plne_zmena_tyden = t0.ockovani_pocet_plne - t7.ockovani_pocet_plne, + vakciny_prijate_pocet_zmena_tyden = t0.vakciny_prijate_pocet - t7.vakciny_prijate_pocet, + vakciny_ockovane_pocet_zmena_tyden = t0.vakciny_ockovane_pocet - t7.vakciny_ockovane_pocet, + vakciny_znicene_pocet_zmena_tyden = t0.vakciny_znicene_pocet - t7.vakciny_znicene_pocet, + vakciny_skladem_pocet_zmena_tyden = t0.vakciny_skladem_pocet - t7.vakciny_skladem_pocet + from kraje_metriky t0 + join kraje_metriky t7 + on t0.kraj_id = t7.kraj_id + where t.kraj_id = t0.kraj_id and t.datum = :datum and t0.datum = :datum and t7.datum = :datum_7 + """ + ), {'datum': self._date, 'datum_7': self._date - timedelta(7)}) + + app.logger.info('Computing kraj metrics - deltas finished.') diff --git a/app/etl/metrics_etl.py b/app/etl/metrics_etl.py new file mode 100644 index 00000000..0d7a492c --- /dev/null +++ b/app/etl/metrics_etl.py @@ -0,0 +1,51 @@ +from datetime import date + +from app import db, app +from app.context import STATUS_FINISHED +from app.etl.center_metrics_etl import CenterMetricsEtl +from app.etl.cr_metrics_etl import CrMetricsEtl +from app.etl.kraj_metrics_etl import KrajMetricsEtl +from app.etl.okres_metrics_etl import OkresMetricsEtl +from app.models import Import + + +class MetricsEtl: + """Base class for computing metrics.""" + + def __init__(self, date_): + self._date = date_ + self._import_id = self._find_import_id() + + self._center_metrics_etl = CenterMetricsEtl(self._date, self._import_id) + self._okres_metrics_etl = OkresMetricsEtl(self._date, self._import_id) + self._kraj_metrics_etl = KrajMetricsEtl(self._date, self._import_id) + self._cr_metrics_etl = CrMetricsEtl(self._date, self._import_id) + + def compute_all(self): + try: + self._center_metrics_etl.compute_all() + self._okres_metrics_etl.compute_all() + self._kraj_metrics_etl.compute_all() + self._cr_metrics_etl.compute_all() + except Exception as e: + app.logger.error(e) + db.session.rollback() + return False + + db.session.commit() + return True + + def _find_import_id(self): + id_ = db.session.query(Import.id) \ + .filter(Import.date == self._date, Import.status == STATUS_FINISHED) \ + .first() + + if id_ is None: + raise Exception("No data for date: '{0}'.".format(self._date)) + + return id_[0] + + +if __name__ == '__main__': + etl = MetricsEtl(date.today()) + etl.compute_all() \ No newline at end of file diff --git a/app/etl/okres_metrics_etl.py b/app/etl/okres_metrics_etl.py new file mode 100644 index 00000000..7637de14 --- /dev/null +++ b/app/etl/okres_metrics_etl.py @@ -0,0 +1,296 @@ +from datetime import timedelta + +from sqlalchemy import func, case, text + +from app import db, app +from app.models import OckovaciMisto, OckovaciMistoMetriky, OckovaniRegistrace, Okres, OkresMetriky, Populace + + +class OkresMetricsEtl: + """Class for computing metrics for okres.""" + + def __init__(self, date_, import_id): + self._date = date_ + self._import_id = import_id + + def compute_all(self): + self._compute_okres_population() + self._compute_okres_registrations() + self._compute_okres_reservations() + self._compute_okres_distributed() + self._compute_okres_used() + self._compute_okres_derived() + self._compute_okres_deltas() + + def _compute_okres_population(self): + """Computes metrics based on population for each okres.""" + population = db.session.query( + Okres.id, func.sum(Populace.pocet).label('pocet_obyvatel_celkem'), + func.sum(case([(Populace.vek >= 18, Populace.pocet)], else_=0)).label('pocet_obyvatel_dospeli') + ).join(Populace, Populace.orp_kod == Okres.id) \ + .group_by(Okres.id) + + for pop in population: + db.session.merge(OkresMetriky( + okres_id=pop.id, + datum=self._date, + pocet_obyvatel_celkem=pop.pocet_obyvatel_celkem, + pocet_obyvatel_dospeli=pop.pocet_obyvatel_dospeli + )) + + app.logger.info('Computing okres metrics - population finished.') + + def _compute_okres_registrations(self): + """Computes metrics based on registrations dataset for each okres.""" + registrations = db.session.query( + Okres.id, func.sum(OckovaciMistoMetriky.registrace_celkem).label('registrace_celkem'), + func.sum(OckovaciMistoMetriky.registrace_fronta).label("registrace_fronta") + ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ + .filter(OckovaciMistoMetriky.datum == self._date) \ + .group_by(Okres.id) \ + .all() + + for registration in registrations: + db.session.merge(OkresMetriky( + okres_id=registration.id, + datum=self._date, + registrace_celkem=registration.registrace_celkem, + registrace_fronta=registration.registrace_fronta + )) + + app.logger.info('Computing okres metrics - registrations finished.') + + def _compute_okres_reservations(self): + """Computes metrics based on reservations dataset for each okres.""" + reservations = db.session.query( + Okres.id, func.sum(OckovaciMistoMetriky.rezervace_celkem).label('rezervace_celkem'), + func.sum(OckovaciMistoMetriky.rezervace_cekajici).label("rezervace_cekajici"), + func.sum(OckovaciMistoMetriky.rezervace_kapacita).label("rezervace_kapacita"), + func.sum(OckovaciMistoMetriky.rezervace_kapacita_1).label("rezervace_kapacita_1"), + func.min(OckovaciMistoMetriky.rezervace_nejblizsi_volno).label('rezervace_nejblizsi_volno') + ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ + .filter(OckovaciMistoMetriky.datum == self._date) \ + .group_by(Okres.id) \ + .all() + + for reservation in reservations: + db.session.merge(OkresMetriky( + okres_id=reservation.id, + datum=self._date, + rezervace_celkem=reservation.rezervace_celkem, + rezervace_cekajici=reservation.rezervace_cekajici, + rezervace_kapacita=reservation.rezervace_kapacita, + rezervace_kapacita_1=reservation.rezervace_kapacita_1, + rezervace_nejblizsi_volno=reservation.rezervace_nejblizsi_volno + )) + + app.logger.info('Computing okres metrics - reservations finished.') + + def _compute_okres_distributed(self): + """Computes metrics based on distributed vaccines dataset for each okres.""" + distributed = db.session.query("okres_id", "vakciny_prijate_pocet").from_statement(text( + """ + select m.okres_id okres_id, ( + coalesce(sum(case + when akce = 'Příjem' + and d.ockovaci_misto_id in (select m1.id from ockovaci_mista m1 where m1.okres_id = m.okres_id) + then pocet_davek + else 0 end + ), 0) + + coalesce(sum(case + when akce = 'Výdej' + and d.cilove_ockovaci_misto_id in (select m2.id from ockovaci_mista m2 where m2.okres_id = m.okres_id) + then pocet_davek + else 0 end + ), 0) + - coalesce(sum(case + when akce = 'Výdej' + and d.ockovaci_misto_id in (select m3.id from ockovaci_mista m3 where m3.okres_id = m.okres_id) + and d.cilove_ockovaci_misto_id != '' + then pocet_davek + else 0 end + ), 0) + ) vakciny_prijate_pocet + from ockovaci_mista m + left join ockovani_distribuce d on (d.ockovaci_misto_id = m.id or d.cilove_ockovaci_misto_id = m.id) + group by (m.okres_id) + """ + )).all() + + for dist in distributed: + db.session.merge(OkresMetriky( + okres_id=dist.okres_id, + datum=self._date, + vakciny_prijate_pocet=dist.vakciny_prijate_pocet + )) + + app.logger.info('Computing okres metrics - distributed vaccines finished.') + + def _compute_okres_used(self): + """Computes metrics based on used vaccines dataset for each okres.""" + used = db.session.query( + Okres.id, func.sum(OckovaciMistoMetriky.vakciny_ockovane_pocet).label('vakciny_ockovane_pocet'), + func.sum(OckovaciMistoMetriky.vakciny_znicene_pocet).label("vakciny_znicene_pocet") + ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaciMistoMetriky, OckovaciMistoMetriky.misto_id == OckovaciMisto.id) \ + .filter(OckovaciMistoMetriky.datum == self._date) \ + .group_by(Okres.id) \ + .all() + + for use in used: + db.session.merge(OkresMetriky( + okres_id=use.id, + datum=self._date, + vakciny_ockovane_pocet=use.vakciny_ockovane_pocet, + vakciny_znicene_pocet=use.vakciny_znicene_pocet + )) + + app.logger.info('Computing okres metrics - used vaccines finished.') + + def _compute_okres_derived(self): + """Computes metrics derived from the previous metrics for each okres.""" + avg_waiting = db.session.query( + Okres.id, + (func.sum((OckovaniRegistrace.datum_rezervace - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) + / func.sum(OckovaniRegistrace.pocet)).label('registrace_prumer_cekani'), + ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum_rezervace >= self._date - timedelta(7)) \ + .group_by(Okres.id) \ + .all() + + for wait in avg_waiting: + db.session.merge(OkresMetriky( + okres_id=wait.id, + datum=self._date, + registrace_prumer_cekani=wait.registrace_prumer_cekani + )) + + avg_queue_waiting = db.session.query( + Okres.id, + (func.sum((self._date - OckovaniRegistrace.datum) * OckovaniRegistrace.pocet) + / func.sum(OckovaniRegistrace.pocet)).label('registrace_fronta_prumer_cekani'), + ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.rezervace == False) \ + .group_by(Okres.id) \ + .all() + + for queue_wait in avg_queue_waiting: + db.session.merge(OkresMetriky( + okres_id=queue_wait.id, + datum=self._date, + registrace_fronta_prumer_cekani=queue_wait.registrace_fronta_prumer_cekani + )) + + success_ratio_7 = db.session.query( + Okres.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_tydenni_uspesnost') + ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(7)) \ + .group_by(Okres.id) \ + .all() + + for ratio in success_ratio_7: + db.session.merge(OkresMetriky( + okres_id=ratio.id, + datum=self._date, + registrace_tydenni_uspesnost=ratio.registrace_tydenni_uspesnost + )) + + success_ratio_14 = db.session.query( + Okres.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_14denni_uspesnost') + ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(14)) \ + .group_by(Okres.id) \ + .all() + + for ratio in success_ratio_14: + db.session.merge(OkresMetriky( + okres_id=ratio.id, + datum=self._date, + registrace_14denni_uspesnost=ratio.registrace_14denni_uspesnost + )) + + success_ratio_30 = db.session.query( + Okres.id, + (1.0 * func.coalesce(func.sum(case([(OckovaniRegistrace.rezervace == True, OckovaniRegistrace.pocet)], else_=0)), 0) + / case([(func.sum(OckovaniRegistrace.pocet) == 0, None)], else_=func.sum(OckovaniRegistrace.pocet))).label('registrace_30denni_uspesnost') + ).join(OckovaciMisto, (OckovaciMisto.okres_id == Okres.id)) \ + .join(OckovaniRegistrace, OckovaciMisto.id == OckovaniRegistrace.ockovaci_misto_id) \ + .filter(OckovaniRegistrace.import_id == self._import_id) \ + .filter(OckovaniRegistrace.datum >= self._date - timedelta(30)) \ + .group_by(Okres.id) \ + .all() + + for ratio in success_ratio_30: + db.session.merge(OkresMetriky( + okres_id=ratio.id, + datum=self._date, + registrace_30denni_uspesnost=ratio.registrace_30denni_uspesnost + )) + + app.logger.info('Computing okres metrics - derived metrics finished.') + + def _compute_okres_deltas(self): + """Computes deltas for previous metrics for each okres.""" + db.session.execute(text( + """ + update okresy_metriky t + set rezervace_celkem_zmena_den = t0.rezervace_celkem - t1.rezervace_celkem, + rezervace_cekajici_zmena_den = t0.rezervace_cekajici - t1.rezervace_cekajici, + rezervace_kapacita_zmena_den = t0.rezervace_kapacita - t1.rezervace_kapacita, + rezervace_kapacita_1_zmena_den = t0.rezervace_kapacita_1 - t1.rezervace_kapacita_1, + registrace_celkem_zmena_den = t0.registrace_celkem - t1.registrace_celkem, + registrace_fronta_zmena_den = t0.registrace_fronta - t1.registrace_fronta, + registrace_tydenni_uspesnost_zmena_den = t0.registrace_tydenni_uspesnost - t1.registrace_tydenni_uspesnost, + registrace_14denni_uspesnost_zmena_den = t0.registrace_14denni_uspesnost - t1.registrace_14denni_uspesnost, + registrace_30denni_uspesnost_zmena_den = t0.registrace_30denni_uspesnost - t1.registrace_30denni_uspesnost, + registrace_prumer_cekani_zmena_den = t0.registrace_prumer_cekani - t1.registrace_prumer_cekani, + registrace_fronta_prumer_cekani_zmena_den = t0.registrace_fronta_prumer_cekani - t1.registrace_fronta_prumer_cekani, + vakciny_prijate_pocet_zmena_den = t0.vakciny_prijate_pocet - t1.vakciny_prijate_pocet, + vakciny_ockovane_pocet_zmena_den = t0.vakciny_ockovane_pocet - t1.vakciny_ockovane_pocet, + vakciny_znicene_pocet_zmena_den = t0.vakciny_znicene_pocet - t1.vakciny_znicene_pocet + from okresy_metriky t0 + join okresy_metriky t1 + on t0.okres_id = t1.okres_id + where t.okres_id = t0.okres_id and t.datum = :datum and t0.datum = :datum and t1.datum = :datum_1 + """ + ), {'datum': self._date, 'datum_1': self._date - timedelta(1)}) + + db.session.execute(text( + """ + update okresy_metriky t + set rezervace_celkem_zmena_tyden = t0.rezervace_celkem - t7.rezervace_celkem, + rezervace_cekajici_zmena_tyden = t0.rezervace_cekajici - t7.rezervace_cekajici, + rezervace_kapacita_zmena_tyden = t0.rezervace_kapacita - t7.rezervace_kapacita, + rezervace_kapacita_1_zmena_tyden = t0.rezervace_kapacita_1 - t7.rezervace_kapacita_1, + registrace_celkem_zmena_tyden = t0.registrace_celkem - t7.registrace_celkem, + registrace_fronta_zmena_tyden = t0.registrace_fronta - t7.registrace_fronta, + registrace_tydenni_uspesnost_zmena_tyden = t0.registrace_tydenni_uspesnost - t7.registrace_tydenni_uspesnost, + registrace_14denni_uspesnost_zmena_tyden = t0.registrace_14denni_uspesnost - t7.registrace_14denni_uspesnost, + registrace_30denni_uspesnost_zmena_tyden = t0.registrace_30denni_uspesnost - t7.registrace_30denni_uspesnost, + registrace_prumer_cekani_zmena_tyden = t0.registrace_prumer_cekani - t7.registrace_prumer_cekani, + registrace_fronta_prumer_cekani_zmena_tyden = t0.registrace_fronta_prumer_cekani - t7.registrace_fronta_prumer_cekani, + vakciny_prijate_pocet_zmena_tyden = t0.vakciny_prijate_pocet - t7.vakciny_prijate_pocet, + vakciny_ockovane_pocet_zmena_tyden = t0.vakciny_ockovane_pocet - t7.vakciny_ockovane_pocet, + vakciny_znicene_pocet_zmena_tyden = t0.vakciny_znicene_pocet - t7.vakciny_znicene_pocet + from okresy_metriky t0 + join okresy_metriky t7 + on t0.okres_id = t7.okres_id + where t.okres_id = t0.okres_id and t.datum = :datum and t0.datum = :datum and t7.datum = :datum_7 + """ + ), {'datum': self._date, 'datum_7': self._date - timedelta(7)}) + + app.logger.info('Computing okres metrics - deltas finished.') diff --git a/app/models.py b/app/models.py index ca03d336..e826a5e0 100644 --- a/app/models.py +++ b/app/models.py @@ -1,5 +1,6 @@ from datetime import datetime -from sqlalchemy import Column, Integer, Unicode, DateTime, Boolean, Float, Date, JSON, Sequence, ForeignKey + +from sqlalchemy import Column, Integer, Unicode, DateTime, Boolean, Float, Date, ForeignKey from sqlalchemy.orm import relationship from app import db @@ -12,71 +13,6 @@ class Kraj(db.Model): nazev = Column(Unicode) -class KrajMetriky(db.Model): - __tablename__ = 'kraje_metriky' - - kraj_id = Column(Unicode, ForeignKey('kraje.id'), primary_key=True) - datum = Column(DateTime, primary_key=True) - pocet_obyvatel_celkem = Column(Integer) - pocet_obyvatel_dospeli = Column(Integer) - rezervace_celkem = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - rezervace_celkem_zmena_den = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za den - rezervace_celkem_zmena_tyden = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za tyden - rezervace_cekajici = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - rezervace_cekajici_zmena_den = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za den - rezervace_cekajici_zmena_tyden = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za tyden - rezervace_kapacita = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - rezervace_kapacita_zmena_den = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za den - rezervace_kapacita_zmena_tyden = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za tyden - registrace_celkem = Column(Integer) # pocet vsech registraci - registrace_celkem_zmena_den = Column(Integer) # pocet vsech registraci - zmena za den - registrace_celkem_zmena_tyden = Column(Integer) # pocet vsech registraci - zmena za tyden - registrace_fronta = Column(Integer) # pocet registraci bez rezervace - registrace_fronta_zmena_den = Column(Integer) # pocet registraci bez rezervace - zmena za den - registrace_fronta_zmena_tyden = Column(Integer) # pocet registraci bez rezervace - zmena za tyden - registrace_tydenni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 7 dni - registrace_tydenni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za den - registrace_tydenni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za tyden - registrace_14denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 14 dni - registrace_14denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za den - registrace_14denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za tyden - registrace_30denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 30 dni - registrace_30denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za den - registrace_30denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za tyden - registrace_prumer_cekani = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - registrace_prumer_cekani_zmena_den = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za den - registrace_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za tyden - ockovani_pocet = Column(Integer) # pocet ockovanych - ockovani_pocet_zmena_den = Column(Integer) # pocet ockovanych - zmena za den - ockovani_pocet_zmena_tyden = Column(Integer) # pocet ockovanych - zmena za tyden - ockovani_pocet_1 = Column(Integer) # pocet ockovanych alespon prvni davkou - ockovani_pocet_1_zmena_den = Column(Integer) # pocet ockovanych alespon prvni davkou - zmena za den - ockovani_pocet_1_zmena_tyden = Column(Integer) # pocet ockovanych alespon prvni davkou - zmena za tyden - ockovani_pocet_2 = Column(Integer) # pocet ockovanych obema davkami - ockovani_pocet_2_zmena_den = Column(Integer) # pocet ockovanych obema davkami - zmena za den - ockovani_pocet_2_zmena_tyden = Column(Integer) # pocet ockovanych obema davkami - zmena za tyden - vakciny_prijate_pocet = Column(Integer) # pocet prijatych vakcin - vakciny_prijate_pocet_zmena_den = Column(Integer) # pocet prijatych vakcin - zmena za den - vakciny_prijate_pocet_zmena_tyden = Column(Integer) # pocet prijatych vakcin - zmena za tyden - vakciny_ockovane_pocet = Column(Integer) # pocet ockovanych vakcin - vakciny_ockovane_pocet_zmena_den = Column(Integer) # pocet ockovanych vakcin - zmena za den - vakciny_ockovane_pocet_zmena_tyden = Column(Integer) # pocet ockovanych vakcin - zmena za tyden - vakciny_znicene_pocet = Column(Integer) # pocet znicenych vakcin - vakciny_znicene_pocet_zmena_den = Column(Integer) # pocet znicenych vakcin - zmena za den - vakciny_znicene_pocet_zmena_tyden = Column(Integer) # pocet znicenych vakcin - zmena za tyden - vakciny_skladem_pocet = Column(Integer) # odhad vakcin skladem - vakciny_skladem_pocet_zmena_den = Column(Integer) # odhad vakcin skladem - zmena za den - vakciny_skladem_pocet_zmena_tyden = Column(Integer) # odhad vakcin skladem - zmena za tyden - - kraj = relationship("Kraj", back_populates="metriky") - - def __repr__(self): - return "" % (self.kraj_id, self.datum) - - -Kraj.metriky = relationship("KrajMetriky", back_populates="kraj") - - class Okres(db.Model): __tablename__ = 'okresy' @@ -93,59 +29,6 @@ def __repr__(self): Kraj.okresy = relationship("Okres", back_populates="kraj") -class OkresMetriky(db.Model): - __tablename__ = 'okresy_metriky' - - okres_id = Column(Unicode, ForeignKey('okresy.id'), primary_key=True) - datum = Column(DateTime, primary_key=True) - pocet_obyvatel_celkem = Column(Integer) - pocet_obyvatel_dospeli = Column(Integer) - rezervace_celkem = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - rezervace_celkem_zmena_den = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za den - rezervace_celkem_zmena_tyden = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za tyden - rezervace_cekajici = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - rezervace_cekajici_zmena_den = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za den - rezervace_cekajici_zmena_tyden = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za tyden - rezervace_kapacita = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - rezervace_kapacita_zmena_den = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za den - rezervace_kapacita_zmena_tyden = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za tyden - registrace_celkem = Column(Integer) # pocet vsech registraci - registrace_celkem_zmena_den = Column(Integer) # pocet vsech registraci - zmena za den - registrace_celkem_zmena_tyden = Column(Integer) # pocet vsech registraci - zmena za tyden - registrace_fronta = Column(Integer) # pocet registraci bez rezervace - registrace_fronta_zmena_den = Column(Integer) # pocet registraci bez rezervace - zmena za den - registrace_fronta_zmena_tyden = Column(Integer) # pocet registraci bez rezervace - zmena za tyden - registrace_tydenni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 7 dni - registrace_tydenni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za den - registrace_tydenni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za tyden - registrace_14denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 14 dni - registrace_14denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za den - registrace_14denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za tyden - registrace_30denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 30 dni - registrace_30denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za den - registrace_30denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za tyden - registrace_prumer_cekani = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - registrace_prumer_cekani_zmena_den = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za den - registrace_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za tyden - vakciny_prijate_pocet = Column(Integer) # pocet prijatych vakcin - vakciny_prijate_pocet_zmena_den = Column(Integer) # pocet prijatych vakcin - zmena za den - vakciny_prijate_pocet_zmena_tyden = Column(Integer) # pocet prijatych vakcin - zmena za tyden - vakciny_ockovane_pocet = Column(Integer) # pocet ockovanych vakcin - vakciny_ockovane_pocet_zmena_den = Column(Integer) # pocet ockovanych vakcin - zmena za den - vakciny_ockovane_pocet_zmena_tyden = Column(Integer) # pocet ockovanych vakcin - zmena za tyden - vakciny_znicene_pocet = Column(Integer) # pocet znicenych vakcin - vakciny_znicene_pocet_zmena_den = Column(Integer) # pocet znicenych vakcin - zmena za den - vakciny_znicene_pocet_zmena_tyden = Column(Integer) # pocet znicenych vakcin - zmena za tyden - - okres = relationship("Okres", back_populates="metriky") - - def __repr__(self): - return "" % (self.id, self.datum) - - -Okres.metriky = relationship("OkresMetriky", back_populates="okres") - - class Populace(db.Model): __tablename__ = 'populace' @@ -197,75 +80,6 @@ def __repr__(self): Okres.ockovaci_mista = relationship("OckovaciMisto", back_populates="okres") -class OckovaciMistoMetriky(db.Model): - __tablename__ = 'ockovaci_mista_metriky' - - misto_id = Column(Unicode, ForeignKey('ockovaci_mista.id'), primary_key=True) - datum = Column(DateTime, primary_key=True) - rezervace_celkem = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - rezervace_celkem_zmena_den = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za den - rezervace_celkem_zmena_tyden = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za tyden - rezervace_cekajici = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - rezervace_cekajici_zmena_den = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za den - rezervace_cekajici_zmena_tyden = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za tyden - rezervace_kapacita = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - rezervace_kapacita_zmena_den = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za den - rezervace_kapacita_zmena_tyden = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za tyden - registrace_celkem = Column(Integer) # pocet vsech registraci - registrace_celkem_zmena_den = Column(Integer) # pocet vsech registraci - zmena za den - registrace_celkem_zmena_tyden = Column(Integer) # pocet vsech registraci - zmena za tyden - registrace_fronta = Column(Integer) # pocet registraci bez rezervace - registrace_fronta_zmena_den = Column(Integer) # pocet registraci bez rezervace - zmena za den - registrace_fronta_zmena_tyden = Column(Integer) # pocet registraci bez rezervace - zmena za tyden - registrace_tydenni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 7 dni - registrace_tydenni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za den - registrace_tydenni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za tyden - registrace_14denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 14 dni - registrace_14denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za den - registrace_14denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za tyden - registrace_30denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 30 dni - registrace_30denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za den - registrace_30denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za tyden - registrace_prumer_cekani = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - registrace_prumer_cekani_zmena_den = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za den - registrace_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za tyden - registrace_odhad_cekani = Column(Float) # odhadovana doba cekani na rezervaci - registrace_odhad_cekani_zmena_den = Column(Float) # odhadovana doba cekani na rezervaci - zmena za den - registrace_odhad_cekani_zmena_tyden = Column(Float) # odhadovana doba cekani na rezervaci - zmena za tyden - ockovani_pocet = Column(Integer) # pocet ockovanych - ockovani_pocet_zmena_den = Column(Integer) # pocet ockovanych - zmena za den - ockovani_pocet_zmena_tyden = Column(Integer) # pocet ockovanych - zmena za tyden - ockovani_pocet_1 = Column(Integer) # pocet ockovanych alespon prvni davkou - ockovani_pocet_1_zmena_den = Column(Integer) # pocet ockovanych alespon prvni davkou - zmena za den - ockovani_pocet_1_zmena_tyden = Column(Integer) # pocet ockovanych alespon prvni davkou - zmena za tyden - ockovani_pocet_2 = Column(Integer) # pocet ockovanych obema davkami - ockovani_pocet_2_zmena_den = Column(Integer) # pocet ockovanych obema davkami - zmena za den - ockovani_pocet_2_zmena_tyden = Column(Integer) # pocet ockovanych obema davkami - zmena za tyden - ockovani_odhad_cekani = Column(Float) # odhad casu potrebneho na naockovani lidi ve fronte a rezervaci - ockovani_odhad_cekani_zmena_den = Column(Float) # odhad casu potrebneho na naockovani lidi ve fronte a rezervaci - zmena za den - ockovani_odhad_cekani_zmena_tyden = Column(Float) # odhad casu potrebneho na naockovani lidi ve fronte a rezervaci - zmena za tyden - vakciny_prijate_pocet = Column(Integer) # pocet prijatych vakcin - vakciny_prijate_pocet_zmena_den = Column(Integer) # pocet prijatych vakcin - zmena za den - vakciny_prijate_pocet_zmena_tyden = Column(Integer) # pocet prijatych vakcin - zmena za tyden - vakciny_ockovane_pocet = Column(Integer) # pocet ockovanych vakcin - vakciny_ockovane_pocet_zmena_den = Column(Integer) # pocet ockovanych vakcin - zmena za den - vakciny_ockovane_pocet_zmena_tyden = Column(Integer) # pocet ockovanych vakcin - zmena za tyden - vakciny_znicene_pocet = Column(Integer) # pocet znicenych vakcin - vakciny_znicene_pocet_zmena_den = Column(Integer) # pocet znicenych vakcin - zmena za den - vakciny_znicene_pocet_zmena_tyden = Column(Integer) # pocet znicenych vakcin - zmena za tyden - vakciny_skladem_pocet = Column(Integer) # odhad vakcin skladem - vakciny_skladem_pocet_zmena_den = Column(Integer) # odhad vakcin skladem - zmena za den - vakciny_skladem_pocet_zmena_tyden = Column(Integer) # odhad vakcin skladem - zmena za tyden - - misto = relationship("OckovaciMisto", back_populates="metriky") - - def __repr__(self): - return "" % (self.id, self.datum) - - -OckovaciMisto.metriky = relationship("OckovaciMistoMetriky", back_populates="misto") - - class Import(db.Model): __tablename__ = 'importy' @@ -412,3 +226,276 @@ class ZdravotnickeStredisko(db.Model): okres = Column(Unicode) okres_kod = Column(Unicode) nrpzs_kod = Column(Unicode) + + +class KrajMetriky(db.Model): + __tablename__ = 'kraje_metriky' + + kraj_id = Column(Unicode, ForeignKey('kraje.id'), primary_key=True) + datum = Column(DateTime, primary_key=True) + pocet_obyvatel_celkem = Column(Integer) + pocet_obyvatel_dospeli = Column(Integer) + rezervace_celkem = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) + rezervace_celkem_zmena_den = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za den + rezervace_celkem_zmena_tyden = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za tyden + rezervace_cekajici = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) + rezervace_cekajici_zmena_den = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za den + rezervace_cekajici_zmena_tyden = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za tyden + rezervace_kapacita = Column(Integer) # kapacita na aktualni den (vsechny kalendare) + rezervace_kapacita_zmena_den = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za den + rezervace_kapacita_zmena_tyden = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za tyden + rezervace_kapacita_1 = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) + rezervace_kapacita_1_zmena_den = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) - zmena za den + rezervace_kapacita_1_zmena_tyden = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) - zmena za tyden + rezervace_nejblizsi_volno = Column(Date) # nejblizsi den s volnym mistem + registrace_celkem = Column(Integer) # pocet vsech registraci + registrace_celkem_zmena_den = Column(Integer) # pocet vsech registraci - zmena za den + registrace_celkem_zmena_tyden = Column(Integer) # pocet vsech registraci - zmena za tyden + registrace_fronta = Column(Integer) # pocet registraci bez rezervace + registrace_fronta_zmena_den = Column(Integer) # pocet registraci bez rezervace - zmena za den + registrace_fronta_zmena_tyden = Column(Integer) # pocet registraci bez rezervace - zmena za tyden + registrace_tydenni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 7 dni + registrace_tydenni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za den + registrace_tydenni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za tyden + registrace_14denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 14 dni + registrace_14denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za den + registrace_14denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za tyden + registrace_30denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 30 dni + registrace_30denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za den + registrace_30denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za tyden + registrace_prumer_cekani = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni + registrace_prumer_cekani_zmena_den = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za den + registrace_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za tyden + registrace_fronta_prumer_cekani = Column(Float) # prumerna doba ve fronte + registrace_fronta_prumer_cekani_zmena_den = Column(Float) # prumerna doba ve fronte - zmena za den + registrace_fronta_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba ve fronte - zmena za tyden + ockovani_pocet_davek = Column(Integer) # pocet ockovanych davek + ockovani_pocet_davek_zmena_den = Column(Integer) # pocet ockovanych davek - zmena za den + ockovani_pocet_davek_zmena_tyden = Column(Integer) # pocet ockovanych davek - zmena za tyden + ockovani_pocet_castecne = Column(Integer) # pocet ockovanych alespon castecne + ockovani_pocet_castecne_zmena_den = Column(Integer) # pocet ockovanych alespon castecne - zmena za den + ockovani_pocet_castecne_zmena_tyden = Column(Integer) # pocet ockovanych alespon castecne - zmena za tyden + ockovani_pocet_plne = Column(Integer) # pocet ockovanych plne (vsechny davky) + ockovani_pocet_plne_zmena_den = Column(Integer) # pocet ockovanych plne (vsechny davky) - zmena za den + ockovani_pocet_plne_zmena_tyden = Column(Integer) # pocet ockovanych plne (vsechny davky) - zmena za tyden + vakciny_prijate_pocet = Column(Integer) # pocet prijatych vakcin + vakciny_prijate_pocet_zmena_den = Column(Integer) # pocet prijatych vakcin - zmena za den + vakciny_prijate_pocet_zmena_tyden = Column(Integer) # pocet prijatych vakcin - zmena za tyden + vakciny_ockovane_pocet = Column(Integer) # pocet ockovanych vakcin + vakciny_ockovane_pocet_zmena_den = Column(Integer) # pocet ockovanych vakcin - zmena za den + vakciny_ockovane_pocet_zmena_tyden = Column(Integer) # pocet ockovanych vakcin - zmena za tyden + vakciny_znicene_pocet = Column(Integer) # pocet znicenych vakcin + vakciny_znicene_pocet_zmena_den = Column(Integer) # pocet znicenych vakcin - zmena za den + vakciny_znicene_pocet_zmena_tyden = Column(Integer) # pocet znicenych vakcin - zmena za tyden + vakciny_skladem_pocet = Column(Integer) # odhad vakcin skladem + vakciny_skladem_pocet_zmena_den = Column(Integer) # odhad vakcin skladem - zmena za den + vakciny_skladem_pocet_zmena_tyden = Column(Integer) # odhad vakcin skladem - zmena za tyden + + kraj = relationship("Kraj", back_populates="metriky") + + def __repr__(self): + return "" % (self.kraj_id, self.datum) + + +Kraj.metriky = relationship("KrajMetriky", back_populates="kraj") + + +class OkresMetriky(db.Model): + __tablename__ = 'okresy_metriky' + + okres_id = Column(Unicode, ForeignKey('okresy.id'), primary_key=True) + datum = Column(DateTime, primary_key=True) + pocet_obyvatel_celkem = Column(Integer) + pocet_obyvatel_dospeli = Column(Integer) + rezervace_celkem = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) + rezervace_celkem_zmena_den = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za den + rezervace_celkem_zmena_tyden = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za tyden + rezervace_cekajici = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) + rezervace_cekajici_zmena_den = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za den + rezervace_cekajici_zmena_tyden = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za tyden + rezervace_kapacita = Column(Integer) # kapacita na aktualni den (vsechny kalendare) + rezervace_kapacita_zmena_den = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za den + rezervace_kapacita_zmena_tyden = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za tyden + rezervace_kapacita_1 = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) + rezervace_kapacita_1_zmena_den = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) - zmena za den + rezervace_kapacita_1_zmena_tyden = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) - zmena za tyden + rezervace_nejblizsi_volno = Column(Date) # nejblizsi den s volnym mistem + registrace_celkem = Column(Integer) # pocet vsech registraci + registrace_celkem_zmena_den = Column(Integer) # pocet vsech registraci - zmena za den + registrace_celkem_zmena_tyden = Column(Integer) # pocet vsech registraci - zmena za tyden + registrace_fronta = Column(Integer) # pocet registraci bez rezervace + registrace_fronta_zmena_den = Column(Integer) # pocet registraci bez rezervace - zmena za den + registrace_fronta_zmena_tyden = Column(Integer) # pocet registraci bez rezervace - zmena za tyden + registrace_tydenni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 7 dni + registrace_tydenni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za den + registrace_tydenni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za tyden + registrace_14denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 14 dni + registrace_14denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za den + registrace_14denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za tyden + registrace_30denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 30 dni + registrace_30denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za den + registrace_30denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za tyden + registrace_prumer_cekani = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni + registrace_prumer_cekani_zmena_den = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za den + registrace_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za tyden + registrace_fronta_prumer_cekani = Column(Float) # prumerna doba ve fronte + registrace_fronta_prumer_cekani_zmena_den = Column(Float) # prumerna doba ve fronte - zmena za den + registrace_fronta_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba ve fronte - zmena za tyden + vakciny_prijate_pocet = Column(Integer) # pocet prijatych vakcin + vakciny_prijate_pocet_zmena_den = Column(Integer) # pocet prijatych vakcin - zmena za den + vakciny_prijate_pocet_zmena_tyden = Column(Integer) # pocet prijatych vakcin - zmena za tyden + vakciny_ockovane_pocet = Column(Integer) # pocet ockovanych vakcin + vakciny_ockovane_pocet_zmena_den = Column(Integer) # pocet ockovanych vakcin - zmena za den + vakciny_ockovane_pocet_zmena_tyden = Column(Integer) # pocet ockovanych vakcin - zmena za tyden + vakciny_znicene_pocet = Column(Integer) # pocet znicenych vakcin + vakciny_znicene_pocet_zmena_den = Column(Integer) # pocet znicenych vakcin - zmena za den + vakciny_znicene_pocet_zmena_tyden = Column(Integer) # pocet znicenych vakcin - zmena za tyden + + okres = relationship("Okres", back_populates="metriky") + + def __repr__(self): + return "" % (self.id, self.datum) + + +Okres.metriky = relationship("OkresMetriky", back_populates="okres") + + +class OckovaciMistoMetriky(db.Model): + __tablename__ = 'ockovaci_mista_metriky' + + misto_id = Column(Unicode, ForeignKey('ockovaci_mista.id'), primary_key=True) + datum = Column(DateTime, primary_key=True) + rezervace_celkem = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) + rezervace_celkem_zmena_den = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za den + rezervace_celkem_zmena_tyden = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za tyden + rezervace_cekajici = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) + rezervace_cekajici_zmena_den = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za den + rezervace_cekajici_zmena_tyden = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za tyden + rezervace_kapacita = Column(Integer) # kapacita na aktualni den (vsechny kalendare) + rezervace_kapacita_zmena_den = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za den + rezervace_kapacita_zmena_tyden = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za tyden + rezervace_kapacita_1 = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) + rezervace_kapacita_1_zmena_den = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) - zmena za den + rezervace_kapacita_1_zmena_tyden = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) - zmena za tyden + rezervace_nejblizsi_volno = Column(Date) # nejblizsi den s volnym mistem + registrace_celkem = Column(Integer) # pocet vsech registraci + registrace_celkem_zmena_den = Column(Integer) # pocet vsech registraci - zmena za den + registrace_celkem_zmena_tyden = Column(Integer) # pocet vsech registraci - zmena za tyden + registrace_fronta = Column(Integer) # pocet registraci bez rezervace + registrace_fronta_zmena_den = Column(Integer) # pocet registraci bez rezervace - zmena za den + registrace_fronta_zmena_tyden = Column(Integer) # pocet registraci bez rezervace - zmena za tyden + registrace_tydenni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 7 dni + registrace_tydenni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za den + registrace_tydenni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za tyden + registrace_14denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 14 dni + registrace_14denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za den + registrace_14denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za tyden + registrace_30denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 30 dni + registrace_30denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za den + registrace_30denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za tyden + registrace_prumer_cekani = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni + registrace_prumer_cekani_zmena_den = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za den + registrace_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za tyden + registrace_odhad_cekani = Column(Float) # odhadovana doba cekani na rezervaci + registrace_odhad_cekani_zmena_den = Column(Float) # odhadovana doba cekani na rezervaci - zmena za den + registrace_odhad_cekani_zmena_tyden = Column(Float) # odhadovana doba cekani na rezervaci - zmena za tyden + registrace_fronta_prumer_cekani = Column(Float) # prumerna doba ve fronte + registrace_fronta_prumer_cekani_zmena_den = Column(Float) # prumerna doba ve fronte - zmena za den + registrace_fronta_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba ve fronte - zmena za tyden + ockovani_pocet_davek = Column(Integer) # pocet ockovanych davek + ockovani_pocet_davek_zmena_den = Column(Integer) # pocet ockovanych davek - zmena za den + ockovani_pocet_davek_zmena_tyden = Column(Integer) # pocet ockovanych davek - zmena za tyden + ockovani_pocet_castecne = Column(Integer) # pocet ockovanych alespon castecne + ockovani_pocet_castecne_zmena_den = Column(Integer) # pocet ockovanych alespon castecne - zmena za den + ockovani_pocet_castecne_zmena_tyden = Column(Integer) # pocet ockovanych alespon castecne - zmena za tyden + ockovani_pocet_plne = Column(Integer) # pocet ockovanych plne (vsechny davky) + ockovani_pocet_plne_zmena_den = Column(Integer) # pocet ockovanych plne (vsechny davky) - zmena za den + ockovani_pocet_plne_zmena_tyden = Column(Integer) # pocet ockovanych plne (vsechny davky) - zmena za tyden + ockovani_odhad_cekani = Column(Float) # odhad casu potrebneho na naockovani lidi ve fronte a rezervaci + ockovani_odhad_cekani_zmena_den = Column(Float) # odhad casu potrebneho na naockovani lidi ve fronte a rezervaci - zmena za den + ockovani_odhad_cekani_zmena_tyden = Column(Float) # odhad casu potrebneho na naockovani lidi ve fronte a rezervaci - zmena za tyden + vakciny_prijate_pocet = Column(Integer) # pocet prijatych vakcin + vakciny_prijate_pocet_zmena_den = Column(Integer) # pocet prijatych vakcin - zmena za den + vakciny_prijate_pocet_zmena_tyden = Column(Integer) # pocet prijatych vakcin - zmena za tyden + vakciny_ockovane_pocet = Column(Integer) # pocet ockovanych vakcin + vakciny_ockovane_pocet_zmena_den = Column(Integer) # pocet ockovanych vakcin - zmena za den + vakciny_ockovane_pocet_zmena_tyden = Column(Integer) # pocet ockovanych vakcin - zmena za tyden + vakciny_znicene_pocet = Column(Integer) # pocet znicenych vakcin + vakciny_znicene_pocet_zmena_den = Column(Integer) # pocet znicenych vakcin - zmena za den + vakciny_znicene_pocet_zmena_tyden = Column(Integer) # pocet znicenych vakcin - zmena za tyden + vakciny_skladem_pocet = Column(Integer) # odhad vakcin skladem + vakciny_skladem_pocet_zmena_den = Column(Integer) # odhad vakcin skladem - zmena za den + vakciny_skladem_pocet_zmena_tyden = Column(Integer) # odhad vakcin skladem - zmena za tyden + + misto = relationship("OckovaciMisto", back_populates="metriky") + + def __repr__(self): + return "" % (self.id, self.datum) + + +OckovaciMisto.metriky = relationship("OckovaciMistoMetriky", back_populates="misto") + + +class CrMetriky(db.Model): + __tablename__ = 'cr_metriky' + + datum = Column(DateTime, primary_key=True) + pocet_obyvatel_celkem = Column(Integer) + pocet_obyvatel_dospeli = Column(Integer) + rezervace_celkem = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) + rezervace_celkem_zmena_den = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za den + rezervace_celkem_zmena_tyden = Column(Integer) # pocet vsech rezervaci (vsechny kalendare) - zmena za tyden + rezervace_cekajici = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) + rezervace_cekajici_zmena_den = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za den + rezervace_cekajici_zmena_tyden = Column(Integer) # pocet rezervaci cekajicich na ockovani (vsechny kalendare) - zmena za tyden + rezervace_kapacita = Column(Integer) # kapacita na aktualni den (vsechny kalendare) + rezervace_kapacita_zmena_den = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za den + rezervace_kapacita_zmena_tyden = Column(Integer) # kapacita na aktualni den (vsechny kalendare) - zmena za tyden + rezervace_kapacita_1 = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) + rezervace_kapacita_1_zmena_den = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) - zmena za den + rezervace_kapacita_1_zmena_tyden = Column(Integer) # kapacita na aktualni den (kalendar pro 1. davky) - zmena za tyden + registrace_celkem = Column(Integer) # pocet vsech registraci + registrace_celkem_zmena_den = Column(Integer) # pocet vsech registraci - zmena za den + registrace_celkem_zmena_tyden = Column(Integer) # pocet vsech registraci - zmena za tyden + registrace_fronta = Column(Integer) # pocet registraci bez rezervace + registrace_fronta_zmena_den = Column(Integer) # pocet registraci bez rezervace - zmena za den + registrace_fronta_zmena_tyden = Column(Integer) # pocet registraci bez rezervace - zmena za tyden + registrace_tydenni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 7 dni + registrace_tydenni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za den + registrace_tydenni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 7 dni - zmena za tyden + registrace_14denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 14 dni + registrace_14denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za den + registrace_14denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 14 dni - zmena za tyden + registrace_30denni_uspesnost = Column(Float) # uspesnost rezervaci za poslednich 30 dni + registrace_30denni_uspesnost_zmena_den = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za den + registrace_30denni_uspesnost_zmena_tyden = Column(Float) # uspesnost rezervaci za poslednich 30 dni - zmena za tyden + registrace_prumer_cekani = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni + registrace_prumer_cekani_zmena_den = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za den + registrace_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba cekani na rezervaci z poslednich 7 dni - zmena za tyden + registrace_fronta_prumer_cekani = Column(Float) # prumerna doba ve fronte + registrace_fronta_prumer_cekani_zmena_den = Column(Float) # prumerna doba ve fronte - zmena za den + registrace_fronta_prumer_cekani_zmena_tyden = Column(Float) # prumerna doba ve fronte - zmena za tyden + ockovani_pocet_davek = Column(Integer) # pocet ockovanych davek + ockovani_pocet_davek_zmena_den = Column(Integer) # pocet ockovanych davek - zmena za den + ockovani_pocet_davek_zmena_tyden = Column(Integer) # pocet ockovanych davek - zmena za tyden + ockovani_pocet_castecne = Column(Integer) # pocet ockovanych alespon castecne + ockovani_pocet_castecne_zmena_den = Column(Integer) # pocet ockovanych alespon castecne - zmena za den + ockovani_pocet_castecne_zmena_tyden = Column(Integer) # pocet ockovanych alespon castecne - zmena za tyden + ockovani_pocet_plne = Column(Integer) # pocet ockovanych plne (vsechny davky) + ockovani_pocet_plne_zmena_den = Column(Integer) # pocet ockovanych plne (vsechny davky) - zmena za den + ockovani_pocet_plne_zmena_tyden = Column(Integer) # pocet ockovanych plne (vsechny davky) - zmena za tyden + vakciny_prijate_pocet = Column(Integer) # pocet prijatych vakcin + vakciny_prijate_pocet_zmena_den = Column(Integer) # pocet prijatych vakcin - zmena za den + vakciny_prijate_pocet_zmena_tyden = Column(Integer) # pocet prijatych vakcin - zmena za tyden + vakciny_ockovane_pocet = Column(Integer) # pocet ockovanych vakcin + vakciny_ockovane_pocet_zmena_den = Column(Integer) # pocet ockovanych vakcin - zmena za den + vakciny_ockovane_pocet_zmena_tyden = Column(Integer) # pocet ockovanych vakcin - zmena za tyden + vakciny_znicene_pocet = Column(Integer) # pocet znicenych vakcin + vakciny_znicene_pocet_zmena_den = Column(Integer) # pocet znicenych vakcin - zmena za den + vakciny_znicene_pocet_zmena_tyden = Column(Integer) # pocet znicenych vakcin - zmena za tyden + vakciny_skladem_pocet = Column(Integer) # odhad vakcin skladem + vakciny_skladem_pocet_zmena_den = Column(Integer) # odhad vakcin skladem - zmena za den + vakciny_skladem_pocet_zmena_tyden = Column(Integer) # odhad vakcin skladem - zmena za tyden + + def __repr__(self): + return "" % (self.datum) \ No newline at end of file diff --git a/app/opendata_fetcher.py b/app/opendata_fetcher.py index bcb876bc..28f7a308 100644 --- a/app/opendata_fetcher.py +++ b/app/opendata_fetcher.py @@ -217,14 +217,18 @@ def _fetch_registrations(self): mista_result = db.session.query(OckovaciMisto.id).all() mista_ids = [id for id, in mista_result] missing_ids = [] + missing_count = 0 + missing_sum = 0 for row in df.itertuples(index=False): misto_id = row[1] if misto_id not in mista_ids: + missing_count += 1 + missing_sum += row[7] if misto_id not in missing_ids: missing_ids.append(misto_id) - app.logger.warn("Center: '{0}' doesn't exist".format(misto_id)) + app.logger.warn("Center: '{0}' doesn't exist.".format(misto_id)) continue db.session.add(OckovaniRegistrace( @@ -239,6 +243,9 @@ def _fetch_registrations(self): import_=self._import )) + if missing_count > 0: + app.logger.warn("Some centers doesn't exist - {} rows ({} registrations) skipped.".format(missing_count, missing_sum)) + app.logger.info('Fetching opendata - registrations finished.') def _fetch_reservations(self): @@ -254,14 +261,16 @@ def _fetch_reservations(self): mista_result = db.session.query(OckovaciMisto.id).all() mista_ids = [id for id, in mista_result] missing_ids = [] + missing_count = 0 for row in df.itertuples(index=False): misto_id = row[1] if misto_id not in mista_ids: + missing_count += 1 if misto_id not in missing_ids: missing_ids.append(misto_id) - app.logger.warn("Center: '{0}' doesn't exist".format(misto_id)) + app.logger.warn("Center: '{0}' doesn't exist.".format(misto_id)) continue db.session.add(OckovaniRezervace( @@ -273,6 +282,9 @@ def _fetch_reservations(self): import_=self._import )) + if missing_count > 0: + app.logger.warn("Some centers doesn't exist - {} rows skipped.".format(missing_count)) + app.logger.info('Fetching opendata - reservations finished.') def _load_json_data(self, url): diff --git a/app/queries.py b/app/queries.py index bd3cdb81..ce8d7bd1 100644 --- a/app/queries.py +++ b/app/queries.py @@ -1,34 +1,12 @@ from datetime import date, timedelta import numpy as np +import pandas as pd from sqlalchemy import func from app import db -from app.models import OckovaciMisto, Import - -import pandas as pd - -STATUS_FINISHED = 'FINISHED' - - -def last_import_id(): - """ - Returns id of the last successful import. - """ - last_id = db.session.query(func.max(Import.id)) \ - .filter(Import.status == STATUS_FINISHED) \ - .first()[0] - return -1 if last_id is None else last_id - - -def last_import_date(): - """ - Returns date of the last successful import. - """ - last_date = db.session.query(func.max(Import.date)) \ - .filter(Import.status == STATUS_FINISHED) \ - .first()[0] - return date.today() if last_date is None else last_date +from app.context import get_import_date, get_import_id +from app.models import OckovaciMisto def unique_nrpzs_subquery(): @@ -39,24 +17,23 @@ def unique_nrpzs_subquery(): .subquery() -def count_vaccines(filter_column, filter_value): +def count_vaccines_center(center_id): mista = pd.read_sql_query( """ select ockovaci_mista.id ockovaci_misto_id, ockovaci_mista.nazev, okres_id, kraj_id from ockovaci_mista join okresy on ockovaci_mista.okres_id=okresy.id - where {}='{}'; - """.format(filter_column, filter_value), + where ockovaci_mista.id='{}'; + """.format(center_id), db.engine ) - mista_ids = ','.join("'" + misto + "'" for misto in mista['ockovaci_misto_id'].tolist()) prijato = pd.read_sql_query( """ select ockovaci_misto_id, vyrobce, sum(pocet_davek) prijato from ockovani_distribuce - where akce = 'Příjem' and ockovaci_misto_id in ({}) and cilove_ockovaci_misto_id not in({}) + where akce = 'Příjem' and ockovaci_misto_id = '{}' and datum < '{}' group by (ockovaci_misto_id, vyrobce); - """.format(mista_ids, mista_ids), + """.format(center_id, get_import_date()), db.engine ) @@ -64,9 +41,9 @@ def count_vaccines(filter_column, filter_value): """ select cilove_ockovaci_misto_id ockovaci_misto_id, vyrobce, sum(pocet_davek) prijato_odjinud from ockovani_distribuce - where akce = 'Výdej' and cilove_ockovaci_misto_id in ({}) and ockovaci_misto_id not in({}) + where akce = 'Výdej' and cilove_ockovaci_misto_id = '{}' and datum < '{}' group by (cilove_ockovaci_misto_id, vyrobce); - """.format(mista_ids, mista_ids), + """.format(center_id, get_import_date()), db.engine ) @@ -74,9 +51,9 @@ def count_vaccines(filter_column, filter_value): """ select ockovaci_misto_id, vyrobce, sum(pocet_davek) vydano from ockovani_distribuce - where akce = 'Výdej' and ockovaci_misto_id in ({}) and cilove_ockovaci_misto_id not in({}) + where akce = 'Výdej' and ockovaci_misto_id = '{}' and datum < '{}' group by (ockovaci_misto_id, vyrobce); - """.format(mista_ids, mista_ids), + """.format(center_id, get_import_date()), db.engine ) @@ -84,15 +61,23 @@ def count_vaccines(filter_column, filter_value): """ select ockovaci_misto_id, vyrobce, sum(pouzite_davky) pouzito, sum(znehodnocene_davky) znehodnoceno from ockovani_spotreba - where ockovaci_misto_id in ({}) + where ockovaci_misto_id = '{}' and datum < '{}' group by (ockovaci_misto_id, vyrobce); - """.format(mista_ids), + """.format(center_id, get_import_date()), + db.engine + ) + + vyrobci = pd.read_sql_query( + """ + select distinct(vyrobce) + from ockovani_distribuce; + """, db.engine ) mista_key = mista mista_key['join'] = 0 - vyrobci_key = spotreba[['vyrobce']].drop_duplicates() + vyrobci_key = vyrobci vyrobci_key['join'] = 0 res = mista_key.merge(vyrobci_key).drop('join', axis=1) @@ -116,7 +101,167 @@ def count_vaccines(filter_column, filter_value): return res -def count_registrations(import_id, filter_column, filter_value): +def count_vaccines_kraj(kraj_id): + mista = pd.read_sql_query( + """ + select ockovaci_mista.id ockovaci_misto_id, ockovaci_mista.nazev, kraj_id + from ockovaci_mista join okresy on ockovaci_mista.okres_id=okresy.id + where kraj_id='{}'; + """.format(kraj_id), + db.engine + ) + mista_ids = ','.join("'" + misto + "'" for misto in mista['ockovaci_misto_id'].tolist()) + + prijato = pd.read_sql_query( + """ + select ockovaci_misto_id, vyrobce, sum(pocet_davek) prijato + from ockovani_distribuce + where akce = 'Příjem' and ockovaci_misto_id in ({}) and datum < '{}' + group by (ockovaci_misto_id, vyrobce); + """.format(mista_ids, get_import_date()), + db.engine + ) + + prijato_odjinud = pd.read_sql_query( + """ + select cilove_ockovaci_misto_id ockovaci_misto_id, vyrobce, sum(pocet_davek) prijato_odjinud + from ockovani_distribuce + where akce = 'Výdej' and cilove_ockovaci_misto_id in ({}) and ockovaci_misto_id not in({}) and datum < '{}' + group by (cilove_ockovaci_misto_id, vyrobce); + """.format(mista_ids, mista_ids, get_import_date()), + db.engine + ) + + vydano = pd.read_sql_query( + """ + select ockovaci_misto_id, vyrobce, sum(pocet_davek) vydano + from ockovani_distribuce + where akce = 'Výdej' and ockovaci_misto_id in ({}) and cilove_ockovaci_misto_id not in({}) and cilove_ockovaci_misto_id != '' and datum < '{}' + group by (ockovaci_misto_id, vyrobce); + """.format(mista_ids, mista_ids, get_import_date()), + db.engine + ) + + spotreba = pd.read_sql_query( + """ + select ockovaci_misto_id, vyrobce, sum(znehodnocene_davky) znehodnoceno + from ockovani_spotreba + where ockovaci_misto_id in ({}) and datum < '{}' + group by (ockovaci_misto_id, vyrobce); + """.format(mista_ids, get_import_date()), + db.engine + ) + + ockovano = pd.read_sql_query( + """ + select kraj_nuts_kod kraj_id, sum(pocet) ockovano, + case + when vakcina = 'COVID-19 Vaccine AstraZeneca' then 'AstraZeneca' + when vakcina = 'COVID-19 Vaccine Moderna' then 'Moderna' + when vakcina = 'Comirnaty' then 'Pfizer' + else 'ostatní' end vyrobce + from ockovani_lide + where kraj_nuts_kod = '{}' and datum < '{}' + group by kraj_nuts_kod, vakcina + """.format(kraj_id, get_import_date()), + db.engine + ) + + vyrobci = pd.read_sql_query( + """ + select distinct(vyrobce) + from ockovani_distribuce; + """, + db.engine + ) + + mista_key = mista + mista_key['join'] = 0 + vyrobci_key = vyrobci + vyrobci_key['join'] = 0 + + res = mista_key.merge(vyrobci_key).drop('join', axis=1) + + res = pd.merge(res, prijato, how="left") + res = pd.merge(res, prijato_odjinud, how="left") + res = pd.merge(res, vydano, how="left") + res = pd.merge(res, spotreba, how="left") + + res['prijato'] = res['prijato'].fillna(0).astype('int') + res['prijato_odjinud'] = res['prijato_odjinud'].fillna(0).astype('int') + res['vydano'] = res['vydano'].fillna(0).astype('int') + res['znehodnoceno'] = res['znehodnoceno'].fillna(0).astype('int') + + res = res.groupby(by=['kraj_id', 'vyrobce'], as_index=False).sum() + + res = pd.merge(res, ockovano, how="left") + + res['ockovano'] = res['ockovano'].fillna(0).astype('int') + + res['prijato_celkem'] = res['prijato'] + res['prijato_odjinud'] - res['vydano'] + res['skladem'] = res['prijato_celkem'] - res['ockovano'] - res['znehodnoceno'] + + res = res.groupby(by=['vyrobce'], as_index=False).sum().sort_values(by=['vyrobce']) + + return res + + +def count_vaccines_cr(): + prijato = pd.read_sql_query( + """ + select vyrobce, sum(pocet_davek) prijato + from ockovani_distribuce + where akce = 'Příjem' and datum < '{}' + group by (vyrobce); + """.format(get_import_date()), + db.engine + ) + + spotreba = pd.read_sql_query( + """ + select vyrobce, sum(znehodnocene_davky) znehodnoceno + from ockovani_spotreba + where datum < '{}' + group by (vyrobce); + """.format(get_import_date()), + db.engine + ) + + ockovano = pd.read_sql_query( + """ + select sum(pocet) ockovano, + case + when vakcina = 'COVID-19 Vaccine AstraZeneca' then 'AstraZeneca' + when vakcina = 'COVID-19 Vaccine Moderna' then 'Moderna' + when vakcina = 'Comirnaty' then 'Pfizer' + else 'ostatní' end vyrobce + from ockovani_lide + where datum < '{}' + group by vakcina + """.format(get_import_date()), + db.engine + ) + + res = pd.merge(prijato, spotreba, how="left") + + res['prijato'] = res['prijato'].fillna(0).astype('int') + res['znehodnoceno'] = res['znehodnoceno'].fillna(0).astype('int') + + res = res.groupby(by=['vyrobce'], as_index=False).sum() + + res = pd.merge(res, ockovano, how="left") + + res['ockovano'] = res['ockovano'].fillna(0).astype('int') + + res['prijato_celkem'] = res['prijato'] + res['skladem'] = res['prijato_celkem'] - res['ockovano'] - res['znehodnoceno'] + + res = res.groupby(by=['vyrobce'], as_index=False).sum().sort_values(by=['vyrobce']) + + return res + + +def count_registrations(filter_column, filter_value): mista = pd.read_sql_query( """ select ockovaci_mista.id ockovaci_misto_id from ockovaci_mista join okresy on ockovaci_mista.okres_id=okresy.id @@ -131,33 +276,95 @@ def count_registrations(import_id, filter_column, filter_value): select * from ockovani_registrace where import_id = {} and ockovaci_misto_id in({}) - """.format(import_id, mista_ids), + """.format(get_import_id(), mista_ids), db.engine ) + df['dnes'] = get_import_date() df['datum_rezervace_fix'] = df['datum_rezervace'].where(df['datum_rezervace'] != date(1970, 1, 1)) - df['fronta'] = df[['pocet']].where(df['rezervace'] == False).fillna(0).astype('int') - df['registrace_7'] = df[['pocet']].where(df['datum'] >= date.today() - timedelta(7)) - df['registrace_7_rez'] = df[['pocet']].where((df['rezervace'] == True) & (df['datum'] >= date.today() - timedelta(7))) - df['registrace_14'] = df[['pocet']].where(df['datum'] >= date.today() - timedelta(14)) - df['registrace_14_rez'] = df[['pocet']].where((df['rezervace'] == True) & (df['datum'] >= date.today() - timedelta(14))) - df['registrace_30'] = df[['pocet']].where(df['datum'] >= date.today() - timedelta(30)) - df['registrace_30_rez'] = df[['pocet']].where((df['rezervace'] == True) & (df['datum'] >= date.today() - timedelta(30))) - df['cekani'] = (df['datum_rezervace_fix'] - df['datum']).astype('timedelta64[ns]').dt.days - df['rezervace_7'] = df[['pocet']].where((df['rezervace'] == True) & (df['datum_rezervace_fix'] >= date.today() - timedelta(7))) - df['rezervace_7_x_cekani'] = df['cekani'] * df['rezervace_7'] + df['fronta_pocet'] = df[['pocet']].where(df['rezervace'] == False).fillna(0).astype('int') + df['fronta_cekani'] = (df['dnes'] - df['datum']).astype('timedelta64[ns]').dt.days + df['fronta_pocet_x_cekani'] = df['fronta_pocet'] * df['fronta_cekani'] + df['registrace_7'] = df[['pocet']].where(df['datum'] >= get_import_date() - timedelta(7)) + df['registrace_7_rez'] = df[['pocet']].where((df['rezervace'] == True) & (df['datum'] >= get_import_date() - timedelta(7))) + # df['registrace_14'] = df[['pocet']].where(df['datum'] >= get_import_date() - timedelta(14)) + # df['registrace_14_rez'] = df[['pocet']].where((df['rezervace'] == True) & (df['datum'] >= get_import_date() - timedelta(14))) + # df['registrace_30'] = df[['pocet']].where(df['datum'] >= get_import_date() - timedelta(30)) + # df['registrace_30_rez'] = df[['pocet']].where((df['rezervace'] == True) & (df['datum'] >= get_import_date() - timedelta(30))) + df['rezervace_7_cekani'] = (df['datum_rezervace_fix'] - df['datum']).astype('timedelta64[ns]').dt.days + df['rezervace_7_pocet'] = df[['pocet']].where((df['rezervace'] == True) & (df['datum_rezervace_fix'] >= get_import_date() - timedelta(7))) + df['rezervace_7_pocet_x_cekani'] = df['rezervace_7_cekani'] * df['rezervace_7_pocet'] df = df.groupby(['vekova_skupina', 'povolani']).sum() df['uspesnost_7'] = ((df['registrace_7_rez'] / df['registrace_7']) * 100).replace({np.nan: None}) - df['uspesnost_14'] = ((df['registrace_14_rez'] / df['registrace_14']) * 100).replace({np.nan: None}) - df['uspesnost_30'] = ((df['registrace_30_rez'] / df['registrace_30']) * 100).replace({np.nan: None}) + # df['uspesnost_14'] = ((df['registrace_14_rez'] / df['registrace_14']) * 100).replace({np.nan: None}) + # df['uspesnost_30'] = ((df['registrace_30_rez'] / df['registrace_30']) * 100).replace({np.nan: None}) df['registrace_7'] = df['registrace_7'].astype('int') df['registrace_7_rez'] = df['registrace_7_rez'].astype('int') - df['registrace_14'] = df['registrace_14'].astype('int') - df['registrace_14_rez'] = df['registrace_14_rez'].astype('int') - df['registrace_30'] = df['registrace_30'].astype('int') - df['registrace_30_rez'] = df['registrace_30_rez'].astype('int') - df['prumer_cekani'] = ((df['rezervace_7_x_cekani'] / df['rezervace_7']) / 7).replace({np.nan: None}) + # df['registrace_14'] = df['registrace_14'].astype('int') + # df['registrace_14_rez'] = df['registrace_14_rez'].astype('int') + # df['registrace_30'] = df['registrace_30'].astype('int') + # df['registrace_30_rez'] = df['registrace_30_rez'].astype('int') + df['fronta_prumer_cekani'] = ((df['fronta_pocet_x_cekani'] / df['fronta_pocet']) / 7).replace({np.nan: None}) + df['rezervace_prumer_cekani'] = ((df['rezervace_7_pocet_x_cekani'] / df['rezervace_7_pocet']) / 7).replace({np.nan: None}) + + return df.reset_index().sort_values(by=['vekova_skupina', 'povolani']) + + +def count_vaccinated(kraj_id=None): + ockovani = pd.read_sql_query( + """ + select vekova_skupina, vakcina, poradi_davky, sum(pocet) pocet_ockovani + from ockovani_lide + where datum < '{}' and (kraj_nuts_kod = '{}' or {}) + group by vekova_skupina, vakcina, poradi_davky + """.format(get_import_date(), kraj_id, kraj_id is None), + db.engine + ) + + if kraj_id is not None: + mista = pd.read_sql_query( + """ + select ockovaci_mista.id ockovaci_misto_id from ockovaci_mista join okresy on ockovaci_mista.okres_id=okresy.id + where kraj_id='{}'; + """.format(kraj_id), + db.engine + ) + mista_ids = ','.join("'" + misto + "'" for misto in mista['ockovaci_misto_id'].tolist()) + else: + mista_ids = "''" + + registrace = pd.read_sql_query( + """ + select vekova_skupina, sum(pocet) pocet_fronta + from ockovani_registrace + where rezervace = false and import_id = {} and (ockovaci_misto_id in({}) or {}) + group by vekova_skupina + """.format(get_import_id(), mista_ids, kraj_id is None), + db.engine + ) + + populace = pd.read_sql_query( + """ + select vekova_skupina, sum(pocet) pocet_vek + from populace p + join populace_kategorie k on (k.min_vek <= vek and k.max_vek >= vek) + where orp_kod = '{}' + group by vekova_skupina + """.format('CZ0' if kraj_id is None else kraj_id), + db.engine + ) + + ockovani['vekova_skupina'] = ockovani['vekova_skupina'].replace(['nezařazeno'], 'neuvedeno') + ockovani['pocet_ockovani_castecne'] = ockovani['pocet_ockovani'].where(ockovani['poradi_davky'] == 1).fillna(0).astype('int') + ockovani['pocet_ockovani_plne'] = ockovani['pocet_ockovani'].where((ockovani['poradi_davky'] == 2) | (ockovani['vakcina'].isin([]))).fillna(0).astype('int') + ockovani_grp = ockovani.groupby(['vekova_skupina']).sum().drop('poradi_davky', axis=1).reset_index() + + merged = pd.merge(ockovani_grp, registrace, how="left") + merged = pd.merge(merged, populace, how="left") + + merged['podil_ockovani_castecne'] = (merged['pocet_ockovani_castecne'] / merged['pocet_vek']).replace({np.nan: None}) + merged['podil_ockovani_plne'] = (merged['pocet_ockovani_plne'] / merged['pocet_vek']).replace({np.nan: None}) - return df.reset_index().sort_values(by=['vekova_skupina', 'povolani']) \ No newline at end of file + return merged \ No newline at end of file diff --git a/app/static/styles/style.css b/app/static/styles/style.css index ad31d734..e01122c7 100644 --- a/app/static/styles/style.css +++ b/app/static/styles/style.css @@ -31,6 +31,14 @@ width: 20% !important; } +.w-30 { + width: 30% !important; +} + +.w-35 { + width: 35% !important; +} + .w-40 { width: 40% !important; } \ No newline at end of file diff --git a/app/templates/kraj.html b/app/templates/kraj.html index 12f22c6d..6541fb0b 100644 --- a/app/templates/kraj.html +++ b/app/templates/kraj.html @@ -14,7 +14,7 @@

Kraj: {{ kraj.nazev }}

-
+
@@ -38,22 +38,23 @@

Kraj: {{ kraj.nazev }}

-
- {{ macros.prehled_mist(mista, days) }} -
+ {{ macros.prehled_mist(mista, days) }}
-
+
{{ macros.metrika('Počet obyvatel (18+)', metriky.pocet_obyvatel_dospeli) }} - {{ macros.metrika('Očkovaní (obě dávky)', metriky.ockovani_pocet_2, delta_day=metriky.ockovani_pocet_2_zmena_den, delta_week=metriky.ockovani_pocet_2_zmena_tyden, color='std') }} - {{ macros.metrika('Očkovaní (obě dávky)', metriky.ockovani_pocet_2, delta_day=metriky.ockovani_pocet_2_zmena_den, delta_week=metriky.ockovani_pocet_2_zmena_tyden, color='std', decimal=True, unit='%', multiply=100, divide=metriky.pocet_obyvatel_dospeli) }} - {{ macros.metrika('Očkováno dávek', metriky.ockovani_pocet, delta_day=metriky.ockovani_pocet_zmena_den, delta_week=metriky.ockovani_pocet_zmena_tyden, color='std') }} - - {{ macros.metrika('Přibližně skladem', metriky.vakciny_skladem_pocet, delta_day=metriky.vakciny_skladem_pocet_zmena_den, delta_week=metriky.vakciny_skladem_pocet_zmena_tyden, warning='Odhadovaný počet dávek skladem.
Údaj je počítán z dat o distribuci vakcín, očkovaných lidech a znehodnocených vakcínách. Informace o počtu očkovaných přichází se zpožděním, proto může být reálný počet výrazně nižší. Tento údaj by měl být přesnější než počet uvedený v tabulce "Stav vakcín", který vychází z jiných dat.') }} + {{ macros.metrika('Částečně očkovaní', metriky.ockovani_pocet_castecne, delta_day=metriky.ockovani_pocet_castecne_zmena_den, delta_week=metriky.ockovani_pocet_castecne_zmena_tyden, color='std', info='Počet lidí očkovaných alespoň jednou dávkou.') }} + {{ macros.metrika('Podíl částečně očkovaných', metriky.ockovani_pocet_castecne, delta_day=metriky.ockovani_pocet_castecne_zmena_den, delta_week=metriky.ockovani_pocet_castecne_zmena_tyden, color='std', decimal=True, unit='%', multiply=100, divide=metriky.pocet_obyvatel_dospeli, warning='Podíl alespoň částečně očkovaných dospělých obyvatel.
Počet očkovaných se vztahuje k místu, kde očkování proběhlo, zatímco počet obyvatel se řídí trvalým bydlištěm!') }} + {{ macros.metrika('Plně očkovaní', metriky.ockovani_pocet_plne, delta_day=metriky.ockovani_pocet_plne_zmena_den, delta_week=metriky.ockovani_pocet_plne_zmena_tyden, color='std', info='Počet lidí plně očkovaných (obě dávky).') }} + {{ macros.metrika('Podíl plně očkovaných', metriky.ockovani_pocet_plne, delta_day=metriky.ockovani_pocet_plne_zmena_den, delta_week=metriky.ockovani_pocet_plne_zmena_tyden, color='std', decimal=True, unit='%', multiply=100, divide=metriky.pocet_obyvatel_dospeli, warning='Podíl plně očkovaných dospělých obyvatel.
Počet očkovaných se vztahuje k místu, kde očkování proběhlo, zatímco počet obyvatel se řídí trvalým bydlištěm!') }} + {{ macros.metrika('Přijaté dávky', metriky.vakciny_prijate_pocet, delta_day=metriky.vakciny_prijate_pocet_zmena_den, delta_week=metriky.vakciny_prijate_pocet_zmena_tyden, color='std', info='Počet dávek přijatých na očkovací centra v kraji.
U dávek vydaných mimo očkovací místa (např. praktickým lékařům) předpokládáme, že zůstaly ve stejném kraji.') }} + {{ macros.metrika('Očkované dávky', metriky.ockovani_pocet_davek, delta_day=metriky.ockovani_pocet_davek_zmena_den, delta_week=metriky.ockovani_pocet_davek_zmena_tyden, color='std', info="Počet dávek očkovaných očkovacími centry a praktickými lékaři v kraji podle vykázaných očkování.") }} + {{ macros.metrika('Přibližně skladem', metriky.vakciny_skladem_pocet, delta_day=metriky.vakciny_skladem_pocet_zmena_den, delta_week=metriky.vakciny_skladem_pocet_zmena_tyden, warning='Odhadovaný počet dávek skladem.
Údaj je počítán z dat o distribuci, spotřebě vakcín a očkovaných lidech. Jednotlivé datové sady mají různá zpoždění a nepřesnosti, proto údaj berte jako orientační.') }} {{ macros.metrika('Čekající ve frontě', metriky.registrace_fronta, delta_day=metriky.registrace_fronta_zmena_den, delta_week=metriky.registrace_fronta_zmena_tyden, color='rev', info='Počet registrovaných čekajících na rezervaci konkrétního termínu (přibližně odpovídá čekajícím na SMS s PIN2).') }} {{ macros.metrika('Čekající s rezervací', metriky.rezervace_cekajici, delta_day=metriky.rezervace_cekajici_zmena_den, delta_week=metriky.rezervace_cekajici_zmena_tyden, info='Počet registrovaných s rezervovaným konkrétním termínem na očkování.') }} - {{ macros.metrika('Dnešní kapacita', metriky.rezervace_kapacita, delta_day=metriky.rezervace_kapacita_zmena_den, delta_week=metriky.rezervace_kapacita_zmena_tyden, color='std', info='Dnešní kapacita pro očkování první dávkou. Získáno z maximální kapacity uvedené v rezervačním systému.') }} - {{ macros.metrika('Čekání na rezervaci', metriky.registrace_prumer_cekani, delta_day=metriky.registrace_prumer_cekani_zmena_den, delta_week=metriky.registrace_prumer_cekani_zmena_tyden, decimal=True, unit='týdne', divide=7, color='rev', info='Průměrná doba mezi registrací a rezervací konkrétního termínu za posledních 7 dní (přibližně odpovídá čekání na SMS s PIN2).') }} + {{ macros.metrika('Dnešní kapacita', metriky.rezervace_kapacita, delta_day=metriky.rezervace_kapacita_zmena_den, delta_week=metriky.rezervace_kapacita_zmena_tyden, color='std', info='Dnešní celková kapacita pro očkování.
Získáno z maximální kapacity uvedené v rezervačním systému.') }} + {{ macros.metrika('Čekání na rezervaci', metriky.registrace_prumer_cekani, delta_day=metriky.registrace_prumer_cekani_zmena_den, delta_week=metriky.registrace_prumer_cekani_zmena_tyden, decimal=True, unit='týdne', divide=7, color='rev', info='Průměrná doba mezi registrací a rezervací konkrétního termínu za posledních 7 dní (přibližně odpovídá čekání na SMS s PIN2). Pokud přednost dostávají prioritní skupiny, odpovídá tento údaj spíše jejich čekání.') }} + {{ macros.metrika('Doba ve frontě', metriky.registrace_fronta_prumer_cekani, delta_day=metriky.registrace_fronta_prumer_cekani_zmena_den, delta_week=metriky.registrace_fronta_prumer_cekani_zmena_tyden, decimal=True, unit='týdne', divide=7, color='rev', info='Průměrná doba strávená čekajícími ve frontě k dnešnímu dni.') }} {{ macros.metrika('7denní úspěšnost', metriky.registrace_tydenni_uspesnost, delta_day=metriky.registrace_tydenni_uspesnost_zmena_den, delta_week=metriky.registrace_tydenni_uspesnost_zmena_tyden, decimal=True, unit='%', multiply=100, color='std', info='Poměr počtu registrovaných za posledních 7 dní s vybraným termínem ku počtu všech registrovaných za posledních 7 dní.') }} {{ macros.metrika('14denní úspěšnost', metriky.registrace_14denni_uspesnost, delta_day=metriky.registrace_14denni_uspesnost_zmena_den, delta_week=metriky.registrace_14denni_uspesnost_zmena_tyden, decimal=True, unit='%', multiply=100, color='std', info='Poměr počtu registrovaných za posledních 14 dní s vybraným termínem ku počtu všech registrovaných za posledních 14 dní.') }} {{ macros.metrika('30denní úspěšnost', metriky.registrace_30denni_uspesnost, delta_day=metriky.registrace_30denni_uspesnost_zmena_den, delta_week=metriky.registrace_30denni_uspesnost_zmena_tyden, decimal=True, unit='%', multiply=100, color='std', info='Poměr počtu registrovaných za posledních 30 dní s vybraným termínem ku počtu všech registrovaných za posledních 30 dní.') }} @@ -62,15 +63,11 @@

Kraj: {{ kraj.nazev }}

{{ macros.stav_registraci(registrations) }}
-
-
- {{ macros.stav_vakcin(vaccines) }} -
-
-
- {{ macros.stav_ockovani(vac_age) }} -
+ {{ macros.stav_ockovani(vaccinated) }} +
+
+ {{ macros.stav_vakcin(vaccines) }}
diff --git a/app/templates/macros.html b/app/templates/macros.html index a46b3adb..83fc2e01 100644 --- a/app/templates/macros.html +++ b/app/templates/macros.html @@ -3,7 +3,7 @@
{% if centers %}
- +
@@ -16,13 +16,13 @@ @@ -75,37 +75,44 @@ {%- endmacro %} + {% macro stav_vakcin(vaccines) -%}
-
Název - Čekání na rezervaci v týdnech - + Čekání na rezervaci + - Týdnů k naočkování registrovaných + Naočkování registrovaných @@ -53,12 +53,12 @@ - {{ (None if item.registrace_prumer_cekani == None else (item.registrace_prumer_cekani / 7)) | format_decimal }} + {{ (None if item.registrace_prumer_cekani == None else (item.registrace_prumer_cekani / 7)) | format_decimal }} {{ 'týdne' if item.registrace_prumer_cekani != None }} - {{ (None if item.ockovani_odhad_cekani == None else (item.ockovani_odhad_cekani / 7)) | format_decimal }} + {{ (None if item.ockovani_odhad_cekani == None else (item.ockovani_odhad_cekani / 7)) | format_decimal }} {{ 'týdne' if item.ockovani_odhad_cekani != None }}
+
+ {% if 'pouzito' in vaccines %} + {% else %} + + {% endif %} @@ -115,7 +122,11 @@ + {% if 'pouzito' in row %} + {% else %} + + {% endif %} @@ -125,39 +136,45 @@ + {% if 'pouzito' in vaccines %} + {% else %} + + {% endif %}
Výrobce Přijato - + Použito - + + + + Očkováno + Zničeno - + Skladem - +
{{ row['vyrobce'] }} {{ row['prijato_celkem'] | format_number }}{{ row['pouzito'] | format_number }}{{ row['ockovano'] | format_number }}{{ row['znehodnoceno'] | format_number }} {{ row['skladem'] | format_number }}
Celkem {{ vaccines['prijato_celkem'].sum() | format_number }}{{ vaccines['pouzito'].sum() | format_number }}{{ vaccines['ockovano'].sum() | format_number }}{{ vaccines['znehodnoceno'].sum() | format_number }} {{ vaccines['skladem'].sum() | format_number }}
-

- Jde o orientační výpočet z distribuce a spotřeby vakcín. Dataset spotřeba vakcín vykazuje - velké zpoždění a nepřesnosti! -

{%- endmacro %} + {% macro stav_registraci(registrations) -%}
- +
- + + + \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", - " \n", " \n", - " \n", - " \n", " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", " \n", + " \n", + " \n", + " \n", + " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -249,21 +298,21 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -277,7 +326,7 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", @@ -291,36 +340,36 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", " \n", - " \n", " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", " \n", " \n", " \n", - " \n", " \n", - " \n", " \n", + " \n", " \n", + " \n", " \n", " \n", "
Věková
skupina
PovoláníPovolání Ve frontě - - Čekání na rezervaci v týdnech - + Doba ve frontě + + + 7denní úspěšnost - {{ row['fronta'] | format_number }} + {{ row['fronta_pocet'] | format_number }} - - {{ row['prumer_cekani'] | format_decimal }} + + {{ row['rezervace_prumer_cekani'] | format_decimal }} {{ 'týdne' if row['rezervace_prumer_cekani'] != None }} + + + + {{ row['fronta_prumer_cekani'] | format_decimal }} {{ 'týdne' if row['fronta_prumer_cekani'] != None }} @@ -195,15 +217,71 @@ {%- endmacro %} + +{% macro stav_ockovani(vaccinated) -%} +
+ + + + + + + + + + + {% for idx, row in vaccinated.iterrows() %} + + + + + + + + + {% endfor %} + + + + + + + + + + + +
Věková skupina + Ve frontě + + + + Částečně očkovaní + + + + Plně očkovaní + + +
{{ row['vekova_skupina'] }}{{ row['pocet_fronta'] | format_number }}{{ row['pocet_ockovani_castecne'] | format_number }}{% if row['podil_ockovani_castecne'] %} {{ (100 * row['podil_ockovani_castecne']) | format_decimal }} % {% endif %}{{ row['pocet_ockovani_plne'] | format_number }}{% if row['podil_ockovani_plne'] %} {{ (100 * row['podil_ockovani_plne']) | format_decimal }} % {% endif %}
Celkem{{ vaccinated['pocet_fronta'].sum() | format_number }}{{ vaccinated['pocet_ockovani_castecne'].sum() | format_number }}{{ (100 * vaccinated['pocet_ockovani_castecne'].sum() / vaccinated['pocet_vek'].sum()) | format_decimal }} %{{ vaccinated['pocet_ockovani_plne'].sum() | format_number }}{{ (100 * vaccinated['pocet_ockovani_plne'].sum() / vaccinated['pocet_vek'].sum()) | format_decimal }} %
+
+{%- endmacro %} + + {% macro metrika(name, number, delta_day=None, delta_week=None, decimal=False, unit='', multiply=1, divide=1, color=None, info=None, warning=None) -%} {% if number != None %} -
+
- {{ name }} + + {{ name }} +
@@ -220,8 +298,7 @@
{% if decimal %} -

{{ ((number * multiply) / divide) | format_decimal }} {{ unit - }}

+

{{ ((number * multiply) / divide) | format_decimal }} {{ unit }}

{% if delta_day != None %} {% set delta_day_mult = (delta_day * multiply) / divide %} @@ -267,61 +344,4 @@

{% endif %} -{%- endmacro %} - -{% macro stav_ockovani(vac_age) -%} - -{% if vac_age %} - - - - - - - - - - - {% set sum=namespace(fronta = 0, sum_1 = 0, sum_2 = 0) %} - {% for item in vac_age %} - {% set sum.fronta = sum.fronta + item.fronta %} - {% set sum.sum_1 = sum.sum_1 + item.sum_1 %} - {% set sum.sum_2 = sum.sum_2 + item.sum_2 %} - - - - - - - {% endfor %} - - - - - - - - - -
Věková skupina - Ve frontě - - - - 1 dávka - - - - 2 dávky - - -
{{ item.vekova_skupina }}{{ item.fronta | format_number }}{{ item.sum_1 | format_number }}{{ item.sum_2 | format_number }}
Celkem{{ sum.fronta | format_number }}{{ sum.sum_1 | format_number }}{{ sum.sum_2 | format_number }}
-{% else %} - -{% endif %} {%- endmacro %} \ No newline at end of file diff --git a/app/templates/mapa.html b/app/templates/mapa.html index 1cdea82d..8c97458c 100644 --- a/app/templates/mapa.html +++ b/app/templates/mapa.html @@ -57,7 +57,7 @@

Očkovací místa

"Bezbariérový přístup: {{ 'Ano' if misto.bezbarierovy_pristup else 'Ne' }}
" + "Čekání na rezervaci v týdnech: {{ (None if misto.registrace_prumer_cekani == None else (misto.registrace_prumer_cekani / 7)) | format_decimal }}
" + "Odhad týdnů potřebných k naočkování lidí ve frontě a rezervacích: {{ (None if misto.ockovani_odhad_cekani == None else (misto.ockovani_odhad_cekani / 7)) | format_decimal }}
" + - "Detail místa"; + 'Detail místa'; card.getFooter().style = "display: none"; card.getContainer().style.padding = "0"; marker.decorate(SMap.Marker.Feature.Card, card); diff --git a/app/templates/misto.html b/app/templates/misto.html index 3314df2a..7c0b4446 100644 --- a/app/templates/misto.html +++ b/app/templates/misto.html @@ -12,8 +12,8 @@

Očkovací místo: {{ misto.nazev }}

-
-
+
+
Podrobnosti o očkovacím místě
@@ -41,7 +41,7 @@
Podrobnosti o očkovacím místě
-
+
Mapa
@@ -53,7 +53,7 @@
Mapa
-
+
3989b3700-401f-4700-a684-ae09d348a3c0Nemocnice HořoviceCZ0202CZ020a91d8128-c379-456c-b04b-1f1d6aa2da76AGE Centrum OlomoucCZ0712CZ071Moderna90007053003000000
4989b3700-401f-4700-a684-ae09d348a3c0Nemocnice HořoviceCZ0202CZ020a91d8128-c379-456c-b04b-1f1d6aa2da76AGE Centrum OlomoucCZ0712CZ071Pfizer264002520406815030663082212
......
82984798c76ec8-f7d1-474a-927c-d4a4fb2dcd0aÚVN Praha - skladCZ0100CZ010Pfizer3276023402251836270036869418387027522
83084898c76ec8-f7d1-474a-927c-d4a4fb2dcd0aÚVN Praha - skladCZ01000
831849cb0f8a24-3c54-467e-9e67-de01f424ea85Česká Lípa očkovací místo CrystalCZ05110
832850cb0f8a24-3c54-467e-9e67-de01f424ea85Česká Lípa očkovací místo CrystalCZ0511CZ051Pfizer02874031140-24037380-3738
833851cb0f8a24-3c54-467e-9e67-de01f424ea85Česká Lípa očkovací místo CrystalCZ0511CZ051AstraZeneca0400040004000-400
\n", - "

834 rows × 11 columns

\n", + "

852 rows × 11 columns

\n", "
" ], "text/plain": [ @@ -328,58 +377,58 @@ "0 63c9078b-0701-4da0-821e-4eaa0d9c9968 \n", "1 63c9078b-0701-4da0-821e-4eaa0d9c9968 \n", "2 63c9078b-0701-4da0-821e-4eaa0d9c9968 \n", - "3 989b3700-401f-4700-a684-ae09d348a3c0 \n", - "4 989b3700-401f-4700-a684-ae09d348a3c0 \n", + "3 a91d8128-c379-456c-b04b-1f1d6aa2da76 \n", + "4 a91d8128-c379-456c-b04b-1f1d6aa2da76 \n", ".. ... \n", - "829 98c76ec8-f7d1-474a-927c-d4a4fb2dcd0a \n", - "830 98c76ec8-f7d1-474a-927c-d4a4fb2dcd0a \n", - "831 cb0f8a24-3c54-467e-9e67-de01f424ea85 \n", - "832 cb0f8a24-3c54-467e-9e67-de01f424ea85 \n", - "833 cb0f8a24-3c54-467e-9e67-de01f424ea85 \n", + "847 98c76ec8-f7d1-474a-927c-d4a4fb2dcd0a \n", + "848 98c76ec8-f7d1-474a-927c-d4a4fb2dcd0a \n", + "849 cb0f8a24-3c54-467e-9e67-de01f424ea85 \n", + "850 cb0f8a24-3c54-467e-9e67-de01f424ea85 \n", + "851 cb0f8a24-3c54-467e-9e67-de01f424ea85 \n", "\n", " nazev okres_id kraj_id \\\n", "0 Krajská zdravotní a.s., - MNUL pracoviště výst... CZ0423 CZ042 \n", "1 Krajská zdravotní a.s., - MNUL pracoviště výst... CZ0423 CZ042 \n", "2 Krajská zdravotní a.s., - MNUL pracoviště výst... CZ0423 CZ042 \n", - "3 Nemocnice Hořovice CZ0202 CZ020 \n", - "4 Nemocnice Hořovice CZ0202 CZ020 \n", + "3 AGE Centrum Olomouc CZ0712 CZ071 \n", + "4 AGE Centrum Olomouc CZ0712 CZ071 \n", ".. ... ... ... \n", - "829 ÚVN Praha - sklad CZ0100 CZ010 \n", - "830 ÚVN Praha - sklad CZ0100 CZ010 \n", - "831 Česká Lípa očkovací místo Crystal CZ0511 CZ051 \n", - "832 Česká Lípa očkovací místo Crystal CZ0511 CZ051 \n", - "833 Česká Lípa očkovací místo Crystal CZ0511 CZ051 \n", + "847 ÚVN Praha - sklad CZ0100 CZ010 \n", + "848 ÚVN Praha - sklad CZ0100 CZ010 \n", + "849 Česká Lípa očkovací místo Crystal CZ0511 CZ051 \n", + "850 Česká Lípa očkovací místo Crystal CZ0511 CZ051 \n", + "851 Česká Lípa očkovací místo Crystal CZ0511 CZ051 \n", "\n", " vyrobce prijato prijato_odjinud vydano pouzito znehodnoceno \\\n", "0 Moderna 0 0 0 0 0 \n", "1 Pfizer 0 0 0 0 0 \n", "2 AstraZeneca 0 0 0 0 0 \n", - "3 Moderna 900 0 70 530 0 \n", - "4 Pfizer 0 4068 150 3066 30 \n", + "3 Moderna 0 0 0 0 0 \n", + "4 Pfizer 264 0 0 252 0 \n", ".. ... ... ... ... ... ... \n", - "829 Pfizer 32760 2340 22518 8694 18 \n", - "830 AstraZeneca 0 0 0 0 0 \n", - "831 Moderna 0 0 0 0 0 \n", - "832 Pfizer 0 2874 0 3114 0 \n", - "833 AstraZeneca 0 400 0 400 0 \n", + "847 Pfizer 36270 0 36 8694 18 \n", + "848 AstraZeneca 0 0 0 0 0 \n", + "849 Moderna 0 0 0 0 0 \n", + "850 Pfizer 0 0 0 3738 0 \n", + "851 AstraZeneca 0 0 0 400 0 \n", "\n", " skladem \n", "0 0 \n", "1 0 \n", "2 0 \n", - "3 300 \n", - "4 822 \n", + "3 0 \n", + "4 12 \n", ".. ... \n", - "829 3870 \n", - "830 0 \n", - "831 0 \n", - "832 -240 \n", - "833 0 \n", + "847 27522 \n", + "848 0 \n", + "849 0 \n", + "850 -3738 \n", + "851 -400 \n", "\n", - "[834 rows x 11 columns]" + "[852 rows x 11 columns]" ] }, - "execution_count": 238, + "execution_count": 72, "metadata": {}, "output_type": "execute_result" } @@ -388,7 +437,7 @@ "mista_key = mista\n", "mista_key['join'] = 0\n", "\n", - "vyrobci_key = spotreba[['vyrobce']].drop_duplicates()\n", + "vyrobci_key = vyrobci\n", "vyrobci_key['join'] = 0\n", "\n", "merged = mista_key.merge(vyrobci_key).drop('join', axis=1)\n",