Skip to content

Commit a9e5fc7

Browse files
authored
Merge pull request #14 from CyberCRI/Feature/focus-group-data-collection
Feature/focus group data collection
2 parents 2eeafb6 + 751b3d8 commit a9e5fc7

5 files changed

Lines changed: 145 additions & 3 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "welearn-database"
3-
version = "1.3.0"
3+
version = "1.4.0.dev0"
44
description = "All stuff related to relationnal database from the WeLearn project"
55
authors = [
66
{name = "Théo",email = "theo.nardin@cri-paris.org"}

tests/test_user_related.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
from sqlalchemy.orm import sessionmaker
77

88
from tests.helpers import handle_schema_with_sqlite
9+
from welearn_database.data.enumeration import FilterType
910
from welearn_database.data.models import Base
1011
from welearn_database.data.models.user_related import (
1112
APIKeyManagement,
1213
Bookmark,
1314
ChatMessage,
1415
DataCollectionCampaignManagement,
1516
EndpointRequest,
17+
FilterUsedInQuery,
1618
InferredUser,
1719
ReturnedDocument,
1820
)
@@ -114,12 +116,14 @@ def test_create_and_read_chat_message(self):
114116
conversation_id=uuid.uuid4(),
115117
role="user",
116118
textual_content="Bonjour",
119+
original_feature_name="chat",
117120
)
118121
self.session.add(chat)
119122
self.session.commit()
120123
result = self.session.query(ChatMessage).filter_by(role="user").first()
121124
self.assertIsNotNone(result)
122125
self.assertEqual(result.textual_content, "Bonjour")
126+
self.assertFalse(result.is_retrieved_by_user)
123127

124128
def test_create_and_read_bookmark(self):
125129
inferred_user = InferredUser(id=uuid.uuid4())
@@ -149,6 +153,7 @@ def test_create_and_read_returned_document(self):
149153
inferred_user_id=inferred_user.id,
150154
conversation_id=uuid.uuid4(),
151155
role="user",
156+
original_feature_name="chat",
152157
textual_content="test",
153158
)
154159
self.session.add(chat)
@@ -193,3 +198,30 @@ def test_create_and_read_endpoint_request(self):
193198
)
194199
self.assertIsNotNone(result)
195200
self.assertEqual(result.http_code, 200)
201+
202+
def test_create_and_read_filter_used_in_query(self):
203+
inferred_user = InferredUser(id=uuid.uuid4())
204+
self.session.add(inferred_user)
205+
self.session.commit()
206+
chat = ChatMessage(
207+
id=uuid.uuid4(),
208+
inferred_user_id=inferred_user.id,
209+
conversation_id=uuid.uuid4(),
210+
role="user",
211+
original_feature_name="chat",
212+
textual_content="test",
213+
)
214+
self.session.add(chat)
215+
self.session.commit()
216+
filter_used = FilterUsedInQuery(
217+
id=uuid.uuid4(),
218+
message_id=chat.id,
219+
filter_type=FilterType.SDG.value,
220+
filter_value="13",
221+
)
222+
self.session.add(filter_used)
223+
self.session.commit()
224+
result = (
225+
self.session.query(FilterUsedInQuery).filter_by(filter_value="13").first()
226+
)
227+
self.assertIsNotNone(result)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""data collection for focus group
2+
3+
Revision ID: 9b4f1da0c1f2
4+
Revises: 2ad4895b2674
5+
Create Date: 2026-02-23 18:11:55.857517
6+
7+
"""
8+
9+
from typing import Sequence, Union
10+
11+
import sqlalchemy as sa
12+
from alembic import op
13+
from sqlalchemy.dialects import postgresql
14+
15+
# revision identifiers, used by Alembic.
16+
revision: str = "9b4f1da0c1f2"
17+
down_revision: Union[str, None] = "2ad4895b2674"
18+
branch_labels: Union[str, Sequence[str], None] = None
19+
depends_on: Union[str, Sequence[str], None] = None
20+
21+
22+
def upgrade() -> None:
23+
op.add_column(
24+
"chat_message",
25+
sa.Column(
26+
"is_retrieved_by_user",
27+
sa.Boolean(),
28+
nullable=False,
29+
default=False,
30+
server_default="False",
31+
),
32+
schema="user_related",
33+
)
34+
op.add_column(
35+
"chat_message",
36+
sa.Column("original_feature_name", sa.String(), nullable=True),
37+
schema="user_related",
38+
)
39+
op.create_table(
40+
"filter_used_in_query",
41+
sa.Column(
42+
"id", sa.Uuid(), server_default=sa.func.gen_random_uuid(), nullable=False
43+
),
44+
sa.Column("message_id", sa.Uuid(), nullable=False),
45+
sa.Column(
46+
"filter_type",
47+
postgresql.ENUM(
48+
"sdg",
49+
"source",
50+
name="filter_type",
51+
schema="user_related",
52+
),
53+
nullable=False,
54+
),
55+
sa.Column("filter_value", sa.String(), nullable=False),
56+
sa.ForeignKeyConstraint(
57+
["message_id"],
58+
["user_related.chat_message.id"],
59+
name="filter_used_in_query_message_id_fkey",
60+
),
61+
sa.PrimaryKeyConstraint("id"),
62+
schema="user_related",
63+
)
64+
65+
66+
def downgrade() -> None:
67+
op.drop_column("chat_message", "is_retrieved_by_user", schema="user_related")
68+
op.drop_column("chat_message", "original_feature_name", schema="user_related")
69+
op.drop_constraint(
70+
"filter_used_in_query_message_id_fkey",
71+
"filter_used_in_query",
72+
schema="user_related",
73+
type_="foreignkey",
74+
)
75+
op.drop_table("filter_used_in_query", schema="user_related")
76+
op.execute("DROP TYPE IF EXISTS user_related.filter_type")

welearn_database/data/enumeration.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,8 @@ class ExternalIdType(StrEnum):
3838
HANDLE = auto()
3939
SLUG = auto()
4040
QID = auto()
41+
42+
43+
class FilterType(StrEnum):
44+
SDG = auto()
45+
SOURCE = auto()

welearn_database/data/models/user_related.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
from uuid import UUID
33

44
from sqlalchemy import ForeignKey, func, types
5-
from sqlalchemy.dialects.postgresql import TIMESTAMP
5+
from sqlalchemy.dialects.postgresql import ENUM, TIMESTAMP
66
from sqlalchemy.orm import Mapped, mapped_column, relationship
77

8-
from welearn_database.data.enumeration import DbSchemaEnum
8+
from welearn_database.data.enumeration import DbSchemaEnum, FilterType
99
from welearn_database.data.models.document_related import WeLearnDocument
1010

1111
from . import Base
@@ -96,6 +96,10 @@ class ChatMessage(Base):
9696
)
9797
role: Mapped[str]
9898
textual_content: Mapped[str]
99+
is_retrieved_by_user: Mapped[bool] = mapped_column(
100+
default=False, server_default="False"
101+
)
102+
original_feature_name: Mapped[str | None]
99103

100104
created_at: Mapped[datetime] = mapped_column(
101105
TIMESTAMP(timezone=False),
@@ -134,6 +138,7 @@ class ReturnedDocument(Base):
134138
nullable=False,
135139
)
136140
is_clicked: Mapped[bool] = mapped_column(default=False)
141+
137142
welearn_document: Mapped["WeLearnDocument"] = relationship()
138143
chat_message: Mapped["ChatMessage"] = relationship()
139144

@@ -240,3 +245,27 @@ class EndpointRequest(Base):
240245
server_default="NOW()",
241246
)
242247
session = relationship("Session", foreign_keys=[session_id])
248+
249+
250+
class FilterUsedInQuery(Base):
251+
__tablename__ = "filter_used_in_query"
252+
__table_args__ = {"schema": DbSchemaEnum.USER_RELATED.value}
253+
254+
id: Mapped[UUID] = mapped_column(
255+
types.Uuid, primary_key=True, nullable=False, server_default="gen_random_uuid()"
256+
)
257+
message_id = mapped_column(
258+
types.Uuid,
259+
ForeignKey(f"{DbSchemaEnum.USER_RELATED.value}.chat_message.id"),
260+
nullable=False,
261+
)
262+
filter_type: Mapped[str] = mapped_column(
263+
ENUM(
264+
*(e.value.lower() for e in FilterType),
265+
name="filter_type",
266+
schema=DbSchemaEnum.USER_RELATED.value,
267+
),
268+
)
269+
filter_value: Mapped[str]
270+
271+
chat_message: Mapped["ChatMessage"] = relationship()

0 commit comments

Comments
 (0)