From 636a941605f3327250555a840fbaf803f502e7b1 Mon Sep 17 00:00:00 2001 From: Piotr Gawron <piotr.gawron@uni.lu> Date: Fri, 17 Apr 2020 09:46:47 +0200 Subject: [PATCH] list of finished appointments is exported --- smash/smash/settings.py | 3 +- smash/web/importer/__init__.py | 7 ++-- smash/web/importer/exporter.py | 53 ++++++++++++++++++++++++- smash/web/importer/exporter_cron_job.py | 45 ++++++++++++++++++--- 4 files changed, 96 insertions(+), 12 deletions(-) diff --git a/smash/smash/settings.py b/smash/smash/settings.py index 7cd843ec..b443f110 100644 --- a/smash/smash/settings.py +++ b/smash/smash/settings.py @@ -76,7 +76,8 @@ CRON_CLASSES = [ 'web.views.kit.KitRequestEmailSendJob', 'web.redcap_connector.RedCapRefreshJob', 'web.views.voucher.ExpireVouchersJob', - 'web.importer.exporter_cron_job.ExporterCronJob', + 'web.importer.exporter_cron_job.SubjectExporterCronJob', + 'web.importer.exporter_cron_job.VisitExporterCronJob', 'web.importer.importer_cron_job.SubjectImporterCronJob', 'web.importer.importer_cron_job.VisitImporterCronJob' ] diff --git a/smash/web/importer/__init__.py b/smash/web/importer/__init__.py index f60887a0..7740b827 100644 --- a/smash/web/importer/__init__.py +++ b/smash/web/importer/__init__.py @@ -1,12 +1,13 @@ from csv_subject_import_reader import CsvSubjectImportReader from csv_tns_subject_import_reader import TnsCsvSubjectImportReader from csv_tns_visit_import_reader import TnsCsvVisitImportReader -from exporter import Exporter -from exporter_cron_job import ExporterCronJob +from exporter import SubjectExporter, VisitExporter +from exporter_cron_job import SubjectExporterCronJob, VisitExporterCronJob from importer import Importer from importer_cron_job import SubjectImporterCronJob, VisitImporterCronJob from subject_import_reader import SubjectImportReader from warning_counter import MsgCounterHandler __all__ = [Importer, SubjectImportReader, CsvSubjectImportReader, SubjectImporterCronJob, VisitImporterCronJob, - Exporter, ExporterCronJob, TnsCsvSubjectImportReader, TnsCsvVisitImportReader, MsgCounterHandler] + SubjectExporter, VisitExporter, SubjectExporterCronJob, VisitExporterCronJob, TnsCsvSubjectImportReader, + TnsCsvVisitImportReader, MsgCounterHandler] diff --git a/smash/web/importer/exporter.py b/smash/web/importer/exporter.py index ebdf57df..6c44efbc 100644 --- a/smash/web/importer/exporter.py +++ b/smash/web/importer/exporter.py @@ -1,14 +1,16 @@ # coding=utf-8 import csv import logging +import sys +import traceback from warning_counter import MsgCounterHandler -from web.models import StudySubject +from web.models import StudySubject, Appointment logger = logging.getLogger(__name__) -class Exporter(object): +class SubjectExporter(object): def __init__(self, filename): # type: (str) -> None self.filename = filename @@ -48,3 +50,50 @@ class Exporter(object): for study_subject in study_subjects: result.append([study_subject.nd_number]) return result + + +class VisitExporter(object): + def __init__(self, filename): + # type: (str) -> None + self.filename = filename + self.exported_count = 0 + self.warning_count = 0 + + def execute(self): + self.exported_count = 0 + self.warning_count = 0 + + warning_counter = MsgCounterHandler() + logging.getLogger('').addHandler(warning_counter) + + with open(self.filename, 'w') as csv_file: + data = self.get_appointments_as_array() + writer = csv.writer(csv_file, quotechar=str(u'"')) + for row in data: + writer.writerow([s.encode("utf-8") for s in row]) + self.exported_count += 1 + + if "WARNING" in warning_counter.level2count: + self.warning_count = warning_counter.level2count["WARNING"] + logging.getLogger('').removeHandler(warning_counter) + + def get_summary(self): + result = "<p>Number of entries: <b>" + str(self.exported_count) + "</b></p>" + style = '' + if self.warning_count > 0: + style = ' color="brown" ' + result += "<p><font " + style + ">Number of raised warnings: <b>" + str(self.warning_count) + "</b></font></p>" + + return result + + def get_appointments_as_array(self): + result = [] + appointments = Appointment.objects.filter(status=Appointment.APPOINTMENT_STATUS_FINISHED) + for appointment in appointments: + try: + if appointment.visit is not None: + result.append([appointment.visit.subject.nd_number, str(appointment.visit.visit_number - 1)]) + except: + traceback.print_exc(file=sys.stdout) + logger.warn("Problem with exporting appointment: " + str(appointment.id)) + return result diff --git a/smash/web/importer/exporter_cron_job.py b/smash/web/importer/exporter_cron_job.py index 8ea23426..6491077e 100644 --- a/smash/web/importer/exporter_cron_job.py +++ b/smash/web/importer/exporter_cron_job.py @@ -6,21 +6,21 @@ import timeout_decorator from django.conf import settings from django_cron import CronJobBase, Schedule -from exporter import Exporter +from exporter import SubjectExporter, VisitExporter from web.models.constants import CRON_JOB_TIMEOUT from ..smash_email import EmailSender logger = logging.getLogger(__name__) -class ExporterCronJob(CronJobBase): +class SubjectExporterCronJob(CronJobBase): RUN_AT_TIMES = getattr(settings, "EXPORT_RUN_AT", ['23:55']) schedule = Schedule(run_at_times=RUN_AT_TIMES) - code = 'web.import_daily_job' # a unique code + code = 'web.export_subject_daily_job' # a unique code @timeout_decorator.timeout(CRON_JOB_TIMEOUT) def do(self): - email_title = "Daily export" + email_title = "Daily subject export" email_recipients = getattr(settings, "DEFAULT_FROM_EMAIL", None) filename = getattr(settings, "DAILY_SUBJECT_EXPORT_FILE", None) @@ -28,9 +28,42 @@ class ExporterCronJob(CronJobBase): if filename is None: logger.info("Exporting subjects skipped. File not defined ") return "export file not defined" - logger.info("Exporting subjects from file: " + filename) + logger.info("Exporting subjects to file: " + filename) try: - exporter = Exporter(settings.DAILY_SUBJECT_EXPORT_FILE) + exporter = SubjectExporter(filename) + exporter.execute() + email_body = exporter.get_summary() + EmailSender().send_email(email_title, + "<h3>Data was successfully exported to file: " + filename + "</h3>" + email_body, + email_recipients) + return "export is successful" + + except: + tb = traceback.format_exc() + EmailSender().send_email(email_title, + "<h3><font color='red'>There was a problem with exporting data to file: " + filename + "</font></h3><pre>" + tb + "</pre>", + email_recipients) + return "export crashed" + + +class VisitExporterCronJob(CronJobBase): + RUN_AT_TIMES = getattr(settings, "EXPORT_RUN_AT", ['23:55']) + schedule = Schedule(run_at_times=RUN_AT_TIMES) + code = 'web.export_visit_daily_job' # a unique code + + @timeout_decorator.timeout(CRON_JOB_TIMEOUT) + def do(self): + email_title = "Daily visit export" + email_recipients = getattr(settings, "DEFAULT_FROM_EMAIL", None) + + filename = getattr(settings, "DAILY_VISIT_EXPORT_FILE", None) + + if filename is None: + logger.info("Exporting visit skipped. File not defined ") + return "export file not defined" + logger.info("Exporting visits to file: " + filename) + try: + exporter = VisitExporter(filename) exporter.execute() email_body = exporter.get_summary() EmailSender().send_email(email_title, -- GitLab