Skip to content

Commit

Permalink
#1134 - Complex Actions (#1166)
Browse files Browse the repository at this point in the history
* #1134 - Complex Actions

added action handlers for following:
  - AddEvent
  - AddPhase
  - CreateWork
  - SetEventDate

* linting fixes

* work plan - sort phases based on ID instead of sort order

* amend last commit

* add event action - make a copy of existing event config instead of using latest event template
  • Loading branch information
salabh-aot authored Nov 7, 2023
1 parent 0ef9faa commit f74273b
Show file tree
Hide file tree
Showing 15 changed files with 307 additions and 157 deletions.
73 changes: 68 additions & 5 deletions epictrack-api/src/api/actions/add_event.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,75 @@
"""Disable work start date action handler"""

from datetime import timedelta

from api.actions.base import ActionFactory
from api.models.event import Event
from api.models import db
from api.models.event_configuration import EventConfiguration
from api.models.phase_code import PhaseCode
from api.models.work_phase import WorkPhase
from api.schemas.response.event_configuration_response import EventConfigurationResponseSchema
from api.schemas.response.event_template_response import EventTemplateResponseSchema


# pylint: disable=import-outside-toplevel

class AddEvent(ActionFactory): # pylint: disable=too-few-public-methods

class AddEvent(ActionFactory):
"""Add a new event"""

def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
return
def run(self, source_event, params) -> None:
"""Adds a new event based on params"""
from api.services.event import EventService

event_data, work_phase_id = self.get_additional_params(params)
event_data.update(
{
"is_active": True,
"work_id": source_event.work_id,
"anticipated_date": source_event.actual_date + timedelta(days=params["start_at"]),
}
)
EventService.create_event(event_data, work_phase_id=work_phase_id)

def get_additional_params(self, params):
"""Returns additional parameter"""
from api.services.work import WorkService

phase = {
"name": params.pop("phase_name"),
"work_type_id": params.pop("work_type_id"),
"ea_act_id": params.pop("ea_act_id"),
}
phase_query = (
db.session.query(PhaseCode).filter_by(**phase, is_active=True).subquery()
)
work_phase = (
db.session.query(WorkPhase)
.join(phase_query, WorkPhase.phase_id == phase_query.c.id)
.filter(WorkPhase.is_active.is_(True))
.first()
)
old_event_config = (
db.session.query(EventConfiguration)
.filter(
EventConfiguration.work_phase_id == work_phase.id,
EventConfiguration.name == params.pop("event_name"),
EventConfiguration.is_active.is_(True),
)
.first()
)

event_configuration = EventConfigurationResponseSchema().dump(old_event_config)
event_configuration["start_at"] = params["start_at"]
del event_configuration["id"]
event_configuration = EventConfiguration(**event_configuration)
event_configuration.flush()
template_json = EventTemplateResponseSchema().dump(old_event_config.event_template)
WorkService.copy_outcome_and_actions(template_json, event_configuration)
event_data = {
"event_configuration_id": event_configuration.id,
"name": event_configuration.name,
"number_of_days": event_configuration.number_of_days,
"source_event_id": event_configuration.parent_id,
}
return event_data, work_phase.id
46 changes: 43 additions & 3 deletions epictrack-api/src/api/actions/add_phase.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,52 @@
"""Disable work start date action handler"""
from datetime import timedelta

from api.actions.base import ActionFactory
from api.models import db
from api.models.event import Event
from api.models.phase_code import PhaseCode
from api.schemas.response.event_template_response import EventTemplateResponseSchema


class AddPhase(ActionFactory): # pylint: disable=too-few-public-methods
# pylint: disable= import-outside-toplevel
class AddPhase(ActionFactory):
"""Add a new phase"""

def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
return
"""Adds a new phase based on params"""
# Importing here to avoid circular imports
from api.services.event_template import EventTemplateService
from api.services.work import WorkService

phase_start_date = source_event.actual_date + timedelta(days=1)
work_phase_data = self.get_additional_params(params)
work_phase_data.update(
{
"work_id": source_event.work.id,
"start_date": f"{phase_start_date}",
"end_date": f"{phase_start_date + timedelta(days=work_phase_data['number_of_days'])}",
}
)
event_templates = EventTemplateService.find_by_phase_id(
work_phase_data["phase_id"]
)
event_template_json = EventTemplateResponseSchema(many=True).dump(
event_templates
)
WorkService.handle_phase(work_phase_data, event_template_json)

def get_additional_params(self, params):
"""Returns additional parameter"""
new_name = params.pop("new_name")
legislated = params.pop("legislated")
params["name"] = params.pop("phase_name")
phase = db.session.query(PhaseCode).filter_by(**params, is_active=True).first()

work_phase_data = {
"phase_id": phase.id,
"name": new_name,
"legislated": legislated,
"number_of_days": phase.number_of_days,
}

return work_phase_data
55 changes: 28 additions & 27 deletions epictrack-api/src/api/actions/create_work.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,38 @@
"""Create work action handler"""
# from datetime import timedelta
from datetime import timedelta

from api.actions.base import ActionFactory


# from api.models import db
# from api.models.work_type import WorkType
from api.models import db
from api.models.work_type import WorkType


class CreateWork(ActionFactory):
"""Create work action"""

def run(self, source_event, params) -> None:
"""Create a new WORK: "Minister's Designation" and link to this work's Project"""
# TODO: Uncomment after work type data is imported
# # Importing here to avoid circular imports
# from api.services.work import WorkService # pylint: disable=import-outside-toplevel
# work_type = (
# db.session.query(WorkType)
# .filter(
# WorkType.name == "Minister's Designation", WorkType.is_active.is_(True)
# )
# .first()
# )
# new_work = {
# "ea_act_id": source_event.work.ea_act_id,
# "work_type_id": work_type.id,
# "start_date": source_event.actual_date + timedelta(days=1),
# "project_id": source_event.work.project_id,
# "ministry_id": source_event.work.ministry_id,
# "federal_involvement_id": source_event.work.federal_involvement_id,
# "title": f"{source_event.work.project.name} - {work_type.report_title}",
# "is_active": True,
# "responsible_epd_id": source_event.work.responsible_epd_id
# }
# WorkService.create_work(new_work)
# Importing here to avoid circular imports
from api.services.work import WorkService # pylint: disable=import-outside-toplevel
work_type = (
db.session.query(WorkType)
.filter(
WorkType.name == "Minister's Designation", WorkType.is_active.is_(True)
)
.first()
)
new_work = {
"ea_act_id": source_event.work.ea_act_id,
"work_type_id": work_type.id,
"start_date": source_event.actual_date + timedelta(days=1),
"project_id": source_event.work.project_id,
"ministry_id": source_event.work.ministry_id,
"federal_involvement_id": source_event.work.federal_involvement_id,
"title": f"{source_event.work.project.name} - {work_type.report_title}",
"is_active": True,
"responsible_epd_id": source_event.work.responsible_epd_id,
# Added because of errors
"work_lead_id": source_event.work.work_lead_id,
"eao_team_id": source_event.work.eao_team_id,
"decision_by_id": source_event.work.decision_by_id,
}
WorkService.create_work(new_work)
39 changes: 39 additions & 0 deletions epictrack-api/src/api/actions/set_event_date.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,49 @@
"""Disable work start date action handler"""

from datetime import timedelta

from api.actions.base import ActionFactory
from api.models import db
from api.models.event import Event
from api.models.event_configuration import EventConfiguration
from api.models.phase_code import PhaseCode
from api.models.work_phase import WorkPhase


class SetEventDate(ActionFactory): # pylint: disable=too-few-public-methods
"""Sets the event date"""

def run(self, source_event, params: dict) -> None:
"""Performs the required operations"""
event_configuration_id = self.get_additional_params(params)
db.session.query(Event).filter(
Event.work_id == source_event.work_id,
Event.is_active.is_(True),
Event.event_configuration_id == event_configuration_id,
).update({
"anticipated_date": source_event.actual_date + timedelta(days=1)
})
db.session.commit()

def get_additional_params(self, params):
"""Returns additional parameter"""
phase = {
"name": params.pop("phase_name"),
"work_type_id": params.pop("work_type_id"),
"ea_act_id": params.pop("ea_act_id"),
}
phase_query = (
db.session.query(PhaseCode).filter_by(**phase, is_active=True).subquery()
)
work_phase = (
db.session.query(WorkPhase)
.join(phase_query, WorkPhase.phase_id == phase_query.c.id)
.filter(WorkPhase.is_active.is_(True))
.first()
)
event_configuration = db.session.query(EventConfiguration).filter(
EventConfiguration.work_phase_id == work_phase.id,
EventConfiguration.name == params["event_name"],
EventConfiguration.is_active.is_(True),
).first()
return event_configuration.id
1 change: 1 addition & 0 deletions epictrack-api/src/api/actions/set_events_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ def run(self, source_event, params):
Event.work_id == source_event.work_id,
Event.anticipated_date >= source_event.actual_date
).update(params)
db.session.commit()
1 change: 1 addition & 0 deletions epictrack-api/src/api/actions/set_phases_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ def run(self, source_event, params):
WorkPhase.work_id == source_event.work_id,
WorkPhase.start_date >= source_event.actual_date
).update(params)
db.session.commit()
2 changes: 1 addition & 1 deletion epictrack-api/src/api/models/work_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.
"""Model to handle all operations related to WorkStatus."""

