Skip to content

Commit

Permalink
#1102 - Create action logic (#1144)
Browse files Browse the repository at this point in the history
* suspension/resumption

* actions

* suspension/resumption

* implement actions - initial

* #1102 - Create action logic

---------

Co-authored-by: Dinesh <dinesh.pb@aot-technologies.com>
  • Loading branch information
salabh-aot and dinesh-aot authored Nov 2, 2023
1 parent 40bb9e1 commit 5493537
Show file tree
Hide file tree
Showing 18 changed files with 182 additions and 158 deletions.
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

0 comments on commit 5493537

Please sign in to comment.