Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1102 - Create action logic #1144

Merged
merged 10 commits into from
Nov 2, 2023
2 changes: 1 addition & 1 deletion epictrack-api/src/api/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""This module holds all the action handlers."""
from .lock_work_start_date import LockWorkStartDate
from .add_event import AddEvent
from .add_phase import AddPhase
from .create_work import CreateWork
from .lock_work_start_date import LockWorkStartDate
from .set_event_date import SetEventDate
from .set_events_status import SetEventsStatus
from .set_phases_status import SetPhasesStatus
Expand Down
4 changes: 0 additions & 4 deletions epictrack-api/src/api/actions/add_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,3 @@ class AddEvent(ActionFactory): # pylint: disable=too-few-public-methods
def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
return

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
4 changes: 0 additions & 4 deletions epictrack-api/src/api/actions/add_phase.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,3 @@ class AddPhase(ActionFactory): # pylint: disable=too-few-public-methods
def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
return

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
6 changes: 3 additions & 3 deletions epictrack-api/src/api/actions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ class ActionFactory(ABC): # pylint: disable=too-few-public-methods
"""Base class for action handlers"""

@abstractmethod
def run(self, source_event: Event, params: dict):
def run(self, source_event: Event, params: dict) -> None:
"""Perform the action"""

@abstractmethod
def get_additional_params(self, params):
def get_additional_params(self, params: dict) -> dict:
"""Returns the derived additional parameters required to perform action from templates"""
return params


ACTION_HANDLER_CLASS_MAPS = {
Expand Down
53 changes: 37 additions & 16 deletions epictrack-api/src/api/actions/create_work.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
"""Disable work start date action handler"""

from api.actions.base import ActionFactory
from api.models.event import Event


class CreateWork(ActionFactory): # pylint: disable=too-few-public-methods
"""Create a new work based on the current project and other parameters"""

def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
return

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
"""Create work action handler"""
# from datetime import timedelta

from api.actions.base import ActionFactory


# 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)
11 changes: 3 additions & 8 deletions epictrack-api/src/api/actions/lock_work_start_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,15 @@

from api.actions.base import ActionFactory
from api.models import db
from api.models.event import Event
from api.models.work import Work


class LockWorkStartDate(ActionFactory): # pylint: disable=too-few-public-methods
"""Disable work start date action"""

def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
def run(self, source_event, params) -> None:
"""Set the work start date and mark start date as locked for changes"""
db.session.query(Work).filter(Work.id == source_event.work_id).update(
{Work.start_date_locked: True}
params
)
db.session.commit()

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
8 changes: 1 addition & 7 deletions epictrack-api/src/api/actions/set_event_date.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
"""Disable work start date action handler"""

from api.actions.base import ActionFactory
from api.models.event import Event


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

def run(self, source_event: Event, params: dict) -> None:
def run(self, source_event, params: dict) -> None:
"""Performs the required operations"""
return

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
31 changes: 15 additions & 16 deletions epictrack-api/src/api/actions/set_events_status.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
"""Disable work start date action handler"""

from api.actions.base import ActionFactory
from api.models.event import Event


class SetEventsStatus(ActionFactory): # pylint: disable=too-few-public-methods
"""Sets all the future events status"""

def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
return

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
"""Set events status action handler"""
from api.actions.base import ActionFactory
from api.models import db
from api.models.event import Event


class SetEventsStatus(ActionFactory):
"""Set events status action"""

def run(self, source_event, params):
"""Sets all future events to INACTIVE"""
db.session.query(Event).filter(
Event.work_id == source_event.work_id,
Event.anticipated_date >= source_event.actual_date
).update(params)
31 changes: 15 additions & 16 deletions epictrack-api/src/api/actions/set_phases_status.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
"""Disable work start date action handler"""

from api.actions.base import ActionFactory
from api.models.event import Event


class SetPhasesStatus(ActionFactory): # pylint: disable=too-few-public-methods
"""Sets all the future phases status"""

def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
return

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
"""Set phases status action handler"""
from api.actions.base import ActionFactory
from api.models import db
from api.models.work_phase import WorkPhase


class SetPhasesStatus(ActionFactory):
"""Set phases status action"""

def run(self, source_event, params):
"""Sets all future PHASEs to INACTIVE"""
db.session.query(WorkPhase).filter(
WorkPhase.work_id == source_event.work_id,
WorkPhase.start_date >= source_event.actual_date
).update(params)
37 changes: 16 additions & 21 deletions epictrack-api/src/api/actions/set_project_status.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
"""Disable work start date action handler"""

from api.actions.base import ActionFactory
from api.models import db
from api.models.event import Event
from api.models.project import Project


class SetProjectStatus(ActionFactory): # pylint: disable=too-few-public-methods
"""Sets the project status active/inactive"""

def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
db.session.query(Project).filter(
Project.id == source_event.work.project.id
).update(params)
db.session.commit()

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
"""Set project status action handler"""

from api.actions.base import ActionFactory
from api.models import db
from api.models.project import Project


class SetProjectStatus(ActionFactory): # pylint: disable=too-few-public-methods
"""Set project status action"""

def run(self, source_event, params) -> None:
"""Sets the project's is_active status to False"""
db.session.query(Project).filter(
Project.id == source_event.work.project_id
).update(params)
db.session.commit()
8 changes: 1 addition & 7 deletions epictrack-api/src/api/actions/set_work_decision_maker.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,10 @@
"""Disable work start date action handler"""

from api.actions.base import ActionFactory
from api.models.event import Event


class SetWorkDecisionMaker(ActionFactory): # pylint: disable=too-few-public-methods
"""Sets the work decision maker"""

def run(self, source_event: Event, params: dict) -> None:
def run(self, source_event, params: dict) -> None:
"""Performs the required operations"""
return

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
35 changes: 19 additions & 16 deletions epictrack-api/src/api/actions/set_work_state.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
"""Disable work start date action handler"""

from api.actions.base import ActionFactory
from api.models.event import Event


class SetWorkState(ActionFactory): # pylint: disable=too-few-public-methods
"""Sets the work state"""

def run(self, source_event: Event, params: dict) -> None:
"""Performs the required operations"""
return

def get_additional_params(self, params):
"""Returns additional parameter"""
return params
"""Set work state action handler"""

from api.actions.base import ActionFactory
from api.models import db
from api.models.work import Work


class SetWorkState(ActionFactory):
"""Set work state status action"""

def run(self, source_event, params) -> None:
"""Sets the work as per action configuration"""
work_state = self.get_additional_params(params)
db.session.query(Work).filter(Work.id == source_event.work_id).update(work_state)
db.session.commit()

def get_additional_params(self, params) -> dict:
"""Returns the derived additional parameters required to perform action from templates"""
return {"work_state": params["work_state"]}
1 change: 1 addition & 0 deletions epictrack-api/src/api/models/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
"""Model to handle all operations related to Event Types."""
import enum

import sqlalchemy as sa

from .code_table import CodeTableVersioned
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Event Template Response response schema"""
from marshmallow import EXCLUDE
from marshmallow import EXCLUDE, fields

from api.models import EventTemplate
from api.schemas.base import AutoSchemaBase
Expand All @@ -29,3 +29,9 @@ class Meta(AutoSchemaBase.Meta):
model = EventTemplate
include_fk = True
unknown = EXCLUDE

event_position = fields.Method("get_event_position")

def get_event_position(self, obj: EventTemplate) -> str:
"""Return value for the event position"""
return obj.event_position if isinstance(obj.event_position, str) else obj.event_position.value
29 changes: 14 additions & 15 deletions epictrack-api/src/api/services/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
import copy
from datetime import datetime, timedelta
from typing import List

from sqlalchemy import and_, or_

from api.actions.action_handler import ActionHandler
from api.exceptions import ResourceNotFoundError, UnprocessableEntityError
from api.models import (PRIMARY_CATEGORIES, CalendarEvent, Event,
EventCategoryEnum, EventConfiguration, EventTypeEnum,
WorkCalendarEvent, WorkPhase, Work, WorkStateEnum, db)
from api.models import (
PRIMARY_CATEGORIES, CalendarEvent, Event, EventCategoryEnum, EventConfiguration, EventTypeEnum, Work,
WorkCalendarEvent, WorkPhase, WorkStateEnum, db)
from api.models.action import Action, ActionEnum
from api.models.action_configuration import ActionConfiguration
from api.models.event_template import EventPositionEnum
Expand All @@ -32,7 +33,7 @@
from .event_configuration import EventConfigurationService


class EventService: # pylint: disable=too-few-public-methods
class EventService:
"""Service to manage event related operations."""

@classmethod
Expand Down Expand Up @@ -141,15 +142,15 @@ def _process_events(
if event.actual_date and event.event_configuration.event_position == EventPositionEnum.END:
cls._complete_work_phase(current_work_phase)
if (
event.event_configuration.event_type_id == EventTypeEnum.TIME_LIMIT_SUSPENSION.value
and event.actual_date
event.event_configuration.event_type_id == EventTypeEnum.TIME_LIMIT_SUSPENSION.value and
event.actual_date
):
current_work_phase.suspended_date = event.actual_date
current_work_phase.is_suspended = True
current_work_phase.update(current_work_phase.as_dict(recursive=False), commit=False)
if (
event.event_configuration.event_type_id == EventTypeEnum.TIME_LIMIT_RESUMPTION.value
and event.actual_date
event.event_configuration.event_type_id == EventTypeEnum.TIME_LIMIT_RESUMPTION.value and
event.actual_date
):
event.number_of_days = (event.actual_date - current_work_phase.suspended_date).days
event.update(event.as_dict(recursive=False), commit=False)
Expand Down Expand Up @@ -268,14 +269,14 @@ def _get_number_of_days_to_be_pushed(cls,
# return 0 days to be pushed unless actual date is entered
return 0 if not event.actual_date else event.number_of_days
if (
event.event_configuration.event_category_id == EventCategoryEnum.SUSPENSION.value
and event.event_configuration.event_type_id == EventTypeEnum.TIME_LIMIT_SUSPENSION.value
event.event_configuration.event_category_id == EventCategoryEnum.SUSPENSION.value and
event.event_configuration.event_type_id == EventTypeEnum.TIME_LIMIT_SUSPENSION.value
):
# always return 0 as suspension does not push the number of days
return 0
if (
event.event_configuration.event_category_id == EventCategoryEnum.SUSPENSION.value
and event.event_configuration.event_type_id == EventTypeEnum.TIME_LIMIT_RESUMPTION.value
event.event_configuration.event_category_id == EventCategoryEnum.SUSPENSION.value and
event.event_configuration.event_type_id == EventTypeEnum.TIME_LIMIT_RESUMPTION.value
):
if event.actual_date:
return (event.actual_date - current_work_phase.suspended_date).days
Expand Down Expand Up @@ -624,6 +625,4 @@ def _process_actions(cls, event: Event, outcome_id: int = None) -> None:
)
for action_configuration in action_configurations:
action_handler = ActionHandler(ActionEnum(action_configuration.action_id))
if action_configuration.action.id == ActionEnum.LOCK_WORK_START_DATE.value:
params = {"work_id": event.work_id, "start_date": event.actual_date, "start_date_locked": True}
action_handler.apply(params)
action_handler.apply(event, action_configuration.additional_params)
Loading