from sqlalchemy import Column, Date, ForeignKey, Integer, String, Text, Boolean
from sqlalchemy import Boolean, Column, Date, ForeignKey, Integer, String, Text
from sqlalchemy.orm import relationship

from .base_model import BaseModelVersioned
Expand Down
11 changes: 7 additions & 4 deletions epictrack-api/src/api/resources/outcome_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@
# limitations under the License.
"""Resource for Outcome Configuration endpoints."""
from http import HTTPStatus

from flask import jsonify, request
from flask_restx import Namespace, Resource, cors

from api.schemas import request as req
from api.schemas import response as res
from api.services.outcome_configuration import OutcomeConfigurationService
from api.utils import auth, constants, profiletime
from api.utils.caching import AppCache
from api.utils.util import cors_preflight
from api.services.outcome_configuration import OutcomeConfigurationService
from api.schemas import request as req
from api.schemas import response as res


API = Namespace('outcome_configurations', description='Outcome Configurations')

Expand All @@ -33,7 +36,7 @@ class OutcomeConfigurations(Resource):
@staticmethod
@cors.crossdomain(origin='*')
@auth.require
@AppCache.cache.cached(timeout=constants.CACHE_DAY_TIMEOUT)
@AppCache.cache.cached(timeout=constants.CACHE_DAY_TIMEOUT, query_string=True)
@profiletime
def get():
"""Return all outcomes based on milestone_id."""
Expand Down
10 changes: 5 additions & 5 deletions epictrack-api/src/api/schemas/response/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Exposes all the response validation schemas"""
from .act_section_response import ActSectionResponseSchema
from .action_template_response import ActionTemplateResponseSchema
from .event import EventResponseSchema
from .event_configuration_response import EventConfigurationResponseSchema
from .event_template_response import EventTemplateResponseSchema
from .indigenous_nation_response import IndigenousResponseNationSchema, WorkIndigenousNationResponseSchema
from .outcome_configuration_response import OutcomeConfigurationResponseSchema
from .outcome_template_response import OutcomeTemplateResponseSchema
from .phase_response import PhaseResponseSchema
from .project_response import ProjectResponseSchema
Expand All @@ -30,8 +32,6 @@
from .user_group_response import UserGroupResponseSchema
from .user_response import UserResponseSchema
from .work_response import (
WorkPhaseResponseSchema, WorkPhaseSkeletonResponseSchema, WorkPhaseTemplateAvailableResponse,
WorkResourceResponseSchema, WorkResponseSchema, WorkStaffRoleReponseSchema,
WorkStatusResponseSchema, WorkIssuesResponseSchema, WorkIssueUpdatesResponseSchema)
from .outcome_configuration_response import OutcomeConfigurationResponseSchema
from .act_section_response import ActSectionResponseSchema
WorkIssuesResponseSchema, WorkIssueUpdatesResponseSchema, WorkPhaseResponseSchema, WorkPhaseSkeletonResponseSchema,
WorkPhaseTemplateAvailableResponse, WorkResourceResponseSchema, WorkResponseSchema, WorkStaffRoleReponseSchema,
WorkStatusResponseSchema)
2 changes: 1 addition & 1 deletion epictrack-api/src/api/schemas/response/work_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from flask_marshmallow import Schema
from marshmallow import EXCLUDE, fields, pre_dump

from api.models import Staff, Work, WorkPhase, WorkStatus, WorkIssues, WorkIssueUpdates
from api.models import Staff, Work, WorkIssues, WorkIssueUpdates, WorkPhase, WorkStatus
from api.schemas import PositionSchema, RoleSchema
from api.schemas.base import AutoSchemaBase
from api.schemas.ea_act import EAActSchema
Expand Down
Loading

0 comments on commit f74273b

Please sign in to comment.