From d4a6acbd9973ce3d061d5dd9ad49a6530da07265 Mon Sep 17 00:00:00 2001 From: hjlarry Date: Sat, 30 Aug 2025 23:49:27 +0800 Subject: [PATCH] add update reply --- api/fields/workflow_comment_fields.py | 5 +- ...27822d22895_add_workflow_comments_table.py | 1 + api/models/comment.py | 4 +- api/services/workflow_comment_service.py | 58 ++++++++++--------- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/api/fields/workflow_comment_fields.py b/api/fields/workflow_comment_fields.py index d285d6c1ab..5f7bd6851a 100644 --- a/api/fields/workflow_comment_fields.py +++ b/api/fields/workflow_comment_fields.py @@ -95,8 +95,5 @@ workflow_comment_reply_create_fields = { # Reply update response fields workflow_comment_reply_update_fields = { "id": fields.String, - "content": fields.String, - "created_by": fields.String, - "created_by_account": fields.Nested(comment_account_fields, allow_null=True), - "created_at": TimestampField, + "updated_at": TimestampField, } diff --git a/api/migrations/versions/2025_08_22_1726-227822d22895_add_workflow_comments_table.py b/api/migrations/versions/2025_08_22_1726-227822d22895_add_workflow_comments_table.py index 9a00b2a89a..5bcd44070d 100644 --- a/api/migrations/versions/2025_08_22_1726-227822d22895_add_workflow_comments_table.py +++ b/api/migrations/versions/2025_08_22_1726-227822d22895_add_workflow_comments_table.py @@ -44,6 +44,7 @@ def upgrade(): sa.Column('content', sa.Text(), nullable=False), sa.Column('created_by', models.types.StringUUID(), nullable=False), sa.Column('created_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), + sa.Column('updated_at', sa.DateTime(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), sa.ForeignKeyConstraint(['comment_id'], ['workflow_comments.id'], name=op.f('workflow_comment_replies_comment_id_fkey'), ondelete='CASCADE'), sa.PrimaryKeyConstraint('id', name='workflow_comment_replies_pkey') ) diff --git a/api/models/comment.py b/api/models/comment.py index e88705b6d6..752d1d7a41 100644 --- a/api/models/comment.py +++ b/api/models/comment.py @@ -140,7 +140,9 @@ class WorkflowCommentReply(Base): content: Mapped[str] = mapped_column(db.Text, nullable=False) created_by: Mapped[str] = mapped_column(StringUUID, nullable=False) created_at: Mapped[datetime] = mapped_column(db.DateTime, nullable=False, server_default=func.current_timestamp()) - + updated_at: Mapped[datetime] = mapped_column( + db.DateTime, nullable=False, server_default=func.current_timestamp(), onupdate=func.current_timestamp() + ) # Relationships comment: Mapped["WorkflowComment"] = relationship("WorkflowComment", back_populates="replies") diff --git a/api/services/workflow_comment_service.py b/api/services/workflow_comment_service.py index 5e4034fd90..010dd3b1ed 100644 --- a/api/services/workflow_comment_service.py +++ b/api/services/workflow_comment_service.py @@ -198,7 +198,7 @@ class WorkflowCommentService: comment.resolved_at = naive_utc_now() comment.resolved_by = user_id session.commit() - + return comment @staticmethod @@ -215,7 +215,7 @@ class WorkflowCommentService: if len(content) > 1000: raise ValueError("Reply content cannot exceed 1000 characters") - with Session(db.engine) as session: + with Session(db.engine, expire_on_commit=False) as session: # Check if comment exists comment = session.get(WorkflowComment, comment_id) if not comment: @@ -240,7 +240,6 @@ class WorkflowCommentService: session.commit() - # Return only what we need - id and created_at return { "id": reply.id, "created_at": reply.created_at @@ -254,42 +253,47 @@ class WorkflowCommentService: mentioned_user_ids: Optional[list[str]] = None ) -> WorkflowCommentReply: """Update a comment reply.""" - reply = db.session.get(WorkflowCommentReply, reply_id) - if not reply: - raise NotFound("Reply not found") - - # Only the creator can update the reply - if reply.created_by != user_id: - raise Forbidden("Only the reply creator can update it") - if len(content.strip()) == 0: raise ValueError("Reply content cannot be empty") if len(content) > 1000: raise ValueError("Reply content cannot exceed 1000 characters") + + with Session(db.engine, expire_on_commit=False) as session: + reply = session.get(WorkflowCommentReply, reply_id) + if not reply: + raise NotFound("Reply not found") - reply.content = content + # Only the creator can update the reply + if reply.created_by != user_id: + raise Forbidden("Only the reply creator can update it") - # Handle mentions for reply updates - add new mentions to parent comment - mentioned_user_ids = mentioned_user_ids or [] - for user_id_str in mentioned_user_ids: - if isinstance(user_id_str, str) and uuid_value(user_id_str): - # Check if mention already exists to avoid duplicates - existing_mention = db.session.query(WorkflowCommentMention).filter( - WorkflowCommentMention.comment_id == reply.comment_id, - WorkflowCommentMention.mentioned_user_id == user_id_str - ).first() - - if not existing_mention: + reply.content = content + + # Update mentions - first remove existing mentions for this reply + existing_mentions = session.scalars( + select(WorkflowCommentMention).where(WorkflowCommentMention.reply_id == reply.id) + ).all() + for mention in existing_mentions: + session.delete(mention) + + # Add mentions + mentioned_user_ids = mentioned_user_ids or [] + for user_id_str in mentioned_user_ids: + if isinstance(user_id_str, str) and uuid_value(user_id_str): mention = WorkflowCommentMention( comment_id=reply.comment_id, - reply_id=reply.id, # This is a reply mention + reply_id=reply.id, mentioned_user_id=user_id_str ) - db.session.add(mention) + session.add(mention) - db.session.commit() - return reply + session.commit() + + return { + "id": reply.id, + "updated_at": reply.updated_at + } @staticmethod def delete_reply(reply_id: str, user_id: str) -> None: