Skip to content

Commit 117b3ec

Browse files
Merge pull request #263 from mapswipe/archive-feature
Archive feature
2 parents 0c29f5b + e6bebfe commit 117b3ec

File tree

5 files changed

+143
-29
lines changed

5 files changed

+143
-29
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
Archive a project.
3+
"""
4+
5+
from mapswipe_workers import auth
6+
from mapswipe_workers.definitions import logger
7+
8+
9+
def archive_project(project_ids: list) -> None:
10+
"""
11+
Archive a project.
12+
13+
Deletes groups, tasks and results from Firebase.
14+
Set status = archived for project in Firebase and Postgres.
15+
"""
16+
for project_id in project_ids:
17+
logger.info("Archive project with the id {0}".format(project_id))
18+
logger.info(
19+
"Delete results, groups and tasks of project with the id {0}".format(
20+
project_id
21+
)
22+
)
23+
24+
fb_db = auth.firebaseDB()
25+
fb_db.reference("v2/results/{0}".format(project_id)).set({})
26+
fb_db.reference("v2/groups/{0}".format(project_id)).set({})
27+
fb_db.reference("v2/tasks/{0}".format(project_id)).set({})
28+
29+
fb_db = auth.firebaseDB()
30+
ref = fb_db.reference("v2/projects/{0}/status".format(project_id))
31+
ref.set({"archived"})
32+
33+
pg_db = auth.postgresDB()
34+
sql_query = (
35+
"UPDATE projects SET status = 'archived' "
36+
+ "WHERE project_id = {0}".format(project_id)
37+
)
38+
pg_db.query(sql_query)

mapswipe_workers/mapswipe_workers/firebase_to_postgres/update_data.py

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
from mapswipe_workers.definitions import logger
55

66

7-
def update_user_data(user_ids=None):
8-
"""
9-
Copies new users from Firebase to Postgres
10-
"""
7+
def update_user_data(user_ids: list = []):
8+
"""Copies new users from Firebase to Postgres."""
119
# TODO: On Conflict
1210
fb_db = auth.firebaseDB()
1311
pg_db = auth.postgresDB()
@@ -24,31 +22,29 @@ def update_user_data(user_ids=None):
2422
try:
2523
last_updated = last_updated[0][0]
2624
logger.info(f"got last updated timestamp: {last_updated}")
27-
except:
25+
except IndexError:
2826
logger.info("could not get last timestamp")
29-
last_updated = None
27+
last_updated = []
3028

31-
if last_updated is None:
32-
# No users in the Postgres database yet.
33-
# Get all users from Firebase.
34-
users = fb_ref.get()
35-
else:
29+
if last_updated:
3630
# Get only new users from Firebase.
3731
last_updated = last_updated.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
3832
fb_query = fb_ref.order_by_child("created").start_at(last_updated)
3933
users = fb_query.get()
4034
# Delete first user in ordered dict.
4135
# This user is already in the database (user.created = last_updated).
4236
if len(users) == 0:
43-
logger.info(
44-
f"there are no new users in firebase based on created timestamp"
45-
)
37+
logger.info("there are no new users in firebase based on created timestamp")
4638
else:
4739
users.popitem(last=False)
40+
else:
41+
# No users in the Postgres database yet.
42+
# Get all users from Firebase.
43+
users = fb_ref.get()
4844

4945
# update users specified in user_ids list
5046
if user_ids:
51-
logger.info(f"will add users to copy_new_users based on user_ids provided")
47+
logger.info("will add users to copy_new_users based on user_ids provided")
5248
for user_id in user_ids:
5349
user = fb_ref.child(user_id).get()
5450
users[user_id] = user
@@ -65,7 +61,8 @@ def update_user_data(user_ids=None):
6561
# if user has no "created" attribute, we set it to current time
6662
created = dt.datetime.utcnow().isoformat()[0:-3] + "Z"
6763
logger.info(
68-
f"user {user_id} didn't have a 'created' attribute. Set it to '{created}' now."
64+
f"user {user_id} didn't have a 'created' attribute. "
65+
f"Set it to '{created}' now."
6966
)
7067

7168
try:
@@ -74,7 +71,8 @@ def update_user_data(user_ids=None):
7471
# if user has no "username" attribute, we set it to None
7572
username = None
7673
logger.info(
77-
f"user {user_id} didn't have a 'username' attribute. Set it to '{username}' now."
74+
f"user {user_id} didn't have a 'username' attribute. "
75+
f"Set it to '{username}' now."
7876
)
7977

8078
query_update_user = """
@@ -98,17 +96,14 @@ def update_user_data(user_ids=None):
9896
logger.info("Updated user data in Potgres")
9997

10098

101-
def update_project_data(project_ids=None):
99+
def update_project_data(project_ids: list = []):
102100
"""
103101
Gets status of projects
104102
from Firebase and updates them in Postgres.
103+
105104
Default behavior is to update all projects.
106105
If called with a list of project ids as parameter
107106
only those projects will be updated.
108-
109-
Parameters
110-
----------
111-
project_ids: list
112107
"""
113108

114109
fb_db = auth.firebaseDB()

