-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* formatting * empty * add initial sites history table implementation * --wip-- * hopefully got alembic working in tests * add migrations * fix rebase * rebase db migrations * tests working * --wip-- * --wip-- * --wip-- * edit_site seems to be working * --wip-- * --wip-- * --wip-- * rebase migrations on top of recent changes * improve tests * --wip-- * --wip-- * update docs * set session and user * comment * lint * formatting * address PR comments
- Loading branch information
Showing
7 changed files
with
254 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
"""create trigger | ||
Revision ID: 12c0ccf6b825 | ||
Revises: c8ef88c250e7 | ||
Create Date: 2024-10-27 20:27:30.805137 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = '12c0ccf6b825' | ||
down_revision = 'c8ef88c250e7' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
create_trigger = """CREATE OR REPLACE FUNCTION log_site_changes() | ||
RETURNS TRIGGER AS $$ | ||
DECLARE | ||
user_uuid UUID; | ||
BEGIN | ||
user_uuid := nullif(current_setting('pvsite_datamodel.current_user_uuid', true), '')::UUID; | ||
IF (TG_OP = 'INSERT' OR TG_OP = 'UPDATE') THEN | ||
INSERT INTO sites_history ( | ||
site_history_uuid, | ||
site_uuid, | ||
site_data, | ||
changed_by, | ||
operation_type, | ||
created_utc | ||
) VALUES ( | ||
gen_random_uuid(), | ||
NEW.site_uuid, | ||
to_jsonb(NEW), | ||
user_uuid, | ||
TG_OP, | ||
NOW() | ||
); | ||
ELSIF TG_OP = 'DELETE' THEN | ||
INSERT INTO sites_history ( | ||
site_history_uuid, | ||
site_uuid, | ||
site_data, | ||
changed_by, | ||
operation_type, | ||
created_utc | ||
) VALUES ( | ||
gen_random_uuid(), | ||
OLD.site_uuid, | ||
to_jsonb(OLD), | ||
user_uuid, | ||
'DELETE', | ||
NOW() | ||
); | ||
END IF; | ||
RETURN NULL; | ||
END; | ||
$$ LANGUAGE plpgsql; | ||
CREATE TRIGGER site_changes_trigger | ||
AFTER INSERT OR UPDATE OR DELETE ON sites | ||
FOR EACH ROW EXECUTE FUNCTION log_site_changes(); | ||
""" | ||
|
||
drop_trigger = """ | ||
DROP TRIGGER IF EXISTS site_changes_trigger ON sites; | ||
DROP FUNCTION IF EXISTS log_site_changes; | ||
""" | ||
|
||
def upgrade() -> None: | ||
op.execute(create_trigger) | ||
pass | ||
|
||
|
||
def downgrade() -> None: | ||
op.execute(drop_trigger) | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
"""site history table | ||
Revision ID: c8ef88c250e7 | ||
Revises: 7a32241916f7 | ||
Create Date: 2024-11-29 22:42:25.535162 | ||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
from sqlalchemy.dialects import postgresql | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = 'c8ef88c250e7' | ||
down_revision = '7a32241916f7' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade() -> None: | ||
op.create_table('sites_history', | ||
sa.Column('site_history_uuid', sa.UUID(), nullable=False), | ||
sa.Column('site_uuid', sa.UUID(), nullable=False, comment='The site which this history record relates to'), | ||
sa.Column('site_data', postgresql.JSONB(astext_type=sa.Text()), nullable=False, comment='A snapshot of the site record as JSONB'), | ||
sa.Column('changed_by', sa.UUID(), nullable=True), | ||
sa.Column('operation_type', sa.TEXT(), nullable=False), | ||
sa.Column('created_utc', sa.DateTime(), nullable=True), | ||
sa.ForeignKeyConstraint(['changed_by'], ['users.user_uuid'], ), | ||
sa.PrimaryKeyConstraint('site_history_uuid') | ||
) | ||
op.create_index(op.f('ix_sites_history_site_uuid'), 'sites_history', ['site_uuid'], unique=False) | ||
|
||
|
||
def downgrade() -> None: | ||
op.drop_index(op.f('ix_sites_history_site_uuid'), table_name='sites_history') | ||
op.drop_table('sites_history') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,13 @@ | |
|
||
from pvsite_datamodel.pydantic_models import PVSiteEditMetadata | ||
from pvsite_datamodel.read.user import get_user_by_email | ||
from pvsite_datamodel.sqlmodels import APIRequestSQL, ForecastSQL, ForecastValueSQL, GenerationSQL | ||
from pvsite_datamodel.sqlmodels import ( | ||
APIRequestSQL, | ||
ForecastSQL, | ||
ForecastValueSQL, | ||
GenerationSQL, | ||
SiteHistorySQL, | ||
) | ||
from pvsite_datamodel.write.client import assign_site_to_client, create_client, edit_client | ||
from pvsite_datamodel.write.database import save_api_call_to_db | ||
from pvsite_datamodel.write.forecast import insert_forecast_values | ||
|
@@ -148,6 +154,47 @@ def test_create_new_site(db_session): | |
) | ||
|
||
|
||
def test_create_new_site_with_user(db_session): | ||
user = get_user_by_email(session=db_session, email="[email protected]") | ||
|
||
site, message = create_site( | ||
session=db_session, | ||
client_site_id=6932, | ||
client_site_name="test_site_1", | ||
latitude=51.0, | ||
longitude=0.0, | ||
capacity_kw=1.0, | ||
user_uuid=user.user_uuid, | ||
) | ||
|
||
# after creating there should be an entry in the history table | ||
h_site = ( | ||
db_session.query(SiteHistorySQL).filter(SiteHistorySQL.operation_type == "INSERT").first() | ||
) | ||
|
||
assert h_site.site_uuid == site.site_uuid | ||
assert h_site.changed_by == user.user_uuid | ||
|
||
# create site without setting user | ||
site_2, _ = create_site( | ||
session=db_session, | ||
client_site_id=6932, | ||
client_site_name="test_site_2", | ||
latitude=51.0, | ||
longitude=0.0, | ||
capacity_kw=1.0, | ||
) | ||
|
||
h_site_2 = ( | ||
db_session.query(SiteHistorySQL) | ||
.filter(SiteHistorySQL.site_uuid == site_2.site_uuid) | ||
.first() | ||
) | ||
|
||
# user should not be set | ||
assert h_site_2.changed_by is None | ||
|
||
|
||
def test_create_new_site_in_specified_country(db_session): | ||
site, message = create_site( | ||
session=db_session, | ||
|
@@ -295,21 +342,42 @@ def test_save_api_call_to_db(db_session): | |
|
||
def test_edit_site(db_session): | ||
"""Test the update of site metadata""" | ||
# history table should be empty | ||
hist_size = db_session.query(SiteHistorySQL).count() | ||
assert hist_size == 0 | ||
|
||
site = make_fake_site(db_session=db_session) | ||
|
||
# history table should contain a single entry | ||
hist_size = db_session.query(SiteHistorySQL).count() | ||
assert hist_size == 1 | ||
|
||
prev_latitude = site.latitude | ||
|
||
metadata_to_update = PVSiteEditMetadata(tilt=15, capacity_kw=None) | ||
|
||
user = get_user_by_email(session=db_session, email="[email protected]") | ||
site, _ = edit_site( | ||
session=db_session, | ||
site_uuid=str(site.site_uuid), | ||
site_info=metadata_to_update, | ||
user_uuid=user.user_uuid, | ||
) | ||
|
||
assert site.tilt == metadata_to_update.tilt | ||
assert site.capacity_kw == metadata_to_update.capacity_kw | ||
assert site.latitude == prev_latitude | ||
|
||
# after editing there should be another entry in the history table | ||
hist_size = db_session.query(SiteHistorySQL).count() | ||
assert hist_size == 2 | ||
h_site = ( | ||
db_session.query(SiteHistorySQL).filter(SiteHistorySQL.operation_type == "UPDATE").first() | ||
) | ||
|
||
assert h_site.site_uuid == site.site_uuid | ||
assert h_site.changed_by == user.user_uuid | ||
|
||
|
||
def test_create_client(db_session): | ||
"""Test to create a new client""" | ||
|