From 486621e2cc45a191ec63683049f15f1ad2f7717b Mon Sep 17 00:00:00 2001 From: Brunno Vanelli Date: Mon, 15 Jul 2024 20:49:23 +0200 Subject: [PATCH] fix: Correct model for latest actual server. --- actual/__init__.py | 3 +++ actual/database.py | 1 + docker/docker-compose.yml | 3 +-- tests/test_integration.py | 20 ++++++++++++++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/actual/__init__.py b/actual/__init__.py index f01efa2..385059e 100644 --- a/actual/__init__.py +++ b/actual/__init__.py @@ -319,6 +319,9 @@ def download_budget(self, encryption_password: str = None): self.import_zip(io.BytesIO(file_bytes)) # actual js always calls validation self.validate() + # run migrations if needed + migration_files = self.data_file_index() + self.run_migrations(migration_files[1:]) self.sync() # create session if not existing if self._in_context and not self._session: diff --git a/actual/database.py b/actual/database.py index 6447923..992dbb1 100644 --- a/actual/database.py +++ b/actual/database.py @@ -328,6 +328,7 @@ class CustomReports(BaseModel, table=True): interval: Optional[str] = Field(default=None, sa_column=Column("interval", Text, server_default=text("'Monthly'"))) color_scheme: Optional[str] = Field(default=None, sa_column=Column("color_scheme", Text)) tombstone: Optional[int] = Field(default=None, sa_column=Column("tombstone", Integer, server_default=text("0"))) + include_current: Optional[int] = Field(default=None, sa_column=Column("include_current", Integer)) class Kvcache(SQLModel, table=True): diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index bd2279a..c71e6da 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,9 +1,8 @@ # Use this script to initialize a local actual server. It serves as the target to test basic functionality of the API. -version: '3' services: actual: container_name: actual - image: docker.io/actualbudget/actual-server:24.5.0 + image: docker.io/actualbudget/actual-server:24.7.0 ports: - '5006:5006' volumes: diff --git a/tests/test_integration.py b/tests/test_integration.py index c10bb5d..2df04b6 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1,10 +1,12 @@ import datetime import pytest +import sqlalchemy.ext.declarative from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import wait_for_logs from actual import Actual +from actual.database import __TABLE_COLUMNS_MAP__ from actual.exceptions import ActualDecryptionError, ActualError, AuthorizationError from actual.queries import ( create_transaction, @@ -122,3 +124,21 @@ def test_reimport_file_from_zip(actual_server, tmp_path): # check if the account can be retrieved with Actual(f"http://localhost:{port}", password="mypass", file="My Budget") as actual: assert len(get_accounts(actual.session)) == 1 + + +def test_models(actual_server): + port = actual_server.get_exposed_port(5006) + with Actual(f"http://localhost:{port}", password="mypass", encryption_password="mypass", bootstrap=True) as actual: + actual.create_budget("My Budget") + # check if the models are matching + base = sqlalchemy.ext.declarative.declarative_base() + metadata = base.metadata + metadata.reflect(actual.engine) + # check first if all tables are present + for table_name, table in metadata.tables.items(): + assert table_name in __TABLE_COLUMNS_MAP__, f"Missing table '{table_name}' on models." + # then assert if all columns are matching the model + for column_name in table.columns.keys(): + assert ( + column_name in __TABLE_COLUMNS_MAP__[table_name]["columns"] + ), f"Missing column '{column_name}' at table '{table_name}'."