mapswipe_workers/mapswipe_workers/mapswipe_workers.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@
1212
CustomError,
1313
logger,
1414
)
15-
from mapswipe_workers.firebase_to_postgres import transfer_results, update_data
15+
from mapswipe_workers.firebase_to_postgres import (
16+
archive_project,
17+
transfer_results,
18+
update_data,
19+
)
1620
from mapswipe_workers.generate_stats import generate_stats
1721
from mapswipe_workers.project_types.build_area import build_area_tutorial
18-
from mapswipe_workers.project_types.change_detection import change_detection_tutorial
22+
from mapswipe_workers.project_types.change_detection import (
23+
change_detection_tutorial,
24+
)
1925
from mapswipe_workers.utils import sentry, slack, user_management
2026

2127

@@ -288,6 +294,31 @@ def run_create_tutorial(input_file):
288294
logger.exception(e)
289295

290296

297+
@click.command("archive")
298+
@click.option(
299+
"--project-id",
300+
"-i",
301+
help=("Archive project with giving project id"),
302+
type=str,
303+
)
304+
@click.option(
305+
"--project-ids",
306+
cls=PythonLiteralOption,
307+
help=(
308+
f"Archive multiple projects. "
309+
f"Provide project id strings as a list: "
310+
f"""["project_a", "project_b"]"""
311+
),
312+
)
313+
def run_archive_project(project_id, project_ids):
314+
"""Archive projects in Postgres. Delete groups, tasks and results from Firebase."""
315+
if not project_ids:
316+
project_ids = [project_id]
317+
update_data.update_project_data(project_ids)
318+
transfer_results.transfer_results(project_ids)
319+
archive_project.archive_project(project_ids)
320+
321+
291322
@click.command("run")
292323
@click.option(
293324
"--schedule",
@@ -431,10 +462,11 @@ def _run_user_management(email, manager):
431462
user_management.remove_project_manager_rights(email)
432463

433464

465+
cli.add_command(run)
466+
cli.add_command(run_archive_project)
434467
cli.add_command(run_create_projects)
468+
cli.add_command(run_create_tutorial)
435469
cli.add_command(run_firebase_to_postgres)
436470
cli.add_command(run_generate_stats)
437471
cli.add_command(run_generate_stats_all_projects)
438472
cli.add_command(run_user_management)
439-
cli.add_command(run_create_tutorial)
440-
cli.add_command(run)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import unittest
2+
3+
from mapswipe_workers import auth
4+
from mapswipe_workers.firebase_to_postgres import archive_project
5+
6+
7+
class TestArchiveProject(unittest.TestCase):
8+
@classmethod
9+
def setUpClass(cls):
10+
"""Set up before tests are run."""
11+
cls.project_id = "test_archive_project"
12+
# TODO: Create project
13+
archive_project.archive_project(cls.project_id)
14+
15+
@classmethod
16+
def tearDownClass(cls):
17+
"""Tear down after tests are run."""
18+
pg_db = auth.postgresDB()
19+
sql_query = "".format(cls.project_id)
20+
pg_db.query(sql_query)
21+
22+
fb_db = auth.firebaseDB()
23+
ref = fb_db.reference("v2/projects/{0}".format(cls.project_id))
24+
ref.set({})
25+
26+
def test_firebase_changes(self):
27+
"""Test if groups, tasks and results are deleted from Firebase."""
28+
fb_db = auth.firebaseDB()
29+
30+
ref = fb_db.reference("v2/groups/{0}".format(self.project_id))
31+
self.assertFalse(ref.get())
32+
33+
ref = fb_db.reference("v2/tasks/{0}".format(self.project_id))
34+
self.assertFalse(ref.get())
35+
36+
ref = fb_db.reference("v2/results/{0}".format(self.project_id))
37+
self.assertFalse(ref.get())
38+
39+
def test_postgres_changes(self):
40+
"""Test if postgres project is archived."""
41+
pg_db = auth.postgresDB()
42+
sql_query = "SELECT archived FROM projects WHERE project_id = {}".format(
43+
self.project_id
44+
)
45+
result = pg_db.retr_query(sql_query)
46+
self.assertEqual(result, "archived")
47+
48+
49+
if __name__ == "__main__":
50+
unittest.main()

postgres/initdb.sql

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
CREATE EXTENSION postgis;
33

44
CREATE TABLE IF NOT EXISTS projects (
5-
archive boolean,
65
created timestamp,
76
created_by varchar,
87
geom geometry(MULTIPOLYGON, 4326),
@@ -48,7 +47,7 @@ CREATE TABLE IF NOT EXISTS tasks (
4847
project_type_specifics json,
4948
PRIMARY KEY (project_id, group_id, task_id),
5049
FOREIGN KEY (project_id) REFERENCES projects (project_id),
51-
FOREIGN KEY (project_id, group_id) REFERENCES GROUPS (project_id, group_id)
50+
FOREIGN KEY (project_id, group_id) REFERENCES groups (project_id, group_id)
5251
);
5352

5453
CREATE INDEX IF NOT EXISTS tasks_task_id ON public.tasks
@@ -78,7 +77,7 @@ CREATE TABLE IF NOT EXISTS results (
7877
result int,
7978
PRIMARY KEY (project_id, group_id, task_id, user_id),
8079
FOREIGN KEY (project_id) REFERENCES projects (project_id),
81-
FOREIGN KEY (project_id, group_id) REFERENCES GROUPS (project_id, group_id),
80+
FOREIGN KEY (project_id, group_id) REFERENCES groups (project_id, group_id),
8281
FOREIGN KEY (project_id, group_id, task_id) REFERENCES tasks (project_id, group_id, task_id),
8382
FOREIGN KEY (user_id) REFERENCES users (user_id)
8483
);

0 commit comments

Comments
 (0)