Skip to content
Snippets Groups Projects
Commit 8640a43c authored by Sabine Schröder's avatar Sabine Schröder
Browse files

#17 and #9: stationmeta patch API writes (one) entry to changelog table;...

#17 and #9: stationmeta patch API writes (one) entry to changelog table; schema shows changelog table when requesting stationmeta from database
parent cbad53cd
No related branches found
No related tags found
No related merge requests found
Pipeline #47354 passed
......@@ -12,7 +12,8 @@ from sqlalchemy.dialects.postgresql import JSONB, ARRAY
from fastapi import File, UploadFile
from fastapi.responses import JSONResponse
from . import models
from .models import StationmetaCore, stationmeta_core_stationmeta_roles_table, stationmeta_core_stationmeta_annotations_table, \
from .models import StationmetaCore, StationmetaChangelog, stationmeta_core_stationmeta_roles_table, \
stationmeta_core_stationmeta_annotations_table, \
CZ_enum, CV_enum, ST_enum, TA_enum
from toardb.generic.models import RS_enum, RC_enum
from .schemas import get_coordinates_from_geom, get_geom_from_coordinates, StationmetaCreate, StationmetaPatch, Coordinates
......@@ -174,7 +175,7 @@ def create_stationmeta(db: Session, stationmeta: StationmetaCreate):
db_stationmeta.coordinates = tmp_coordinates
return db_stationmeta
def patch_stationmeta(db: Session, station_id: int, stationmeta: StationmetaPatch):
def patch_stationmeta(db: Session, description: str, station_id: int, stationmeta: StationmetaPatch):
stationmeta_dict = stationmeta.dict()
roles_data = stationmeta_dict.pop('roles', None)
annotations_data = stationmeta_dict.pop('annotations', None)
......@@ -183,6 +184,8 @@ def patch_stationmeta(db: Session, station_id: int, stationmeta: StationmetaPatc
aux_urls_data = stationmeta_dict.pop('aux_urls', None)
globalmeta_data = stationmeta_dict.pop('globalmeta', None)
globalservice_data = stationmeta_dict.pop('globalservice', None)
# prepare changelog entry/entries
db_changelog = StationmetaChangelog(description=description, station_id=station_id, author_id=1, type_of_change=1)
# there's a mismatch with coordinates --> how to automatically switch back and forth?!
# ==> the following two commands are not working
# ==> workaround
......@@ -194,7 +197,9 @@ def patch_stationmeta(db: Session, station_id: int, stationmeta: StationmetaPatc
db_stationmeta.coordinates = get_geom_from_coordinates(db_stationmeta.coordinates)
for k, v in stationmeta_dict.items():
if v is not None:
db_changelog.old_value=str(getattr(db_stationmeta,k))
setattr(db_stationmeta,k,stationmeta_dict[k])
db_changelog.new_value=str(getattr(db_stationmeta,k))
result = db.commit()
db.refresh(db_stationmeta)
# store roles and update association table
......@@ -269,6 +274,9 @@ def patch_stationmeta(db: Session, station_id: int, stationmeta: StationmetaPatc
db.add(db_globalservice)
db.commit()
db.refresh(db_globalservice)
# add patch to changelog table
db.add(db_changelog)
db.commit()
# there's a mismatch with coordinates --> how to automatically switch back and forth?!
db_stationmeta.coordinates = tmp_coordinates
return db_stationmeta
......
......@@ -3,7 +3,7 @@
class StationmetaChangelog(Base)
================================
"""
from sqlalchemy import Column, DateTime, BigInteger, ForeignKey, String, \
from sqlalchemy import Column, DateTime, BigInteger, ForeignKey, String, text, \
Text, CheckConstraint, Table, Sequence
from sqlalchemy.orm import relationship
from .models_core import StationmetaCore
......@@ -19,7 +19,7 @@ class StationmetaChangelog(Base):
+================+==========================+===========+==========+========================================================+
| id | bigint | | not null | nextval('stationmeta_changelog_id_seq'::regclass) |
+----------------+--------------------------+-----------+----------+--------------------------------------------------------+
| datetime | timestamp with time zone | | not null | |
| datetime | timestamp with time zone | | not null | now() |
+----------------+--------------------------+-----------+----------+--------------------------------------------------------+
| station_id | bigint | | not null | |
+----------------+--------------------------+-----------+----------+--------------------------------------------------------+
......@@ -43,17 +43,17 @@ class StationmetaChangelog(Base):
__tablename__ = 'stationmeta_changelog'
id = Column(BigInteger, STATIONMETA_CHANGELOG_ID_SEQ, primary_key=True, server_default=STATIONMETA_CHANGELOG_ID_SEQ.next_value())
datetime = Column(DateTime(True), nullable=False)
datetime = Column(DateTime(True), nullable=False, server_default=text("now()"))
description = Column(Text, nullable=False)
old_value = Column(String(256), nullable=False)
new_value = Column(String(256), nullable=False)
# do not use string declaration here (not working for pytest)
# use the explicit class name here,
# see: https://groups.google.com/forum/#!topic/sqlalchemy/YjGhE4d6K4U
station_id = Column(ForeignKey(StationmetaCore.id), nullable=False)
station_id = Column(ForeignKey(StationmetaCore.id, deferrable=True, initially='DEFERRED'), nullable=False)
author_id = Column(ForeignKey(AuthUser.id), nullable=False)
# still to check for some pytest solution for controlled vocabulary
type_of_change = Column(ForeignKey('cl_Vocabulary.enum_val'), nullable=False)
type_of_change = Column(ForeignKey('cl_vocabulary.enum_val'), nullable=False)
author = relationship('AuthUser')
station = relationship('StationmetaCore')
......
......@@ -87,6 +87,7 @@ class StationmetaCore_WithoutCoords(Base):
aux_urls = relationship('StationmetaAuxUrl', back_populates='station')
globalmeta = relationship('StationmetaGlobal', uselist=False, back_populates='station')
globalservice = relationship('StationmetaGlobalService', uselist=False, back_populates='station')
changelog = relationship('StationmetaChangelog', back_populates='station')
# for nested view
timeseries = relationship("Timeseries", back_populates="station")
......
......@@ -448,6 +448,27 @@ class StationmetaRole(StationmetaRoleBase):
class Config:
orm_mode = True
# ======== StationmetaChangelog =========
class StationmetaChangelogBase(BaseModel):
id: int
datetime: dt.datetime
description: str
old_value: str
new_value: str
station_id: int
author_id: int
type_of_change: int
class StationmetaChangelog(StationmetaChangelogBase):
id: int
class Config:
orm_mode = True
# ======== for nested view/upload =========
class StationmetaBase(StationmetaCoreBase):
......@@ -457,6 +478,7 @@ class StationmetaBase(StationmetaCoreBase):
aux_docs: List[StationmetaAuxDoc] = None
aux_urls: List[StationmetaAuxUrl] = None
globalmeta: StationmetaGlobal = None
changelog: List[StationmetaChangelog] = None
class Config:
orm_mode = True
......
......@@ -60,11 +60,11 @@ def create_stationmeta_core(stationmeta: schemas.StationmetaCreate = Body(..., e
return crud.create_stationmeta(db=db, stationmeta=stationmeta)
@router.patch('/stationmeta/{station_code}', response_model=schemas.StationmetaPatch)
def patch_stationmeta_core(station_code: str, stationmeta: schemas.StationmetaPatch = Body(..., embed = True), db: Session = Depends(get_db)):
def patch_stationmeta_core(station_code: str, description: str, stationmeta: schemas.StationmetaPatch = Body(..., embed = True), db: Session = Depends(get_db)):
db_stationmeta = crud.get_stationmeta(db, station_code=station_code)
if db_stationmeta is None:
raise HTTPException(status_code=404, detail="Station for patching not found.")
return crud.patch_stationmeta(db=db, station_id=db_stationmeta.id, stationmeta=stationmeta)
return crud.patch_stationmeta(db=db, description=description, station_id=db_stationmeta.id, stationmeta=stationmeta)
@router.patch('/stationmeta/delete_field/{station_code}', response_model=schemas.StationmetaPatch)
def patch_stationmeta_core(station_code: str, field: str, db: Session = Depends(get_db)):
......
......@@ -3,7 +3,7 @@
class TimeseriesChangelog(Base)
===============================
"""
from sqlalchemy import Column, DateTime, ForeignKey, BigInteger, String, CHAR, \
from sqlalchemy import Column, DateTime, ForeignKey, BigInteger, String, CHAR, text, \
Text, Table, Sequence
from sqlalchemy.orm import relationship
from .models_core import Timeseries
......@@ -19,7 +19,7 @@ class TimeseriesChangelog(Base):
+================+==========================+===========+==========+==================================================+
| id | bigint | | not null | nextval('timeseries_changelog_id_seq'::regclass) |
+----------------+--------------------------+-----------+----------+--------------------------------------------------+
| datetime | timestamp with time zone | | not null | |
| datetime | timestamp with time zone | | not null | now() |
+----------------+--------------------------+-----------+----------+--------------------------------------------------+
| timeseries_id | bigint | | not null | |
+----------------+--------------------------+-----------+----------+--------------------------------------------------+
......@@ -50,7 +50,7 @@ class TimeseriesChangelog(Base):
__tablename__ = 'timeseries_changelog'
id = Column(BigInteger, TIMESERIES_CHANGELOG_ID_SEQ, primary_key=True, server_default=TIMESERIES_CHANGELOG_ID_SEQ.next_value())
datetime = Column(DateTime(True), nullable=False)
datetime = Column(DateTime(True), nullable=False, server_default=text("now()"))
description = Column(Text, nullable=False)
old_value = Column(String(256), nullable=False)
new_value = Column(String(256), nullable=False)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment