diff --git a/smash/web/migrations/0179_visitimportdata.py b/smash/web/migrations/0179_visitimportdata.py index 43beb8cc01cc67d43c77dee80cfd28a3d97c0d22..98be3741686f3b768e3e541319a43803beff7a4b 100644 --- a/smash/web/migrations/0179_visitimportdata.py +++ b/smash/web/migrations/0179_visitimportdata.py @@ -1,4 +1,4 @@ -# Generated by Django 2.0.13 on 2020-11-17 07:22 +# Generated by Django 2.0.13 on 2020-11-18 10:51 from django.db import migrations, models import django.db.models.deletion @@ -12,18 +12,41 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='VisitImportData', + name='EtlData', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('filename', models.CharField(blank=True, default='', max_length=128, verbose_name='File used for automatic import')), + ('run_at_times', models.CharField(blank=True, default='', max_length=1024, verbose_name='At what time automatic import should run')), + ], + ), + migrations.CreateModel( + name='VisitImportData', + fields=[ + ('etldata_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='web.EtlData')), + ('subject_id_column_name', models.CharField(default='donor_id', max_length=128, verbose_name='Subject id column name')), + ('visit_date_column_name', models.CharField(default='dateofvisit', max_length=128, verbose_name='Visit date column name')), + ('location_column_name', models.CharField(default='adressofvisit', max_length=128, verbose_name='Location column name')), + ('visit_number_column_name', models.CharField(default='visit_id', max_length=128, verbose_name='Visit number column name')), ('appointment_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='web.AppointmentType', verbose_name='Default appointment type')), - ('import_worker', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Worker', verbose_name='Worker used by importer')), - ('study', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='web.Study', verbose_name='Study')), - ('subject_id_column_name', models.CharField(blank=False, default='donor_id', max_length=128, null=False,verbose_name='Subject id column name')), - ('visit_date_column_name', models.CharField(blank=False, default='dateofvisit', max_length=128, null=False,verbose_name='Visit date column name')), - ('location_column_name', models.CharField(blank=False, default='adressofvisit', max_length=128, null=False,verbose_name='Location column name')), - ('visit_number_column_name', models.CharField(blank=False, default='visit_id', max_length=128, null=False,verbose_name='Visit number column name')), - ('filename', models.CharField(blank=True, default='', max_length=128, null=False, verbose_name='File used for automatic import')), - ('run_at_times', models.CharField(blank=True, default='', max_length=1024, null=False, verbose_name='At what time automatic import should run')), ], + bases=('web.etldata',), + ), + migrations.AddField( + model_name='etldata', + name='import_worker', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='web.Worker', verbose_name='Worker used by importer'), ), + migrations.AddField( + model_name='etldata', + name='study', + field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to='web.Study', verbose_name='Study'), + ), + migrations.CreateModel( + name='SubjectImportData', + fields=[ + ('etldata_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='web.EtlData')), + ], + bases=('web.etldata',), + ), + ] diff --git a/smash/web/models/__init__.py b/smash/web/models/__init__.py index 376f0f96d5e9f820e6ed3862418b08280fd2b624..07cf110eacd4187c33590a8ca3d64f06ea4f5f54 100644 --- a/smash/web/models/__init__.py +++ b/smash/web/models/__init__.py @@ -39,7 +39,7 @@ from .mail_template import MailTemplate from .missing_subject import MissingSubject from .inconsistent_subject import InconsistentSubject, InconsistentField -from .etl import VisitImportData +from .etl import VisitImportData, SubjectImportData __all__ = [Study, FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room, Subject, StudySubject, StudySubjectList, SubjectColumns, StudyNotificationParameters, diff --git a/smash/web/models/etl/__init__.py b/smash/web/models/etl/__init__.py index 98fb9988d5cf755972c854b35ae5d39684f97dfa..7b6f5699f77ab6e49c3576cd96e8872ae3c5d1c1 100644 --- a/smash/web/models/etl/__init__.py +++ b/smash/web/models/etl/__init__.py @@ -1,3 +1,4 @@ from .visit_import import VisitImportData +from .subject_import import SubjectImportData -__all__ = [VisitImportData] +__all__ = [VisitImportData, SubjectImportData] diff --git a/smash/web/models/etl/etl.py b/smash/web/models/etl/etl.py new file mode 100644 index 0000000000000000000000000000000000000000..c2a430f197248a37b2fbe862ac3ed827ed3a1cda --- /dev/null +++ b/smash/web/models/etl/etl.py @@ -0,0 +1,49 @@ +# coding=utf-8 +import logging +import os + +from django.conf import settings +from django.db import models + +logger = logging.getLogger(__name__) + + +class EtlData(models.Model): + study = models.ForeignKey("web.Study", + verbose_name='Study', + editable=False, + null=False, + on_delete=models.CASCADE + ) + + import_worker = models.ForeignKey("web.Worker", + verbose_name='Worker used by importer', + blank=True, + null=True, + on_delete=models.CASCADE + ) + + filename = models.CharField(max_length=128, + verbose_name='File used for automatic import', + default='', + null=False, + blank=True + ) + run_at_times = models.CharField(max_length=1024, + verbose_name='At what time automatic import should run', + default='', + null=False, + blank=True + ) + + def file_available(self) -> bool: + if self.filename is None or self.filename == '': + return False + absolute_path = self.get_absolute_file_path() + if os.path.basename(absolute_path) != self.filename: + logger.warning('File "{}" outside defined ETL_ROOT: {}'.format(self.filename, settings.ETL_ROOT)) + return False + return os.path.isfile(absolute_path) + + def get_absolute_file_path(self) -> str: + return os.path.join(settings.ETL_ROOT, self.filename) diff --git a/smash/web/models/etl/subject_import.py b/smash/web/models/etl/subject_import.py new file mode 100644 index 0000000000000000000000000000000000000000..5884586995e0b39eeb05c7b07caaa483ea6394ed --- /dev/null +++ b/smash/web/models/etl/subject_import.py @@ -0,0 +1,10 @@ +# coding=utf-8 +import logging + +from web.models.etl.etl import EtlData + +logger = logging.getLogger(__name__) + + +class SubjectImportData(EtlData): + pass diff --git a/smash/web/models/etl/visit_import.py b/smash/web/models/etl/visit_import.py index ac83ecf7f7ace8a88326483535afb875c1bcdba9..b7b4abf57bf0f3e94f1eda241028094ad0e2c045 100644 --- a/smash/web/models/etl/visit_import.py +++ b/smash/web/models/etl/visit_import.py @@ -1,21 +1,14 @@ # coding=utf-8 import logging -import os -from django.conf import settings from django.db import models -logger = logging.getLogger(__name__) +from web.models.etl.etl import EtlData +logger = logging.getLogger(__name__) -class VisitImportData(models.Model): - study = models.ForeignKey("web.Study", - verbose_name='Study', - editable=False, - null=False, - on_delete=models.CASCADE - ) +class VisitImportData(EtlData): appointment_type = models.ForeignKey("web.AppointmentType", verbose_name='Default appointment type', blank=True, @@ -23,13 +16,6 @@ class VisitImportData(models.Model): on_delete=models.CASCADE ) - import_worker = models.ForeignKey("web.Worker", - verbose_name='Worker used by importer', - blank=True, - null=True, - on_delete=models.CASCADE - ) - subject_id_column_name = models.CharField(max_length=128, verbose_name='Subject id column name', default='donor_id', @@ -43,39 +29,17 @@ class VisitImportData(models.Model): null=False, blank=False ) + location_column_name = models.CharField(max_length=128, verbose_name='Location column name', default='adressofvisit', null=False, blank=False ) + visit_number_column_name = models.CharField(max_length=128, verbose_name='Visit number column name', default='visit_id', null=False, blank=False ) - filename = models.CharField(max_length=128, - verbose_name='File used for automatic import', - default='', - null=False, - blank=True - ) - run_at_times = models.CharField(max_length=1024, - verbose_name='At what time automatic import should run', - default='', - null=False, - blank=True - ) - - def file_available(self): - if self.filename is None or self.filename == '': - return False - absolute_path = self.get_absolute_file_path() - if os.path.basename(absolute_path) != self.filename: - logger.warning('File "{}" outside defined ETL_ROOT: {}'.format(self.filename, settings.ETL_ROOT)) - return False - return os.path.isfile(absolute_path) - - def get_absolute_file_path(self) -> str: - return os.path.join(settings.ETL_ROOT, self.filename)