Skip to content

feat: add deliberation schemas for session creation, update, and deci…#35

Merged
codeline401 merged 2 commits into
developfrom
feature/notes-deliberations
Jun 9, 2026
Merged

feat: add deliberation schemas for session creation, update, and deci…#35
codeline401 merged 2 commits into
developfrom
feature/notes-deliberations

Conversation

@codeline401

@codeline401 codeline401 commented Jun 9, 2026

Copy link
Copy Markdown
Owner

…sion upsert

Summary by CodeRabbit

Release Notes

  • New Features
    • Added deliberation module for managing class academic sessions, including creating sessions, recording individual student decisions and outcomes, adding remarks and warnings, and validating sessions with success rate tracking.
    • Session management supports optional reporting and allows supervisors to approve deliberations once all decisions are finalized.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@codeline401, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 50 minutes and 24 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 318892fd-9e1a-4a17-9ba2-fd14944d9055

📥 Commits

Reviewing files that changed from the base of the PR and between 00421c3 and 87ee526.

📒 Files selected for processing (1)
  • apps/api/src/controllers/deliberationController.ts
📝 Walkthrough

Walkthrough

This PR introduces a complete student deliberation (approval/decision) module across database, backend API, and frontend. It adds new schema with deliberation sessions and decisions, validates inputs via Zod, implements five async controllers with role-based access control, exposes API endpoints under the class notes router, and replaces the deliberation UI placeholder with a fully functional React component using React Query for state management.

Changes

Student Deliberation Workflow

Layer / File(s) Summary
Deliberation Data Model
apps/api/prisma/migrations/20260604065820_add_deliberation_module/migration.sql, apps/api/prisma/migrations/20260608071106_fix_commentaire_deliberation_decision/migration.sql, apps/api/prisma/schema.prisma
Database schema adds four enums (DeliberationStatut, DecisionPassage, MentionDeliberation, AvertissementDeliberation) and two tables: DeliberationSession (per-class/per-period sessions with status, report, creator/validator) and DeliberationDecision (per-student decisions with passage, mention, warning, comment). Migrations create tables and fix column typo. Schema wires back-relations to User, School, Classe, and Eleve.
API Validation Schemas
apps/api/src/schemas/deliberationSchema.ts
Zod schemas define request validation for session create/update and decision upsert operations, with required vs optional field semantics. TypeScript types are exported for controller and frontend use.
Backend Controllers and Routes
apps/api/src/controllers/deliberationController.ts, apps/api/src/routes/notesRoute.ts
Five async controllers implement get, create, update, upsert decisions, and validate workflows with authorization helpers, success-rate calculation, and transaction-safe decision upsertion. Routes register endpoints at /api/classes/:classeId/notes/deliberations with role-based middleware and consistent error handling.
Frontend Deliberation UI
apps/web/src/components/notes/DeliberationTab.tsx
React component replaces placeholder with full deliberation sessions and decisions interface. Uses React Query to fetch classes, students, and sessions; manages local state for editable form rows. Mutations create/update sessions, save decisions, and validate with query invalidation. Renders session sidebar, detail panel with compte-rendu textarea and per-student decision selects, and action buttons. Role-based access control disables editing and shows authorization error when needed; validated sessions display success-rate alerts.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Route
  participant Auth
  participant Controller
  participant Prisma
  Client->>Route: POST/PUT /deliberations
  Route->>Auth: authorizeRoles
  Auth->>Route: verify role/school
  Route->>Controller: handle request
  Controller->>Controller: validate with Zod
  Controller->>Prisma: query/create/update session/decision
  Prisma->>Controller: return result or error
  Controller->>Route: send response
  Route->>Client: 200/400/403/404/500
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • codeline401/school-mgt-saas#30: Introduces the placeholder DeliberationTab component and wires the Notes & Examens page routes; this PR replaces that placeholder with the full deliberation implementation.

Poem

