cs-models 0.0.827__py3-none-any.whl → 0.0.847__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cs_models/resources/CompanyOUS/models.py +2 -0
- cs_models/resources/CompanyOUS/schemas.py +4 -0
- cs_models/resources/CompanySEC/models.py +2 -0
- cs_models/resources/CompanySEC/schemas.py +4 -0
- cs_models/resources/DeepResearchAgenticUnit/__init__.py +14 -0
- cs_models/resources/DeepResearchAgenticUnit/models.py +123 -0
- cs_models/resources/DeepResearchAgenticUnit/schemas.py +50 -0
- cs_models/resources/DeepResearchSession/__init__.py +20 -0
- cs_models/resources/DeepResearchSession/models.py +170 -0
- cs_models/resources/DeepResearchSession/schemas.py +94 -0
- cs_models/resources/DeepResearchSubTask/__init__.py +20 -0
- cs_models/resources/DeepResearchSubTask/models.py +177 -0
- cs_models/resources/DeepResearchSubTask/schemas.py +105 -0
- cs_models/resources/MeetingUserDocument/__init__.py +0 -0
- cs_models/resources/MeetingUserDocument/models.py +39 -0
- cs_models/resources/MeetingUserDocument/schemas.py +17 -0
- cs_models/resources/PipelineCrawlSession/__init__.py +0 -0
- cs_models/resources/PipelineCrawlSession/models.py +67 -0
- cs_models/resources/PipelineCrawlSession/schemas.py +22 -0
- cs_models/resources/PipelineCrawledPage/__init__.py +0 -0
- cs_models/resources/PipelineCrawledPage/models.py +80 -0
- cs_models/resources/PipelineCrawledPage/schemas.py +34 -0
- cs_models/resources/PipelineDrugPortfolio/__init__.py +0 -0
- cs_models/resources/PipelineDrugPortfolio/models.py +92 -0
- cs_models/resources/PipelineDrugPortfolio/schemas.py +31 -0
- cs_models/resources/PipelineExtractionLog/__init__.py +0 -0
- cs_models/resources/PipelineExtractionLog/models.py +55 -0
- cs_models/resources/PipelineExtractionLog/schemas.py +23 -0
- cs_models/resources/PubmedMeetingSellSideSignal/__init__.py +0 -0
- cs_models/resources/PubmedMeetingSellSideSignal/models.py +64 -0
- cs_models/resources/PubmedMeetingSellSideSignal/schemas.py +21 -0
- cs_models/resources/PubmedMeetingUserDocument/__init__.py +0 -0
- cs_models/resources/PubmedMeetingUserDocument/models.py +40 -0
- cs_models/resources/PubmedMeetingUserDocument/schemas.py +16 -0
- cs_models/resources/SellSideAbstractMention/__init__.py +0 -0
- cs_models/resources/SellSideAbstractMention/models.py +57 -0
- cs_models/resources/SellSideAbstractMention/schemas.py +28 -0
- cs_models/resources/SellSideAbstractMentionLink/__init__.py +0 -0
- cs_models/resources/SellSideAbstractMentionLink/models.py +60 -0
- cs_models/resources/SellSideAbstractMentionLink/schemas.py +24 -0
- cs_models/resources/SellSideSource/__init__.py +0 -0
- cs_models/resources/SellSideSource/models.py +25 -0
- cs_models/resources/SellSideSource/schemas.py +13 -0
- cs_models/resources/UserDocument/models.py +7 -0
- cs_models/resources/UserDocument/schemas.py +2 -0
- cs_models/resources/UserDocumentAccess/models.py +6 -0
- cs_models/resources/UserDocumentAccess/schemas.py +1 -0
- cs_models/resources/Workbook/models.py +9 -0
- cs_models/resources/Workbook/schemas.py +6 -0
- cs_models/resources/WorkbookCommentThread/__init__.py +0 -0
- cs_models/resources/WorkbookCommentThread/models.py +59 -0
- cs_models/resources/WorkbookCommentThread/schemas.py +35 -0
- cs_models/resources/WorkbookThreadComment/__init__.py +0 -0
- cs_models/resources/WorkbookThreadComment/models.py +38 -0
- cs_models/resources/WorkbookThreadComment/schemas.py +14 -0
- {cs_models-0.0.827.dist-info → cs_models-0.0.847.dist-info}/METADATA +1 -1
- {cs_models-0.0.827.dist-info → cs_models-0.0.847.dist-info}/RECORD +59 -14
- {cs_models-0.0.827.dist-info → cs_models-0.0.847.dist-info}/WHEEL +0 -0
- {cs_models-0.0.827.dist-info → cs_models-0.0.847.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from sqlalchemy import (
|
|
2
|
+
Column,
|
|
3
|
+
Integer,
|
|
4
|
+
String,
|
|
5
|
+
DateTime,
|
|
6
|
+
Text,
|
|
7
|
+
ForeignKey,
|
|
8
|
+
Enum,
|
|
9
|
+
)
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
from ...database import Base
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PipelineExtractionLogModel(Base):
|
|
16
|
+
__tablename__ = 'pipeline_extraction_logs'
|
|
17
|
+
|
|
18
|
+
id = Column(Integer, primary_key=True)
|
|
19
|
+
session_id = Column(
|
|
20
|
+
Integer,
|
|
21
|
+
ForeignKey('pipeline_crawl_sessions.id'),
|
|
22
|
+
nullable=False,
|
|
23
|
+
index=True,
|
|
24
|
+
)
|
|
25
|
+
page_id = Column(
|
|
26
|
+
Integer,
|
|
27
|
+
ForeignKey('pipeline_crawled_pages.id'),
|
|
28
|
+
nullable=True,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Log details (MySQL ENUM)
|
|
32
|
+
log_level = Column(
|
|
33
|
+
Enum('debug', 'info', 'warning', 'error'),
|
|
34
|
+
nullable=False,
|
|
35
|
+
default='info',
|
|
36
|
+
index=True,
|
|
37
|
+
)
|
|
38
|
+
message = Column(Text, nullable=False)
|
|
39
|
+
|
|
40
|
+
# Context
|
|
41
|
+
extraction_method = Column(String(50), nullable=True)
|
|
42
|
+
model_name = Column(String(128), nullable=True)
|
|
43
|
+
tokens_used = Column(Integer, nullable=True)
|
|
44
|
+
api_latency_ms = Column(Integer, nullable=True)
|
|
45
|
+
|
|
46
|
+
# Error tracking
|
|
47
|
+
exception_type = Column(String(256), nullable=True)
|
|
48
|
+
exception_message = Column(Text, nullable=True)
|
|
49
|
+
stack_trace = Column(Text, nullable=True)
|
|
50
|
+
|
|
51
|
+
# Retry tracking
|
|
52
|
+
attempt_number = Column(Integer, nullable=True, default=1)
|
|
53
|
+
max_attempts = Column(Integer, nullable=True, default=3)
|
|
54
|
+
|
|
55
|
+
created_at = Column(DateTime, nullable=False, default=datetime.utcnow, index=True)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from marshmallow import Schema, fields
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PipelineExtractionLogSchema(Schema):
|
|
5
|
+
id = fields.Int(dump_only=True)
|
|
6
|
+
session_id = fields.Int(required=True)
|
|
7
|
+
page_id = fields.Int(allow_none=True)
|
|
8
|
+
log_level = fields.Str(required=True)
|
|
9
|
+
message = fields.Str(required=True)
|
|
10
|
+
extraction_method = fields.Str(allow_none=True)
|
|
11
|
+
model_name = fields.Str(allow_none=True)
|
|
12
|
+
tokens_used = fields.Int(allow_none=True)
|
|
13
|
+
api_latency_ms = fields.Int(allow_none=True)
|
|
14
|
+
exception_type = fields.Str(allow_none=True)
|
|
15
|
+
exception_message = fields.Str(allow_none=True)
|
|
16
|
+
stack_trace = fields.Str(allow_none=True)
|
|
17
|
+
attempt_number = fields.Int(allow_none=True)
|
|
18
|
+
max_attempts = fields.Int(allow_none=True)
|
|
19
|
+
created_at = fields.DateTime(dump_only=True)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PipelineExtractionLogResourceSchema(PipelineExtractionLogSchema):
|
|
23
|
+
pass
|
|
File without changes
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from sqlalchemy import (
|
|
2
|
+
Column,
|
|
3
|
+
Integer,
|
|
4
|
+
Float,
|
|
5
|
+
DateTime,
|
|
6
|
+
ForeignKey,
|
|
7
|
+
UniqueConstraint,
|
|
8
|
+
)
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
from ...database import Base
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PubmedMeetingSellSideSignalModel(Base):
|
|
15
|
+
__tablename__ = "pubmed_meeting_sell_side_signals"
|
|
16
|
+
|
|
17
|
+
id = Column(Integer, primary_key=True)
|
|
18
|
+
|
|
19
|
+
pubmed_id = Column(
|
|
20
|
+
Integer,
|
|
21
|
+
ForeignKey("pubmed.id"),
|
|
22
|
+
nullable=False,
|
|
23
|
+
index=True,
|
|
24
|
+
)
|
|
25
|
+
meeting_id = Column(
|
|
26
|
+
Integer,
|
|
27
|
+
ForeignKey("meetings.id"),
|
|
28
|
+
nullable=False,
|
|
29
|
+
index=True,
|
|
30
|
+
)
|
|
31
|
+
sell_side_source_id = Column(
|
|
32
|
+
Integer,
|
|
33
|
+
ForeignKey("sell_side_sources.id"),
|
|
34
|
+
nullable=False,
|
|
35
|
+
index=True,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# intensity
|
|
39
|
+
doc_count = Column(Integer, nullable=False) # distinct notes
|
|
40
|
+
mention_count = Column(Integer, nullable=False) # total mentions across those notes
|
|
41
|
+
|
|
42
|
+
# sentiment summary
|
|
43
|
+
avg_sentiment = Column(Float, nullable=True)
|
|
44
|
+
max_sentiment = Column(Float, nullable=True)
|
|
45
|
+
|
|
46
|
+
first_mention_at = Column(DateTime, nullable=True)
|
|
47
|
+
last_mention_at = Column(DateTime, nullable=True)
|
|
48
|
+
|
|
49
|
+
created_at = Column(DateTime, default=lambda: datetime.utcnow(), nullable=False)
|
|
50
|
+
updated_at = Column(
|
|
51
|
+
DateTime,
|
|
52
|
+
default=lambda: datetime.utcnow(),
|
|
53
|
+
onupdate=lambda: datetime.utcnow(),
|
|
54
|
+
nullable=False,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
__table_args__ = (
|
|
58
|
+
UniqueConstraint(
|
|
59
|
+
"pubmed_id",
|
|
60
|
+
"meeting_id",
|
|
61
|
+
"sell_side_source_id",
|
|
62
|
+
name="uq_pubmed_meeting_source",
|
|
63
|
+
),
|
|
64
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from marshmallow import Schema, fields, validate
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PubmedMeetingSellSideSignalResourceSchema(Schema):
|
|
5
|
+
id = fields.Integer(dump_only=True)
|
|
6
|
+
|
|
7
|
+
pubmed_id = fields.Integer(required=True)
|
|
8
|
+
meeting_id = fields.Integer(required=True)
|
|
9
|
+
sell_side_source_id = fields.Integer(required=True)
|
|
10
|
+
|
|
11
|
+
doc_count = fields.Integer(required=True)
|
|
12
|
+
mention_count = fields.Integer(required=True)
|
|
13
|
+
|
|
14
|
+
avg_sentiment = fields.Float(allow_none=True)
|
|
15
|
+
max_sentiment = fields.Float(allow_none=True)
|
|
16
|
+
|
|
17
|
+
first_mention_at = fields.DateTime(allow_none=True)
|
|
18
|
+
last_mention_at = fields.DateTime(allow_none=True)
|
|
19
|
+
|
|
20
|
+
created_at = fields.DateTime(dump_only=True)
|
|
21
|
+
updated_at = fields.DateTime(dump_only=True)
|
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from sqlalchemy import (
|
|
4
|
+
Column,
|
|
5
|
+
Text,
|
|
6
|
+
Integer,
|
|
7
|
+
DateTime,
|
|
8
|
+
ForeignKey,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from ...database import Base
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PubmedMeetingUserDocumentModel(Base):
|
|
15
|
+
__tablename__ = "pubmed_meeting_user_documents"
|
|
16
|
+
|
|
17
|
+
id = Column(Integer, primary_key=True)
|
|
18
|
+
pubmed_id = Column(
|
|
19
|
+
Integer,
|
|
20
|
+
ForeignKey('pubmed.id'),
|
|
21
|
+
nullable=False,
|
|
22
|
+
)
|
|
23
|
+
meeting_id = Column(
|
|
24
|
+
Integer,
|
|
25
|
+
ForeignKey('meetings.id'),
|
|
26
|
+
nullable=False,
|
|
27
|
+
)
|
|
28
|
+
user_document_id = Column(
|
|
29
|
+
Integer,
|
|
30
|
+
ForeignKey('user_documents.id'),
|
|
31
|
+
nullable=False,
|
|
32
|
+
)
|
|
33
|
+
details = Column(Text, nullable=True)
|
|
34
|
+
updated_at = Column(
|
|
35
|
+
DateTime,
|
|
36
|
+
nullable=False,
|
|
37
|
+
# https://stackoverflow.com/questions/58776476/why-doesnt-freezegun-work-with-sqlalchemy-default-values
|
|
38
|
+
default=lambda: datetime.utcnow(),
|
|
39
|
+
onupdate=lambda: datetime.utcnow(),
|
|
40
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from marshmallow import (
|
|
2
|
+
Schema,
|
|
3
|
+
fields,
|
|
4
|
+
validate,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PubmedMeetingUserDocumentResourceSchema(Schema):
|
|
9
|
+
not_blank = validate.Length(min=1, error='Field cannot be blank')
|
|
10
|
+
|
|
11
|
+
id = fields.Integer(dump_only=True)
|
|
12
|
+
pubmed_id = fields.Integer(required=True)
|
|
13
|
+
meeting_id = fields.Integer(required=True)
|
|
14
|
+
user_document_id = fields.Integer(required=True)
|
|
15
|
+
details = fields.String(allow_none=True)
|
|
16
|
+
updated_at = fields.DateTime()
|
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from sqlalchemy import (
|
|
2
|
+
Column,
|
|
3
|
+
Integer,
|
|
4
|
+
String,
|
|
5
|
+
Float,
|
|
6
|
+
Text,
|
|
7
|
+
DateTime,
|
|
8
|
+
ForeignKey,
|
|
9
|
+
)
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
from ...database import Base
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SellSideAbstractMentionModel(Base):
|
|
16
|
+
__tablename__ = "sell_side_abstract_mentions"
|
|
17
|
+
|
|
18
|
+
id = Column(Integer, primary_key=True)
|
|
19
|
+
|
|
20
|
+
# which PDF / note
|
|
21
|
+
user_document_id = Column(
|
|
22
|
+
Integer,
|
|
23
|
+
ForeignKey("user_documents.id"),
|
|
24
|
+
nullable=False,
|
|
25
|
+
index=True,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# which conference
|
|
29
|
+
meeting_id = Column(
|
|
30
|
+
Integer,
|
|
31
|
+
ForeignKey("meetings.id"),
|
|
32
|
+
nullable=False,
|
|
33
|
+
index=True,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
# optional locator
|
|
37
|
+
page_number = Column(Integer, nullable=True)
|
|
38
|
+
|
|
39
|
+
# raw LLM fields
|
|
40
|
+
title = Column(Text, nullable=True)
|
|
41
|
+
url = Column(Text, nullable=True)
|
|
42
|
+
abstract_number = Column(String(64), nullable=True)
|
|
43
|
+
abstract_search_query = Column(Text, nullable=True)
|
|
44
|
+
context = Column(Text, nullable=True)
|
|
45
|
+
sentiment = Column(Text, nullable=True)
|
|
46
|
+
llm_confidence = Column(Float, nullable=True)
|
|
47
|
+
|
|
48
|
+
raw_json = Column(Text, nullable=True)
|
|
49
|
+
|
|
50
|
+
created_at = Column(DateTime, default=lambda: datetime.utcnow(), nullable=False)
|
|
51
|
+
updated_at = Column(
|
|
52
|
+
DateTime,
|
|
53
|
+
default=lambda: datetime.utcnow(),
|
|
54
|
+
onupdate=lambda: datetime.utcnow(),
|
|
55
|
+
nullable=False,
|
|
56
|
+
)
|
|
57
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from marshmallow import Schema, fields
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SellSideAbstractMentionResourceSchema(Schema):
|
|
5
|
+
id = fields.Integer(dump_only=True)
|
|
6
|
+
|
|
7
|
+
# which PDF / note
|
|
8
|
+
user_document_id = fields.Integer(required=True)
|
|
9
|
+
# which conference
|
|
10
|
+
meeting_id = fields.Integer(required=True)
|
|
11
|
+
|
|
12
|
+
page_number = fields.Integer(allow_none=True)
|
|
13
|
+
char_start = fields.Integer(allow_none=True)
|
|
14
|
+
char_end = fields.Integer(allow_none=True)
|
|
15
|
+
|
|
16
|
+
title = fields.String(allow_none=True)
|
|
17
|
+
url = fields.String(allow_none=True)
|
|
18
|
+
abstract_number = fields.String(allow_none=True)
|
|
19
|
+
abstract_search_query = fields.String(allow_none=True)
|
|
20
|
+
context = fields.String(allow_none=True)
|
|
21
|
+
sentiment = fields.String(allow_none=True)
|
|
22
|
+
|
|
23
|
+
llm_confidence = fields.Float(allow_none=True)
|
|
24
|
+
|
|
25
|
+
raw_json = fields.String(allow_none=True)
|
|
26
|
+
|
|
27
|
+
created_at = fields.DateTime(dump_only=True)
|
|
28
|
+
updated_at = fields.DateTime(dump_only=True)
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from sqlalchemy import (
|
|
2
|
+
Column,
|
|
3
|
+
Integer,
|
|
4
|
+
String,
|
|
5
|
+
Float,
|
|
6
|
+
Boolean,
|
|
7
|
+
DateTime,
|
|
8
|
+
ForeignKey,
|
|
9
|
+
)
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
|
|
12
|
+
from ...database import Base
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SellSideAbstractMentionLinkModel(Base):
|
|
16
|
+
__tablename__ = "sell_side_abstract_mention_links"
|
|
17
|
+
|
|
18
|
+
id = Column(Integer, primary_key=True)
|
|
19
|
+
|
|
20
|
+
mention_id = Column(
|
|
21
|
+
Integer,
|
|
22
|
+
ForeignKey("sell_side_abstract_mentions.id"),
|
|
23
|
+
nullable=False,
|
|
24
|
+
index=True,
|
|
25
|
+
)
|
|
26
|
+
pubmed_id = Column(
|
|
27
|
+
Integer,
|
|
28
|
+
ForeignKey("pubmed.id"),
|
|
29
|
+
nullable=False,
|
|
30
|
+
index=True,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# where did this candidate come from?
|
|
34
|
+
match_source = Column(
|
|
35
|
+
String(64),
|
|
36
|
+
nullable=False,
|
|
37
|
+
) # e.g. "grid_cited", "abstract_number", "url", "title_fuzzy", "context_llm"
|
|
38
|
+
|
|
39
|
+
# overall score + feature-level scores
|
|
40
|
+
match_score = Column(Float, nullable=False)
|
|
41
|
+
number_score = Column(Float, nullable=True)
|
|
42
|
+
url_score = Column(Float, nullable=True)
|
|
43
|
+
title_score = Column(Float, nullable=True)
|
|
44
|
+
context_score = Column(Float, nullable=True)
|
|
45
|
+
llm_score = Column(Float, nullable=True)
|
|
46
|
+
|
|
47
|
+
is_primary = Column(Boolean, nullable=False, default=False)
|
|
48
|
+
|
|
49
|
+
created_at = Column(DateTime, default=lambda: datetime.utcnow(), nullable=False)
|
|
50
|
+
updated_at = Column(
|
|
51
|
+
DateTime,
|
|
52
|
+
default=lambda: datetime.utcnow(),
|
|
53
|
+
onupdate=lambda: datetime.utcnow(),
|
|
54
|
+
nullable=False,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
__table_args__ = (
|
|
58
|
+
# you can keep multiple rows per pair (for debugging) or enforce uniqueness:
|
|
59
|
+
# UniqueConstraint("mention_id", "pubmed_id", name="uq_mention_pubmed"),
|
|
60
|
+
)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from marshmallow import Schema, fields, validate
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SellSideAbstractMentionLinkResourceSchema(Schema):
|
|
5
|
+
id = fields.Integer(dump_only=True)
|
|
6
|
+
|
|
7
|
+
mention_id = fields.Integer(required=True)
|
|
8
|
+
pubmed_id = fields.Integer(required=True)
|
|
9
|
+
|
|
10
|
+
# e.g. "grid_cited", "abstract_number", "url", "title_fuzzy", "context_llm"
|
|
11
|
+
match_source = fields.String(required=True, validate=validate.Length(min=1))
|
|
12
|
+
|
|
13
|
+
match_score = fields.Float(required=True)
|
|
14
|
+
|
|
15
|
+
number_score = fields.Float(allow_none=True)
|
|
16
|
+
url_score = fields.Float(allow_none=True)
|
|
17
|
+
title_score = fields.Float(allow_none=True)
|
|
18
|
+
context_score = fields.Float(allow_none=True)
|
|
19
|
+
llm_score = fields.Float(allow_none=True)
|
|
20
|
+
|
|
21
|
+
is_primary = fields.Boolean(required=True)
|
|
22
|
+
|
|
23
|
+
created_at = fields.DateTime(dump_only=True)
|
|
24
|
+
updated_at = fields.DateTime(dump_only=True)
|
|
File without changes
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from sqlalchemy import (
|
|
2
|
+
Column,
|
|
3
|
+
Integer,
|
|
4
|
+
String,
|
|
5
|
+
DateTime,
|
|
6
|
+
)
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
|
|
9
|
+
from ...database import Base
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SellSideSourceModel(Base):
|
|
13
|
+
__tablename__ = "sell_side_sources"
|
|
14
|
+
|
|
15
|
+
id = Column(Integer, primary_key=True)
|
|
16
|
+
name = Column(String(255), nullable=False, unique=True) # "Morgan Stanley"
|
|
17
|
+
code = Column(String(64), nullable=False, unique=True) # "MS", "JPM"
|
|
18
|
+
|
|
19
|
+
created_at = Column(DateTime, default=lambda: datetime.utcnow(), nullable=False)
|
|
20
|
+
updated_at = Column(
|
|
21
|
+
DateTime,
|
|
22
|
+
default=lambda: datetime.utcnow(),
|
|
23
|
+
onupdate=lambda: datetime.utcnow(),
|
|
24
|
+
nullable=False,
|
|
25
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from marshmallow import Schema, fields, validate
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SellSideSourceResourceSchema(Schema):
|
|
5
|
+
id = fields.Integer(dump_only=True)
|
|
6
|
+
|
|
7
|
+
# e.g. "Morgan Stanley"
|
|
8
|
+
name = fields.String(required=True, validate=validate.Length(min=1))
|
|
9
|
+
# e.g. "MS", "JPM"
|
|
10
|
+
code = fields.String(allow_none=True)
|
|
11
|
+
|
|
12
|
+
created_at = fields.DateTime(dump_only=True)
|
|
13
|
+
updated_at = fields.DateTime(dump_only=True)
|
|
@@ -33,6 +33,13 @@ class UserDocumentModel(Base):
|
|
|
33
33
|
metadata_info = Column(Text, nullable=True)
|
|
34
34
|
status = Column(String(128), nullable=True)
|
|
35
35
|
page_count = Column(Integer, nullable=True)
|
|
36
|
+
sell_side_source_id = Column(
|
|
37
|
+
Integer,
|
|
38
|
+
ForeignKey("sell_side_sources.id"),
|
|
39
|
+
nullable=True,
|
|
40
|
+
index=True,
|
|
41
|
+
)
|
|
42
|
+
sell_side_note_type = Column(String(64), nullable=True)
|
|
36
43
|
updated_at = Column(
|
|
37
44
|
DateTime,
|
|
38
45
|
nullable=False,
|
|
@@ -21,4 +21,6 @@ class UserDocumentResourceSchema(Schema):
|
|
|
21
21
|
category = fields.String(allow_none=True)
|
|
22
22
|
status = fields.String(allow_none=True)
|
|
23
23
|
page_count = fields.Integer(allow_none=True)
|
|
24
|
+
sell_side_source_id = fields.Integer(allow_none=True)
|
|
25
|
+
sell_side_note_type = fields.String(allow_none=True)
|
|
24
26
|
updated_at = fields.DateTime(dump_only=True)
|
|
@@ -4,6 +4,7 @@ from sqlalchemy import (
|
|
|
4
4
|
String,
|
|
5
5
|
DateTime,
|
|
6
6
|
Boolean,
|
|
7
|
+
ForeignKey,
|
|
7
8
|
)
|
|
8
9
|
from datetime import datetime
|
|
9
10
|
|
|
@@ -15,6 +16,11 @@ class UserDocumentAccessModel(Base):
|
|
|
15
16
|
|
|
16
17
|
id = Column(Integer, primary_key=True)
|
|
17
18
|
user_id = Column(String(128), nullable=False, index=True)
|
|
19
|
+
user_document_id = Column(
|
|
20
|
+
Integer,
|
|
21
|
+
ForeignKey('user_documents.id'),
|
|
22
|
+
nullable=False,
|
|
23
|
+
)
|
|
18
24
|
provider_permission_id = Column(String(255), nullable=True)
|
|
19
25
|
is_inherited = Column(Boolean, default=False)
|
|
20
26
|
source_provider = Column(String(32), nullable=True)
|
|
@@ -10,6 +10,7 @@ class UserDocumentAccessResourceSchema(Schema):
|
|
|
10
10
|
|
|
11
11
|
id = fields.Integer(dump_only=True)
|
|
12
12
|
user_id = fields.String(required=True)
|
|
13
|
+
user_document_id = fields.Integer(required=True)
|
|
13
14
|
provider_permission_id = fields.String(allow_none=True)
|
|
14
15
|
is_inherited = fields.Boolean(allow_none=True)
|
|
15
16
|
source_provider = fields.String(allow_none=True)
|
|
@@ -10,6 +10,7 @@ from sqlalchemy.orm import relationship
|
|
|
10
10
|
|
|
11
11
|
from ...database import Base
|
|
12
12
|
from ..WorkbookBlock.models import WorkbookBlockModel
|
|
13
|
+
from ..WorkbookCommentThread.models import WorkbookCommentThreadModel
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class WorkbookModel(Base):
|
|
@@ -35,3 +36,11 @@ class WorkbookModel(Base):
|
|
|
35
36
|
order_by=WorkbookBlockModel.sequence_number,
|
|
36
37
|
back_populates="workbook",
|
|
37
38
|
)
|
|
39
|
+
|
|
40
|
+
comment_threads = relationship(
|
|
41
|
+
"WorkbookCommentThreadModel",
|
|
42
|
+
primaryjoin="and_(WorkbookModel.id==WorkbookCommentThreadModel.workbook_id, "
|
|
43
|
+
"or_(WorkbookCommentThreadModel.is_deleted==False, WorkbookCommentThreadModel.is_deleted==None))",
|
|
44
|
+
order_by=WorkbookCommentThreadModel.updated_at.desc(),
|
|
45
|
+
back_populates="workbook",
|
|
46
|
+
)
|
|
@@ -6,6 +6,7 @@ from marshmallow import (
|
|
|
6
6
|
from ..WorkbookBlock.schemas import (
|
|
7
7
|
WorkbookBlockResourceSchema,
|
|
8
8
|
)
|
|
9
|
+
from ..WorkbookCommentThread.schemas import WorkbookCommentThreadResourceSchema
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class WorkbookResourceSchema(Schema):
|
|
@@ -19,6 +20,11 @@ class WorkbookResourceSchema(Schema):
|
|
|
19
20
|
many=True,
|
|
20
21
|
dump_only=True,
|
|
21
22
|
)
|
|
23
|
+
comment_threads = fields.Nested(
|
|
24
|
+
WorkbookCommentThreadResourceSchema(exclude=("workbook_id",)),
|
|
25
|
+
many=True,
|
|
26
|
+
dump_only=True,
|
|
27
|
+
)
|
|
22
28
|
is_deleted = fields.Boolean(allow_none=True)
|
|
23
29
|
is_public = fields.Boolean(allow_none=True)
|
|
24
30
|
is_help_center = fields.Boolean(allow_none=True)
|
|
File without changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from sqlalchemy import Column, DateTime, Boolean, ForeignKey, Integer, Text, String
|
|
4
|
+
from sqlalchemy.orm import relationship
|
|
5
|
+
|
|
6
|
+
from ...database import Base
|
|
7
|
+
from ..WorkbookThreadComment.models import WorkbookThreadCommentModel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class WorkbookCommentThreadModel(Base):
|
|
11
|
+
"""
|
|
12
|
+
Represents a comment thread tied to a text selection in a workbook block.
|
|
13
|
+
"""
|
|
14
|
+
__tablename__ = "workbook_comment_threads"
|
|
15
|
+
|
|
16
|
+
id = Column(Integer, primary_key=True)
|
|
17
|
+
workbook_id = Column(
|
|
18
|
+
Integer,
|
|
19
|
+
ForeignKey("workbooks.id", ondelete="CASCADE"),
|
|
20
|
+
nullable=False,
|
|
21
|
+
)
|
|
22
|
+
block_uid = Column(String(64), nullable=False) # Root parent block UID
|
|
23
|
+
|
|
24
|
+
# Selection context
|
|
25
|
+
selected_text = Column(Text, nullable=False) # The highlighted text
|
|
26
|
+
|
|
27
|
+
# Thread status
|
|
28
|
+
is_resolved = Column(Boolean, default=False, nullable=False)
|
|
29
|
+
resolved_by = Column(String(128), nullable=True) # user_id who resolved
|
|
30
|
+
resolved_at = Column(DateTime, nullable=True)
|
|
31
|
+
|
|
32
|
+
# Soft delete
|
|
33
|
+
is_deleted = Column(Boolean, default=False, nullable=True)
|
|
34
|
+
|
|
35
|
+
# Timestamps
|
|
36
|
+
created_at = Column(DateTime, nullable=False, default=lambda: datetime.utcnow())
|
|
37
|
+
updated_at = Column(
|
|
38
|
+
DateTime,
|
|
39
|
+
nullable=False,
|
|
40
|
+
default=lambda: datetime.utcnow(),
|
|
41
|
+
onupdate=lambda: datetime.utcnow(),
|
|
42
|
+
)
|
|
43
|
+
created_by = Column(String(128), nullable=False) # user_id who created thread
|
|
44
|
+
|
|
45
|
+
# Smart Grid Cells
|
|
46
|
+
cell_session_id = Column(Integer, nullable=True)
|
|
47
|
+
cell_user_query_id = Column(Integer, nullable=True)
|
|
48
|
+
|
|
49
|
+
# Relationships
|
|
50
|
+
workbook = relationship("WorkbookModel", back_populates="comment_threads")
|
|
51
|
+
|
|
52
|
+
comments = relationship(
|
|
53
|
+
"WorkbookThreadCommentModel",
|
|
54
|
+
primaryjoin="and_(WorkbookCommentThreadModel.id==WorkbookThreadCommentModel.thread_id, "
|
|
55
|
+
"or_(WorkbookThreadCommentModel.is_deleted==False, WorkbookThreadCommentModel.is_deleted==None))",
|
|
56
|
+
order_by=WorkbookThreadCommentModel.sequence_number,
|
|
57
|
+
back_populates="thread",
|
|
58
|
+
lazy="joined", # Eager load comments when loading thread
|
|
59
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from marshmallow import Schema, fields, EXCLUDE
|
|
2
|
+
from ..WorkbookThreadComment.schemas import (
|
|
3
|
+
WorkbookThreadCommentSchema,
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class WorkbookCommentThreadResourceSchema(Schema):
|
|
8
|
+
"""Class for AssistantCommandResource schema"""
|
|
9
|
+
class Meta:
|
|
10
|
+
unknown = EXCLUDE
|
|
11
|
+
|
|
12
|
+
id = fields.Integer(dump_only=True, data_key="thread_id")
|
|
13
|
+
workbook_id = fields.Integer(required=True)
|
|
14
|
+
block_uid = fields.String(required=True)
|
|
15
|
+
selected_text = fields.String(required=True)
|
|
16
|
+
|
|
17
|
+
# Thread status
|
|
18
|
+
is_resolved = fields.Boolean(allow_none=True)
|
|
19
|
+
resolved_by = fields.String(allow_none=True)
|
|
20
|
+
resolved_at = fields.DateTime(allow_none=True)
|
|
21
|
+
|
|
22
|
+
# Soft delete
|
|
23
|
+
is_deleted = fields.Boolean(allow_none=True)
|
|
24
|
+
|
|
25
|
+
# Timestamps
|
|
26
|
+
created_at = fields.DateTime(dump_only=True)
|
|
27
|
+
updated_at = fields.DateTime(dump_only=True)
|
|
28
|
+
created_by = fields.String(required=True)
|
|
29
|
+
|
|
30
|
+
# Smart Grid Cells
|
|
31
|
+
cell_session_id = fields.Integer(allow_none=True)
|
|
32
|
+
cell_user_query_id = fields.Integer(allow_none=True)
|
|
33
|
+
|
|
34
|
+
# Nested comments
|
|
35
|
+
comments = fields.Nested(WorkbookThreadCommentSchema(exclude=("thread_id",)), many=True, dump_only=True)
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
|
|
3
|
+
from sqlalchemy import Column, DateTime, Boolean, ForeignKey, Integer, Text, String
|
|
4
|
+
from sqlalchemy.orm import relationship
|
|
5
|
+
|
|
6
|
+
from ...database import Base
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WorkbookThreadCommentModel(Base):
|
|
10
|
+
"""
|
|
11
|
+
Represents an individual comment within a thread.
|
|
12
|
+
"""
|
|
13
|
+
__tablename__ = "workbook_thread_comments"
|
|
14
|
+
|
|
15
|
+
id = Column(Integer, primary_key=True)
|
|
16
|
+
thread_id = Column(
|
|
17
|
+
Integer,
|
|
18
|
+
ForeignKey("workbook_comment_threads.id", ondelete="CASCADE"),
|
|
19
|
+
nullable=False,
|
|
20
|
+
)
|
|
21
|
+
user_id = Column(String(128), nullable=False)
|
|
22
|
+
sequence_number = Column(Integer, nullable=False) # 1 = initial comment
|
|
23
|
+
comment = Column(Text, nullable=False)
|
|
24
|
+
|
|
25
|
+
# Soft delete
|
|
26
|
+
is_deleted = Column(Boolean, default=False, nullable=True)
|
|
27
|
+
|
|
28
|
+
# Timestamps
|
|
29
|
+
created_at = Column(DateTime, nullable=False, default=lambda: datetime.utcnow())
|
|
30
|
+
updated_at = Column(
|
|
31
|
+
DateTime,
|
|
32
|
+
nullable=False,
|
|
33
|
+
default=lambda: datetime.utcnow(),
|
|
34
|
+
onupdate=lambda: datetime.utcnow(),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Relationships
|
|
38
|
+
thread = relationship("WorkbookCommentThreadModel", back_populates="comments")
|