Skip to content

Commit

Permalink
Merge pull request #928 from ChildMindInstitute/release-20231208.5
Browse files Browse the repository at this point in the history
Release 20231208.5
  • Loading branch information
vshvechko authored Dec 13, 2023
2 parents 676366d + c1f5af0 commit 026ac1e
Show file tree
Hide file tree
Showing 67 changed files with 1,702 additions and 842 deletions.
3 changes: 2 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ pyld = "==2.0.3"
types-requests = "==2.31.0.10"
types-pytz = "==2023.3.1.1"
gevent = "~=23.9"

types-aiofiles = "==23.2.0.0"
types-cachetools = "==5.3.0.7"
[requires]
python_version = "3.10"
284 changes: 150 additions & 134 deletions Pipfile.lock

Large diffs are not rendered by default.

68 changes: 58 additions & 10 deletions src/apps/activities/crud/activity_history.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import uuid

from sqlalchemy import any_, distinct, exists, select
from sqlalchemy import distinct, exists, select, update
from sqlalchemy.orm import Query

from apps.activities.db.schemas import (
ActivityHistorySchema,
ActivityItemHistorySchema,
ActivitySchema,
)
from apps.activities.domain.response_type_config import (
PerformanceTaskType,
Expand Down Expand Up @@ -112,17 +113,14 @@ async def get_applet_assessment(
return db_result.scalars().first()

async def get_reviewable_activities(
self, applet_id_versions: list[str]
self, activity_version_ids: list[str]
) -> list[ActivityHistorySchema]:
if not applet_id_versions:
if not activity_version_ids:
return []

query: Query = (
select(ActivityHistorySchema)
.where(
ActivityHistorySchema.applet_id == any_(applet_id_versions),
ActivityHistorySchema.is_reviewable.is_(True),
)
.where(ActivityHistorySchema.id_version.in_(activity_version_ids))
.order_by(
ActivityHistorySchema.applet_id, ActivityHistorySchema.order
)
Expand Down Expand Up @@ -179,14 +177,13 @@ async def get_by_applet_id_for_summary(
query = query.distinct(ActivityHistorySchema.id)
db_result = await self._execute(query)
schemas = []
for activity_history_schema, is_performance in db_result.all():
activity_history_schema.is_performance_task = is_performance
for activity_history_schema, _ in db_result.all():
schemas.append(activity_history_schema)

return schemas

async def get_by_applet_id_version(
self, applet_id_version: str
self, applet_id_version: str, non_performance=False
) -> ActivityHistorySchema:
query: Query = select(ActivityHistorySchema)
query = query.where(
Expand All @@ -195,6 +192,24 @@ async def get_by_applet_id_version(
query = query.where(
ActivityHistorySchema.is_reviewable == False # noqa
)
if non_performance:
activity_types_query: Query = select(ActivityItemHistorySchema.id)
activity_types_query = activity_types_query.where(
ActivityItemHistorySchema.response_type.in_(
[
PerformanceTaskType.FLANKER,
PerformanceTaskType.GYROSCOPE,
PerformanceTaskType.TOUCH,
PerformanceTaskType.ABTRAILS,
ResponseType.STABILITYTRACKER,
]
)
)
activity_types_query = activity_types_query.where(
ActivityItemHistorySchema.activity_id
== ActivityHistorySchema.id_version
)
query.where(~exists(activity_types_query))
db_result = await self._execute(query)

return db_result.scalars().all()
Expand Down Expand Up @@ -253,3 +268,36 @@ async def get_activity_id_versions_for_report(
)
db_result = await self._execute(query)
return db_result.scalars().all()

async def update_by_id(self, id_, **values):
subquery: Query = select(ActivityHistorySchema.id_version)
subquery = subquery.where(ActivityHistorySchema.id == id_)
subquery = subquery.limit(1)
subquery = subquery.order_by(ActivityHistorySchema.created_at.desc())
subquery = subquery.subquery()

query = update(ActivityHistorySchema)
query = query.where(
ActivityHistorySchema.id_version.in_(select([subquery]))
)
query = query.values(**values)
query = query.returning(ActivityHistorySchema)
await self._execute(query)

async def get_assessment_version_id(self, applet: uuid.UUID) -> str:
query: Query = (
select(ActivityHistorySchema.id_version)
.select_from(ActivitySchema)
.join(
ActivityHistorySchema,
ActivityHistorySchema.id == ActivitySchema.id,
)
.where(
ActivitySchema.applet_id == applet,
ActivitySchema.is_reviewable.is_(True),
)
.order_by(ActivityHistorySchema.created_at.desc())
.limit(1)
)
db_result = await self._execute(query)
return db_result.scalars().first()
51 changes: 46 additions & 5 deletions src/apps/activities/crud/activity_item_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from apps.activities.db.schemas import (
ActivityHistorySchema,
ActivityItemHistorySchema,
ActivitySchema,
)
from apps.applets.db.schemas import AppletHistorySchema
from infrastructure.database import BaseCRUD
Expand Down Expand Up @@ -86,24 +87,64 @@ async def get_by_activity_id_versions(
return db_result.scalars().all()

async def get_applets_assessments(
self, applet_id_version: str
self,
applet_id: uuid.UUID,
) -> list[ActivityItemHistorySchema]:
subquery: Query = (
select(ActivityHistorySchema.id_version)
.join(
ActivitySchema, ActivitySchema.id == ActivityHistorySchema.id
)
.where(
ActivitySchema.is_reviewable.is_(True),
ActivitySchema.applet_id == applet_id,
)
.order_by(ActivityHistorySchema.created_at.desc())
.limit(1)
.subquery()
)

query: Query = select(ActivityItemHistorySchema)
query = query.join(
ActivityHistorySchema,
ActivityHistorySchema.id_version
== ActivityItemHistorySchema.activity_id,
)
query = query.where(
ActivityHistorySchema.applet_id == applet_id_version
query = query.join(
ActivitySchema, ActivitySchema.id == ActivityHistorySchema.id
)
query = query.where(ActivitySchema.applet_id == applet_id)
query = query.where(
ActivityHistorySchema.is_reviewable == True # noqa: E712
ActivityHistorySchema.is_reviewable == True, # noqa: E712
ActivityHistorySchema.id_version.in_(subquery),
)
query = query.order_by(ActivityItemHistorySchema.order.asc())
db_result = await self._execute(query)

return db_result.scalars().all()
res = db_result.scalars().all()
return res

async def get_assessment_activity_items(
self, id_version: str | None
) -> list[ActivityItemHistorySchema | None]:
if not id_version:
return []
query: Query = select(ActivityItemHistorySchema)
query = query.join(
ActivityHistorySchema,
ActivityHistorySchema.id_version
== ActivityItemHistorySchema.activity_id,
)
query = query.join(
ActivitySchema, ActivitySchema.id == ActivityHistorySchema.id
)
query = query.where(
ActivityHistorySchema.is_reviewable == True, # noqa: E712
ActivityHistorySchema.id_version == id_version,
)
db_result = await self._execute(query)
res = db_result.scalars().all()
return res

async def get_activity_items(
self, activity_id: uuid.UUID, versions: list[str] | None
Expand Down
24 changes: 23 additions & 1 deletion src/apps/activities/db/schemas/activity.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
from sqlalchemy import REAL, Boolean, Column, ForeignKey, String, Text, text
from sqlalchemy import (
REAL,
Boolean,
Column,
ForeignKey,
String,
Text,
func,
text,
)
from sqlalchemy.dialects.postgresql import JSONB, UUID
from sqlalchemy.ext.hybrid import hybrid_property

from apps.activities.domain.response_type_config import PerformanceTaskType
from infrastructure.database.base import Base

__all__ = ["ActivitySchema", "ActivityHistorySchema"]
Expand All @@ -23,6 +34,17 @@ class _BaseActivitySchema:
extra_fields = Column(
JSONB(), default=dict, server_default=text("'{}'::jsonb")
)
performance_task_type = Column(String(255), nullable=True)

@hybrid_property
def is_performance_task(self) -> bool:
return self.performance_task_type in PerformanceTaskType.get_values()

@is_performance_task.expression # type: ignore[no-redef]
def is_performance_task(cls) -> bool:
return func.coalesce(cls.performance_task_type, "").in_(
PerformanceTaskType.get_values()
)


class ActivitySchema(Base, _BaseActivitySchema):
Expand Down
3 changes: 3 additions & 0 deletions src/apps/activities/domain/activity_base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from pydantic import BaseModel, Field

from apps.activities.domain.response_type_config import PerformanceTaskType
from apps.activities.domain.scores_reports import (
ScoresAndReports,
SubscaleSetting,
Expand All @@ -20,3 +21,5 @@ class ActivityBase(BaseModel):
scores_and_reports: ScoresAndReports | None = None
subscale_setting: SubscaleSetting | None = None
report_included_item_name: str | None = None
performance_task_type: PerformanceTaskType | None = None
is_performance_task: bool = False
9 changes: 7 additions & 2 deletions src/apps/activities/domain/activity_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from apps.activities.domain.activity_item_base import BaseActivityItem
from apps.activities.domain.custom_validation import (
validate_item_flow,
validate_performance_task_type,
validate_score_and_sections,
validate_subscales,
)
Expand All @@ -29,10 +30,10 @@ class ActivityCreate(ActivityBase, InternalModel):

@root_validator()
def validate_existing_ids_for_duplicate(cls, values):
items = values.get("items", [])
items: list[ActivityItemCreate] = values.get("items", [])

item_names = set()
for item in items: # type:ActivityItemCreate
for item in items:
if item.name in item_names:
raise DuplicateActivityItemNameNameError()
item_names.add(item.name)
Expand All @@ -49,3 +50,7 @@ def validate_scores_and_reports_conditional_logic(cls, values):
@root_validator()
def validate_subscales(cls, values):
return validate_subscales(values)

@root_validator()
def validate_performance_task_type(cls, values):
return validate_performance_task_type(values)
17 changes: 1 addition & 16 deletions src/apps/activities/domain/activity_full.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import uuid
from datetime import datetime

from pydantic import Field, validator
from pydantic import Field

from apps.activities.domain.activity_base import ActivityBase
from apps.activities.domain.activity_item_base import BaseActivityItem
from apps.activities.domain.custom_validation import (
validate_is_performance_task,
validate_performance_task_type,
)
from apps.activities.domain.response_type_config import PerformanceTaskType
from apps.shared.domain import InternalModel, PublicModel


Expand Down Expand Up @@ -46,13 +41,3 @@ class PublicActivityFull(ActivityBase, PublicModel):
id: uuid.UUID
items: list[PublicActivityItemFull] = Field(default_factory=list)
created_at: datetime
is_performance_task: bool = False
performance_task_type: PerformanceTaskType | None = None

@validator("is_performance_task", always=True)
def validate_is_performance_task_full(cls, value, values):
return validate_is_performance_task(value, values)

@validator("performance_task_type", always=True)
def validate_performance_task_type_full(cls, value, values):
return validate_performance_task_type(value, values)
3 changes: 1 addition & 2 deletions src/apps/activities/domain/activity_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class ActivityHistory(InternalModel):
is_hidden: bool | None = False
scores_and_reports: ScoresAndReports | None = None
subscale_setting: SubscaleSetting | None = None
performance_task_type: PerformanceTaskType | None = None


class ActivityHistoryChange(InternalModel):
Expand Down Expand Up @@ -99,8 +100,6 @@ class ActivityHistoryTranslatedExport(ActivityBase, PublicModel):
version: str | None = None
description: str # type: ignore[assignment]
created_at: datetime.datetime
is_performance_task: bool = False
performance_task_type: PerformanceTaskType | None = None
items: list[ActivityItemSingleLanguageDetailPublic] = Field(
default_factory=list
)
9 changes: 7 additions & 2 deletions src/apps/activities/domain/activity_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from apps.activities.domain.activity_item_base import BaseActivityItem
from apps.activities.domain.custom_validation import (
validate_item_flow,
validate_performance_task_type,
validate_score_and_sections,
validate_subscales,
)
Expand All @@ -29,10 +30,10 @@ class ActivityUpdate(ActivityBase, InternalModel):

@root_validator()
def validate_existing_ids_for_duplicate(cls, values):
items = values.get("items", [])
items: list[ActivityItemUpdate] = values.get("items", [])

item_names = set()
for item in items: # type:ActivityItemUpdate
for item in items:
if item.name in item_names:
raise DuplicateActivityItemNameNameError()
item_names.add(item.name)
Expand All @@ -50,6 +51,10 @@ def validate_score_and_sections_conditional_logic(cls, values):
def validate_subscales(cls, values):
return validate_subscales(values)

@root_validator()
def validate_performance_task_type(cls, values):
return validate_performance_task_type(values)


class ActivityReportConfiguration(PublicModel):
report_included_item_name: str | None
Loading

0 comments on commit 026ac1e

Please sign in to comment.