🐰 Deliberations bloom in the database,
Five controllers shepherd decisions with grace,
A Zod-validated waltz through approval's embrace,
React queries dance on the frontend's stage,
Where teachers script success, page after page.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title accurately describes the primary change: adding deliberation schemas. However, it is truncated and incomplete, cutting off mid-word at 'deci…', which makes it unclear and unprofessional. Complete the pull request title to its full form: 'feat: add deliberation schemas for session creation, update, and decision upsert' to clearly communicate the complete scope of the change.
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 (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/notes-deliberations

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 coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/src/controllers/deliberationController.ts`:
- Around line 190-205: The update call on prisma.deliberationSession in the
deliberationController is using the wrong field name `perdiodeLabel`, so updates
from `payload.periodeLabel` are ignored; fix it by changing the key in the
update payload to the correct `periodeLabel` (inside the object constructed
where you currently spread { perdiodeLabel: payload.periodeLabel }) so that
prisma.deliberationSession.update correctly applies the period label change and
returns the updatedSession with decisions.

In `@apps/api/src/routes/notesRoute.ts`:
- Around line 132-174: The route-level authorization in notesRoute.ts currently
allows Role.USER but not Role.PROF, while deliberationController.ts's canEdit()
allows Role.SUDO_ADMIN, Role.ADMIN, Role.PROF; update the authorizeRoles(...)
calls for the four deliberation endpoints (the handlers
createDeliberationSession, updateDeliberationSession,
upsertDeliberationDecisions, validateDeliberationSession) to match canEdit() by
replacing Role.USER with Role.PROF so the middleware and canEdit() enforce the
same set: Role.SUDO_ADMIN, Role.ADMIN, Role.PROF.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0e1b52f5-aeec-48b2-9459-6f4ca3b84f1f

📥 Commits

Reviewing files that changed from the base of the PR and between 1bc18aa and 00421c3.

⛔ Files ignored due to path filters (14)
  • apps/api/src/generated/prisma/browser.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/client.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/commonInputTypes.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/enums.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/internal/class.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/internal/prismaNamespace.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/internal/prismaNamespaceBrowser.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/models.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/models/Classe.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/models/DeliberationDecision.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/models/DeliberationSession.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/models/Eleve.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/models/School.ts is excluded by !**/generated/**
  • apps/api/src/generated/prisma/models/User.ts is excluded by !**/generated/**
📒 Files selected for processing (7)
  • apps/api/prisma/migrations/20260604065820_add_deliberation_module/migration.sql
  • apps/api/prisma/migrations/20260608071106_fix_commentaire_deliberation_decision/migration.sql
  • apps/api/prisma/schema.prisma
  • apps/api/src/controllers/deliberationController.ts
  • apps/api/src/routes/notesRoute.ts
  • apps/api/src/schemas/deliberationSchema.ts
  • apps/web/src/components/notes/DeliberationTab.tsx

Comment thread apps/api/src/controllers/deliberationController.ts
Comment on lines +132 to +174
/**
* POST /api/classes/:classeId/notes/deliberations
* Modification : USER, ADMIN, SUDO_ADMIN
*/
router.post(
"/deliberations",
authenticate,
authorizeRoles(Role.SUDO_ADMIN, Role.ADMIN, Role.USER),
createDeliberationSession,
);

/**
* PUT /api/classes/:classeId/notes/deliberations/:sessionId
* Modification : USER, ADMIN, SUDO_ADMIN
*/
router.put(
"/deliberations/:sessionId",
authenticate,
authorizeRoles(Role.SUDO_ADMIN, Role.ADMIN, Role.USER),
updateDeliberationSession,
);

/**
* PUT /api/classes/:classeId/notes/deliberations/:sessionId/decisions
* Modification : USER, ADMIN, SUDO_ADMIN
*/
router.put(
"/deliberations/:sessionId/decisions",
authenticate,
authorizeRoles(Role.SUDO_ADMIN, Role.ADMIN, Role.USER),
upsertDeliberationDecisions,
);

/**
* POST /api/classes/:classeId/notes/deliberations/:sessionId/validate
* Validation finale : USER, ADMIN, SUDO_ADMIN
*/
router.post(
"/deliberations/:sessionId/validate",
authenticate,
authorizeRoles(Role.SUDO_ADMIN, Role.ADMIN, Role.USER),
validateDeliberationSession,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the canEdit function in the controller
rg -n "function canEdit" apps/api/src/controllers/deliberationController.ts -A 3

# Check if there's a consistent pattern for similar routes
rg -n "authorizeRoles.*PROF" apps/api/src/routes/

Repository: codeline401/school-mgt-saas

Length of output: 2228


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the exact route middleware definitions around lines ~120-180
nl -ba apps/api/src/routes/notesRoute.ts | sed -n '100,200p'

# Show canEdit definition (already found) and where it’s used in deliberation controller
nl -ba apps/api/src/controllers/deliberationController.ts | sed -n '1,220p'

# Specifically find call sites of canEdit in the controller
rg -n "canEdit\(" apps/api/src/controllers/deliberationController.ts -n

Repository: codeline401/school-mgt-saas

Length of output: 114


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# routes: exact middleware definitions for deliberation endpoints
cat -n apps/api/src/routes/notesRoute.ts | sed -n '100,220p'

# controller: canEdit definition and relevant sections
cat -n apps/api/src/controllers/deliberationController.ts | sed -n '1,260p'

# where canEdit is used
rg -n "canEdit\\(" apps/api/src/controllers/deliberationController.ts

Repository: codeline401/school-mgt-saas

Length of output: 14159


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the validateDeliberationSession implementation area (around the last canEdit call)
cat -n apps/api/src/controllers/deliberationController.ts | sed -n '260,420p'

Repository: codeline401/school-mgt-saas

Length of output: 5987


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "createDeliberationSession|updateDeliberationSession|upsertDeliberationDecisions|validateDeliberationSession" apps/api/src/routes/

Repository: codeline401/school-mgt-saas

Length of output: 611


Role authorization mismatch for deliberation modification endpoints.

  • apps/api/src/routes/notesRoute.ts authorizes modification endpoints (/deliberations, /deliberations/:sessionId, /deliberations/:sessionId/decisions, /deliberations/:sessionId/validate) for Role.SUDO_ADMIN, Role.ADMIN, Role.USER (no Role.PROF).
  • apps/api/src/controllers/deliberationController.ts canEdit() allows Role.SUDO_ADMIN, Role.ADMIN, Role.PROF (no Role.USER) and each modification handler returns 403 when canEdit() fails.

Consequence: PROF is blocked at middleware (403) and USER passes middleware but is rejected by canEdit() (403).
Align authorizeRoles(...) in the routes with canEdit() access policy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/routes/notesRoute.ts` around lines 132 - 174, The route-level
authorization in notesRoute.ts currently allows Role.USER but not Role.PROF,
while deliberationController.ts's canEdit() allows Role.SUDO_ADMIN, Role.ADMIN,
Role.PROF; update the authorizeRoles(...) calls for the four deliberation
endpoints (the handlers createDeliberationSession, updateDeliberationSession,
upsertDeliberationDecisions, validateDeliberationSession) to match canEdit() by
replacing Role.USER with Role.PROF so the middleware and canEdit() enforce the
same set: Role.SUDO_ADMIN, Role.ADMIN, Role.PROF.

@codeline401 codeline401 merged commit acc8733 into develop Jun 9, 2026
2 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.

1 participant