Skip to content

Commit 026ac1e

Browse files
authored
Merge pull request #928 from ChildMindInstitute/release-20231208.5
Release 20231208.5
2 parents 676366d + c1f5af0 commit 026ac1e

67 files changed

Lines changed: 1702 additions & 842 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Pipfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ pyld = "==2.0.3"
8585
types-requests = "==2.31.0.10"
8686
types-pytz = "==2023.3.1.1"
8787
gevent = "~=23.9"
88-
88+
types-aiofiles = "==23.2.0.0"
89+
types-cachetools = "==5.3.0.7"
8990
[requires]
9091
python_version = "3.10"

Pipfile.lock

Lines changed: 150 additions & 134 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/apps/activities/crud/activity_history.py

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import uuid
22

3-
from sqlalchemy import any_, distinct, exists, select
3+
from sqlalchemy import distinct, exists, select, update
44
from sqlalchemy.orm import Query
55

66
from apps.activities.db.schemas import (
77
ActivityHistorySchema,
88
ActivityItemHistorySchema,
9+
ActivitySchema,
910
)
1011
from apps.activities.domain.response_type_config import (
1112
PerformanceTaskType,
@@ -112,17 +113,14 @@ async def get_applet_assessment(
112113
return db_result.scalars().first()
113114

114115
async def get_reviewable_activities(
115-
self, applet_id_versions: list[str]
116+
self, activity_version_ids: list[str]
116117
) -> list[ActivityHistorySchema]:
117-
if not applet_id_versions:
118+
if not activity_version_ids:
118119
return []
119120

120121
query: Query = (
121122
select(ActivityHistorySchema)
122-
.where(
123-
ActivityHistorySchema.applet_id == any_(applet_id_versions),
124-
ActivityHistorySchema.is_reviewable.is_(True),
125-
)
123+
.where(ActivityHistorySchema.id_version.in_(activity_version_ids))
126124
.order_by(
127125
ActivityHistorySchema.applet_id, ActivityHistorySchema.order
128126
)
@@ -179,14 +177,13 @@ async def get_by_applet_id_for_summary(
179177
query = query.distinct(ActivityHistorySchema.id)
180178
db_result = await self._execute(query)
181179
schemas = []
182-
for activity_history_schema, is_performance in db_result.all():
183-
activity_history_schema.is_performance_task = is_performance
180+
for activity_history_schema, _ in db_result.all():
184181
schemas.append(activity_history_schema)
185182

186183
return schemas
187184

188185
async def get_by_applet_id_version(
189-
self, applet_id_version: str
186+
self, applet_id_version: str, non_performance=False
190187
) -> ActivityHistorySchema:
191188
query: Query = select(ActivityHistorySchema)
192189
query = query.where(
@@ -195,6 +192,24 @@ async def get_by_applet_id_version(
195192
query = query.where(
196193
ActivityHistorySchema.is_reviewable == False # noqa
197194
)
195+
if non_performance:
196+
activity_types_query: Query = select(ActivityItemHistorySchema.id)
197+
activity_types_query = activity_types_query.where(
198+
ActivityItemHistorySchema.response_type.in_(
199+
[
200+
PerformanceTaskType.FLANKER,
201+
PerformanceTaskType.GYROSCOPE,
202+
PerformanceTaskType.TOUCH,
203+
PerformanceTaskType.ABTRAILS,
204+
ResponseType.STABILITYTRACKER,
205+
]
206+
)
207+
)
208+
activity_types_query = activity_types_query.where(
209+
ActivityItemHistorySchema.activity_id
210+
== ActivityHistorySchema.id_version
211+
)
212+
query.where(~exists(activity_types_query))
198213
db_result = await self._execute(query)
199214

200215
return db_result.scalars().all()
@@ -253,3 +268,36 @@ async def get_activity_id_versions_for_report(
253268
)
254269
db_result = await self._execute(query)
255270
return db_result.scalars().all()
271+
272+
async def update_by_id(self, id_, **values):
273+
subquery: Query = select(ActivityHistorySchema.id_version)
274+
subquery = subquery.where(ActivityHistorySchema.id == id_)
275+
subquery = subquery.limit(1)
276+
subquery = subquery.order_by(ActivityHistorySchema.created_at.desc())
277+
subquery = subquery.subquery()
278+
279+
query = update(ActivityHistorySchema)
280+
query = query.where(
281+
ActivityHistorySchema.id_version.in_(select([subquery]))
282+
)
283+
query = query.values(**values)
284+
query = query.returning(ActivityHistorySchema)
285+
await self._execute(query)
286+
287+
async def get_assessment_version_id(self, applet: uuid.UUID) -> str:
288+
query: Query = (
289+
select(ActivityHistorySchema.id_version)
290+
.select_from(ActivitySchema)
291+
.join(
292+
ActivityHistorySchema,
293+
ActivityHistorySchema.id == ActivitySchema.id,
294+
)
295+
.where(
296+
ActivitySchema.applet_id == applet,
297+
ActivitySchema.is_reviewable.is_(True),
298+
)
299+
.order_by(ActivityHistorySchema.created_at.desc())
300+
.limit(1)
301+
)
302+
db_result = await self._execute(query)
303+
return db_result.scalars().first()

src/apps/activities/crud/activity_item_history.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from apps.activities.db.schemas import (
77
ActivityHistorySchema,
88
ActivityItemHistorySchema,
9+
ActivitySchema,
910
)
1011
from apps.applets.db.schemas import AppletHistorySchema
1112
from infrastructure.database import BaseCRUD
@@ -86,24 +87,64 @@ async def get_by_activity_id_versions(
8687
return db_result.scalars().all()
8788

8889
async def get_applets_assessments(
89-
self, applet_id_version: str
90+
self,
91+
applet_id: uuid.UUID,
9092
) -> list[ActivityItemHistorySchema]:
93+
subquery: Query = (
94+
select(ActivityHistorySchema.id_version)
95+
.join(
96+
ActivitySchema, ActivitySchema.id == ActivityHistorySchema.id
97+
)
98+
.where(
99+
ActivitySchema.is_reviewable.is_(True),
100+
ActivitySchema.applet_id == applet_id,
101+
)
102+
.order_by(ActivityHistorySchema.created_at.desc())
103+
.limit(1)
104+
.subquery()
105+
)
106+
91107
query: Query = select(ActivityItemHistorySchema)
92108
query = query.join(
93109
ActivityHistorySchema,
94110
ActivityHistorySchema.id_version
95111
== ActivityItemHistorySchema.activity_id,
96112
)
97-
query = query.where(
98-
ActivityHistorySchema.applet_id == applet_id_version
113+
query = query.join(
114+
ActivitySchema, ActivitySchema.id == ActivityHistorySchema.id
99115
)
116+
query = query.where(ActivitySchema.applet_id == applet_id)
100117
query = query.where(
101-
ActivityHistorySchema.is_reviewable == True # noqa: E712
118+
ActivityHistorySchema.is_reviewable == True, # noqa: E712
119+
ActivityHistorySchema.id_version.in_(subquery),
102120
)
103121
query = query.order_by(ActivityItemHistorySchema.order.asc())
104122
db_result = await self._execute(query)
105123

106-
return db_result.scalars().all()
124+
res = db_result.scalars().all()
125+
return res
126+
127+
async def get_assessment_activity_items(
128+
self, id_version: str | None
129+
) -> list[ActivityItemHistorySchema | None]:
130+
if not id_version:
131+
return []
132+
query: Query = select(ActivityItemHistorySchema)
133+
query = query.join(
134+
ActivityHistorySchema,
135+
ActivityHistorySchema.id_version
136+
== ActivityItemHistorySchema.activity_id,
137+
)
138+
query = query.join(
139+
ActivitySchema, ActivitySchema.id == ActivityHistorySchema.id
140+
)
141+
query = query.where(
142+
ActivityHistorySchema.is_reviewable == True, # noqa: E712
143+
ActivityHistorySchema.id_version == id_version,
144+
)
145+
db_result = await self._execute(query)
146+
res = db_result.scalars().all()
147+
return res
107148

108149
async def get_activity_items(
109150
self, activity_id: uuid.UUID, versions: list[str] | None

src/apps/activities/db/schemas/activity.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1-
from sqlalchemy import REAL, Boolean, Column, ForeignKey, String, Text, text
1+
from sqlalchemy import (
2+
REAL,
3+
Boolean,
4+
Column,
5+
ForeignKey,
6+
String,
7+
Text,
8+
func,
9+
text,
10+
)
211
from sqlalchemy.dialects.postgresql import JSONB, UUID
12+
from sqlalchemy.ext.hybrid import hybrid_property
313

14+
from apps.activities.domain.response_type_config import PerformanceTaskType
415
from infrastructure.database.base import Base
516

617
__all__ = ["ActivitySchema", "ActivityHistorySchema"]
@@ -23,6 +34,17 @@ class _BaseActivitySchema:
2334
extra_fields = Column(
2435
JSONB(), default=dict, server_default=text("'{}'::jsonb")
2536
)
37+
performance_task_type = Column(String(255), nullable=True)
38+
39+
@hybrid_property
40+
def is_performance_task(self) -> bool:
41+
return self.performance_task_type in PerformanceTaskType.get_values()
42+
43+
@is_performance_task.expression # type: ignore[no-redef]
44+
def is_performance_task(cls) -> bool:
45+
return func.coalesce(cls.performance_task_type, "").in_(
46+
PerformanceTaskType.get_values()
47+
)
2648

2749

2850
class ActivitySchema(Base, _BaseActivitySchema):

src/apps/activities/domain/activity_base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from pydantic import BaseModel, Field
22

3+
from apps.activities.domain.response_type_config import PerformanceTaskType
34
from apps.activities.domain.scores_reports import (
45
ScoresAndReports,
56
SubscaleSetting,
@@ -20,3 +21,5 @@ class ActivityBase(BaseModel):
2021
scores_and_reports: ScoresAndReports | None = None
2122
subscale_setting: SubscaleSetting | None = None
2223
report_included_item_name: str | None = None
24+
performance_task_type: PerformanceTaskType | None = None
25+
is_performance_task: bool = False

src/apps/activities/domain/activity_create.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from apps.activities.domain.activity_item_base import BaseActivityItem
77
from apps.activities.domain.custom_validation import (
88
validate_item_flow,
9+
validate_performance_task_type,
910
validate_score_and_sections,
1011
validate_subscales,
1112
)
@@ -29,10 +30,10 @@ class ActivityCreate(ActivityBase, InternalModel):
2930

3031
@root_validator()
3132
def validate_existing_ids_for_duplicate(cls, values):
32-
items = values.get("items", [])
33+
items: list[ActivityItemCreate] = values.get("items", [])
3334

3435
item_names = set()
35-
for item in items: # type:ActivityItemCreate
36+
for item in items:
3637
if item.name in item_names:
3738
raise DuplicateActivityItemNameNameError()
3839
item_names.add(item.name)
@@ -49,3 +50,7 @@ def validate_scores_and_reports_conditional_logic(cls, values):
4950
@root_validator()
5051
def validate_subscales(cls, values):
5152
return validate_subscales(values)
53+
54+
@root_validator()
55+
def validate_performance_task_type(cls, values):
56+
return validate_performance_task_type(values)

src/apps/activities/domain/activity_full.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
import uuid
22
from datetime import datetime
33

4-
from pydantic import Field, validator
4+
from pydantic import Field
55

66
from apps.activities.domain.activity_base import ActivityBase
77
from apps.activities.domain.activity_item_base import BaseActivityItem
8-
from apps.activities.domain.custom_validation import (
9-
validate_is_performance_task,
10-
validate_performance_task_type,
11-
)
12-
from apps.activities.domain.response_type_config import PerformanceTaskType
138
from apps.shared.domain import InternalModel, PublicModel
149

1510

@@ -46,13 +41,3 @@ class PublicActivityFull(ActivityBase, PublicModel):
4641
id: uuid.UUID
4742
items: list[PublicActivityItemFull] = Field(default_factory=list)
4843
created_at: datetime
49-
is_performance_task: bool = False
50-
performance_task_type: PerformanceTaskType | None = None
51-
52-
@validator("is_performance_task", always=True)
53-
def validate_is_performance_task_full(cls, value, values):
54-
return validate_is_performance_task(value, values)
55-
56-
@validator("performance_task_type", always=True)
57-
def validate_performance_task_type_full(cls, value, values):
58-
return validate_performance_task_type(value, values)

src/apps/activities/domain/activity_history.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class ActivityHistory(InternalModel):
5252
is_hidden: bool | None = False
5353
scores_and_reports: ScoresAndReports | None = None
5454
subscale_setting: SubscaleSetting | None = None
55+
performance_task_type: PerformanceTaskType | None = None
5556

5657

5758
class ActivityHistoryChange(InternalModel):
@@ -99,8 +100,6 @@ class ActivityHistoryTranslatedExport(ActivityBase, PublicModel):
99100
version: str | None = None
100101
description: str # type: ignore[assignment]
101102
created_at: datetime.datetime
102-
is_performance_task: bool = False
103-
performance_task_type: PerformanceTaskType | None = None
104103
items: list[ActivityItemSingleLanguageDetailPublic] = Field(
105104
default_factory=list
106105
)

src/apps/activities/domain/activity_update.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from apps.activities.domain.activity_item_base import BaseActivityItem
77
from apps.activities.domain.custom_validation import (
88
validate_item_flow,
9+
validate_performance_task_type,
910
validate_score_and_sections,
1011
validate_subscales,
1112
)
@@ -29,10 +30,10 @@ class ActivityUpdate(ActivityBase, InternalModel):
2930

3031
@root_validator()
3132
def validate_existing_ids_for_duplicate(cls, values):
32-
items = values.get("items", [])
33+
items: list[ActivityItemUpdate] = values.get("items", [])
3334

3435
item_names = set()
35-
for item in items: # type:ActivityItemUpdate
36+
for item in items:
3637
if item.name in item_names:
3738
raise DuplicateActivityItemNameNameError()
3839
item_names.add(item.name)
@@ -50,6 +51,10 @@ def validate_score_and_sections_conditional_logic(cls, values):
5051
def validate_subscales(cls, values):
5152
return validate_subscales(values)
5253

54+
@root_validator()
55+
def validate_performance_task_type(cls, values):
56+
return validate_performance_task_type(values)
57+
5358

5459
class ActivityReportConfiguration(PublicModel):
5560
report_included_item_name: str | None

0 commit comments

Comments
 (0)