Files
alrahma_sunday_school_api/docs/api_parent_promotion_controller_plan.md
T
2026-06-04 02:24:41 -04:00

3.0 KiB
Raw Blame History

ParentPromotionController plan

Scope

  • Controller: app/Http/Controllers/Api/Parents/ParentPromotionController.php
  • Purpose: parent portal endpoints for promotion + enrollment workflow.
  • Primary dependencies:
    • App\Services\Promotions\PromotionEnrollmentService
    • App\Services\Promotions\PromotionQueryService
  • Models:
    • App\Models\StudentPromotionRecord
    • App\Models\Student (ownership verification fallback)

Routes

All routes are under v1 + parents group:

  • Base prefix: ... /api/v1/parents/promotions
  • Group middleware: parent.access

Endpoints:

  • GET /api/v1/parents/promotions/overview
  • GET /api/v1/parents/promotions/{promotionId}show
  • POST /api/v1/parents/promotions/{promotionId}/startstart
  • PATCH /api/v1/parents/promotions/{promotionId}/stepsupdateSteps
  • POST /api/v1/parents/promotions/{promotionId}/submitsubmit

Authentication & authorization

  • Parent context resolved via parentIdOrUnauthorized():
    • prefers request attribute primary_parent_id (set by parent.access)
    • falls back to auth()->id()
  • Ownership is enforced in loadOwnedRecord():
    • Primary check: StudentPromotionRecord.parent_id == parentId
    • Fallback: loads Student.parent_id for the records student_id
    • If not owned: returns 403 { ok:false, message:"You are not authorised..." }

Requests/validation

  • overview: ParentPromotionOverviewRequest (optional next_school_year)
  • updateSteps: ParentEnrollmentStepRequest (steps() accessor provides structured step payload)

Response shapes

  • overview:
    • { ok:true, records, next_school_year, message }
    • Note: records are returned as provided by PromotionEnrollmentService::overviewForParent(...) (already shaped for the client)
  • show / start / updateSteps / submit:
    • { ok:true, data: StudentPromotionResource(...) }

State transitions (high-level)

  • startPromotionEnrollmentService::startEnrollment(...)
  • updateStepsPromotionEnrollmentService::updateSteps(...)
  • submitPromotionEnrollmentService::submitEnrollment(...)
  • Conflicts (invalid transition / deadline / status) surface as 409 with { ok:false, message }.

Error handling expectations

  • Unauthorized → 401 { ok:false, message:"Unauthorized." }
  • Record not found → 404 { ok:false, message:"Promotion record not found." }
  • Not owned → 403 { ok:false, message:"You are not authorised..." }
  • Invalid transition → 409 { ok:false, message }

Test plan (feature)

  • Ownership:
    • Parent cannot access another parents record (403).
    • Record with mismatched parent_id but student belongs to parent passes ownership check.
  • Happy path:
    • overview returns list for parent.
    • start moves record to started state and returns updated resource.
    • updateSteps persists steps and returns updated resource.
    • submit transitions to submitted state.
  • Conflict cases:
    • Submitting without required steps → 409.
    • Past deadline → 409 (as enforced by service).