From f47e48fed7b754c0b17238db1e7ba134aaeb8130 Mon Sep 17 00:00:00 2001 From: Horia Coman Date: Mon, 17 Jun 2024 21:42:55 +0300 Subject: [PATCH] Merged branch bugfix/associate-big-plans-and-inbox-tasks into develop --- .../domain/time_plans/time_plan_activity.py | 8 +++ .../repository/sqlite/domain/time_plans.py | 24 +++++++ .../inbox_tasks/associate_with_big_plan.py | 63 +++++++++++++++++++ 3 files changed, 95 insertions(+) diff --git a/src/core/jupiter/core/domain/time_plans/time_plan_activity.py b/src/core/jupiter/core/domain/time_plans/time_plan_activity.py index 42d99045..67d103c2 100644 --- a/src/core/jupiter/core/domain/time_plans/time_plan_activity.py +++ b/src/core/jupiter/core/domain/time_plans/time_plan_activity.py @@ -139,3 +139,11 @@ class TimePlanAlreadyAssociatedWithTargetError(EntityAlreadyExistsError): class TimePlanActivityRespository(LeafEntityRepository[TimePlanActivity], abc.ABC): """An error raised when a time plan is already associated with a target entity.""" + + @abc.abstractmethod + async def find_all_with_target( + self, + target: TimePlanActivityTarget, + target_ref_id: EntityId, + ) -> list[EntityId]: + """Find all time plan ids with a certain entity in their activity set.""" diff --git a/src/core/jupiter/core/repository/sqlite/domain/time_plans.py b/src/core/jupiter/core/repository/sqlite/domain/time_plans.py index f07303a3..09055717 100644 --- a/src/core/jupiter/core/repository/sqlite/domain/time_plans.py +++ b/src/core/jupiter/core/repository/sqlite/domain/time_plans.py @@ -12,6 +12,9 @@ TimePlanActivityRespository, TimePlanAlreadyAssociatedWithTargetError, ) +from jupiter.core.domain.time_plans.time_plan_activity_target import ( + TimePlanActivityTarget, +) from jupiter.core.framework.base.entity_id import EntityId from jupiter.core.framework.base.entity_name import EntityName from jupiter.core.framework.realm import RealmCodecRegistry @@ -159,3 +162,24 @@ def __init__( metadata, already_exists_err_cls=TimePlanAlreadyAssociatedWithTargetError, ) + + async def find_all_with_target( + self, target: TimePlanActivityTarget, target_ref_id: EntityId + ) -> list[EntityId]: + """Find all time plan activities with a target.""" + query_stmt = ( + self._table.select() + .where( + self._table.c.target == target.value, + ) + .where( + self._table.c.target_ref_id == target_ref_id.as_int(), + ) + .where( + self._table.c.archived.is_(False), + ) + ) + + results = await self._connection.execute(query_stmt) + + return [self._row_to_entity(row).parent_ref_id for row in results] diff --git a/src/core/jupiter/core/use_cases/inbox_tasks/associate_with_big_plan.py b/src/core/jupiter/core/use_cases/inbox_tasks/associate_with_big_plan.py index dfc8ae98..db6c733f 100644 --- a/src/core/jupiter/core/use_cases/inbox_tasks/associate_with_big_plan.py +++ b/src/core/jupiter/core/use_cases/inbox_tasks/associate_with_big_plan.py @@ -6,7 +6,21 @@ CannotModifyGeneratedTaskError, InboxTask, ) +from jupiter.core.domain.infra.generic_creator import generic_creator from jupiter.core.domain.storage_engine import DomainUnitOfWork +from jupiter.core.domain.time_plans.time_plan import TimePlan +from jupiter.core.domain.time_plans.time_plan_activity import ( + TimePlanActivity, + TimePlanActivityRespository, + TimePlanAlreadyAssociatedWithTargetError, +) +from jupiter.core.domain.time_plans.time_plan_activity_feasability import ( + TimePlanActivityFeasability, +) +from jupiter.core.domain.time_plans.time_plan_activity_kind import TimePlanActivityKind +from jupiter.core.domain.time_plans.time_plan_activity_target import ( + TimePlanActivityTarget, +) from jupiter.core.framework.base.entity_id import EntityId from jupiter.core.framework.errors import InputValidationError from jupiter.core.framework.use_case import ( @@ -42,6 +56,7 @@ async def _perform_transactional_mutation( args: InboxTaskAssociateWithBigPlanArgs, ) -> None: """Execute the command's action.""" + workspace = context.workspace inbox_task = await uow.get_for(InboxTask).load_by_id(args.ref_id) try: @@ -54,6 +69,54 @@ async def _perform_transactional_mutation( project_ref_id=big_plan.project_ref_id, big_plan_ref_id=args.big_plan_ref_id, ) + + if workspace.is_feature_available(WorkspaceFeature.TIME_PLANS): + # We go to all timeplans where this inbox task has an activity + # and add an activity for the big plan if there isn't one. + # But we don't go to all timeplans and remove the big plan. That's + # done just one. + time_plan_ref_ids = await uow.get( + TimePlanActivityRespository + ).find_all_with_target( + target=TimePlanActivityTarget.INBOX_TASK, + target_ref_id=args.ref_id, + ) + + for time_plan_ref_id in time_plan_ref_ids: + try: + big_plan_activity = ( + TimePlanActivity.new_activity_for_big_plan( + ctx=context.domain_context, + time_plan_ref_id=time_plan_ref_id, + big_plan_ref_id=args.big_plan_ref_id, + kind=TimePlanActivityKind.MAKE_PROGRESS, + feasability=TimePlanActivityFeasability.MUST_DO, + ) + ) + + _ = await generic_creator( + uow, progress_reporter, big_plan_activity + ) + from rich import print + + print(big_plan) + if ( + big_plan.actionable_date is None + or big_plan.due_date is None + ): + time_plan = await uow.get_for(TimePlan).load_by_id( + time_plan_ref_id + ) + big_plan = big_plan.change_dates_via_time_plan( + context.domain_context, + actionable_date=time_plan.start_date, + due_date=time_plan.end_date, + ) + await uow.get_for(BigPlan).save(big_plan) + await progress_reporter.mark_updated(big_plan) + except TimePlanAlreadyAssociatedWithTargetError: + # We were already working on this plan, no need to panic + pass else: inbox_task = inbox_task.release_from_big_plan( ctx=context.domain_context,