From d2f2e22a371e48ac6761639bd460da31c4ff8d07 Mon Sep 17 00:00:00 2001
From: schroeder5 <s.schroeder@fz-juelich.de>
Date: Tue, 30 Jun 2020 00:46:02 +0200
Subject: [PATCH] #4: nested download was extended for timeseries; TBD: showing
 nested station information is not working yet; also changed programme from
 many-to-many to 1:n

---
 toardb/stationmeta/models_core.py     |  3 +++
 toardb/timeseries/crud.py             | 18 +-----------------
 toardb/timeseries/models.py           |  2 +-
 toardb/timeseries/models_core.py      | 15 ++++++++++++---
 toardb/timeseries/models_programme.py | 13 +------------
 toardb/timeseries/schemas.py          |  8 ++++++--
 toardb/variables/models.py            |  1 +
 7 files changed, 25 insertions(+), 35 deletions(-)

diff --git a/toardb/stationmeta/models_core.py b/toardb/stationmeta/models_core.py
index 074af60..4383d7a 100644
--- a/toardb/stationmeta/models_core.py
+++ b/toardb/stationmeta/models_core.py
@@ -104,6 +104,9 @@ class StationmetaCore(Base):
     globalmeta = relationship('StationmetaGlobal', uselist=False, back_populates='station')
     globalservice = relationship('StationmetaGlobalService', uselist=False, back_populates='station')
 
+    # for nested view
+    timeseries = relationship("Timeseries", back_populates="station")
+
 #   cv_vocabulary = relationship('CvVocabulary')
 #   ta_vocabulary = relationship('TaVocabulary')
 #   st_vocabulary = relationship('StVocabulary')
diff --git a/toardb/timeseries/crud.py b/toardb/timeseries/crud.py
index 55624b3..4fec5d0 100644
--- a/toardb/timeseries/crud.py
+++ b/toardb/timeseries/crud.py
@@ -9,7 +9,7 @@ from sqlalchemy.orm import Session
 from fastapi.responses import JSONResponse
 from . import models
 from .models import timeseries_timeseries_roles_table, \
-                    timeseries_timeseries_annotations_table, timeseries_timeseries_programmes_table, \
+                    timeseries_timeseries_annotations_table, \
                     DA_enum, SF_enum, AT_enum, DS_enum
 from toardb.generic.models import RS_enum, RC_enum
 from .schemas import TimeseriesCreate
@@ -80,7 +80,6 @@ def create_timeseries(db: Session, timeseries: TimeseriesCreate):
     timeseries_dict = timeseries.dict()
     roles_data = timeseries_dict.pop('roles', None)
     annotations_data = timeseries_dict.pop('annotations', None)
-    programmes_data = timeseries_dict.pop('programmes', None)
     db_timeseries = models.Timeseries(**timeseries_dict)
     db_timeseries.access_rights = get_value_from_str(DA_enum,db_timeseries.access_rights)
     db_timeseries.sampling_frequency = get_value_from_str(SF_enum,db_timeseries.sampling_frequency)
@@ -123,21 +122,6 @@ def create_timeseries(db: Session, timeseries: TimeseriesCreate):
                 annotation_id = db_annotation.id
             db.execute(insert(timeseries_timeseries_annotations_table).values(timeseries_id=timeseries_id, annotation_id=annotation_id))
             db.commit()
-    # store programmes and update association table
-    if programmes_data:
-        for r in programmes_data:
-            db_programme = models.TimeseriesProgramme(**r)
-            # check whether programme is already present in database
-            db_object = get_unique_timeseries_programme(db, db_programme.name, db_programme.homepage)
-            if db_object:
-                programme_id = db_object.id
-            else:
-                db.add(db_programme)
-                db.commit()
-                db.refresh(db_programme)
-                programme_id = db_programme.id
-            db.execute(insert(timeseries_timeseries_programmes_table).values(timeseries_id=timeseries_id, programme_id=programme_id))
-            db.commit()
     # there is a mismatch with additional_metadata
     # in upload command, we have now: "additional_metadata": "{}"
     # but return from this method gives (=database): "additional_metadata": {}
