diff --git a/src/apps/answers/crud/answers.py b/src/apps/answers/crud/answers.py index 275615fabc9..865a0435382 100644 --- a/src/apps/answers/crud/answers.py +++ b/src/apps/answers/crud/answers.py @@ -803,7 +803,7 @@ async def get_by_applet_id_and_readiness_to_share_data( query: Query = select(AnswerSchema) query = query.where(AnswerSchema.applet_id == applet_id) query = query.where(AnswerSchema.respondent_id == respondent_id) - query = query.where(AnswerSchema.is_data_share.is_(True)) + query = query.where(AnswerSchema.consent_to_share.is_(True)) query = query.order_by(AnswerSchema.created_at.asc()) db_result = await self._execute(query) return db_result.scalars().all() @@ -813,7 +813,7 @@ async def get_respondents_by_applet_id_and_readiness_to_share_data( ) -> list[AnswerSchema] | None: query: Query = select(AnswerSchema.respondent_id) query = query.where(AnswerSchema.applet_id == applet_id) - query = query.where(AnswerSchema.is_data_share.is_(True)) + query = query.where(AnswerSchema.consent_to_share.is_(True)) query = query.order_by(AnswerSchema.created_at.asc()) db_result = await self._execute(query) return db_result.scalars().all() diff --git a/src/apps/answers/db/schemas.py b/src/apps/answers/db/schemas.py index 4ff454a9810..e161ab1c8cb 100644 --- a/src/apps/answers/db/schemas.py +++ b/src/apps/answers/db/schemas.py @@ -40,7 +40,7 @@ class AnswerSchema(HistoryAware, Base): target_subject_id = Column(UUID(as_uuid=True), nullable=True, index=True) source_subject_id = Column(UUID(as_uuid=True), nullable=True, index=True) relation = Column(String(length=20), nullable=True) - is_data_share = Column(Boolean(), default=False) + consent_to_share = Column(Boolean(), default=False) answer_item = relationship( "AnswerItemSchema", diff --git a/src/apps/answers/domain/answers.py b/src/apps/answers/domain/answers.py index e7fe0910282..9477a83a17f 100644 --- a/src/apps/answers/domain/answers.py +++ b/src/apps/answers/domain/answers.py @@ -100,7 +100,7 @@ class AppletAnswerCreate(InternalModel): client: ClientMeta target_subject_id: uuid.UUID | None source_subject_id: uuid.UUID | None - is_data_share: bool + consent_to_share: bool _dates_from_ms = validator("created_at", pre=True, allow_reuse=True)(datetime_from_ms) diff --git a/src/apps/answers/service.py b/src/apps/answers/service.py index d7e88045c19..5b708905056 100644 --- a/src/apps/answers/service.py +++ b/src/apps/answers/service.py @@ -243,7 +243,7 @@ async def _create_answer(self, applet_answer: AppletAnswerCreate) -> AnswerSchem target_subject_id=target_subject.id, source_subject_id=source_subject.id if source_subject else None, relation=relation, - is_data_share=applet_answer.is_data_share, + consent_to_share=applet_answer.consent_to_share, ) ) item_answer = applet_answer.answer diff --git a/src/apps/answers/tests/conftest.py b/src/apps/answers/tests/conftest.py index bf1a1a72c76..3df3867ff0a 100644 --- a/src/apps/answers/tests/conftest.py +++ b/src/apps/answers/tests/conftest.py @@ -197,6 +197,7 @@ def answer_create( answer=answer_item_create, created_at=datetime.datetime.utcnow().replace(microsecond=0), client=client_meta, + consent_to_share=False, ) @@ -221,6 +222,7 @@ def answer_with_alert_create( created_at=datetime.datetime.utcnow().replace(microsecond=0), client=client_meta, alerts=[answer_alert], + consent_to_share=False, ) @@ -245,6 +247,7 @@ def public_answer_create( answer=item_create, created_at=datetime.datetime.utcnow().replace(microsecond=0), client=client_meta, + consent_to_share=False, ) @@ -264,6 +267,7 @@ def answer_with_flow_create( client=client_meta, flow_id=applet.activity_flows[0].id, is_flow_completed=True, + consent_to_share=False, ) @@ -294,6 +298,7 @@ def answer_reviewable_activity_create( answer=item_create, created_at=datetime.datetime.utcnow().replace(microsecond=0), client=client_meta, + consent_to_share=False, ) @@ -455,6 +460,7 @@ def tom_answer_create_data(tom, applet_with_reviewable_activity) -> AppletAnswer user_public_key=str(tom.id), ), client=ClientMeta(app_id=f"{uuid.uuid4()}", app_version="1.1", width=984, height=623), + consent_to_share=False, ) diff --git a/src/apps/answers/tests/test_answer_for_cases.py b/src/apps/answers/tests/test_answer_for_cases.py index af9286c690d..1c066df92d0 100644 --- a/src/apps/answers/tests/test_answer_for_cases.py +++ b/src/apps/answers/tests/test_answer_for_cases.py @@ -86,6 +86,7 @@ async def test_answer_activity_items_create_for_respondent( start_time=10, end_time=11, ), + consent_to_share=False, ) response = await client.post(self.answer_url, data=create_data) @@ -121,6 +122,7 @@ async def test_answer_activity_items_create_for_respondent( start_time=10, end_time=11, ), + consent_to_share=False, ) response = await client.post(self.answer_url, data=create_data) diff --git a/src/apps/answers/tests/test_answers.py b/src/apps/answers/tests/test_answers.py index 86c1c946f08..544d25ca4dc 100644 --- a/src/apps/answers/tests/test_answers.py +++ b/src/apps/answers/tests/test_answers.py @@ -144,6 +144,7 @@ async def tom_answer_on_reviewable_applet( user_public_key=str(tom.id), ), client=ClientMeta(app_id=f"{uuid.uuid4()}", app_version="1.1", width=984, height=623), + consent_to_share=False, ) ) @@ -167,6 +168,7 @@ async def tom_answer_activity_flow(session: AsyncSession, tom: User, applet_with identifier="encrypted_identifier", ), client=ClientMeta(app_id=f"{uuid.uuid4()}", app_version="1.1", width=984, height=623), + consent_to_share=False, ) ) @@ -197,6 +199,7 @@ def applet_with_flow_answer_create(applet_with_flow: AppletFull) -> list[AppletA **answer_item_data, ), **answer_data, + consent_to_share=False, ), # flow#2 submission#1 AppletAnswerCreate( @@ -210,6 +213,7 @@ def applet_with_flow_answer_create(applet_with_flow: AppletFull) -> list[AppletA **answer_item_data, ), **answer_data, + consent_to_share=False, ), AppletAnswerCreate( submit_id=submit_id, @@ -218,6 +222,7 @@ def applet_with_flow_answer_create(applet_with_flow: AppletFull) -> list[AppletA activity_id=applet_with_flow.activities[1].id, answer=ItemAnswerCreate(item_ids=[applet_with_flow.activities[1].items[0].id], **answer_item_data), **answer_data, + consent_to_share=False, ), # flow#1 submission#2 AppletAnswerCreate( @@ -231,6 +236,7 @@ def applet_with_flow_answer_create(applet_with_flow: AppletFull) -> list[AppletA **answer_item_data, ), **answer_data, + consent_to_share=False, ), ] return answers @@ -266,6 +272,7 @@ async def tom_answer_activity_no_flow(session: AsyncSession, tom: User, applet_w user_public_key=str(tom.id), ), client=ClientMeta(app_id=f"{uuid.uuid4()}", app_version="1.1", width=984, height=623), + consent_to_share=False, ) ) @@ -368,6 +375,7 @@ async def tom_answer_activity_flow_not_completed( identifier="encrypted_identifier", ), client=ClientMeta(app_id=f"{uuid.uuid4()}", app_version="1.1", width=984, height=623), + consent_to_share=False, ) ) @@ -1400,6 +1408,7 @@ async def test_summary_activities_submitted_date_with_answers( user_public_key=str(tom.id), ), client=ClientMeta(app_id=f"{uuid.uuid4()}", app_version="1.1", width=984, height=623), + consent_to_share=False, ) ) submit_dates.append(answer.created_at) diff --git a/src/apps/integrations/loris/tests/test_api_applet.py b/src/apps/integrations/loris/tests/test_api_applet.py new file mode 100644 index 00000000000..b5e4213a60f --- /dev/null +++ b/src/apps/integrations/loris/tests/test_api_applet.py @@ -0,0 +1,25 @@ +import uuid +from unittest.mock import AsyncMock, patch + +from fastapi import BackgroundTasks + +from apps.integrations.loris.api.applets import start_transmit_process +from apps.shared.test.client import TestClient +from apps.users.domain import User + + +async def test_start_transmit_process(client: TestClient, user: User, uuid_zero: uuid.UUID, session): + with patch("apps.authentication.deps.get_current_user", return_value=user): + with patch("infrastructure.database.deps.get_session", return_value=session): + with patch("apps.integrations.loris.api.applets.integration", new_callable=AsyncMock) as mock_integration: + background_tasks = BackgroundTasks() + + response = await start_transmit_process( + applet_id=uuid_zero, background_tasks=background_tasks, user=user, session=session + ) + + for task in background_tasks.tasks: + await task() + + assert response.status_code == 202 + mock_integration.assert_called_once_with(uuid_zero, session, user) diff --git a/src/apps/integrations/loris/tests/test_crud_relationship.py b/src/apps/integrations/loris/tests/test_crud_relationship.py new file mode 100644 index 00000000000..e60afa9dcbc --- /dev/null +++ b/src/apps/integrations/loris/tests/test_crud_relationship.py @@ -0,0 +1,127 @@ +import uuid +from unittest.mock import AsyncMock, MagicMock + +import pytest +from sqlalchemy.exc import IntegrityError + +from apps.integrations.loris.crud.user_relationship import MlLorisUserRelationshipCRUD +from apps.integrations.loris.db.schemas import MlLorisUserRelationshipSchema +from apps.integrations.loris.domain import MlLorisUserRelationship +from apps.integrations.loris.errors import MlLorisUserRelationshipError, MlLorisUserRelationshipNotFoundError + + +@pytest.fixture +def relationship_data(uuid_zero: uuid.UUID): + return {"ml_user_uuid": uuid_zero, "loris_user_id": "loris_user_123"} + + +@pytest.fixture +def relationship_schema(relationship_data): + return MlLorisUserRelationshipSchema(**relationship_data) + + +@pytest.fixture +def relationship_instance(relationship_data): + return MlLorisUserRelationship(**relationship_data) + + +@pytest.fixture +async def crud(session): + return MlLorisUserRelationshipCRUD(session) + + +@pytest.mark.asyncio +async def test_save(crud, relationship_schema, relationship_instance, mocker): + mock_create = mocker.patch.object(crud, "_create", return_value=AsyncMock()) + mock_create.return_value = relationship_schema + + result = await crud.save(relationship_schema) + + assert result == relationship_instance + mock_create.assert_called_once_with(relationship_schema) + + +@pytest.mark.asyncio +async def test_save_integrity_error(crud, relationship_schema, mocker): + mock_create = mocker.patch.object(crud, "_create", side_effect=IntegrityError("mock", "mock", "mock")) + + with pytest.raises(MlLorisUserRelationshipError): + await crud.save(relationship_schema) + + mock_create.assert_called_once_with(relationship_schema) + + +@pytest.mark.asyncio +async def test_get_by_ml_user_id(crud, relationship_schema, relationship_instance, mocker): + ml_user_uuid = relationship_schema.ml_user_uuid + + mock_execute = mocker.patch.object(crud, "_execute", return_value=MagicMock()) + mock_scalars = mock_execute.return_value.scalars.return_value + mock_scalars.one_or_none = MagicMock(return_value=relationship_schema) + + result = await crud.get_by_ml_user_id(ml_user_uuid) + + assert result == relationship_instance + mock_execute.assert_called_once() + mock_scalars.one_or_none.assert_called_once() + + +@pytest.mark.asyncio +async def test_get_by_ml_user_id_not_found(crud, relationship_schema, mocker): + ml_user_uuid = relationship_schema.ml_user_uuid + + mock_execute = mocker.patch.object(crud, "_execute", return_value=MagicMock()) + mock_scalars = mock_execute.return_value.scalars.return_value + mock_scalars.one_or_none = MagicMock(return_value=None) + + with pytest.raises(MlLorisUserRelationshipNotFoundError): + await crud.get_by_ml_user_id(ml_user_uuid) + + mock_execute.assert_called_once() + mock_scalars.one_or_none.assert_called_once() + + +@pytest.mark.asyncio +async def test_get_by_loris_user_id(crud, relationship_schema, relationship_instance, mocker): + loris_user_id = relationship_schema.loris_user_id + + mock_execute = mocker.patch.object(crud, "_execute", return_value=MagicMock()) + mock_scalars = mock_execute.return_value.scalars.return_value + mock_scalars.one_or_none = MagicMock(return_value=relationship_schema) + + result = await crud.get_by_loris_user_id(loris_user_id) + + assert result == relationship_instance + mock_execute.assert_called_once() + mock_scalars.one_or_none.assert_called_once() + + +@pytest.mark.asyncio +async def test_get_by_loris_user_id_not_found(crud, relationship_schema, mocker): + loris_user_id = relationship_schema.loris_user_id + + mock_execute = mocker.patch.object(crud, "_execute", return_value=MagicMock()) + mock_scalars = mock_execute.return_value.scalars.return_value + mock_scalars.one_or_none = MagicMock(return_value=None) + + with pytest.raises(MlLorisUserRelationshipNotFoundError): + await crud.get_by_loris_user_id(loris_user_id) + + mock_execute.assert_called_once() + mock_scalars.one_or_none.assert_called_once() + + +# @pytest.mark.asyncio +# async def test_update(crud, relationship_schema, relationship_instance, mocker): +# ml_user_uuid = relationship_schema.ml_user_uuid + +# mock_update_one = mocker.patch.object(crud, '_update_one', return_value=relationship_schema) + +# result = await crud.update(ml_user_uuid, relationship_instance) + +# assert result == relationship_instance +# mock_update_one.assert_called_once_with( +# lookup="ml_user_uuid", +# value=ml_user_uuid, +# schema=relationship_schema +# ) diff --git a/src/apps/integrations/loris/tests/test_domain.py b/src/apps/integrations/loris/tests/test_domain.py new file mode 100644 index 00000000000..63159e01b3f --- /dev/null +++ b/src/apps/integrations/loris/tests/test_domain.py @@ -0,0 +1,239 @@ +import datetime +import uuid + +from apps.integrations.loris.domain import ( + Activitie, + Consent, + ConsentCreate, + ConsentRequest, + ConsentUpdate, + ConsentUpdateRequest, + Item, + MlLorisUserRelationship, + MlLorisUserRelationshipBase, + MlLorisUserRelationshipCreate, + PublicConsent, + UnencryptedApplet, +) + + +def test_item_model(uuid_zero: uuid.UUID): + item_id = uuid_zero + item_data = { + "id": item_id, + "question": "What is your name?", + "responseType": "text", + "responseValues": None, + "config": {"max_length": 100}, + "name": "name", + "isHidden": False, + "conditionalLogic": None, + "allowEdit": True, + } + item = Item(**item_data) + assert item.id == item_id + assert item.question == item_data["question"] + assert item.responseType == item_data["responseType"] + assert item.responseValues == item_data["responseValues"] + assert item.config == item_data["config"] + assert item.name == item_data["name"] + assert item.isHidden == item_data["isHidden"] + assert item.conditionalLogic == item_data["conditionalLogic"] + assert item.allowEdit == item_data["allowEdit"] + + +def test_activitie_model(uuid_zero: uuid.UUID): + activitie_id = uuid_zero + item_id = uuid_zero + created_at = datetime.datetime.now() + activitie_data = { + "id": activitie_id, + "name": "Survey", + "description": "A simple survey", + "splash_screen": "", + "image": "", + "order": 1, + "createdAt": created_at, + "items": [ + { + "id": item_id, + "question": "What is your name?", + "responseType": "text", + "responseValues": None, + "config": {"max_length": 100}, + "name": "name", + "isHidden": False, + "conditionalLogic": None, + "allowEdit": True, + } + ], + } + activitie = Activitie(**activitie_data) + assert activitie.id == activitie_id + assert activitie.name == activitie_data["name"] + assert activitie.description == activitie_data["description"] + assert activitie.splash_screen == activitie_data["splash_screen"] + assert activitie.image == activitie_data["image"] + assert activitie.order == activitie_data["order"] + assert activitie.createdAt == activitie_data["createdAt"] + assert len(activitie.items) == 1 + assert activitie.items[0].id == item_id + + +def test_unencrypted_applet_model(uuid_zero: uuid.UUID): + applet_id = uuid_zero + activitie_id = uuid_zero + item_id = uuid_zero + created_at = datetime.datetime.now() + applet_data = { + "id": applet_id, + "displayName": "Health Survey", + "description": "A survey for health", + "activities": [ + { + "id": activitie_id, + "name": "Survey", + "description": "A simple survey", + "splash_screen": "", + "image": "", + "order": 1, + "createdAt": created_at, + "items": [ + { + "id": item_id, + "question": "What is your name?", + "responseType": "text", + "responseValues": None, + "config": {"max_length": 100}, + "name": "name", + "isHidden": False, + "conditionalLogic": None, + "allowEdit": True, + } + ], + } + ], + } + applet = UnencryptedApplet(**applet_data) + assert applet.id == applet_id + assert applet.displayName == applet_data["displayName"] + assert applet.description == applet_data["description"] + assert len(applet.activities) == 1 + assert applet.activities[0].id == activitie_id + + +def test_consent_create_model(uuid_zero: uuid.UUID): + user_id = uuid_zero + consent_data = { + "user_id": user_id, + "is_ready_share_data": True, + "is_ready_share_media_data": False, + } + consent = ConsentCreate(**consent_data) + assert consent.user_id == user_id + assert consent.is_ready_share_data == consent_data["is_ready_share_data"] + assert consent.is_ready_share_media_data == consent_data["is_ready_share_media_data"] + + +def test_consent_update_model(uuid_zero: uuid.UUID): + user_id = uuid_zero + consent_data = { + "user_id": user_id, + "is_ready_share_data": True, + "is_ready_share_media_data": False, + } + consent = ConsentUpdate(**consent_data) + assert consent.user_id == user_id + assert consent.is_ready_share_data == consent_data["is_ready_share_data"] + assert consent.is_ready_share_media_data == consent_data["is_ready_share_media_data"] + + +def test_consent_model(uuid_zero: uuid.UUID): + user_id = uuid_zero + consent_id = uuid_zero + consent_data = { + "id": consent_id, + "user_id": user_id, + "is_ready_share_data": True, + "is_ready_share_media_data": False, + } + consent = Consent(**consent_data) + assert consent.id == consent_id + assert consent.user_id == user_id + assert consent.is_ready_share_data == consent_data["is_ready_share_data"] + assert consent.is_ready_share_media_data == consent_data["is_ready_share_media_data"] + + +def test_public_consent_model(uuid_zero: uuid.UUID): + user_id = uuid_zero + consent_data = { + "user_id": user_id, + "is_ready_share_data": True, + "is_ready_share_media_data": False, + } + consent = PublicConsent(**consent_data) + assert consent.user_id == user_id + assert consent.is_ready_share_data == consent_data["is_ready_share_data"] + assert consent.is_ready_share_media_data == consent_data["is_ready_share_media_data"] + + +def test_consent_request_model(uuid_zero: uuid.UUID): + user_id = uuid_zero + consent_data = { + "user_id": user_id, + "is_ready_share_data": True, + "is_ready_share_media_data": False, + } + consent = ConsentRequest(**consent_data) + assert consent.user_id == user_id + assert consent.is_ready_share_data == consent_data["is_ready_share_data"] + assert consent.is_ready_share_media_data == consent_data["is_ready_share_media_data"] + + +def test_consent_update_request_model(uuid_zero: uuid.UUID): + user_id = uuid_zero + consent_data = { + "user_id": user_id, + "is_ready_share_data": True, + "is_ready_share_media_data": False, + } + consent = ConsentUpdateRequest(**consent_data) + assert consent.user_id == user_id + assert consent.is_ready_share_data == consent_data["is_ready_share_data"] + assert consent.is_ready_share_media_data == consent_data["is_ready_share_media_data"] + + +def test_ml_loris_user_relationship_base_model(uuid_zero: uuid.UUID): + ml_user_uuid = uuid_zero + loris_user_id = "loris_user_123" + relationship_data = { + "ml_user_uuid": ml_user_uuid, + "loris_user_id": loris_user_id, + } + relationship = MlLorisUserRelationshipBase(**relationship_data) + assert relationship.ml_user_uuid == ml_user_uuid + assert relationship.loris_user_id == loris_user_id + + +def test_ml_loris_user_relationship_create_model(uuid_zero: uuid.UUID): + ml_user_uuid = uuid_zero + loris_user_id = "loris_user_123" + relationship_data = { + "ml_user_uuid": ml_user_uuid, + "loris_user_id": loris_user_id, + } + relationship = MlLorisUserRelationshipCreate(**relationship_data) + assert relationship.ml_user_uuid == ml_user_uuid + assert relationship.loris_user_id == loris_user_id + + +def test_ml_loris_user_relationship_model(uuid_zero: uuid.UUID): + ml_user_uuid = uuid_zero + loris_user_id = "loris_user_123" + relationship_data = { + "ml_user_uuid": ml_user_uuid, + "loris_user_id": loris_user_id, + } + relationship = MlLorisUserRelationship(**relationship_data) + assert relationship.ml_user_uuid == ml_user_uuid + assert relationship.loris_user_id == loris_user_id diff --git a/src/apps/integrations/loris/tests/test_routes.py b/src/apps/integrations/loris/tests/test_routes.py new file mode 100644 index 00000000000..a5e3e3cb840 --- /dev/null +++ b/src/apps/integrations/loris/tests/test_routes.py @@ -0,0 +1,58 @@ +import uuid + +import pytest + +from apps.integrations.loris.router import router as loris_router +from apps.shared.test.client import TestClient +from apps.users.domain import User + + +@pytest.mark.usefixtures("user") +class TestLorisRouter: + start_transmit_process_url = loris_router.url_path_for("start_transmit_process") + consent_create_url = loris_router.url_path_for("consent_create") + # consent_get_by_id_url = loris_router.url_path_for("consent_get_by_id") + # consent_get_by_user_id_url = loris_router.url_path_for("consent_get_by_user_id") + # consent_update_url = loris_router.url_path_for("consent_update") + + async def test_start_transmit_process(self, client: TestClient, user: User, uuid_zero: uuid.UUID): + applet_data = {"applet_id": str(uuid_zero)} + client.login(user) + response = await client.post(self.start_transmit_process_url, query=applet_data) + assert response.status_code == 202 + + # async def test_consent_create(self, client: TestClient, user: User, uuid_zero: uuid.UUID): + # payload = { + # "userId": str(uuid_zero), + # "isReadyShareData": True, + # "isReadyShareMediaData": True + # } + # client.login(user) + # response = await client.post(self.consent_create_url, data=payload) + # assert response.status_code == 201 + + # async def test_consent_get_by_id(self, client: TestClient, user: User, uuid_zero: uuid.UUID): + # # create consent + # consent_id = str(uuid_zero) + # client.login(user) + # response = await client.get(f"/integrations/loris/consent/{consent_id}/") + # assert response.status_code == 200 + + # async def test_consent_get_by_user_id(self, client: TestClient, user: User, uuid_zero: uuid.UUID): + # # create consent + # user_id = str(uuid_zero) + # client.login(user) + # response = await client.get(f"/integrations/loris/consent/users/{user_id}/") + # assert response.status_code == 200 + + # async def test_consent_update(self, client: TestClient, user: User, uuid_zero: uuid.UUID): + # # create consent + # consent_id = str(uuid_zero) + # client.login(user) + # payload = { + # "userId": str(uuid_zero), + # "isReadyShareData": False, + # "isReadyShareMediaData": True + # } + # response = await client.put(f"/integrations/loris/consent/{consent_id}/", data=payload) + # assert response.status_code == 200 diff --git a/src/apps/subjects/tests/tests.py b/src/apps/subjects/tests/tests.py index 386906c79e5..1aad6f42727 100644 --- a/src/apps/subjects/tests/tests.py +++ b/src/apps/subjects/tests/tests.py @@ -101,6 +101,7 @@ def answer_create_payload(applet_one: AppletFull): width=819, height=1080, ), + consent_to_share=False, ) diff --git a/src/apps/users/tests/test_reencrypt_user_answers.py b/src/apps/users/tests/test_reencrypt_user_answers.py index 679a6c99de2..9b526398fef 100644 --- a/src/apps/users/tests/test_reencrypt_user_answers.py +++ b/src/apps/users/tests/test_reencrypt_user_answers.py @@ -111,6 +111,7 @@ async def answer( answer=answer_item_create, created_at=datetime.datetime.utcnow(), client=client_meta, + consent_to_share=False, ) srv = AnswerService(session, user.id) answer = await srv.create_answer(answer_create) @@ -133,6 +134,7 @@ async def answer_second( answer=answer_item_create, created_at=datetime.datetime.utcnow(), client=client_meta, + consent_to_share=False, ) srv = AnswerService(session, user.id) answer = await srv.create_answer(answer_create) @@ -156,6 +158,7 @@ async def answer_arbitrary( answer=answer_item_create, created_at=datetime.datetime.utcnow(), client=client_meta, + consent_to_share=False, ) srv = AnswerService(session, user.id, arbitrary_session=arbitrary_session) answer = await srv.create_answer(answer_create) diff --git a/src/apps/workspaces/tests/test_workspaces.py b/src/apps/workspaces/tests/test_workspaces.py index a9023c859da..979b0e8da48 100644 --- a/src/apps/workspaces/tests/test_workspaces.py +++ b/src/apps/workspaces/tests/test_workspaces.py @@ -124,6 +124,7 @@ async def tom_answer_applet_one(session, tom: User, applet_one: AppletFull): client=ClientMeta(app_id="web", app_version="1.1.0", width="800", height="600"), target_subject_id=subject.id, source_subject_id=subject.id, + consent_to_share=False, ) return await AnswerService(session, tom.id).create_answer(activity_answer) diff --git a/src/infrastructure/database/migrations/versions/2024_06_13_14_07-rename_is_data_share_to_consent_to_.py b/src/infrastructure/database/migrations/versions/2024_06_13_14_07-rename_is_data_share_to_consent_to_.py new file mode 100644 index 00000000000..1c9679aa5d4 --- /dev/null +++ b/src/infrastructure/database/migrations/versions/2024_06_13_14_07-rename_is_data_share_to_consent_to_.py @@ -0,0 +1,38 @@ +"""Rename is_data_share to consent_to_share in answers + +Revision ID: 70c50aba13b7 +Revises: 215b0687963b +Create Date: 2024-06-13 14:07:50.101496 + +""" + +import sqlalchemy as sa +from alembic import op +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = "70c50aba13b7" +down_revision = "215b0687963b" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "answers", sa.Column("consent_to_share", sa.Boolean(), nullable=True) + ) + op.drop_column("answers", "is_data_share") + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "answers", + sa.Column( + "is_data_share", sa.BOOLEAN(), autoincrement=False, nullable=True + ), + ) + op.drop_column("answers", "consent_to_share") + # ### end Alembic commands ### diff --git a/src/infrastructure/database/migrations_arbitrary/versions/2024_06_10_10_30_add_consent_to_share_to_answers_in_.py b/src/infrastructure/database/migrations_arbitrary/versions/2024_06_10_10_30_add_consent_to_share_to_answers_in_.py new file mode 100644 index 00000000000..73ce55b4f0e --- /dev/null +++ b/src/infrastructure/database/migrations_arbitrary/versions/2024_06_10_10_30_add_consent_to_share_to_answers_in_.py @@ -0,0 +1,26 @@ +"""Add consent_to_share to answers in arbitarary db + +Revision ID: 9d525e813ce5 +Revises: 267dd5b56abf +Create Date: 2024-06-10 17:27:59.319326 + +""" + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "9d525e813ce5" +down_revision = "267dd5b56abf" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.add_column( + "answers", sa.Column("consent_to_share", sa.Boolean(), nullable=True) + ) + + +def downgrade() -> None: + op.drop_column("answers", "consent_to_share")