From 0d4fe49561dd17e555b8f94369f98c9d505cdaf8 Mon Sep 17 00:00:00 2001 From: David Whittaker Date: Fri, 18 Oct 2024 09:52:29 -0700 Subject: [PATCH] Adding project_id column to Feedback table --- .../versions/2024-10-16_3c49f62d7914.py | 39 +++++++++++++++++-- src/dispatch/database/service.py | 7 ++-- src/dispatch/feedback/incident/models.py | 15 ++++--- .../dispatch/src/feedback/incident/Table.vue | 2 + .../dispatch/src/feedback/incident/store.js | 1 + 5 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/dispatch/database/revisions/tenant/versions/2024-10-16_3c49f62d7914.py b/src/dispatch/database/revisions/tenant/versions/2024-10-16_3c49f62d7914.py index c3545e233deb..caad8de0efa5 100644 --- a/src/dispatch/database/revisions/tenant/versions/2024-10-16_3c49f62d7914.py +++ b/src/dispatch/database/revisions/tenant/versions/2024-10-16_3c49f62d7914.py @@ -1,4 +1,4 @@ -"""Adds case_id to feedback +"""Adds case_id and project_id to feedback Revision ID: 3c49f62d7914 Revises: b8c1a8a4d957 @@ -8,6 +8,8 @@ from alembic import op import sqlalchemy as sa +from sqlalchemy.orm import Session +from dispatch.feedback.incident.models import Feedback # revision identifiers, used by Alembic. revision = "3c49f62d7914" @@ -19,12 +21,43 @@ def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column("feedback", sa.Column("case_id", sa.Integer(), nullable=True)) - op.create_foreign_key(None, "feedback", "case", ["case_id"], ["id"], ondelete="CASCADE") + op.create_foreign_key( + "assoc_feedback_case_id_fkey", + "feedback", + "case", + ["case_id"], + ["id"], + ondelete="CASCADE", + ) + op.add_column("feedback", sa.Column("project_id", sa.Integer(), nullable=True)) + op.create_foreign_key( + "assoc_feedback_project_id_fkey", + "feedback", + "project", + ["project_id"], + ["id"], + ondelete="CASCADE", + ) + + bind = op.get_bind() + session = Session(bind=bind) + + instances = session.query(Feedback).all() + + for instance in instances: + if instance.incident: + instance.project_id = instance.incident.project_id + elif instance.case: + instance.project_id = instance.case.project_id + + session.commit() # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### - op.drop_constraint(None, "feedback", type_="foreignkey") + op.drop_constraint("assoc_feedback_case_id_fkey", "feedback", type_="foreignkey") op.drop_column("feedback", "case_id") + op.drop_constraint("assoc_feedback_project_id_fkey", "feedback", type_="foreignkey") + op.drop_column("feedback", "project_id") # ### end Alembic commands ### diff --git a/src/dispatch/database/service.py b/src/dispatch/database/service.py index 1d7728358df8..209a3735b86f 100644 --- a/src/dispatch/database/service.py +++ b/src/dispatch/database/service.py @@ -185,9 +185,8 @@ def build_filters(filter_spec): if not _is_iterable_filter(fn_args): raise BadFilterFormat( - "`{}` value must be an iterable across the function " "arguments".format( - boolean_function.key - ) + "`{}` value must be an iterable across the function " + "arguments".format(boolean_function.key) ) if boolean_function.only_one_arg and len(fn_args) != 1: raise BadFilterFormat( @@ -347,8 +346,8 @@ def apply_filter_specific_joins(model: Base, filter_spec: dict, query: orm.query # this is required because by default sqlalchemy-filter's auto-join # knows nothing about how to join many-many relationships. model_map = { - (Feedback, "Project"): (Incident, False), (Feedback, "Incident"): (Incident, False), + (Feedback, "Case"): (Case, False), (Task, "Project"): (Incident, False), (Task, "Incident"): (Incident, False), (Task, "IncidentPriority"): (Incident, False), diff --git a/src/dispatch/feedback/incident/models.py b/src/dispatch/feedback/incident/models.py index 88b73da22768..a2ec86a358a8 100644 --- a/src/dispatch/feedback/incident/models.py +++ b/src/dispatch/feedback/incident/models.py @@ -8,7 +8,14 @@ from dispatch.database.core import Base from dispatch.incident.models import IncidentReadMinimal -from dispatch.models import DispatchBase, TimeStampMixin, FeedbackMixin, PrimaryKey, Pagination +from dispatch.models import ( + DispatchBase, + TimeStampMixin, + FeedbackMixin, + PrimaryKey, + Pagination, + ProjectMixin, +) from dispatch.participant.models import ParticipantRead from dispatch.project.models import ProjectRead from dispatch.case.models import CaseReadMinimal @@ -16,7 +23,7 @@ from .enums import FeedbackRating -class Feedback(TimeStampMixin, FeedbackMixin, Base): +class Feedback(TimeStampMixin, FeedbackMixin, ProjectMixin, Base): # Columns id = Column(Integer, primary_key=True) @@ -33,10 +40,6 @@ class Feedback(TimeStampMixin, FeedbackMixin, Base): ) ) - @hybrid_property - def project(self): - return self.incident.project if self.incident else self.case.project - # Pydantic models class FeedbackBase(DispatchBase): diff --git a/src/dispatch/static/dispatch/src/feedback/incident/Table.vue b/src/dispatch/static/dispatch/src/feedback/incident/Table.vue index 4854c0ea38ff..d6b4184a063c 100644 --- a/src/dispatch/static/dispatch/src/feedback/incident/Table.vue +++ b/src/dispatch/static/dispatch/src/feedback/incident/Table.vue @@ -130,6 +130,7 @@ export default { "table.options.descending", "table.options.filters", "table.options.filters.incident", + "table.options.filters.case", "table.options.filters.rating", "table.options.filters.feedback", "table.options.filters.participant", @@ -179,6 +180,7 @@ export default { vm.sortBy, vm.descending, vm.incident, + vm.case, vm.rating, vm.feedback, vm.project, diff --git a/src/dispatch/static/dispatch/src/feedback/incident/store.js b/src/dispatch/static/dispatch/src/feedback/incident/store.js index cd536d146da5..727e87107f4f 100644 --- a/src/dispatch/static/dispatch/src/feedback/incident/store.js +++ b/src/dispatch/static/dispatch/src/feedback/incident/store.js @@ -9,6 +9,7 @@ const getDefaultSelectedState = () => { feedback: null, id: null, incident: null, + case: null, participant: null, project: null, rating: null,