diff --git a/toardb/timeseries/models.py b/toardb/timeseries/models.py
index 352acbb..4f26163 100644
--- a/toardb/timeseries/models.py
+++ b/toardb/timeseries/models.py
@@ -1,7 +1,7 @@
 from .models_core import Timeseries
 from .models_role import TimeseriesRole, timeseries_timeseries_roles_table
 from .models_annotation import TimeseriesAnnotation, timeseries_timeseries_annotations_table
-from .models_programme import TimeseriesProgramme, timeseries_timeseries_programmes_table
+from .models_programme import TimeseriesProgramme
 from toardb.base import Base
 
 from sqlalchemy import Table, Column, Integer, String
diff --git a/toardb/timeseries/models_core.py b/toardb/timeseries/models_core.py
index 3492dd0..ab54806 100644
--- a/toardb/timeseries/models_core.py
+++ b/toardb/timeseries/models_core.py
@@ -6,9 +6,11 @@ class Timeseries (Base)
 from sqlalchemy import Column, DateTime, Float, ForeignKey, Integer, text, String, \
                        Text, CheckConstraint, UniqueConstraint, PrimaryKeyConstraint, \
                        Sequence
+from sqlalchemy.orm import relationship
 from sqlalchemy.dialects.postgresql import JSONB
 from toardb.stationmeta.models import StationmetaCore
 from toardb.variables.models import Variable
+from .models_programme import TimeseriesProgramme
 from toardb.base import Base
 
 
@@ -51,6 +53,8 @@ class Timeseries(Base):
     +---------------------+--------------------------+-----------+----------+----------------------------------------+
     | variable_id         | integer                  |           |          |                                        |
     +---------------------+--------------------------+-----------+----------+----------------------------------------+
+    | programme_id        | integer                  |           |          |                                        |
+    +---------------------+--------------------------+-----------+----------+----------------------------------------+
     Indexes:
         "timeseries_pkey" PRIMARY KEY, btree (id)
         "timeseries_station_id_variable_id_label_uniq" UNIQUE CONSTRAINT, btree (station_id, variable_id, label)
@@ -69,6 +73,7 @@ class Timeseries(Base):
         "timeseries_measurement_method_fk_mm_vocabulary_enum_val" FOREIGN KEY (measurement_method) REFERENCES mm_vocabulary(enum_val)
         "timeseries_sampling_frequency_fk_sf_vocabulary_enum_val" FOREIGN KEY (sampling_frequency) REFERENCES sf_vocabulary(enum_val)
         "timeseries_source_fk_ds_vocabulary_enum_val" FOREIGN KEY (source) REFERENCES ds_vocabulary(enum_val)
+        "timeseries_programme_id_fk_timeseries_programmes_id" FOREIGN KEY (programme_id) REFERENCES timeseries_programmes(id)
     Referenced by:
         TABLE "data" CONSTRAINT "data_timeseries_id_fk_timeseries_id" FOREIGN KEY (timeseries_id) REFERENCES timeseries(id) DEFERRABLE INITIALLY DEFERRED
         TABLE "timeseries_timeseries_annotations" CONSTRAINT "timeseries_timeseries_annotations_timeseries_id_fk_timeseries_id" FOREIGN KEY (timeseries_id) REFERENCES timeseries(id) DEFERRABLE INITIALLY DEFERRED
@@ -104,9 +109,13 @@ class Timeseries(Base):
 # see: https://groups.google.com/forum/#!topic/sqlalchemy/YjGhE4d6K4U
     station_id = Column(ForeignKey(StationmetaCore.id, deferrable=True, initially='DEFERRED'), index=True)
     variable_id = Column(ForeignKey(Variable.id, deferrable=True, initially='DEFERRED'), index=True)
-# how to reactivate the following lines?!
-#   station = relationship('StationmetaCore')
-#   variable = relationship('Variable')
+    programme_id = Column(ForeignKey(TimeseriesProgramme.id))
+
+    # for the nested view
+    station = relationship('StationmetaCore')
+    variable = relationship('Variable')
+    programme = relationship('TimeseriesProgramme')
+
 #   da_vocabulary = relationship('DaVocabulary')
 #   at_vocabulary = relationship('AtVocabulary')
 #   mm_vocabulary = relationship('MmVocabulary')
diff --git a/toardb/timeseries/models_programme.py b/toardb/timeseries/models_programme.py
index fc44d59..8bdbcaa 100644
--- a/toardb/timeseries/models_programme.py
+++ b/toardb/timeseries/models_programme.py
@@ -3,17 +3,10 @@
 class TimeseriesProgramme (Base)
 ================================
 """
-from sqlalchemy import Column, Integer, text, String, Text, ForeignKey, Table, Sequence
+from sqlalchemy import Column, Integer, String, Text, Sequence
 from sqlalchemy.orm import relationship
 from toardb.base import Base
 
-# many-to-many relationships
-timeseries_timeseries_programmes_table = Table('timeseries_timeseries_programmes', Base.metadata,
-    Column('timeseries_id', Integer, ForeignKey('timeseries.id')),
-    Column('programme_id', Integer, ForeignKey('timeseries_programmes.id'))
-)
-
-
 TIMESERIES_PROGRAMMES_ID_SEQ = Sequence('timeseries_programmes_id_seq')  # define sequence explicitly
 class TimeseriesProgramme(Base):
     """ Table "public.timeseries_programmes"
@@ -42,7 +35,3 @@ class TimeseriesProgramme(Base):
     homepage = Column(String(200), nullable=False)
     description = Column(Text, nullable=False)
 
-    timeseries = relationship("Timeseries",
-        secondary=timeseries_timeseries_programmes_table,
-        backref="programmes")
-
diff --git a/toardb/timeseries/schemas.py b/toardb/timeseries/schemas.py
index b89622b..85cb310 100644
--- a/toardb/timeseries/schemas.py
+++ b/toardb/timeseries/schemas.py
@@ -10,6 +10,8 @@ from pydantic import BaseModel, Json, validator
 import datetime as dt
 from toardb.generic.models import RS_enum, RC_enum
 from .models import DA_enum, SF_enum, AT_enum, DS_enum, MM_enum
+from toardb.variables.schemas import Variable 
+#from toardb.stationmeta.schemas import StationmetaCoreCreate
 
 # ======== Timeseries =========
 
@@ -29,6 +31,7 @@ class TimeseriesCoreBase(BaseModel):
     date_modified: dt.datetime
     station_id: int
     variable_id: int
+    programme_id: int
     additional_metadata: Json
 
     @validator('access_rights')
@@ -185,7 +188,9 @@ class TimeseriesProgramme(TimeseriesProgrammeBase):
 class TimeseriesBase(TimeseriesCoreBase):
     roles: List[TimeseriesRole] = None
     annotations: List[TimeseriesAnnotation] = None
-    programmes: List[TimeseriesProgramme] = None
+    variable: Variable
+#   station: StationmetaCoreCreate
+    programme: TimeseriesProgramme
 
     class Config:
         orm_mode = True
@@ -193,7 +198,6 @@ class TimeseriesBase(TimeseriesCoreBase):
 class TimeseriesCreate(TimeseriesCoreCreate):
     roles: List[TimeseriesRoleCreate] = None
     annotations: List[TimeseriesAnnotation] = None
-    programmes: List[TimeseriesProgramme] = None
 
     class Config:
         orm_mode = True
diff --git a/toardb/variables/models.py b/toardb/variables/models.py
index 22315aa..7e2cb50 100644
--- a/toardb/variables/models.py
+++ b/toardb/variables/models.py
@@ -44,3 +44,4 @@ class Variable(Base):
     units = Column(String(64), nullable=False)
     chemical_formula = Column(String(128), nullable=False)
 
+    timeseries = relationship("Timeseries", back_populates="variable")
-- 
GitLab