Skip to content

feat(funnels): add task completion endpoint (M4-BE-011)#116

Merged
Homoakin619 merged 2 commits into
devfrom
feat/M4-BE-011-task-completion
May 28, 2026
Merged

feat(funnels): add task completion endpoint (M4-BE-011)#116
Homoakin619 merged 2 commits into
devfrom
feat/M4-BE-011-task-completion

Conversation

@ibraheembello
Copy link
Copy Markdown
Contributor

@ibraheembello ibraheembello commented May 28, 2026

Description

Adds PATCH /api/funnels/:funnelId/stages/:stageId/tasks/:taskId so a user can mark a stage task as complete or incomplete. Builds the write side of the stage task model that previously had only read paths, and unblocks M4-BE-012 dependencies that need a stage to be considered done.

The endpoint:

  • Verifies the funnel -> stage -> task ownership chain in one pass; any break surfaces as a unified 404 (Funnel task not found or not accessible.) to avoid leaking cross-user resource existence.
  • Returns 403 with the existing FUNNEL_STAGE_LOCKED_MESSAGE when the parent stage is locked, naming the prior stage that still needs to be completed.
  • Is idempotent: marking an already-complete task complete (or a pending task pending) is a no-op that returns 200 with the current state, no write performed.
  • Uses repository.save(loadedEntity) via the new StageTaskModelAction.saveTask so the StageTask.@BeforeUpdate syncCompletionState() hook keeps is_complete and completed_at in sync rather than the service writing those fields directly.

Related Issue

Implements ticket M4-BE-011 (Milestone 4 - Profile, Notifications & Stage Execution).

Type of Change

  • feat: New feature

How Has This Been Tested?

  • Unit tests
  • Manual tests

11 service tests cover every acceptance criterion (AC-01 through AC-09 plus an AC-09 mirror and a locked-stage fallback). Each was driven against the running API three times back to back; results were identical and matched the AC table.

Test Evidence

image image image image image image image image image

Documentation Screenshots (if applicable)

image image

Checklist

  • My code follows the project's coding style
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published

Summary by CodeRabbit

  • New Features

    • Added ability to update task status within funnel stages
    • Tasks can now be marked as complete or reopened to pending status
    • Automatic timestamp tracking records task status changes
    • Built-in validation prevents invalid status transitions
  • Tests

    • Comprehensive test coverage added for task status update functionality

Review Change Stack

ibraheembello added 2 commits May 28, 2026 12:48
Adds PATCH /api/funnels/:funnelId/stages/:stageId/tasks/:taskId so
users can mark a stage task complete or pending. Ownership is
verified as a single funnel -> stage -> task chain that surfaces any
break as a 404, parent-stage locked returns 403, and same-status
requests are idempotent. The save path lets the StageTask
@BeforeUpdate hook drive is_complete and completed_at instead of
writing them directly.
…mpletion

# Conflicts:
#	src/modules/funnels/actions/stage-task.action.ts
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

📝 Walkthrough

Walkthrough

This PR adds a complete task status update feature to the funnels module. It introduces a new PATCH endpoint that allows users to update the status (pending/complete) of tasks within funnel stages, including request validation, ownership verification, stage-lock checks, idempotent behavior, and comprehensive error handling.

Changes

Task Status Update Feature

Layer / File(s) Summary
Request and response contracts
src/modules/funnels/dto/update-task-status.dto.ts, src/modules/funnels/interfaces/funnels.interfaces.ts, src/constants/system.messages.ts
UpdateTaskStatusDto validates the incoming status field using @IsIn, TaskUpdateResult defines the response shape with task identity and state metadata, and new system message constants for not-found and success scenarios.
Data persistence methods
src/modules/funnels/actions/stage-task.action.ts
findOwnedTask queries a task by both id and stage_id, and saveTask persists the updated task via repository.
Business logic and orchestration
src/modules/funnels/services/funnels.service.ts
updateTaskStatus method verifies user ownership of the funnel, checks stage-lock status, fetches and validates the task, returns early if the task already has the requested status (idempotent), updates and persists changes otherwise, and returns a normalized TaskUpdateResult.
HTTP controller and routing
src/modules/funnels/controllers/funnels.controller.ts
New PATCH /:funnelId/stages/:stageId/tasks/:taskId endpoint extracts userId and path params, validates the body with UpdateTaskStatusDto, calls the service, and returns a standardized success response.
API documentation and examples
src/modules/funnels/docs/funnels-swagger.doc.ts
UpdateTaskStatusDecorators factory documents the endpoint with examples for success, idempotent returns, not-found, locked-stage forbidden, and validation-failure responses.
Comprehensive test suite
src/modules/funnels/services/tests/task-status-update.service.spec.ts
Test module with mocked dependencies verifies task transitions (pending to complete, complete to pending), ownership and stage-lock authorization, idempotency, DTO validation errors, and proper error messaging for missing resources and locked stages.

Sequence Diagram

sequenceDiagram
  participant Client
  participant Controller as FunnelsController
  participant Service as FunnelsService
  participant Action as StageTaskModelAction
  participant Repo as Repository
  
  Client->>Controller: PATCH /funnels/{funnelId}/stages/{stageId}/tasks/{taskId}
  Controller->>Service: updateTaskStatus(userId, funnelId, stageId, taskId, status)
  Service->>Action: findByFunnelAndUser(funnelId, userId)
  Action-->>Service: Funnel or null
  Service->>Action: findStageInFunnel(stageId)
  Action-->>Service: FunnelStage or null
  alt Stage is locked
    Service-->>Controller: ForbiddenException with lock message
  else Stage is not locked
    Service->>Action: findOwnedTask(taskId, stageId)
    Action-->>Service: StageTask or null
    alt Task not found
      Service-->>Controller: NotFoundException
    else Task found
      alt Status unchanged
        Service-->>Controller: current TaskUpdateResult
      else Status changed
        Service->>Action: saveTask(updated task)
        Repo-->>Action: persisted StageTask
        Action-->>Service: saved entity
        Service-->>Controller: new TaskUpdateResult
      end
    end
  end
  Controller-->>Client: { statusCode: 200, message, data: TaskUpdateResult }
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • akinwalexander
  • sage-ali
  • Nuel-09
  • nsien-prestige
  • JohnUghiovhe
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat(funnels): add task completion endpoint (M4-BE-011)' accurately summarizes the main change: adding a new endpoint for task status updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/M4-BE-011-task-completion

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Actionable comments posted: 0

@Homoakin619 Homoakin619 merged commit 1daa62f into dev May 28, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants