Skip to content

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Campus Resource Management System (CRMS) Documentation

Overview

CRMS is a full-stack, multi-tenant application for managing campus resource bookings (e.g., classrooms, labs, auditoriums). It supports role-based access (STUDENT, FACULTY, ADMIN, SUPER_ADMIN), booking workflows with approval/rejection/cancellation, conflict resolution, event-driven notifications, and a dashboard-based UI.

Key Features:

  • Multi-tenancy: Institutions (universities) own users/resources.
  • Secure auth (JWT, bcrypt, role guards).
  • REST API with Swagger docs.
  • Prisma ORM for PostgreSQL with migrations/soft-deletes.
  • Event-driven notifications (EventBus pattern).
  • Booking conflict strategies.
  • Frontend dashboard with booking/resource/user management UI.
  • Role-based access control (STUDENT, FACULTY, ADMIN, SUPER_ADMIN).

Tech Stack

Backend

  • Runtime: Node.js, Express 5, TypeScript
  • Database: PostgreSQL via Prisma 6
  • Auth: JWT 9, bcryptjs
  • Security: helmet, cors, express-rate-limit
  • Real-time: Socket.io 4 (placeholder — not currently wired)
  • Docs: Swagger-jsdoc, redoc-express
  • Dev: nodemon, ts-node

Frontend

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • Styling: TailwindCSS 4, PostCSS
  • UI: Custom dashboard components (FullCalendar 6 installed but not actively used)
  • Networking: Axios, Socket.io-client 4 (placeholder)
  • Linting: ESLint 9, eslint-config-next

Architecture

Clean Architecture / Layered / DDD-inspired:

  • Controllers: Handle HTTP req/res (e.g., UserController, BookingController).
  • Routes: Express routers (auth.routes.ts, booking.routes.ts).
  • Services: Business logic (UserService calls domain models/validators).
  • Models: Domain entities (User subclasses via Factory).
  • Mappers: Domain <-> DTO conversions.
  • Middleware: Auth, validation, etc.
  • Shared: Errors (DomainError), Types. EventBus: In-memory pub/sub for notifications and booking lifecycle events.
  • patterns/: Explicit GoF implementations.

Backend Infrastructure Deep Dive

How Backend Works (Request Flow)

  1. Entry: Express app (server.ts) mounts routes/middleware/Swagger. src/app.ts registers event handlers.
  2. Middleware Pipeline: CORS, rate-limit, helmet, auth (JWT verify + role/institution scope).
  3. Routing: /api/v1/[auth|users|resources|bookings|institutions] -> controller methods.
  4. Controller -> Service: Extract actor (req.user), call service (e.g., bookingService.create(actor, dto)).
  5. Service -> Domain: Validate, use Factory/State/Strategy, map DTO->domain, persist via Prisma.
  6. Domain -> Prisma: Repos/services query with tenant filter (where: {institutionId, deletedAt: null}).
  7. Post-persist: Observer notify -> EventBus publish -> Log/Notification handlers.
  8. Error Handling: DomainError -> standardized JSON error response.

Sequence Diagram: Create Booking

sequenceDiagram
participant Client
participant Controller
participant Service
participant Strategy
participant Prisma
participant Observer
participant EventBus
Client->>Controller: POST /bookings
Controller->>Service: create(actor, dto)
Service->>Factory: create Resource/User domain
Service->>Strategy: resolveConflicts(overlaps)
alt Conflict
Strategy-->>Service: DomainError
Service-->>Controller: 400
else OK
Service->>Prisma: booking.create()
Prisma-->>Service: Booking
Service->>Observer: notify(BookingSubject)
Observer->>EventBus: publish('BOOKING_CREATED', payload)
end
Service-->>Controller: DTO
Controller-->>Client: 201 JSON
Loading

Detailed API Endpoints (Controllers)

MethodEndpointControllerDescriptionAuth/Role
POST/auth/loginAuthControllerJWT tokenpublic
GET/usersUserControllerList institution usersinstitution admin+
PATCH/users/:idUserControllerUpdate rolesuperadmin/admin
DELETE/users/:idUserControllerSoft deleteadmin+
POST/bookingsBookingControllerCreate bookinginstitution user
PATCH/bookings/:id/approveBookingControllerApprove (state trans)faculty+
PATCH/bookings/:id/rejectBookingControllerRejectfaculty+
PATCH/bookings/:id/cancelBookingControllerCancelowner
GET/resourcesResourceControllerList availableuser
POST/resourcesResourceControllerCreate resourceadmin
POST/institutionsInstitutionControllerCreate institutionsuperadmin

Proceed with Development:

  • Extend Booking: Add to BookingService, controller/route method, Prisma field, State transition.
  • New Endpoint: Add controller method, route file new.routes.ts, mount in server.ts.
  • Custom Validation: Domain model method or Factory.
  • Prisma Changes: schema.prisma -> npx prisma generate migrate dev.
  • EventBus Events: Extend handlers in src/events/handlers/ and register in src/app.ts.
  • Testing: Unit (services/domain), E2E (supertest + prisma mock).

Prisma Integration

  • Tenant-aware: Services append {institutionId: actor.institutionId!, deletedAt: null}.
  • Relations: Eager-load (include: {user: true, resource: true}) to avoid N+1.
  • Indexes (recommended): Composite on institutionId + deletedAt, resourceId + startTime.

Design Patterns

Explicit implementations in backend/src/patterns/:

  1. Factory Method (factory/UserFactory.ts):

    • Creates User subclasses (Student, Faculty, Admin) based on role.
    • Validates props, handles polymorphism.
  2. Observer (observer/):

    • BookingSubject.ts: Subject for booking state changes.
    • NotificationObserver.ts: Observer for notifications.
  3. State (state/):

    • BookingState.ts: Abstract base.
    • Concrete: PendingState.ts, ApprovedState.ts, RejectedState.ts, CancelledState.ts.
    • Encapsulates booking lifecycle transitions.
  4. Strategy (strategy/):

    • Conflict resolution for overlapping bookings.
    • StrictConflictStrategy.ts, PriorityConflictStrategy.ts, ConflictStrategy.ts.

Other Patterns:

  • Repository (implicit via Prisma).
  • DTO (mappers).
  • MVC (controllers/routes/services).
  • Singleton/Dependency Injection (services instantiated in controllers).
  • Command (booking create/approve/reject).

Database Schema (ER Diagram)

erDiagram
Institution ||--o{ User : owns
Institution ||--o{ Resource : owns
User ||--o{ Booking : creates
Resource ||--o{ Booking : booked_as
User ||--o{ Notification : receives
Institution {
string id PK
string name UK
string domain
datetime deletedAt
}
User {
string id PK
string email UK
string passwordHash
enum role
string institutionId FK
datetime deletedAt
}
Resource {
string id PK
string name
string type
string description
int capacity
string institutionId FK
boolean isActive
datetime deletedAt
}
Booking {
string id PK
string userId FK
string resourceId FK
datetime startTime
datetime endTime
enum status
}
Notification {
string id PK
string message
boolean isRead
string userId FK
}
Loading

Enums:

  • Role: STUDENT, FACULTY, ADMIN, SUPER_ADMIN
  • BookingStatus: PENDING, APPROVED, REJECTED, CANCELLED

Class Diagram (Key Domain Classes)

classDiagram
class User {
+string id
+string email
+UserRole role
+string? institutionId
+create(props)
}
class Student {
<<extends User>>
}
class Faculty {
<<extends User>>
}
class Admin {
<<extends User>>
}
class UserFactory {
+static User create(UserProps)
}
class BookingState {
<<abstract>>
+handle()
}
class PendingState {
<<extends BookingState>>
}
class ApprovedState {
<<extends BookingState>>
}
class BookingSubject {
+attach(Observer)
+detach(Observer)
+notify()
}
class NotificationObserver {
<<implements Observer>>
+update()
}
class ConflictStrategy {
<<interface>>
+resolve(Booking[])
}
UserFactory ..|> User
User <|-- Student
User <|-- Faculty
User <|-- Admin
BookingState <|-- PendingState : uses
BookingSubject *-- NotificationObserver
ConflictStrategy <|.. StrictConflictStrategy
Loading

API Endpoints (Inferred from Controllers/Routes)

  • Users: GET /users (institution), PATCH /users/:id, DELETE /users/:id (soft).
  • Bookings: POST /bookings, PATCH /bookings/:id/approve|reject|cancel.
  • Resources: CRUD for institution resources.
  • Institutions: Create/manage.
  • EventBus: Pub/sub events for notifications and booking lifecycle.

Frontend Structure

Next.js App Router:

  • src/app/layout.tsx: Root layout (dark mode, CSS variables).
  • src/app/page.tsx: Redirects to /login.
  • (auth)/login|register: Auth pages.
  • (dashboard)/bookings|calendar|resources|users|institutions: Protected dashboard pages. (Note: calendar currently redirects to /bookings.)

Key Technical Details

  • Multi-tenancy: All queries scoped by institutionId from JWT.
  • Security: Role guards in middleware/services, rate-limiting, helmet.
  • Error Handling: DomainError for business rules.
  • Validation: Factory/service level.
  • Soft Deletes: deletedAt timestamps.
  • Dev Workflow: npm run dev (backend: nodemon ts-node server.ts; frontend: next dev).

Potential User Questions (FAQ)

Basic Setup & Usage

  1. How to setup the project locally?

    • Backend: cd backend && npm i, setup .env with DATABASE_URL, npx prisma generate && npx prisma migrate dev, npm run dev.
    • Frontend: cd frontend && npm i, npm run dev.
  2. How to add a new user role (e.g., MAINTENANCE)?

    • Add to Prisma Role enum.
    • Create Maintenance.ts model extending User.
    • Add case in UserFactory.create() switch.
    • Update role guards in middleware/services.
  3. How do booking conflicts get resolved?

    • Service layer uses Strategy pattern (PriorityConflictStrategy etc.) to detect overlaps via Prisma queries.
    • Throws DomainError if unresolved; configurable per institution/role.
  4. How do notifications work?

    • Observer: BookingSubject.notify() triggers NotificationObserver on state changes.
    • EventBus publishes events (BOOKING_CREATED, BOOKING_APPROVED, etc.) to registered handlers (LogHandler, NotificationHandler).

Advanced Technical Questions & Tradeoffs

  1. Why Prisma over raw SQL/Sequelize? Tradeoffs?

    • Pros: Type-safe queries, migrations auto, schema-first (great for TS).
    • Cons: N+1 perf issues (use include/select), less control over complex joins, migration lock-in.
    • Mitigation: Raw queries for perf-critical (e.g., booking overlaps).
  2. Clean Architecture worth the folder complexity?

    • Pros: Testable, decoupled (services pure), scalable for teams.
    • Cons: Boilerplate (mappers/DTOs), overkill for small apps, learning curve.
    • Here: Justified by patterns/multi-tenancy.
  3. State pattern for bookings: Benefits vs simple enum?

    • Pros: Encapsulates transitions (e.g., PENDING->APPROVED only), extensible.
    • Cons: More classes/files vs enum if-checks.
    • Tradeoff: Maintainability wins for complex workflows.
  4. Multi-tenancy via institutionId filtering: Secure/scalable?

    • Pros: Single DB (cost-effective), row-level isolation.
    • Cons: Accidental data leaks if filter missed, perf (index on institutionId).
    • Alt: Schema-per-tenant (complex), DB-per-tenant (expensive).
    • Enforced in services/middleware.
  5. Socket.io vs Server-Sent Events/polling for notifications?

    • Pros: Bidirectional, rooms (per institution), fallback transports.
    • Cons: WebSocket overhead, scaling (Redis adapter needed for prod).
    • Here: Socket.io is installed as a placeholder; currently EventBus handles notifications server-side. WebSocket delivery can be wired later.
  6. Next.js App Router vs Pages Router?

    • Pros: File-based routing, React Server Components (perf), colocation.
    • Cons: Breaking changes, Server Actions learning curve.
    • Tradeoff: Future-proof, but migrate carefully.
  7. FullCalendar: Status and limitations?

    • Status: Installed but not currently active (calendar page redirects to /bookings).
    • Pros: Rich views (timegrid), React integration, customizable.
    • Cons: Client-side (no SSR events), paid for advanced (recurring).
    • Alt: Custom with shadcn/ui + react-big-calendar.
  8. TypeScript strict mode? Enforced?

    • Pros: Catches domain errors early (e.g., role enums).
    • Cons: Verbose (mappers for Prisma raw types).
    • Config: tsconfig strict: true recommended.
  9. Soft deletes: Pros/Cons vs hard delete?

    • Pros: Audit trail, undo possible, GDPR compliance.
    • Cons: DB bloat, perf (index on deletedAt), query complexity (deletedAt IS NULL).
    • Here: Scoped in Prisma relations.
  10. Scaling API: Monolith ok? Microservices?

    • Current: Fine for campus (rate-limit helps).
    • Tradeoff: Microservices (per institution?) add service mesh complexity; stick to monolith + horizontal scale.

Files Structure

CRMS/
├── backend/
│ ├── prisma/schema.prisma (ER)
│ ├── server.ts (Express entry)
│ ├── src/
│ │ ├── app.ts (event handler registration)
│ │ ├── config/ (env, db)
│ │ ├── controllers/*.ts (5 files)
│ │ ├── docs/ (swagger, redoc)
│ │ ├── events/ (EventBus, handlers)
│ │ ├── middleware/ (auth, rate limit, validation, role guards)
│ │ ├── mappers/ (UserMapper, InstitutionMapper)
│ │ ├── models/ (User, Booking, Resource, etc.)
│ │ ├── routes/*.ts (5 files)
│ │ ├── services/ (business logic)
│ │ ├── shared/ (DomainError, query helpers, response, type guards)
│ │ ├── types/ (bcrypt.d.ts)
│ │ ├── validators/ (Zod schemas)
│ │ └── patterns/ (factory/observer/state/strategy)
│ └── socket/ (placeholder)
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx, page.tsx
│ │ │ ├── (auth)/login|register/
│ │ │ ├── (dashboard)/bookings|calendar|resources|users|institutions/
│ │ │ └── pending/
│ │ ├── components/ (layout, ui, dashboard)
│ │ ├── hooks/ (useAuth)
│ │ ├── lib/ (api, cn)
│ │ └── types/ (auth)

About

About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - ElusiveParadox/crms: About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL. · GitHub
Skip to content

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Campus Resource Management System (CRMS) Documentation

Overview

CRMS is a full-stack, multi-tenant application for managing campus resource bookings (e.g., classrooms, labs, auditoriums). It supports role-based access (STUDENT, FACULTY, ADMIN, SUPER_ADMIN), booking workflows with approval/rejection/cancellation, conflict resolution, event-driven notifications, and a dashboard-based UI.

Key Features:

  • Multi-tenancy: Institutions (universities) own users/resources.
  • Secure auth (JWT, bcrypt, role guards).
  • REST API with Swagger docs.
  • Prisma ORM for PostgreSQL with migrations/soft-deletes.
  • Event-driven notifications (EventBus pattern).
  • Booking conflict strategies.
  • Frontend dashboard with booking/resource/user management UI.
  • Role-based access control (STUDENT, FACULTY, ADMIN, SUPER_ADMIN).

Tech Stack

Backend

  • Runtime: Node.js, Express 5, TypeScript
  • Database: PostgreSQL via Prisma 6
  • Auth: JWT 9, bcryptjs
  • Security: helmet, cors, express-rate-limit
  • Real-time: Socket.io 4 (placeholder — not currently wired)
  • Docs: Swagger-jsdoc, redoc-express
  • Dev: nodemon, ts-node

Frontend

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • Styling: TailwindCSS 4, PostCSS
  • UI: Custom dashboard components (FullCalendar 6 installed but not actively used)
  • Networking: Axios, Socket.io-client 4 (placeholder)
  • Linting: ESLint 9, eslint-config-next

Architecture

Clean Architecture / Layered / DDD-inspired:

  • Controllers: Handle HTTP req/res (e.g., UserController, BookingController).
  • Routes: Express routers (auth.routes.ts, booking.routes.ts).
  • Services: Business logic (UserService calls domain models/validators).
  • Models: Domain entities (User subclasses via Factory).
  • Mappers: Domain <-> DTO conversions.
  • Middleware: Auth, validation, etc.
  • Shared: Errors (DomainError), Types. EventBus: In-memory pub/sub for notifications and booking lifecycle events.
  • patterns/: Explicit GoF implementations.

Backend Infrastructure Deep Dive

How Backend Works (Request Flow)

  1. Entry: Express app (server.ts) mounts routes/middleware/Swagger. src/app.ts registers event handlers.
  2. Middleware Pipeline: CORS, rate-limit, helmet, auth (JWT verify + role/institution scope).
  3. Routing: /api/v1/[auth|users|resources|bookings|institutions] -> controller methods.
  4. Controller -> Service: Extract actor (req.user), call service (e.g., bookingService.create(actor, dto)).
  5. Service -> Domain: Validate, use Factory/State/Strategy, map DTO->domain, persist via Prisma.
  6. Domain -> Prisma: Repos/services query with tenant filter (where: {institutionId, deletedAt: null}).
  7. Post-persist: Observer notify -> EventBus publish -> Log/Notification handlers.
  8. Error Handling: DomainError -> standardized JSON error response.

Sequence Diagram: Create Booking

sequenceDiagram
participant Client
participant Controller
participant Service
participant Strategy
participant Prisma
participant Observer
participant EventBus
Client->>Controller: POST /bookings
Controller->>Service: create(actor, dto)
Service->>Factory: create Resource/User domain
Service->>Strategy: resolveConflicts(overlaps)
alt Conflict
Strategy-->>Service: DomainError
Service-->>Controller: 400
else OK
Service->>Prisma: booking.create()
Prisma-->>Service: Booking
Service->>Observer: notify(BookingSubject)
Observer->>EventBus: publish('BOOKING_CREATED', payload)
end
Service-->>Controller: DTO
Controller-->>Client: 201 JSON
Loading

Detailed API Endpoints (Controllers)

MethodEndpointControllerDescriptionAuth/Role
POST/auth/loginAuthControllerJWT tokenpublic
GET/usersUserControllerList institution usersinstitution admin+
PATCH/users/:idUserControllerUpdate rolesuperadmin/admin
DELETE/users/:idUserControllerSoft deleteadmin+
POST/bookingsBookingControllerCreate bookinginstitution user
PATCH/bookings/:id/approveBookingControllerApprove (state trans)faculty+
PATCH/bookings/:id/rejectBookingControllerRejectfaculty+
PATCH/bookings/:id/cancelBookingControllerCancelowner
GET/resourcesResourceControllerList availableuser
POST/resourcesResourceControllerCreate resourceadmin
POST/institutionsInstitutionControllerCreate institutionsuperadmin

Proceed with Development:

  • Extend Booking: Add to BookingService, controller/route method, Prisma field, State transition.
  • New Endpoint: Add controller method, route file new.routes.ts, mount in server.ts.
  • Custom Validation: Domain model method or Factory.
  • Prisma Changes: schema.prisma -> npx prisma generate migrate dev.
  • EventBus Events: Extend handlers in src/events/handlers/ and register in src/app.ts.
  • Testing: Unit (services/domain), E2E (supertest + prisma mock).

Prisma Integration

  • Tenant-aware: Services append {institutionId: actor.institutionId!, deletedAt: null}.
  • Relations: Eager-load (include: {user: true, resource: true}) to avoid N+1.
  • Indexes (recommended): Composite on institutionId + deletedAt, resourceId + startTime.

Design Patterns

Explicit implementations in backend/src/patterns/:

  1. Factory Method (factory/UserFactory.ts):

    • Creates User subclasses (Student, Faculty, Admin) based on role.
    • Validates props, handles polymorphism.
  2. Observer (observer/):

    • BookingSubject.ts: Subject for booking state changes.
    • NotificationObserver.ts: Observer for notifications.
  3. State (state/):

    • BookingState.ts: Abstract base.
    • Concrete: PendingState.ts, ApprovedState.ts, RejectedState.ts, CancelledState.ts.
    • Encapsulates booking lifecycle transitions.
  4. Strategy (strategy/):

    • Conflict resolution for overlapping bookings.
    • StrictConflictStrategy.ts, PriorityConflictStrategy.ts, ConflictStrategy.ts.

Other Patterns:

  • Repository (implicit via Prisma).
  • DTO (mappers).
  • MVC (controllers/routes/services).
  • Singleton/Dependency Injection (services instantiated in controllers).
  • Command (booking create/approve/reject).

Database Schema (ER Diagram)

erDiagram
Institution ||--o{ User : owns
Institution ||--o{ Resource : owns
User ||--o{ Booking : creates
Resource ||--o{ Booking : booked_as
User ||--o{ Notification : receives
Institution {
string id PK
string name UK
string domain
datetime deletedAt
}
User {
string id PK
string email UK
string passwordHash
enum role
string institutionId FK
datetime deletedAt
}
Resource {
string id PK
string name
string type
string description
int capacity
string institutionId FK
boolean isActive
datetime deletedAt
}
Booking {
string id PK
string userId FK
string resourceId FK
datetime startTime
datetime endTime
enum status
}
Notification {
string id PK
string message
boolean isRead
string userId FK
}
Loading

Enums:

  • Role: STUDENT, FACULTY, ADMIN, SUPER_ADMIN
  • BookingStatus: PENDING, APPROVED, REJECTED, CANCELLED

Class Diagram (Key Domain Classes)

classDiagram
class User {
+string id
+string email
+UserRole role
+string? institutionId
+create(props)
}
class Student {
<<extends User>>
}
class Faculty {
<<extends User>>
}
class Admin {
<<extends User>>
}
class UserFactory {
+static User create(UserProps)
}
class BookingState {
<<abstract>>
+handle()
}
class PendingState {
<<extends BookingState>>
}
class ApprovedState {
<<extends BookingState>>
}
class BookingSubject {
+attach(Observer)
+detach(Observer)
+notify()
}
class NotificationObserver {
<<implements Observer>>
+update()
}
class ConflictStrategy {
<<interface>>
+resolve(Booking[])
}
UserFactory ..|> User
User <|-- Student
User <|-- Faculty
User <|-- Admin
BookingState <|-- PendingState : uses
BookingSubject *-- NotificationObserver
ConflictStrategy <|.. StrictConflictStrategy
Loading

API Endpoints (Inferred from Controllers/Routes)

  • Users: GET /users (institution), PATCH /users/:id, DELETE /users/:id (soft).
  • Bookings: POST /bookings, PATCH /bookings/:id/approve|reject|cancel.
  • Resources: CRUD for institution resources.
  • Institutions: Create/manage.
  • EventBus: Pub/sub events for notifications and booking lifecycle.

Frontend Structure

Next.js App Router:

  • src/app/layout.tsx: Root layout (dark mode, CSS variables).
  • src/app/page.tsx: Redirects to /login.
  • (auth)/login|register: Auth pages.
  • (dashboard)/bookings|calendar|resources|users|institutions: Protected dashboard pages. (Note: calendar currently redirects to /bookings.)

Key Technical Details

  • Multi-tenancy: All queries scoped by institutionId from JWT.
  • Security: Role guards in middleware/services, rate-limiting, helmet.
  • Error Handling: DomainError for business rules.
  • Validation: Factory/service level.
  • Soft Deletes: deletedAt timestamps.
  • Dev Workflow: npm run dev (backend: nodemon ts-node server.ts; frontend: next dev).

Potential User Questions (FAQ)

Basic Setup & Usage

  1. How to setup the project locally?

    • Backend: cd backend && npm i, setup .env with DATABASE_URL, npx prisma generate && npx prisma migrate dev, npm run dev.
    • Frontend: cd frontend && npm i, npm run dev.
  2. How to add a new user role (e.g., MAINTENANCE)?

    • Add to Prisma Role enum.
    • Create Maintenance.ts model extending User.
    • Add case in UserFactory.create() switch.
    • Update role guards in middleware/services.
  3. How do booking conflicts get resolved?

    • Service layer uses Strategy pattern (PriorityConflictStrategy etc.) to detect overlaps via Prisma queries.
    • Throws DomainError if unresolved; configurable per institution/role.
  4. How do notifications work?

    • Observer: BookingSubject.notify() triggers NotificationObserver on state changes.
    • EventBus publishes events (BOOKING_CREATED, BOOKING_APPROVED, etc.) to registered handlers (LogHandler, NotificationHandler).

Advanced Technical Questions & Tradeoffs

  1. Why Prisma over raw SQL/Sequelize? Tradeoffs?

    • Pros: Type-safe queries, migrations auto, schema-first (great for TS).
    • Cons: N+1 perf issues (use include/select), less control over complex joins, migration lock-in.
    • Mitigation: Raw queries for perf-critical (e.g., booking overlaps).
  2. Clean Architecture worth the folder complexity?

    • Pros: Testable, decoupled (services pure), scalable for teams.
    • Cons: Boilerplate (mappers/DTOs), overkill for small apps, learning curve.
    • Here: Justified by patterns/multi-tenancy.
  3. State pattern for bookings: Benefits vs simple enum?

    • Pros: Encapsulates transitions (e.g., PENDING->APPROVED only), extensible.
    • Cons: More classes/files vs enum if-checks.
    • Tradeoff: Maintainability wins for complex workflows.
  4. Multi-tenancy via institutionId filtering: Secure/scalable?

    • Pros: Single DB (cost-effective), row-level isolation.
    • Cons: Accidental data leaks if filter missed, perf (index on institutionId).
    • Alt: Schema-per-tenant (complex), DB-per-tenant (expensive).
    • Enforced in services/middleware.
  5. Socket.io vs Server-Sent Events/polling for notifications?

    • Pros: Bidirectional, rooms (per institution), fallback transports.
    • Cons: WebSocket overhead, scaling (Redis adapter needed for prod).
    • Here: Socket.io is installed as a placeholder; currently EventBus handles notifications server-side. WebSocket delivery can be wired later.
  6. Next.js App Router vs Pages Router?

    • Pros: File-based routing, React Server Components (perf), colocation.
    • Cons: Breaking changes, Server Actions learning curve.
    • Tradeoff: Future-proof, but migrate carefully.
  7. FullCalendar: Status and limitations?

    • Status: Installed but not currently active (calendar page redirects to /bookings).
    • Pros: Rich views (timegrid), React integration, customizable.
    • Cons: Client-side (no SSR events), paid for advanced (recurring).
    • Alt: Custom with shadcn/ui + react-big-calendar.
  8. TypeScript strict mode? Enforced?

    • Pros: Catches domain errors early (e.g., role enums).
    • Cons: Verbose (mappers for Prisma raw types).
    • Config: tsconfig strict: true recommended.
  9. Soft deletes: Pros/Cons vs hard delete?

    • Pros: Audit trail, undo possible, GDPR compliance.
    • Cons: DB bloat, perf (index on deletedAt), query complexity (deletedAt IS NULL).
    • Here: Scoped in Prisma relations.
  10. Scaling API: Monolith ok? Microservices?

    • Current: Fine for campus (rate-limit helps).
    • Tradeoff: Microservices (per institution?) add service mesh complexity; stick to monolith + horizontal scale.

Files Structure

CRMS/
├── backend/
│ ├── prisma/schema.prisma (ER)
│ ├── server.ts (Express entry)
│ ├── src/
│ │ ├── app.ts (event handler registration)
│ │ ├── config/ (env, db)
│ │ ├── controllers/*.ts (5 files)
│ │ ├── docs/ (swagger, redoc)
│ │ ├── events/ (EventBus, handlers)
│ │ ├── middleware/ (auth, rate limit, validation, role guards)
│ │ ├── mappers/ (UserMapper, InstitutionMapper)
│ │ ├── models/ (User, Booking, Resource, etc.)
│ │ ├── routes/*.ts (5 files)
│ │ ├── services/ (business logic)
│ │ ├── shared/ (DomainError, query helpers, response, type guards)
│ │ ├── types/ (bcrypt.d.ts)
│ │ ├── validators/ (Zod schemas)
│ │ └── patterns/ (factory/observer/state/strategy)
│ └── socket/ (placeholder)
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx, page.tsx
│ │ │ ├── (auth)/login|register/
│ │ │ ├── (dashboard)/bookings|calendar|resources|users|institutions/
│ │ │ └── pending/
│ │ ├── components/ (layout, ui, dashboard)
│ │ ├── hooks/ (useAuth)
│ │ ├── lib/ (api, cn)
│ │ └── types/ (auth)

About

About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - ElusiveParadox/crms: About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL. · GitHub
Skip to content

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Campus Resource Management System (CRMS) Documentation

Overview

CRMS is a full-stack, multi-tenant application for managing campus resource bookings (e.g., classrooms, labs, auditoriums). It supports role-based access (STUDENT, FACULTY, ADMIN, SUPER_ADMIN), booking workflows with approval/rejection/cancellation, conflict resolution, event-driven notifications, and a dashboard-based UI.

Key Features:

  • Multi-tenancy: Institutions (universities) own users/resources.
  • Secure auth (JWT, bcrypt, role guards).
  • REST API with Swagger docs.
  • Prisma ORM for PostgreSQL with migrations/soft-deletes.
  • Event-driven notifications (EventBus pattern).
  • Booking conflict strategies.
  • Frontend dashboard with booking/resource/user management UI.
  • Role-based access control (STUDENT, FACULTY, ADMIN, SUPER_ADMIN).

Tech Stack

Backend

  • Runtime: Node.js, Express 5, TypeScript
  • Database: PostgreSQL via Prisma 6
  • Auth: JWT 9, bcryptjs
  • Security: helmet, cors, express-rate-limit
  • Real-time: Socket.io 4 (placeholder — not currently wired)
  • Docs: Swagger-jsdoc, redoc-express
  • Dev: nodemon, ts-node

Frontend

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • Styling: TailwindCSS 4, PostCSS
  • UI: Custom dashboard components (FullCalendar 6 installed but not actively used)
  • Networking: Axios, Socket.io-client 4 (placeholder)
  • Linting: ESLint 9, eslint-config-next

Architecture

Clean Architecture / Layered / DDD-inspired:

  • Controllers: Handle HTTP req/res (e.g., UserController, BookingController).
  • Routes: Express routers (auth.routes.ts, booking.routes.ts).
  • Services: Business logic (UserService calls domain models/validators).
  • Models: Domain entities (User subclasses via Factory).
  • Mappers: Domain <-> DTO conversions.
  • Middleware: Auth, validation, etc.
  • Shared: Errors (DomainError), Types. EventBus: In-memory pub/sub for notifications and booking lifecycle events.
  • patterns/: Explicit GoF implementations.

Backend Infrastructure Deep Dive

How Backend Works (Request Flow)

  1. Entry: Express app (server.ts) mounts routes/middleware/Swagger. src/app.ts registers event handlers.
  2. Middleware Pipeline: CORS, rate-limit, helmet, auth (JWT verify + role/institution scope).
  3. Routing: /api/v1/[auth|users|resources|bookings|institutions] -> controller methods.
  4. Controller -> Service: Extract actor (req.user), call service (e.g., bookingService.create(actor, dto)).
  5. Service -> Domain: Validate, use Factory/State/Strategy, map DTO->domain, persist via Prisma.
  6. Domain -> Prisma: Repos/services query with tenant filter (where: {institutionId, deletedAt: null}).
  7. Post-persist: Observer notify -> EventBus publish -> Log/Notification handlers.
  8. Error Handling: DomainError -> standardized JSON error response.

Sequence Diagram: Create Booking

sequenceDiagram
participant Client
participant Controller
participant Service
participant Strategy
participant Prisma
participant Observer
participant EventBus
Client->>Controller: POST /bookings
Controller->>Service: create(actor, dto)
Service->>Factory: create Resource/User domain
Service->>Strategy: resolveConflicts(overlaps)
alt Conflict
Strategy-->>Service: DomainError
Service-->>Controller: 400
else OK
Service->>Prisma: booking.create()
Prisma-->>Service: Booking
Service->>Observer: notify(BookingSubject)
Observer->>EventBus: publish('BOOKING_CREATED', payload)
end
Service-->>Controller: DTO
Controller-->>Client: 201 JSON
Loading

Detailed API Endpoints (Controllers)

MethodEndpointControllerDescriptionAuth/Role
POST/auth/loginAuthControllerJWT tokenpublic
GET/usersUserControllerList institution usersinstitution admin+
PATCH/users/:idUserControllerUpdate rolesuperadmin/admin
DELETE/users/:idUserControllerSoft deleteadmin+
POST/bookingsBookingControllerCreate bookinginstitution user
PATCH/bookings/:id/approveBookingControllerApprove (state trans)faculty+
PATCH/bookings/:id/rejectBookingControllerRejectfaculty+
PATCH/bookings/:id/cancelBookingControllerCancelowner
GET/resourcesResourceControllerList availableuser
POST/resourcesResourceControllerCreate resourceadmin
POST/institutionsInstitutionControllerCreate institutionsuperadmin

Proceed with Development:

  • Extend Booking: Add to BookingService, controller/route method, Prisma field, State transition.
  • New Endpoint: Add controller method, route file new.routes.ts, mount in server.ts.
  • Custom Validation: Domain model method or Factory.
  • Prisma Changes: schema.prisma -> npx prisma generate migrate dev.
  • EventBus Events: Extend handlers in src/events/handlers/ and register in src/app.ts.
  • Testing: Unit (services/domain), E2E (supertest + prisma mock).

Prisma Integration

  • Tenant-aware: Services append {institutionId: actor.institutionId!, deletedAt: null}.
  • Relations: Eager-load (include: {user: true, resource: true}) to avoid N+1.
  • Indexes (recommended): Composite on institutionId + deletedAt, resourceId + startTime.

Design Patterns

Explicit implementations in backend/src/patterns/:

  1. Factory Method (factory/UserFactory.ts):

    • Creates User subclasses (Student, Faculty, Admin) based on role.
    • Validates props, handles polymorphism.
  2. Observer (observer/):

    • BookingSubject.ts: Subject for booking state changes.
    • NotificationObserver.ts: Observer for notifications.
  3. State (state/):

    • BookingState.ts: Abstract base.
    • Concrete: PendingState.ts, ApprovedState.ts, RejectedState.ts, CancelledState.ts.
    • Encapsulates booking lifecycle transitions.
  4. Strategy (strategy/):

    • Conflict resolution for overlapping bookings.
    • StrictConflictStrategy.ts, PriorityConflictStrategy.ts, ConflictStrategy.ts.

Other Patterns:

  • Repository (implicit via Prisma).
  • DTO (mappers).
  • MVC (controllers/routes/services).
  • Singleton/Dependency Injection (services instantiated in controllers).
  • Command (booking create/approve/reject).

Database Schema (ER Diagram)

erDiagram
Institution ||--o{ User : owns
Institution ||--o{ Resource : owns
User ||--o{ Booking : creates
Resource ||--o{ Booking : booked_as
User ||--o{ Notification : receives
Institution {
string id PK
string name UK
string domain
datetime deletedAt
}
User {
string id PK
string email UK
string passwordHash
enum role
string institutionId FK
datetime deletedAt
}
Resource {
string id PK
string name
string type
string description
int capacity
string institutionId FK
boolean isActive
datetime deletedAt
}
Booking {
string id PK
string userId FK
string resourceId FK
datetime startTime
datetime endTime
enum status
}
Notification {
string id PK
string message
boolean isRead
string userId FK
}
Loading

Enums:

  • Role: STUDENT, FACULTY, ADMIN, SUPER_ADMIN
  • BookingStatus: PENDING, APPROVED, REJECTED, CANCELLED

Class Diagram (Key Domain Classes)

classDiagram
class User {
+string id
+string email
+UserRole role
+string? institutionId
+create(props)
}
class Student {
<<extends User>>
}
class Faculty {
<<extends User>>
}
class Admin {
<<extends User>>
}
class UserFactory {
+static User create(UserProps)
}
class BookingState {
<<abstract>>
+handle()
}
class PendingState {
<<extends BookingState>>
}
class ApprovedState {
<<extends BookingState>>
}
class BookingSubject {
+attach(Observer)
+detach(Observer)
+notify()
}
class NotificationObserver {
<<implements Observer>>
+update()
}
class ConflictStrategy {
<<interface>>
+resolve(Booking[])
}
UserFactory ..|> User
User <|-- Student
User <|-- Faculty
User <|-- Admin
BookingState <|-- PendingState : uses
BookingSubject *-- NotificationObserver
ConflictStrategy <|.. StrictConflictStrategy
Loading

API Endpoints (Inferred from Controllers/Routes)

  • Users: GET /users (institution), PATCH /users/:id, DELETE /users/:id (soft).
  • Bookings: POST /bookings, PATCH /bookings/:id/approve|reject|cancel.
  • Resources: CRUD for institution resources.
  • Institutions: Create/manage.
  • EventBus: Pub/sub events for notifications and booking lifecycle.

Frontend Structure

Next.js App Router:

  • src/app/layout.tsx: Root layout (dark mode, CSS variables).
  • src/app/page.tsx: Redirects to /login.
  • (auth)/login|register: Auth pages.
  • (dashboard)/bookings|calendar|resources|users|institutions: Protected dashboard pages. (Note: calendar currently redirects to /bookings.)

Key Technical Details

  • Multi-tenancy: All queries scoped by institutionId from JWT.
  • Security: Role guards in middleware/services, rate-limiting, helmet.
  • Error Handling: DomainError for business rules.
  • Validation: Factory/service level.
  • Soft Deletes: deletedAt timestamps.
  • Dev Workflow: npm run dev (backend: nodemon ts-node server.ts; frontend: next dev).

Potential User Questions (FAQ)

Basic Setup & Usage

  1. How to setup the project locally?

    • Backend: cd backend && npm i, setup .env with DATABASE_URL, npx prisma generate && npx prisma migrate dev, npm run dev.
    • Frontend: cd frontend && npm i, npm run dev.
  2. How to add a new user role (e.g., MAINTENANCE)?

    • Add to Prisma Role enum.
    • Create Maintenance.ts model extending User.
    • Add case in UserFactory.create() switch.
    • Update role guards in middleware/services.
  3. How do booking conflicts get resolved?

    • Service layer uses Strategy pattern (PriorityConflictStrategy etc.) to detect overlaps via Prisma queries.
    • Throws DomainError if unresolved; configurable per institution/role.
  4. How do notifications work?

    • Observer: BookingSubject.notify() triggers NotificationObserver on state changes.
    • EventBus publishes events (BOOKING_CREATED, BOOKING_APPROVED, etc.) to registered handlers (LogHandler, NotificationHandler).

Advanced Technical Questions & Tradeoffs

  1. Why Prisma over raw SQL/Sequelize? Tradeoffs?

    • Pros: Type-safe queries, migrations auto, schema-first (great for TS).
    • Cons: N+1 perf issues (use include/select), less control over complex joins, migration lock-in.
    • Mitigation: Raw queries for perf-critical (e.g., booking overlaps).
  2. Clean Architecture worth the folder complexity?

    • Pros: Testable, decoupled (services pure), scalable for teams.
    • Cons: Boilerplate (mappers/DTOs), overkill for small apps, learning curve.
    • Here: Justified by patterns/multi-tenancy.
  3. State pattern for bookings: Benefits vs simple enum?

    • Pros: Encapsulates transitions (e.g., PENDING->APPROVED only), extensible.
    • Cons: More classes/files vs enum if-checks.
    • Tradeoff: Maintainability wins for complex workflows.
  4. Multi-tenancy via institutionId filtering: Secure/scalable?

    • Pros: Single DB (cost-effective), row-level isolation.
    • Cons: Accidental data leaks if filter missed, perf (index on institutionId).
    • Alt: Schema-per-tenant (complex), DB-per-tenant (expensive).
    • Enforced in services/middleware.
  5. Socket.io vs Server-Sent Events/polling for notifications?

    • Pros: Bidirectional, rooms (per institution), fallback transports.
    • Cons: WebSocket overhead, scaling (Redis adapter needed for prod).
    • Here: Socket.io is installed as a placeholder; currently EventBus handles notifications server-side. WebSocket delivery can be wired later.
  6. Next.js App Router vs Pages Router?

    • Pros: File-based routing, React Server Components (perf), colocation.
    • Cons: Breaking changes, Server Actions learning curve.
    • Tradeoff: Future-proof, but migrate carefully.
  7. FullCalendar: Status and limitations?

    • Status: Installed but not currently active (calendar page redirects to /bookings).
    • Pros: Rich views (timegrid), React integration, customizable.
    • Cons: Client-side (no SSR events), paid for advanced (recurring).
    • Alt: Custom with shadcn/ui + react-big-calendar.
  8. TypeScript strict mode? Enforced?

    • Pros: Catches domain errors early (e.g., role enums).
    • Cons: Verbose (mappers for Prisma raw types).
    • Config: tsconfig strict: true recommended.
  9. Soft deletes: Pros/Cons vs hard delete?

    • Pros: Audit trail, undo possible, GDPR compliance.
    • Cons: DB bloat, perf (index on deletedAt), query complexity (deletedAt IS NULL).
    • Here: Scoped in Prisma relations.
  10. Scaling API: Monolith ok? Microservices?

    • Current: Fine for campus (rate-limit helps).
    • Tradeoff: Microservices (per institution?) add service mesh complexity; stick to monolith + horizontal scale.

Files Structure

CRMS/
├── backend/
│ ├── prisma/schema.prisma (ER)
│ ├── server.ts (Express entry)
│ ├── src/
│ │ ├── app.ts (event handler registration)
│ │ ├── config/ (env, db)
│ │ ├── controllers/*.ts (5 files)
│ │ ├── docs/ (swagger, redoc)
│ │ ├── events/ (EventBus, handlers)
│ │ ├── middleware/ (auth, rate limit, validation, role guards)
│ │ ├── mappers/ (UserMapper, InstitutionMapper)
│ │ ├── models/ (User, Booking, Resource, etc.)
│ │ ├── routes/*.ts (5 files)
│ │ ├── services/ (business logic)
│ │ ├── shared/ (DomainError, query helpers, response, type guards)
│ │ ├── types/ (bcrypt.d.ts)
│ │ ├── validators/ (Zod schemas)
│ │ └── patterns/ (factory/observer/state/strategy)
│ └── socket/ (placeholder)
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx, page.tsx
│ │ │ ├── (auth)/login|register/
│ │ │ ├── (dashboard)/bookings|calendar|resources|users|institutions/
│ │ │ └── pending/
│ │ ├── components/ (layout, ui, dashboard)
│ │ ├── hooks/ (useAuth)
│ │ ├── lib/ (api, cn)
│ │ └── types/ (auth)

About

About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - ElusiveParadox/crms: About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL. · GitHub
Skip to content

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Campus Resource Management System (CRMS) Documentation

Overview

CRMS is a full-stack, multi-tenant application for managing campus resource bookings (e.g., classrooms, labs, auditoriums). It supports role-based access (STUDENT, FACULTY, ADMIN, SUPER_ADMIN), booking workflows with approval/rejection/cancellation, conflict resolution, event-driven notifications, and a dashboard-based UI.

Key Features:

  • Multi-tenancy: Institutions (universities) own users/resources.
  • Secure auth (JWT, bcrypt, role guards).
  • REST API with Swagger docs.
  • Prisma ORM for PostgreSQL with migrations/soft-deletes.
  • Event-driven notifications (EventBus pattern).
  • Booking conflict strategies.
  • Frontend dashboard with booking/resource/user management UI.
  • Role-based access control (STUDENT, FACULTY, ADMIN, SUPER_ADMIN).

Tech Stack

Backend

  • Runtime: Node.js, Express 5, TypeScript
  • Database: PostgreSQL via Prisma 6
  • Auth: JWT 9, bcryptjs
  • Security: helmet, cors, express-rate-limit
  • Real-time: Socket.io 4 (placeholder — not currently wired)
  • Docs: Swagger-jsdoc, redoc-express
  • Dev: nodemon, ts-node

Frontend

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • Styling: TailwindCSS 4, PostCSS
  • UI: Custom dashboard components (FullCalendar 6 installed but not actively used)
  • Networking: Axios, Socket.io-client 4 (placeholder)
  • Linting: ESLint 9, eslint-config-next

Architecture

Clean Architecture / Layered / DDD-inspired:

  • Controllers: Handle HTTP req/res (e.g., UserController, BookingController).
  • Routes: Express routers (auth.routes.ts, booking.routes.ts).
  • Services: Business logic (UserService calls domain models/validators).
  • Models: Domain entities (User subclasses via Factory).
  • Mappers: Domain <-> DTO conversions.
  • Middleware: Auth, validation, etc.
  • Shared: Errors (DomainError), Types. EventBus: In-memory pub/sub for notifications and booking lifecycle events.
  • patterns/: Explicit GoF implementations.

Backend Infrastructure Deep Dive

How Backend Works (Request Flow)

  1. Entry: Express app (server.ts) mounts routes/middleware/Swagger. src/app.ts registers event handlers.
  2. Middleware Pipeline: CORS, rate-limit, helmet, auth (JWT verify + role/institution scope).
  3. Routing: /api/v1/[auth|users|resources|bookings|institutions] -> controller methods.
  4. Controller -> Service: Extract actor (req.user), call service (e.g., bookingService.create(actor, dto)).
  5. Service -> Domain: Validate, use Factory/State/Strategy, map DTO->domain, persist via Prisma.
  6. Domain -> Prisma: Repos/services query with tenant filter (where: {institutionId, deletedAt: null}).
  7. Post-persist: Observer notify -> EventBus publish -> Log/Notification handlers.
  8. Error Handling: DomainError -> standardized JSON error response.

Sequence Diagram: Create Booking

sequenceDiagram
participant Client
participant Controller
participant Service
participant Strategy
participant Prisma
participant Observer
participant EventBus
Client->>Controller: POST /bookings
Controller->>Service: create(actor, dto)
Service->>Factory: create Resource/User domain
Service->>Strategy: resolveConflicts(overlaps)
alt Conflict
Strategy-->>Service: DomainError
Service-->>Controller: 400
else OK
Service->>Prisma: booking.create()
Prisma-->>Service: Booking
Service->>Observer: notify(BookingSubject)
Observer->>EventBus: publish('BOOKING_CREATED', payload)
end
Service-->>Controller: DTO
Controller-->>Client: 201 JSON
Loading

Detailed API Endpoints (Controllers)

MethodEndpointControllerDescriptionAuth/Role
POST/auth/loginAuthControllerJWT tokenpublic
GET/usersUserControllerList institution usersinstitution admin+
PATCH/users/:idUserControllerUpdate rolesuperadmin/admin
DELETE/users/:idUserControllerSoft deleteadmin+
POST/bookingsBookingControllerCreate bookinginstitution user
PATCH/bookings/:id/approveBookingControllerApprove (state trans)faculty+
PATCH/bookings/:id/rejectBookingControllerRejectfaculty+
PATCH/bookings/:id/cancelBookingControllerCancelowner
GET/resourcesResourceControllerList availableuser
POST/resourcesResourceControllerCreate resourceadmin
POST/institutionsInstitutionControllerCreate institutionsuperadmin

Proceed with Development:

  • Extend Booking: Add to BookingService, controller/route method, Prisma field, State transition.
  • New Endpoint: Add controller method, route file new.routes.ts, mount in server.ts.
  • Custom Validation: Domain model method or Factory.
  • Prisma Changes: schema.prisma -> npx prisma generate migrate dev.
  • EventBus Events: Extend handlers in src/events/handlers/ and register in src/app.ts.
  • Testing: Unit (services/domain), E2E (supertest + prisma mock).

Prisma Integration

  • Tenant-aware: Services append {institutionId: actor.institutionId!, deletedAt: null}.
  • Relations: Eager-load (include: {user: true, resource: true}) to avoid N+1.
  • Indexes (recommended): Composite on institutionId + deletedAt, resourceId + startTime.

Design Patterns

Explicit implementations in backend/src/patterns/:

  1. Factory Method (factory/UserFactory.ts):

    • Creates User subclasses (Student, Faculty, Admin) based on role.
    • Validates props, handles polymorphism.
  2. Observer (observer/):

    • BookingSubject.ts: Subject for booking state changes.
    • NotificationObserver.ts: Observer for notifications.
  3. State (state/):

    • BookingState.ts: Abstract base.
    • Concrete: PendingState.ts, ApprovedState.ts, RejectedState.ts, CancelledState.ts.
    • Encapsulates booking lifecycle transitions.
  4. Strategy (strategy/):

    • Conflict resolution for overlapping bookings.
    • StrictConflictStrategy.ts, PriorityConflictStrategy.ts, ConflictStrategy.ts.

Other Patterns:

  • Repository (implicit via Prisma).
  • DTO (mappers).
  • MVC (controllers/routes/services).
  • Singleton/Dependency Injection (services instantiated in controllers).
  • Command (booking create/approve/reject).

Database Schema (ER Diagram)

erDiagram
Institution ||--o{ User : owns
Institution ||--o{ Resource : owns
User ||--o{ Booking : creates
Resource ||--o{ Booking : booked_as
User ||--o{ Notification : receives
Institution {
string id PK
string name UK
string domain
datetime deletedAt
}
User {
string id PK
string email UK
string passwordHash
enum role
string institutionId FK
datetime deletedAt
}
Resource {
string id PK
string name
string type
string description
int capacity
string institutionId FK
boolean isActive
datetime deletedAt
}
Booking {
string id PK
string userId FK
string resourceId FK
datetime startTime
datetime endTime
enum status
}
Notification {
string id PK
string message
boolean isRead
string userId FK
}
Loading

Enums:

  • Role: STUDENT, FACULTY, ADMIN, SUPER_ADMIN
  • BookingStatus: PENDING, APPROVED, REJECTED, CANCELLED

Class Diagram (Key Domain Classes)

classDiagram
class User {
+string id
+string email
+UserRole role
+string? institutionId
+create(props)
}
class Student {
<<extends User>>
}
class Faculty {
<<extends User>>
}
class Admin {
<<extends User>>
}
class UserFactory {
+static User create(UserProps)
}
class BookingState {
<<abstract>>
+handle()
}
class PendingState {
<<extends BookingState>>
}
class ApprovedState {
<<extends BookingState>>
}
class BookingSubject {
+attach(Observer)
+detach(Observer)
+notify()
}
class NotificationObserver {
<<implements Observer>>
+update()
}
class ConflictStrategy {
<<interface>>
+resolve(Booking[])
}
UserFactory ..|> User
User <|-- Student
User <|-- Faculty
User <|-- Admin
BookingState <|-- PendingState : uses
BookingSubject *-- NotificationObserver
ConflictStrategy <|.. StrictConflictStrategy
Loading

API Endpoints (Inferred from Controllers/Routes)

  • Users: GET /users (institution), PATCH /users/:id, DELETE /users/:id (soft).
  • Bookings: POST /bookings, PATCH /bookings/:id/approve|reject|cancel.
  • Resources: CRUD for institution resources.
  • Institutions: Create/manage.
  • EventBus: Pub/sub events for notifications and booking lifecycle.

Frontend Structure

Next.js App Router:

  • src/app/layout.tsx: Root layout (dark mode, CSS variables).
  • src/app/page.tsx: Redirects to /login.
  • (auth)/login|register: Auth pages.
  • (dashboard)/bookings|calendar|resources|users|institutions: Protected dashboard pages. (Note: calendar currently redirects to /bookings.)

Key Technical Details

  • Multi-tenancy: All queries scoped by institutionId from JWT.
  • Security: Role guards in middleware/services, rate-limiting, helmet.
  • Error Handling: DomainError for business rules.
  • Validation: Factory/service level.
  • Soft Deletes: deletedAt timestamps.
  • Dev Workflow: npm run dev (backend: nodemon ts-node server.ts; frontend: next dev).

Potential User Questions (FAQ)

Basic Setup & Usage

  1. How to setup the project locally?

    • Backend: cd backend && npm i, setup .env with DATABASE_URL, npx prisma generate && npx prisma migrate dev, npm run dev.
    • Frontend: cd frontend && npm i, npm run dev.
  2. How to add a new user role (e.g., MAINTENANCE)?

    • Add to Prisma Role enum.
    • Create Maintenance.ts model extending User.
    • Add case in UserFactory.create() switch.
    • Update role guards in middleware/services.
  3. How do booking conflicts get resolved?

    • Service layer uses Strategy pattern (PriorityConflictStrategy etc.) to detect overlaps via Prisma queries.
    • Throws DomainError if unresolved; configurable per institution/role.
  4. How do notifications work?

    • Observer: BookingSubject.notify() triggers NotificationObserver on state changes.
    • EventBus publishes events (BOOKING_CREATED, BOOKING_APPROVED, etc.) to registered handlers (LogHandler, NotificationHandler).

Advanced Technical Questions & Tradeoffs

  1. Why Prisma over raw SQL/Sequelize? Tradeoffs?

    • Pros: Type-safe queries, migrations auto, schema-first (great for TS).
    • Cons: N+1 perf issues (use include/select), less control over complex joins, migration lock-in.
    • Mitigation: Raw queries for perf-critical (e.g., booking overlaps).
  2. Clean Architecture worth the folder complexity?

    • Pros: Testable, decoupled (services pure), scalable for teams.
    • Cons: Boilerplate (mappers/DTOs), overkill for small apps, learning curve.
    • Here: Justified by patterns/multi-tenancy.
  3. State pattern for bookings: Benefits vs simple enum?

    • Pros: Encapsulates transitions (e.g., PENDING->APPROVED only), extensible.
    • Cons: More classes/files vs enum if-checks.
    • Tradeoff: Maintainability wins for complex workflows.
  4. Multi-tenancy via institutionId filtering: Secure/scalable?

    • Pros: Single DB (cost-effective), row-level isolation.
    • Cons: Accidental data leaks if filter missed, perf (index on institutionId).
    • Alt: Schema-per-tenant (complex), DB-per-tenant (expensive).
    • Enforced in services/middleware.
  5. Socket.io vs Server-Sent Events/polling for notifications?

    • Pros: Bidirectional, rooms (per institution), fallback transports.
    • Cons: WebSocket overhead, scaling (Redis adapter needed for prod).
    • Here: Socket.io is installed as a placeholder; currently EventBus handles notifications server-side. WebSocket delivery can be wired later.
  6. Next.js App Router vs Pages Router?

    • Pros: File-based routing, React Server Components (perf), colocation.
    • Cons: Breaking changes, Server Actions learning curve.
    • Tradeoff: Future-proof, but migrate carefully.
  7. FullCalendar: Status and limitations?

    • Status: Installed but not currently active (calendar page redirects to /bookings).
    • Pros: Rich views (timegrid), React integration, customizable.
    • Cons: Client-side (no SSR events), paid for advanced (recurring).
    • Alt: Custom with shadcn/ui + react-big-calendar.
  8. TypeScript strict mode? Enforced?

    • Pros: Catches domain errors early (e.g., role enums).
    • Cons: Verbose (mappers for Prisma raw types).
    • Config: tsconfig strict: true recommended.
  9. Soft deletes: Pros/Cons vs hard delete?

    • Pros: Audit trail, undo possible, GDPR compliance.
    • Cons: DB bloat, perf (index on deletedAt), query complexity (deletedAt IS NULL).
    • Here: Scoped in Prisma relations.
  10. Scaling API: Monolith ok? Microservices?

    • Current: Fine for campus (rate-limit helps).
    • Tradeoff: Microservices (per institution?) add service mesh complexity; stick to monolith + horizontal scale.

Files Structure

CRMS/
├── backend/
│ ├── prisma/schema.prisma (ER)
│ ├── server.ts (Express entry)
│ ├── src/
│ │ ├── app.ts (event handler registration)
│ │ ├── config/ (env, db)
│ │ ├── controllers/*.ts (5 files)
│ │ ├── docs/ (swagger, redoc)
│ │ ├── events/ (EventBus, handlers)
│ │ ├── middleware/ (auth, rate limit, validation, role guards)
│ │ ├── mappers/ (UserMapper, InstitutionMapper)
│ │ ├── models/ (User, Booking, Resource, etc.)
│ │ ├── routes/*.ts (5 files)
│ │ ├── services/ (business logic)
│ │ ├── shared/ (DomainError, query helpers, response, type guards)
│ │ ├── types/ (bcrypt.d.ts)
│ │ ├── validators/ (Zod schemas)
│ │ └── patterns/ (factory/observer/state/strategy)
│ └── socket/ (placeholder)
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx, page.tsx
│ │ │ ├── (auth)/login|register/
│ │ │ ├── (dashboard)/bookings|calendar|resources|users|institutions/
│ │ │ └── pending/
│ │ ├── components/ (layout, ui, dashboard)
│ │ ├── hooks/ (useAuth)
│ │ ├── lib/ (api, cn)
│ │ └── types/ (auth)

About

About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - ElusiveParadox/crms: About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL. · GitHub
Skip to content

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Campus Resource Management System (CRMS) Documentation

Overview

CRMS is a full-stack, multi-tenant application for managing campus resource bookings (e.g., classrooms, labs, auditoriums). It supports role-based access (STUDENT, FACULTY, ADMIN, SUPER_ADMIN), booking workflows with approval/rejection/cancellation, conflict resolution, event-driven notifications, and a dashboard-based UI.

Key Features:

  • Multi-tenancy: Institutions (universities) own users/resources.
  • Secure auth (JWT, bcrypt, role guards).
  • REST API with Swagger docs.
  • Prisma ORM for PostgreSQL with migrations/soft-deletes.
  • Event-driven notifications (EventBus pattern).
  • Booking conflict strategies.
  • Frontend dashboard with booking/resource/user management UI.
  • Role-based access control (STUDENT, FACULTY, ADMIN, SUPER_ADMIN).

Tech Stack

Backend

  • Runtime: Node.js, Express 5, TypeScript
  • Database: PostgreSQL via Prisma 6
  • Auth: JWT 9, bcryptjs
  • Security: helmet, cors, express-rate-limit
  • Real-time: Socket.io 4 (placeholder — not currently wired)
  • Docs: Swagger-jsdoc, redoc-express
  • Dev: nodemon, ts-node

Frontend

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • Styling: TailwindCSS 4, PostCSS
  • UI: Custom dashboard components (FullCalendar 6 installed but not actively used)
  • Networking: Axios, Socket.io-client 4 (placeholder)
  • Linting: ESLint 9, eslint-config-next

Architecture

Clean Architecture / Layered / DDD-inspired:

  • Controllers: Handle HTTP req/res (e.g., UserController, BookingController).
  • Routes: Express routers (auth.routes.ts, booking.routes.ts).
  • Services: Business logic (UserService calls domain models/validators).
  • Models: Domain entities (User subclasses via Factory).
  • Mappers: Domain <-> DTO conversions.
  • Middleware: Auth, validation, etc.
  • Shared: Errors (DomainError), Types. EventBus: In-memory pub/sub for notifications and booking lifecycle events.
  • patterns/: Explicit GoF implementations.

Backend Infrastructure Deep Dive

How Backend Works (Request Flow)

  1. Entry: Express app (server.ts) mounts routes/middleware/Swagger. src/app.ts registers event handlers.
  2. Middleware Pipeline: CORS, rate-limit, helmet, auth (JWT verify + role/institution scope).
  3. Routing: /api/v1/[auth|users|resources|bookings|institutions] -> controller methods.
  4. Controller -> Service: Extract actor (req.user), call service (e.g., bookingService.create(actor, dto)).
  5. Service -> Domain: Validate, use Factory/State/Strategy, map DTO->domain, persist via Prisma.
  6. Domain -> Prisma: Repos/services query with tenant filter (where: {institutionId, deletedAt: null}).
  7. Post-persist: Observer notify -> EventBus publish -> Log/Notification handlers.
  8. Error Handling: DomainError -> standardized JSON error response.

Sequence Diagram: Create Booking

sequenceDiagram
participant Client
participant Controller
participant Service
participant Strategy
participant Prisma
participant Observer
participant EventBus
Client->>Controller: POST /bookings
Controller->>Service: create(actor, dto)
Service->>Factory: create Resource/User domain
Service->>Strategy: resolveConflicts(overlaps)
alt Conflict
Strategy-->>Service: DomainError
Service-->>Controller: 400
else OK
Service->>Prisma: booking.create()
Prisma-->>Service: Booking
Service->>Observer: notify(BookingSubject)
Observer->>EventBus: publish('BOOKING_CREATED', payload)
end
Service-->>Controller: DTO
Controller-->>Client: 201 JSON
Loading

Detailed API Endpoints (Controllers)

MethodEndpointControllerDescriptionAuth/Role
POST/auth/loginAuthControllerJWT tokenpublic
GET/usersUserControllerList institution usersinstitution admin+
PATCH/users/:idUserControllerUpdate rolesuperadmin/admin
DELETE/users/:idUserControllerSoft deleteadmin+
POST/bookingsBookingControllerCreate bookinginstitution user
PATCH/bookings/:id/approveBookingControllerApprove (state trans)faculty+
PATCH/bookings/:id/rejectBookingControllerRejectfaculty+
PATCH/bookings/:id/cancelBookingControllerCancelowner
GET/resourcesResourceControllerList availableuser
POST/resourcesResourceControllerCreate resourceadmin
POST/institutionsInstitutionControllerCreate institutionsuperadmin

Proceed with Development:

  • Extend Booking: Add to BookingService, controller/route method, Prisma field, State transition.
  • New Endpoint: Add controller method, route file new.routes.ts, mount in server.ts.
  • Custom Validation: Domain model method or Factory.
  • Prisma Changes: schema.prisma -> npx prisma generate migrate dev.
  • EventBus Events: Extend handlers in src/events/handlers/ and register in src/app.ts.
  • Testing: Unit (services/domain), E2E (supertest + prisma mock).

Prisma Integration

  • Tenant-aware: Services append {institutionId: actor.institutionId!, deletedAt: null}.
  • Relations: Eager-load (include: {user: true, resource: true}) to avoid N+1.
  • Indexes (recommended): Composite on institutionId + deletedAt, resourceId + startTime.

Design Patterns

Explicit implementations in backend/src/patterns/:

  1. Factory Method (factory/UserFactory.ts):

    • Creates User subclasses (Student, Faculty, Admin) based on role.
    • Validates props, handles polymorphism.
  2. Observer (observer/):

    • BookingSubject.ts: Subject for booking state changes.
    • NotificationObserver.ts: Observer for notifications.
  3. State (state/):

    • BookingState.ts: Abstract base.
    • Concrete: PendingState.ts, ApprovedState.ts, RejectedState.ts, CancelledState.ts.
    • Encapsulates booking lifecycle transitions.
  4. Strategy (strategy/):

    • Conflict resolution for overlapping bookings.
    • StrictConflictStrategy.ts, PriorityConflictStrategy.ts, ConflictStrategy.ts.

Other Patterns:

  • Repository (implicit via Prisma).
  • DTO (mappers).
  • MVC (controllers/routes/services).
  • Singleton/Dependency Injection (services instantiated in controllers).
  • Command (booking create/approve/reject).

Database Schema (ER Diagram)

erDiagram
Institution ||--o{ User : owns
Institution ||--o{ Resource : owns
User ||--o{ Booking : creates
Resource ||--o{ Booking : booked_as
User ||--o{ Notification : receives
Institution {
string id PK
string name UK
string domain
datetime deletedAt
}
User {
string id PK
string email UK
string passwordHash
enum role
string institutionId FK
datetime deletedAt
}
Resource {
string id PK
string name
string type
string description
int capacity
string institutionId FK
boolean isActive
datetime deletedAt
}
Booking {
string id PK
string userId FK
string resourceId FK
datetime startTime
datetime endTime
enum status
}
Notification {
string id PK
string message
boolean isRead
string userId FK
}
Loading

Enums:

  • Role: STUDENT, FACULTY, ADMIN, SUPER_ADMIN
  • BookingStatus: PENDING, APPROVED, REJECTED, CANCELLED

Class Diagram (Key Domain Classes)

classDiagram
class User {
+string id
+string email
+UserRole role
+string? institutionId
+create(props)
}
class Student {
<<extends User>>
}
class Faculty {
<<extends User>>
}
class Admin {
<<extends User>>
}
class UserFactory {
+static User create(UserProps)
}
class BookingState {
<<abstract>>
+handle()
}
class PendingState {
<<extends BookingState>>
}
class ApprovedState {
<<extends BookingState>>
}
class BookingSubject {
+attach(Observer)
+detach(Observer)
+notify()
}
class NotificationObserver {
<<implements Observer>>
+update()
}
class ConflictStrategy {
<<interface>>
+resolve(Booking[])
}
UserFactory ..|> User
User <|-- Student
User <|-- Faculty
User <|-- Admin
BookingState <|-- PendingState : uses
BookingSubject *-- NotificationObserver
ConflictStrategy <|.. StrictConflictStrategy
Loading

API Endpoints (Inferred from Controllers/Routes)

  • Users: GET /users (institution), PATCH /users/:id, DELETE /users/:id (soft).
  • Bookings: POST /bookings, PATCH /bookings/:id/approve|reject|cancel.
  • Resources: CRUD for institution resources.
  • Institutions: Create/manage.
  • EventBus: Pub/sub events for notifications and booking lifecycle.

Frontend Structure

Next.js App Router:

  • src/app/layout.tsx: Root layout (dark mode, CSS variables).
  • src/app/page.tsx: Redirects to /login.
  • (auth)/login|register: Auth pages.
  • (dashboard)/bookings|calendar|resources|users|institutions: Protected dashboard pages. (Note: calendar currently redirects to /bookings.)

Key Technical Details

  • Multi-tenancy: All queries scoped by institutionId from JWT.
  • Security: Role guards in middleware/services, rate-limiting, helmet.
  • Error Handling: DomainError for business rules.
  • Validation: Factory/service level.
  • Soft Deletes: deletedAt timestamps.
  • Dev Workflow: npm run dev (backend: nodemon ts-node server.ts; frontend: next dev).

Potential User Questions (FAQ)

Basic Setup & Usage

  1. How to setup the project locally?

    • Backend: cd backend && npm i, setup .env with DATABASE_URL, npx prisma generate && npx prisma migrate dev, npm run dev.
    • Frontend: cd frontend && npm i, npm run dev.
  2. How to add a new user role (e.g., MAINTENANCE)?

    • Add to Prisma Role enum.
    • Create Maintenance.ts model extending User.
    • Add case in UserFactory.create() switch.
    • Update role guards in middleware/services.
  3. How do booking conflicts get resolved?

    • Service layer uses Strategy pattern (PriorityConflictStrategy etc.) to detect overlaps via Prisma queries.
    • Throws DomainError if unresolved; configurable per institution/role.
  4. How do notifications work?

    • Observer: BookingSubject.notify() triggers NotificationObserver on state changes.
    • EventBus publishes events (BOOKING_CREATED, BOOKING_APPROVED, etc.) to registered handlers (LogHandler, NotificationHandler).

Advanced Technical Questions & Tradeoffs

  1. Why Prisma over raw SQL/Sequelize? Tradeoffs?

    • Pros: Type-safe queries, migrations auto, schema-first (great for TS).
    • Cons: N+1 perf issues (use include/select), less control over complex joins, migration lock-in.
    • Mitigation: Raw queries for perf-critical (e.g., booking overlaps).
  2. Clean Architecture worth the folder complexity?

    • Pros: Testable, decoupled (services pure), scalable for teams.
    • Cons: Boilerplate (mappers/DTOs), overkill for small apps, learning curve.
    • Here: Justified by patterns/multi-tenancy.
  3. State pattern for bookings: Benefits vs simple enum?

    • Pros: Encapsulates transitions (e.g., PENDING->APPROVED only), extensible.
    • Cons: More classes/files vs enum if-checks.
    • Tradeoff: Maintainability wins for complex workflows.
  4. Multi-tenancy via institutionId filtering: Secure/scalable?

    • Pros: Single DB (cost-effective), row-level isolation.
    • Cons: Accidental data leaks if filter missed, perf (index on institutionId).
    • Alt: Schema-per-tenant (complex), DB-per-tenant (expensive).
    • Enforced in services/middleware.
  5. Socket.io vs Server-Sent Events/polling for notifications?

    • Pros: Bidirectional, rooms (per institution), fallback transports.
    • Cons: WebSocket overhead, scaling (Redis adapter needed for prod).
    • Here: Socket.io is installed as a placeholder; currently EventBus handles notifications server-side. WebSocket delivery can be wired later.
  6. Next.js App Router vs Pages Router?

    • Pros: File-based routing, React Server Components (perf), colocation.
    • Cons: Breaking changes, Server Actions learning curve.
    • Tradeoff: Future-proof, but migrate carefully.
  7. FullCalendar: Status and limitations?

    • Status: Installed but not currently active (calendar page redirects to /bookings).
    • Pros: Rich views (timegrid), React integration, customizable.
    • Cons: Client-side (no SSR events), paid for advanced (recurring).
    • Alt: Custom with shadcn/ui + react-big-calendar.
  8. TypeScript strict mode? Enforced?

    • Pros: Catches domain errors early (e.g., role enums).
    • Cons: Verbose (mappers for Prisma raw types).
    • Config: tsconfig strict: true recommended.
  9. Soft deletes: Pros/Cons vs hard delete?

    • Pros: Audit trail, undo possible, GDPR compliance.
    • Cons: DB bloat, perf (index on deletedAt), query complexity (deletedAt IS NULL).
    • Here: Scoped in Prisma relations.
  10. Scaling API: Monolith ok? Microservices?

    • Current: Fine for campus (rate-limit helps).
    • Tradeoff: Microservices (per institution?) add service mesh complexity; stick to monolith + horizontal scale.

Files Structure

CRMS/
├── backend/
│ ├── prisma/schema.prisma (ER)
│ ├── server.ts (Express entry)
│ ├── src/
│ │ ├── app.ts (event handler registration)
│ │ ├── config/ (env, db)
│ │ ├── controllers/*.ts (5 files)
│ │ ├── docs/ (swagger, redoc)
│ │ ├── events/ (EventBus, handlers)
│ │ ├── middleware/ (auth, rate limit, validation, role guards)
│ │ ├── mappers/ (UserMapper, InstitutionMapper)
│ │ ├── models/ (User, Booking, Resource, etc.)
│ │ ├── routes/*.ts (5 files)
│ │ ├── services/ (business logic)
│ │ ├── shared/ (DomainError, query helpers, response, type guards)
│ │ ├── types/ (bcrypt.d.ts)
│ │ ├── validators/ (Zod schemas)
│ │ └── patterns/ (factory/observer/state/strategy)
│ └── socket/ (placeholder)
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx, page.tsx
│ │ │ ├── (auth)/login|register/
│ │ │ ├── (dashboard)/bookings|calendar|resources|users|institutions/
│ │ │ └── pending/
│ │ ├── components/ (layout, ui, dashboard)
│ │ ├── hooks/ (useAuth)
│ │ ├── lib/ (api, cn)
│ │ └── types/ (auth)

About

About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - ElusiveParadox/crms: About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL. · GitHub
Skip to content

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Campus Resource Management System (CRMS) Documentation

Overview

CRMS is a full-stack, multi-tenant application for managing campus resource bookings (e.g., classrooms, labs, auditoriums). It supports role-based access (STUDENT, FACULTY, ADMIN, SUPER_ADMIN), booking workflows with approval/rejection/cancellation, conflict resolution, event-driven notifications, and a dashboard-based UI.

Key Features:

  • Multi-tenancy: Institutions (universities) own users/resources.
  • Secure auth (JWT, bcrypt, role guards).
  • REST API with Swagger docs.
  • Prisma ORM for PostgreSQL with migrations/soft-deletes.
  • Event-driven notifications (EventBus pattern).
  • Booking conflict strategies.
  • Frontend dashboard with booking/resource/user management UI.
  • Role-based access control (STUDENT, FACULTY, ADMIN, SUPER_ADMIN).

Tech Stack

Backend

  • Runtime: Node.js, Express 5, TypeScript
  • Database: PostgreSQL via Prisma 6
  • Auth: JWT 9, bcryptjs
  • Security: helmet, cors, express-rate-limit
  • Real-time: Socket.io 4 (placeholder — not currently wired)
  • Docs: Swagger-jsdoc, redoc-express
  • Dev: nodemon, ts-node

Frontend

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • Styling: TailwindCSS 4, PostCSS
  • UI: Custom dashboard components (FullCalendar 6 installed but not actively used)
  • Networking: Axios, Socket.io-client 4 (placeholder)
  • Linting: ESLint 9, eslint-config-next

Architecture

Clean Architecture / Layered / DDD-inspired:

  • Controllers: Handle HTTP req/res (e.g., UserController, BookingController).
  • Routes: Express routers (auth.routes.ts, booking.routes.ts).
  • Services: Business logic (UserService calls domain models/validators).
  • Models: Domain entities (User subclasses via Factory).
  • Mappers: Domain <-> DTO conversions.
  • Middleware: Auth, validation, etc.
  • Shared: Errors (DomainError), Types. EventBus: In-memory pub/sub for notifications and booking lifecycle events.
  • patterns/: Explicit GoF implementations.

Backend Infrastructure Deep Dive

How Backend Works (Request Flow)

  1. Entry: Express app (server.ts) mounts routes/middleware/Swagger. src/app.ts registers event handlers.
  2. Middleware Pipeline: CORS, rate-limit, helmet, auth (JWT verify + role/institution scope).
  3. Routing: /api/v1/[auth|users|resources|bookings|institutions] -> controller methods.
  4. Controller -> Service: Extract actor (req.user), call service (e.g., bookingService.create(actor, dto)).
  5. Service -> Domain: Validate, use Factory/State/Strategy, map DTO->domain, persist via Prisma.
  6. Domain -> Prisma: Repos/services query with tenant filter (where: {institutionId, deletedAt: null}).
  7. Post-persist: Observer notify -> EventBus publish -> Log/Notification handlers.
  8. Error Handling: DomainError -> standardized JSON error response.

Sequence Diagram: Create Booking

sequenceDiagram
participant Client
participant Controller
participant Service
participant Strategy
participant Prisma
participant Observer
participant EventBus
Client->>Controller: POST /bookings
Controller->>Service: create(actor, dto)
Service->>Factory: create Resource/User domain
Service->>Strategy: resolveConflicts(overlaps)
alt Conflict
Strategy-->>Service: DomainError
Service-->>Controller: 400
else OK
Service->>Prisma: booking.create()
Prisma-->>Service: Booking
Service->>Observer: notify(BookingSubject)
Observer->>EventBus: publish('BOOKING_CREATED', payload)
end
Service-->>Controller: DTO
Controller-->>Client: 201 JSON
Loading

Detailed API Endpoints (Controllers)

MethodEndpointControllerDescriptionAuth/Role
POST/auth/loginAuthControllerJWT tokenpublic
GET/usersUserControllerList institution usersinstitution admin+
PATCH/users/:idUserControllerUpdate rolesuperadmin/admin
DELETE/users/:idUserControllerSoft deleteadmin+
POST/bookingsBookingControllerCreate bookinginstitution user
PATCH/bookings/:id/approveBookingControllerApprove (state trans)faculty+
PATCH/bookings/:id/rejectBookingControllerRejectfaculty+
PATCH/bookings/:id/cancelBookingControllerCancelowner
GET/resourcesResourceControllerList availableuser
POST/resourcesResourceControllerCreate resourceadmin
POST/institutionsInstitutionControllerCreate institutionsuperadmin

Proceed with Development:

  • Extend Booking: Add to BookingService, controller/route method, Prisma field, State transition.
  • New Endpoint: Add controller method, route file new.routes.ts, mount in server.ts.
  • Custom Validation: Domain model method or Factory.
  • Prisma Changes: schema.prisma -> npx prisma generate migrate dev.
  • EventBus Events: Extend handlers in src/events/handlers/ and register in src/app.ts.
  • Testing: Unit (services/domain), E2E (supertest + prisma mock).

Prisma Integration

  • Tenant-aware: Services append {institutionId: actor.institutionId!, deletedAt: null}.
  • Relations: Eager-load (include: {user: true, resource: true}) to avoid N+1.
  • Indexes (recommended): Composite on institutionId + deletedAt, resourceId + startTime.

Design Patterns

Explicit implementations in backend/src/patterns/:

  1. Factory Method (factory/UserFactory.ts):

    • Creates User subclasses (Student, Faculty, Admin) based on role.
    • Validates props, handles polymorphism.
  2. Observer (observer/):

    • BookingSubject.ts: Subject for booking state changes.
    • NotificationObserver.ts: Observer for notifications.
  3. State (state/):

    • BookingState.ts: Abstract base.
    • Concrete: PendingState.ts, ApprovedState.ts, RejectedState.ts, CancelledState.ts.
    • Encapsulates booking lifecycle transitions.
  4. Strategy (strategy/):

    • Conflict resolution for overlapping bookings.
    • StrictConflictStrategy.ts, PriorityConflictStrategy.ts, ConflictStrategy.ts.

Other Patterns:

  • Repository (implicit via Prisma).
  • DTO (mappers).
  • MVC (controllers/routes/services).
  • Singleton/Dependency Injection (services instantiated in controllers).
  • Command (booking create/approve/reject).

Database Schema (ER Diagram)

erDiagram
Institution ||--o{ User : owns
Institution ||--o{ Resource : owns
User ||--o{ Booking : creates
Resource ||--o{ Booking : booked_as
User ||--o{ Notification : receives
Institution {
string id PK
string name UK
string domain
datetime deletedAt
}
User {
string id PK
string email UK
string passwordHash
enum role
string institutionId FK
datetime deletedAt
}
Resource {
string id PK
string name
string type
string description
int capacity
string institutionId FK
boolean isActive
datetime deletedAt
}
Booking {
string id PK
string userId FK
string resourceId FK
datetime startTime
datetime endTime
enum status
}
Notification {
string id PK
string message
boolean isRead
string userId FK
}
Loading

Enums:

  • Role: STUDENT, FACULTY, ADMIN, SUPER_ADMIN
  • BookingStatus: PENDING, APPROVED, REJECTED, CANCELLED

Class Diagram (Key Domain Classes)

classDiagram
class User {
+string id
+string email
+UserRole role
+string? institutionId
+create(props)
}
class Student {
<<extends User>>
}
class Faculty {
<<extends User>>
}
class Admin {
<<extends User>>
}
class UserFactory {
+static User create(UserProps)
}
class BookingState {
<<abstract>>
+handle()
}
class PendingState {
<<extends BookingState>>
}
class ApprovedState {
<<extends BookingState>>
}
class BookingSubject {
+attach(Observer)
+detach(Observer)
+notify()
}
class NotificationObserver {
<<implements Observer>>
+update()
}
class ConflictStrategy {
<<interface>>
+resolve(Booking[])
}
UserFactory ..|> User
User <|-- Student
User <|-- Faculty
User <|-- Admin
BookingState <|-- PendingState : uses
BookingSubject *-- NotificationObserver
ConflictStrategy <|.. StrictConflictStrategy
Loading

API Endpoints (Inferred from Controllers/Routes)

  • Users: GET /users (institution), PATCH /users/:id, DELETE /users/:id (soft).
  • Bookings: POST /bookings, PATCH /bookings/:id/approve|reject|cancel.
  • Resources: CRUD for institution resources.
  • Institutions: Create/manage.
  • EventBus: Pub/sub events for notifications and booking lifecycle.

Frontend Structure

Next.js App Router:

  • src/app/layout.tsx: Root layout (dark mode, CSS variables).
  • src/app/page.tsx: Redirects to /login.
  • (auth)/login|register: Auth pages.
  • (dashboard)/bookings|calendar|resources|users|institutions: Protected dashboard pages. (Note: calendar currently redirects to /bookings.)

Key Technical Details

  • Multi-tenancy: All queries scoped by institutionId from JWT.
  • Security: Role guards in middleware/services, rate-limiting, helmet.
  • Error Handling: DomainError for business rules.
  • Validation: Factory/service level.
  • Soft Deletes: deletedAt timestamps.
  • Dev Workflow: npm run dev (backend: nodemon ts-node server.ts; frontend: next dev).

Potential User Questions (FAQ)

Basic Setup & Usage

  1. How to setup the project locally?

    • Backend: cd backend && npm i, setup .env with DATABASE_URL, npx prisma generate && npx prisma migrate dev, npm run dev.
    • Frontend: cd frontend && npm i, npm run dev.
  2. How to add a new user role (e.g., MAINTENANCE)?

    • Add to Prisma Role enum.
    • Create Maintenance.ts model extending User.
    • Add case in UserFactory.create() switch.
    • Update role guards in middleware/services.
  3. How do booking conflicts get resolved?

    • Service layer uses Strategy pattern (PriorityConflictStrategy etc.) to detect overlaps via Prisma queries.
    • Throws DomainError if unresolved; configurable per institution/role.
  4. How do notifications work?

    • Observer: BookingSubject.notify() triggers NotificationObserver on state changes.
    • EventBus publishes events (BOOKING_CREATED, BOOKING_APPROVED, etc.) to registered handlers (LogHandler, NotificationHandler).

Advanced Technical Questions & Tradeoffs

  1. Why Prisma over raw SQL/Sequelize? Tradeoffs?

    • Pros: Type-safe queries, migrations auto, schema-first (great for TS).
    • Cons: N+1 perf issues (use include/select), less control over complex joins, migration lock-in.
    • Mitigation: Raw queries for perf-critical (e.g., booking overlaps).
  2. Clean Architecture worth the folder complexity?

    • Pros: Testable, decoupled (services pure), scalable for teams.
    • Cons: Boilerplate (mappers/DTOs), overkill for small apps, learning curve.
    • Here: Justified by patterns/multi-tenancy.
  3. State pattern for bookings: Benefits vs simple enum?

    • Pros: Encapsulates transitions (e.g., PENDING->APPROVED only), extensible.
    • Cons: More classes/files vs enum if-checks.
    • Tradeoff: Maintainability wins for complex workflows.
  4. Multi-tenancy via institutionId filtering: Secure/scalable?

    • Pros: Single DB (cost-effective), row-level isolation.
    • Cons: Accidental data leaks if filter missed, perf (index on institutionId).
    • Alt: Schema-per-tenant (complex), DB-per-tenant (expensive).
    • Enforced in services/middleware.
  5. Socket.io vs Server-Sent Events/polling for notifications?

    • Pros: Bidirectional, rooms (per institution), fallback transports.
    • Cons: WebSocket overhead, scaling (Redis adapter needed for prod).
    • Here: Socket.io is installed as a placeholder; currently EventBus handles notifications server-side. WebSocket delivery can be wired later.
  6. Next.js App Router vs Pages Router?

    • Pros: File-based routing, React Server Components (perf), colocation.
    • Cons: Breaking changes, Server Actions learning curve.
    • Tradeoff: Future-proof, but migrate carefully.
  7. FullCalendar: Status and limitations?

    • Status: Installed but not currently active (calendar page redirects to /bookings).
    • Pros: Rich views (timegrid), React integration, customizable.
    • Cons: Client-side (no SSR events), paid for advanced (recurring).
    • Alt: Custom with shadcn/ui + react-big-calendar.
  8. TypeScript strict mode? Enforced?

    • Pros: Catches domain errors early (e.g., role enums).
    • Cons: Verbose (mappers for Prisma raw types).
    • Config: tsconfig strict: true recommended.
  9. Soft deletes: Pros/Cons vs hard delete?

    • Pros: Audit trail, undo possible, GDPR compliance.
    • Cons: DB bloat, perf (index on deletedAt), query complexity (deletedAt IS NULL).
    • Here: Scoped in Prisma relations.
  10. Scaling API: Monolith ok? Microservices?

    • Current: Fine for campus (rate-limit helps).
    • Tradeoff: Microservices (per institution?) add service mesh complexity; stick to monolith + horizontal scale.

Files Structure

CRMS/
├── backend/
│ ├── prisma/schema.prisma (ER)
│ ├── server.ts (Express entry)
│ ├── src/
│ │ ├── app.ts (event handler registration)
│ │ ├── config/ (env, db)
│ │ ├── controllers/*.ts (5 files)
│ │ ├── docs/ (swagger, redoc)
│ │ ├── events/ (EventBus, handlers)
│ │ ├── middleware/ (auth, rate limit, validation, role guards)
│ │ ├── mappers/ (UserMapper, InstitutionMapper)
│ │ ├── models/ (User, Booking, Resource, etc.)
│ │ ├── routes/*.ts (5 files)
│ │ ├── services/ (business logic)
│ │ ├── shared/ (DomainError, query helpers, response, type guards)
│ │ ├── types/ (bcrypt.d.ts)
│ │ ├── validators/ (Zod schemas)
│ │ └── patterns/ (factory/observer/state/strategy)
│ └── socket/ (placeholder)
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx, page.tsx
│ │ │ ├── (auth)/login|register/
│ │ │ ├── (dashboard)/bookings|calendar|resources|users|institutions/
│ │ │ └── pending/
│ │ ├── components/ (layout, ui, dashboard)
│ │ ├── hooks/ (useAuth)
│ │ ├── lib/ (api, cn)
│ │ └── types/ (auth)

About

About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - ElusiveParadox/crms: About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL. · GitHub
Skip to content

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Campus Resource Management System (CRMS) Documentation

Overview

CRMS is a full-stack, multi-tenant application for managing campus resource bookings (e.g., classrooms, labs, auditoriums). It supports role-based access (STUDENT, FACULTY, ADMIN, SUPER_ADMIN), booking workflows with approval/rejection/cancellation, conflict resolution, event-driven notifications, and a dashboard-based UI.

Key Features:

  • Multi-tenancy: Institutions (universities) own users/resources.
  • Secure auth (JWT, bcrypt, role guards).
  • REST API with Swagger docs.
  • Prisma ORM for PostgreSQL with migrations/soft-deletes.
  • Event-driven notifications (EventBus pattern).
  • Booking conflict strategies.
  • Frontend dashboard with booking/resource/user management UI.
  • Role-based access control (STUDENT, FACULTY, ADMIN, SUPER_ADMIN).

Tech Stack

Backend

  • Runtime: Node.js, Express 5, TypeScript
  • Database: PostgreSQL via Prisma 6
  • Auth: JWT 9, bcryptjs
  • Security: helmet, cors, express-rate-limit
  • Real-time: Socket.io 4 (placeholder — not currently wired)
  • Docs: Swagger-jsdoc, redoc-express
  • Dev: nodemon, ts-node

Frontend

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • Styling: TailwindCSS 4, PostCSS
  • UI: Custom dashboard components (FullCalendar 6 installed but not actively used)
  • Networking: Axios, Socket.io-client 4 (placeholder)
  • Linting: ESLint 9, eslint-config-next

Architecture

Clean Architecture / Layered / DDD-inspired:

  • Controllers: Handle HTTP req/res (e.g., UserController, BookingController).
  • Routes: Express routers (auth.routes.ts, booking.routes.ts).
  • Services: Business logic (UserService calls domain models/validators).
  • Models: Domain entities (User subclasses via Factory).
  • Mappers: Domain <-> DTO conversions.
  • Middleware: Auth, validation, etc.
  • Shared: Errors (DomainError), Types. EventBus: In-memory pub/sub for notifications and booking lifecycle events.
  • patterns/: Explicit GoF implementations.

Backend Infrastructure Deep Dive

How Backend Works (Request Flow)

  1. Entry: Express app (server.ts) mounts routes/middleware/Swagger. src/app.ts registers event handlers.
  2. Middleware Pipeline: CORS, rate-limit, helmet, auth (JWT verify + role/institution scope).
  3. Routing: /api/v1/[auth|users|resources|bookings|institutions] -> controller methods.
  4. Controller -> Service: Extract actor (req.user), call service (e.g., bookingService.create(actor, dto)).
  5. Service -> Domain: Validate, use Factory/State/Strategy, map DTO->domain, persist via Prisma.
  6. Domain -> Prisma: Repos/services query with tenant filter (where: {institutionId, deletedAt: null}).
  7. Post-persist: Observer notify -> EventBus publish -> Log/Notification handlers.
  8. Error Handling: DomainError -> standardized JSON error response.

Sequence Diagram: Create Booking

sequenceDiagram
participant Client
participant Controller
participant Service
participant Strategy
participant Prisma
participant Observer
participant EventBus
Client->>Controller: POST /bookings
Controller->>Service: create(actor, dto)
Service->>Factory: create Resource/User domain
Service->>Strategy: resolveConflicts(overlaps)
alt Conflict
Strategy-->>Service: DomainError
Service-->>Controller: 400
else OK
Service->>Prisma: booking.create()
Prisma-->>Service: Booking
Service->>Observer: notify(BookingSubject)
Observer->>EventBus: publish('BOOKING_CREATED', payload)
end
Service-->>Controller: DTO
Controller-->>Client: 201 JSON
Loading

Detailed API Endpoints (Controllers)

MethodEndpointControllerDescriptionAuth/Role
POST/auth/loginAuthControllerJWT tokenpublic
GET/usersUserControllerList institution usersinstitution admin+
PATCH/users/:idUserControllerUpdate rolesuperadmin/admin
DELETE/users/:idUserControllerSoft deleteadmin+
POST/bookingsBookingControllerCreate bookinginstitution user
PATCH/bookings/:id/approveBookingControllerApprove (state trans)faculty+
PATCH/bookings/:id/rejectBookingControllerRejectfaculty+
PATCH/bookings/:id/cancelBookingControllerCancelowner
GET/resourcesResourceControllerList availableuser
POST/resourcesResourceControllerCreate resourceadmin
POST/institutionsInstitutionControllerCreate institutionsuperadmin

Proceed with Development:

  • Extend Booking: Add to BookingService, controller/route method, Prisma field, State transition.
  • New Endpoint: Add controller method, route file new.routes.ts, mount in server.ts.
  • Custom Validation: Domain model method or Factory.
  • Prisma Changes: schema.prisma -> npx prisma generate migrate dev.
  • EventBus Events: Extend handlers in src/events/handlers/ and register in src/app.ts.
  • Testing: Unit (services/domain), E2E (supertest + prisma mock).

Prisma Integration

  • Tenant-aware: Services append {institutionId: actor.institutionId!, deletedAt: null}.
  • Relations: Eager-load (include: {user: true, resource: true}) to avoid N+1.
  • Indexes (recommended): Composite on institutionId + deletedAt, resourceId + startTime.

Design Patterns

Explicit implementations in backend/src/patterns/:

  1. Factory Method (factory/UserFactory.ts):

    • Creates User subclasses (Student, Faculty, Admin) based on role.
    • Validates props, handles polymorphism.
  2. Observer (observer/):

    • BookingSubject.ts: Subject for booking state changes.
    • NotificationObserver.ts: Observer for notifications.
  3. State (state/):

    • BookingState.ts: Abstract base.
    • Concrete: PendingState.ts, ApprovedState.ts, RejectedState.ts, CancelledState.ts.
    • Encapsulates booking lifecycle transitions.
  4. Strategy (strategy/):

    • Conflict resolution for overlapping bookings.
    • StrictConflictStrategy.ts, PriorityConflictStrategy.ts, ConflictStrategy.ts.

Other Patterns:

  • Repository (implicit via Prisma).
  • DTO (mappers).
  • MVC (controllers/routes/services).
  • Singleton/Dependency Injection (services instantiated in controllers).
  • Command (booking create/approve/reject).

Database Schema (ER Diagram)

erDiagram
Institution ||--o{ User : owns
Institution ||--o{ Resource : owns
User ||--o{ Booking : creates
Resource ||--o{ Booking : booked_as
User ||--o{ Notification : receives
Institution {
string id PK
string name UK
string domain
datetime deletedAt
}
User {
string id PK
string email UK
string passwordHash
enum role
string institutionId FK
datetime deletedAt
}
Resource {
string id PK
string name
string type
string description
int capacity
string institutionId FK
boolean isActive
datetime deletedAt
}
Booking {
string id PK
string userId FK
string resourceId FK
datetime startTime
datetime endTime
enum status
}
Notification {
string id PK
string message
boolean isRead
string userId FK
}
Loading

Enums:

  • Role: STUDENT, FACULTY, ADMIN, SUPER_ADMIN
  • BookingStatus: PENDING, APPROVED, REJECTED, CANCELLED

Class Diagram (Key Domain Classes)

classDiagram
class User {
+string id
+string email
+UserRole role
+string? institutionId
+create(props)
}
class Student {
<<extends User>>
}
class Faculty {
<<extends User>>
}
class Admin {
<<extends User>>
}
class UserFactory {
+static User create(UserProps)
}
class BookingState {
<<abstract>>
+handle()
}
class PendingState {
<<extends BookingState>>
}
class ApprovedState {
<<extends BookingState>>
}
class BookingSubject {
+attach(Observer)
+detach(Observer)
+notify()
}
class NotificationObserver {
<<implements Observer>>
+update()
}
class ConflictStrategy {
<<interface>>
+resolve(Booking[])
}
UserFactory ..|> User
User <|-- Student
User <|-- Faculty
User <|-- Admin
BookingState <|-- PendingState : uses
BookingSubject *-- NotificationObserver
ConflictStrategy <|.. StrictConflictStrategy
Loading

API Endpoints (Inferred from Controllers/Routes)

  • Users: GET /users (institution), PATCH /users/:id, DELETE /users/:id (soft).
  • Bookings: POST /bookings, PATCH /bookings/:id/approve|reject|cancel.
  • Resources: CRUD for institution resources.
  • Institutions: Create/manage.
  • EventBus: Pub/sub events for notifications and booking lifecycle.

Frontend Structure

Next.js App Router:

  • src/app/layout.tsx: Root layout (dark mode, CSS variables).
  • src/app/page.tsx: Redirects to /login.
  • (auth)/login|register: Auth pages.
  • (dashboard)/bookings|calendar|resources|users|institutions: Protected dashboard pages. (Note: calendar currently redirects to /bookings.)

Key Technical Details

  • Multi-tenancy: All queries scoped by institutionId from JWT.
  • Security: Role guards in middleware/services, rate-limiting, helmet.
  • Error Handling: DomainError for business rules.
  • Validation: Factory/service level.
  • Soft Deletes: deletedAt timestamps.
  • Dev Workflow: npm run dev (backend: nodemon ts-node server.ts; frontend: next dev).

Potential User Questions (FAQ)

Basic Setup & Usage

  1. How to setup the project locally?

    • Backend: cd backend && npm i, setup .env with DATABASE_URL, npx prisma generate && npx prisma migrate dev, npm run dev.
    • Frontend: cd frontend && npm i, npm run dev.
  2. How to add a new user role (e.g., MAINTENANCE)?

    • Add to Prisma Role enum.
    • Create Maintenance.ts model extending User.
    • Add case in UserFactory.create() switch.
    • Update role guards in middleware/services.
  3. How do booking conflicts get resolved?

    • Service layer uses Strategy pattern (PriorityConflictStrategy etc.) to detect overlaps via Prisma queries.
    • Throws DomainError if unresolved; configurable per institution/role.
  4. How do notifications work?

    • Observer: BookingSubject.notify() triggers NotificationObserver on state changes.
    • EventBus publishes events (BOOKING_CREATED, BOOKING_APPROVED, etc.) to registered handlers (LogHandler, NotificationHandler).

Advanced Technical Questions & Tradeoffs

  1. Why Prisma over raw SQL/Sequelize? Tradeoffs?

    • Pros: Type-safe queries, migrations auto, schema-first (great for TS).
    • Cons: N+1 perf issues (use include/select), less control over complex joins, migration lock-in.
    • Mitigation: Raw queries for perf-critical (e.g., booking overlaps).
  2. Clean Architecture worth the folder complexity?

    • Pros: Testable, decoupled (services pure), scalable for teams.
    • Cons: Boilerplate (mappers/DTOs), overkill for small apps, learning curve.
    • Here: Justified by patterns/multi-tenancy.
  3. State pattern for bookings: Benefits vs simple enum?

    • Pros: Encapsulates transitions (e.g., PENDING->APPROVED only), extensible.
    • Cons: More classes/files vs enum if-checks.
    • Tradeoff: Maintainability wins for complex workflows.
  4. Multi-tenancy via institutionId filtering: Secure/scalable?

    • Pros: Single DB (cost-effective), row-level isolation.
    • Cons: Accidental data leaks if filter missed, perf (index on institutionId).
    • Alt: Schema-per-tenant (complex), DB-per-tenant (expensive).
    • Enforced in services/middleware.
  5. Socket.io vs Server-Sent Events/polling for notifications?

    • Pros: Bidirectional, rooms (per institution), fallback transports.
    • Cons: WebSocket overhead, scaling (Redis adapter needed for prod).
    • Here: Socket.io is installed as a placeholder; currently EventBus handles notifications server-side. WebSocket delivery can be wired later.
  6. Next.js App Router vs Pages Router?

    • Pros: File-based routing, React Server Components (perf), colocation.
    • Cons: Breaking changes, Server Actions learning curve.
    • Tradeoff: Future-proof, but migrate carefully.
  7. FullCalendar: Status and limitations?

    • Status: Installed but not currently active (calendar page redirects to /bookings).
    • Pros: Rich views (timegrid), React integration, customizable.
    • Cons: Client-side (no SSR events), paid for advanced (recurring).
    • Alt: Custom with shadcn/ui + react-big-calendar.
  8. TypeScript strict mode? Enforced?

    • Pros: Catches domain errors early (e.g., role enums).
    • Cons: Verbose (mappers for Prisma raw types).
    • Config: tsconfig strict: true recommended.
  9. Soft deletes: Pros/Cons vs hard delete?

    • Pros: Audit trail, undo possible, GDPR compliance.
    • Cons: DB bloat, perf (index on deletedAt), query complexity (deletedAt IS NULL).
    • Here: Scoped in Prisma relations.
  10. Scaling API: Monolith ok? Microservices?

    • Current: Fine for campus (rate-limit helps).
    • Tradeoff: Microservices (per institution?) add service mesh complexity; stick to monolith + horizontal scale.

Files Structure

CRMS/
├── backend/
│ ├── prisma/schema.prisma (ER)
│ ├── server.ts (Express entry)
│ ├── src/
│ │ ├── app.ts (event handler registration)
│ │ ├── config/ (env, db)
│ │ ├── controllers/*.ts (5 files)
│ │ ├── docs/ (swagger, redoc)
│ │ ├── events/ (EventBus, handlers)
│ │ ├── middleware/ (auth, rate limit, validation, role guards)
│ │ ├── mappers/ (UserMapper, InstitutionMapper)
│ │ ├── models/ (User, Booking, Resource, etc.)
│ │ ├── routes/*.ts (5 files)
│ │ ├── services/ (business logic)
│ │ ├── shared/ (DomainError, query helpers, response, type guards)
│ │ ├── types/ (bcrypt.d.ts)
│ │ ├── validators/ (Zod schemas)
│ │ └── patterns/ (factory/observer/state/strategy)
│ └── socket/ (placeholder)
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx, page.tsx
│ │ │ ├── (auth)/login|register/
│ │ │ ├── (dashboard)/bookings|calendar|resources|users|institutions/
│ │ │ └── pending/
│ │ ├── components/ (layout, ui, dashboard)
│ │ ├── hooks/ (useAuth)
│ │ ├── lib/ (api, cn)
│ │ └── types/ (auth)

About

About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - ElusiveParadox/crms: About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL. · GitHub
Skip to content

Latest commit

History

17 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Campus Resource Management System (CRMS) Documentation

Overview

CRMS is a full-stack, multi-tenant application for managing campus resource bookings (e.g., classrooms, labs, auditoriums). It supports role-based access (STUDENT, FACULTY, ADMIN, SUPER_ADMIN), booking workflows with approval/rejection/cancellation, conflict resolution, event-driven notifications, and a dashboard-based UI.

Key Features:

  • Multi-tenancy: Institutions (universities) own users/resources.
  • Secure auth (JWT, bcrypt, role guards).
  • REST API with Swagger docs.
  • Prisma ORM for PostgreSQL with migrations/soft-deletes.
  • Event-driven notifications (EventBus pattern).
  • Booking conflict strategies.
  • Frontend dashboard with booking/resource/user management UI.
  • Role-based access control (STUDENT, FACULTY, ADMIN, SUPER_ADMIN).

Tech Stack

Backend

  • Runtime: Node.js, Express 5, TypeScript
  • Database: PostgreSQL via Prisma 6
  • Auth: JWT 9, bcryptjs
  • Security: helmet, cors, express-rate-limit
  • Real-time: Socket.io 4 (placeholder — not currently wired)
  • Docs: Swagger-jsdoc, redoc-express
  • Dev: nodemon, ts-node

Frontend

  • Framework: Next.js 16 (App Router), React 19, TypeScript
  • Styling: TailwindCSS 4, PostCSS
  • UI: Custom dashboard components (FullCalendar 6 installed but not actively used)
  • Networking: Axios, Socket.io-client 4 (placeholder)
  • Linting: ESLint 9, eslint-config-next

Architecture

Clean Architecture / Layered / DDD-inspired:

  • Controllers: Handle HTTP req/res (e.g., UserController, BookingController).
  • Routes: Express routers (auth.routes.ts, booking.routes.ts).
  • Services: Business logic (UserService calls domain models/validators).
  • Models: Domain entities (User subclasses via Factory).
  • Mappers: Domain <-> DTO conversions.
  • Middleware: Auth, validation, etc.
  • Shared: Errors (DomainError), Types. EventBus: In-memory pub/sub for notifications and booking lifecycle events.
  • patterns/: Explicit GoF implementations.

Backend Infrastructure Deep Dive

How Backend Works (Request Flow)

  1. Entry: Express app (server.ts) mounts routes/middleware/Swagger. src/app.ts registers event handlers.
  2. Middleware Pipeline: CORS, rate-limit, helmet, auth (JWT verify + role/institution scope).
  3. Routing: /api/v1/[auth|users|resources|bookings|institutions] -> controller methods.
  4. Controller -> Service: Extract actor (req.user), call service (e.g., bookingService.create(actor, dto)).
  5. Service -> Domain: Validate, use Factory/State/Strategy, map DTO->domain, persist via Prisma.
  6. Domain -> Prisma: Repos/services query with tenant filter (where: {institutionId, deletedAt: null}).
  7. Post-persist: Observer notify -> EventBus publish -> Log/Notification handlers.
  8. Error Handling: DomainError -> standardized JSON error response.

Sequence Diagram: Create Booking

sequenceDiagram
participant Client
participant Controller
participant Service
participant Strategy
participant Prisma
participant Observer
participant EventBus
Client->>Controller: POST /bookings
Controller->>Service: create(actor, dto)
Service->>Factory: create Resource/User domain
Service->>Strategy: resolveConflicts(overlaps)
alt Conflict
Strategy-->>Service: DomainError
Service-->>Controller: 400
else OK
Service->>Prisma: booking.create()
Prisma-->>Service: Booking
Service->>Observer: notify(BookingSubject)
Observer->>EventBus: publish('BOOKING_CREATED', payload)
end
Service-->>Controller: DTO
Controller-->>Client: 201 JSON
Loading

Detailed API Endpoints (Controllers)

MethodEndpointControllerDescriptionAuth/Role
POST/auth/loginAuthControllerJWT tokenpublic
GET/usersUserControllerList institution usersinstitution admin+
PATCH/users/:idUserControllerUpdate rolesuperadmin/admin
DELETE/users/:idUserControllerSoft deleteadmin+
POST/bookingsBookingControllerCreate bookinginstitution user
PATCH/bookings/:id/approveBookingControllerApprove (state trans)faculty+
PATCH/bookings/:id/rejectBookingControllerRejectfaculty+
PATCH/bookings/:id/cancelBookingControllerCancelowner
GET/resourcesResourceControllerList availableuser
POST/resourcesResourceControllerCreate resourceadmin
POST/institutionsInstitutionControllerCreate institutionsuperadmin

Proceed with Development:

  • Extend Booking: Add to BookingService, controller/route method, Prisma field, State transition.
  • New Endpoint: Add controller method, route file new.routes.ts, mount in server.ts.
  • Custom Validation: Domain model method or Factory.
  • Prisma Changes: schema.prisma -> npx prisma generate migrate dev.
  • EventBus Events: Extend handlers in src/events/handlers/ and register in src/app.ts.
  • Testing: Unit (services/domain), E2E (supertest + prisma mock).

Prisma Integration

  • Tenant-aware: Services append {institutionId: actor.institutionId!, deletedAt: null}.
  • Relations: Eager-load (include: {user: true, resource: true}) to avoid N+1.
  • Indexes (recommended): Composite on institutionId + deletedAt, resourceId + startTime.

Design Patterns

Explicit implementations in backend/src/patterns/:

  1. Factory Method (factory/UserFactory.ts):

    • Creates User subclasses (Student, Faculty, Admin) based on role.
    • Validates props, handles polymorphism.
  2. Observer (observer/):

    • BookingSubject.ts: Subject for booking state changes.
    • NotificationObserver.ts: Observer for notifications.
  3. State (state/):

    • BookingState.ts: Abstract base.
    • Concrete: PendingState.ts, ApprovedState.ts, RejectedState.ts, CancelledState.ts.
    • Encapsulates booking lifecycle transitions.
  4. Strategy (strategy/):

    • Conflict resolution for overlapping bookings.
    • StrictConflictStrategy.ts, PriorityConflictStrategy.ts, ConflictStrategy.ts.

Other Patterns:

  • Repository (implicit via Prisma).
  • DTO (mappers).
  • MVC (controllers/routes/services).
  • Singleton/Dependency Injection (services instantiated in controllers).
  • Command (booking create/approve/reject).

Database Schema (ER Diagram)

erDiagram
Institution ||--o{ User : owns
Institution ||--o{ Resource : owns
User ||--o{ Booking : creates
Resource ||--o{ Booking : booked_as
User ||--o{ Notification : receives
Institution {
string id PK
string name UK
string domain
datetime deletedAt
}
User {
string id PK
string email UK
string passwordHash
enum role
string institutionId FK
datetime deletedAt
}
Resource {
string id PK
string name
string type
string description
int capacity
string institutionId FK
boolean isActive
datetime deletedAt
}
Booking {
string id PK
string userId FK
string resourceId FK
datetime startTime
datetime endTime
enum status
}
Notification {
string id PK
string message
boolean isRead
string userId FK
}
Loading

Enums:

  • Role: STUDENT, FACULTY, ADMIN, SUPER_ADMIN
  • BookingStatus: PENDING, APPROVED, REJECTED, CANCELLED

Class Diagram (Key Domain Classes)

classDiagram
class User {
+string id
+string email
+UserRole role
+string? institutionId
+create(props)
}
class Student {
<<extends User>>
}
class Faculty {
<<extends User>>
}
class Admin {
<<extends User>>
}
class UserFactory {
+static User create(UserProps)
}
class BookingState {
<<abstract>>
+handle()
}
class PendingState {
<<extends BookingState>>
}
class ApprovedState {
<<extends BookingState>>
}
class BookingSubject {
+attach(Observer)
+detach(Observer)
+notify()
}
class NotificationObserver {
<<implements Observer>>
+update()
}
class ConflictStrategy {
<<interface>>
+resolve(Booking[])
}
UserFactory ..|> User
User <|-- Student
User <|-- Faculty
User <|-- Admin
BookingState <|-- PendingState : uses
BookingSubject *-- NotificationObserver
ConflictStrategy <|.. StrictConflictStrategy
Loading

API Endpoints (Inferred from Controllers/Routes)

  • Users: GET /users (institution), PATCH /users/:id, DELETE /users/:id (soft).
  • Bookings: POST /bookings, PATCH /bookings/:id/approve|reject|cancel.
  • Resources: CRUD for institution resources.
  • Institutions: Create/manage.
  • EventBus: Pub/sub events for notifications and booking lifecycle.

Frontend Structure

Next.js App Router:

  • src/app/layout.tsx: Root layout (dark mode, CSS variables).
  • src/app/page.tsx: Redirects to /login.
  • (auth)/login|register: Auth pages.
  • (dashboard)/bookings|calendar|resources|users|institutions: Protected dashboard pages. (Note: calendar currently redirects to /bookings.)

Key Technical Details

  • Multi-tenancy: All queries scoped by institutionId from JWT.
  • Security: Role guards in middleware/services, rate-limiting, helmet.
  • Error Handling: DomainError for business rules.
  • Validation: Factory/service level.
  • Soft Deletes: deletedAt timestamps.
  • Dev Workflow: npm run dev (backend: nodemon ts-node server.ts; frontend: next dev).

Potential User Questions (FAQ)

Basic Setup & Usage

  1. How to setup the project locally?

    • Backend: cd backend && npm i, setup .env with DATABASE_URL, npx prisma generate && npx prisma migrate dev, npm run dev.
    • Frontend: cd frontend && npm i, npm run dev.
  2. How to add a new user role (e.g., MAINTENANCE)?

    • Add to Prisma Role enum.
    • Create Maintenance.ts model extending User.
    • Add case in UserFactory.create() switch.
    • Update role guards in middleware/services.
  3. How do booking conflicts get resolved?

    • Service layer uses Strategy pattern (PriorityConflictStrategy etc.) to detect overlaps via Prisma queries.
    • Throws DomainError if unresolved; configurable per institution/role.
  4. How do notifications work?

    • Observer: BookingSubject.notify() triggers NotificationObserver on state changes.
    • EventBus publishes events (BOOKING_CREATED, BOOKING_APPROVED, etc.) to registered handlers (LogHandler, NotificationHandler).

Advanced Technical Questions & Tradeoffs

  1. Why Prisma over raw SQL/Sequelize? Tradeoffs?

    • Pros: Type-safe queries, migrations auto, schema-first (great for TS).
    • Cons: N+1 perf issues (use include/select), less control over complex joins, migration lock-in.
    • Mitigation: Raw queries for perf-critical (e.g., booking overlaps).
  2. Clean Architecture worth the folder complexity?

    • Pros: Testable, decoupled (services pure), scalable for teams.
    • Cons: Boilerplate (mappers/DTOs), overkill for small apps, learning curve.
    • Here: Justified by patterns/multi-tenancy.
  3. State pattern for bookings: Benefits vs simple enum?

    • Pros: Encapsulates transitions (e.g., PENDING->APPROVED only), extensible.
    • Cons: More classes/files vs enum if-checks.
    • Tradeoff: Maintainability wins for complex workflows.
  4. Multi-tenancy via institutionId filtering: Secure/scalable?

    • Pros: Single DB (cost-effective), row-level isolation.
    • Cons: Accidental data leaks if filter missed, perf (index on institutionId).
    • Alt: Schema-per-tenant (complex), DB-per-tenant (expensive).
    • Enforced in services/middleware.
  5. Socket.io vs Server-Sent Events/polling for notifications?

    • Pros: Bidirectional, rooms (per institution), fallback transports.
    • Cons: WebSocket overhead, scaling (Redis adapter needed for prod).
    • Here: Socket.io is installed as a placeholder; currently EventBus handles notifications server-side. WebSocket delivery can be wired later.
  6. Next.js App Router vs Pages Router?

    • Pros: File-based routing, React Server Components (perf), colocation.
    • Cons: Breaking changes, Server Actions learning curve.
    • Tradeoff: Future-proof, but migrate carefully.
  7. FullCalendar: Status and limitations?

    • Status: Installed but not currently active (calendar page redirects to /bookings).
    • Pros: Rich views (timegrid), React integration, customizable.
    • Cons: Client-side (no SSR events), paid for advanced (recurring).
    • Alt: Custom with shadcn/ui + react-big-calendar.
  8. TypeScript strict mode? Enforced?

    • Pros: Catches domain errors early (e.g., role enums).
    • Cons: Verbose (mappers for Prisma raw types).
    • Config: tsconfig strict: true recommended.
  9. Soft deletes: Pros/Cons vs hard delete?

    • Pros: Audit trail, undo possible, GDPR compliance.
    • Cons: DB bloat, perf (index on deletedAt), query complexity (deletedAt IS NULL).
    • Here: Scoped in Prisma relations.
  10. Scaling API: Monolith ok? Microservices?

    • Current: Fine for campus (rate-limit helps).
    • Tradeoff: Microservices (per institution?) add service mesh complexity; stick to monolith + horizontal scale.

Files Structure

CRMS/
├── backend/
│ ├── prisma/schema.prisma (ER)
│ ├── server.ts (Express entry)
│ ├── src/
│ │ ├── app.ts (event handler registration)
│ │ ├── config/ (env, db)
│ │ ├── controllers/*.ts (5 files)
│ │ ├── docs/ (swagger, redoc)
│ │ ├── events/ (EventBus, handlers)
│ │ ├── middleware/ (auth, rate limit, validation, role guards)
│ │ ├── mappers/ (UserMapper, InstitutionMapper)
│ │ ├── models/ (User, Booking, Resource, etc.)
│ │ ├── routes/*.ts (5 files)
│ │ ├── services/ (business logic)
│ │ ├── shared/ (DomainError, query helpers, response, type guards)
│ │ ├── types/ (bcrypt.d.ts)
│ │ ├── validators/ (Zod schemas)
│ │ └── patterns/ (factory/observer/state/strategy)
│ └── socket/ (placeholder)
├── frontend/
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx, page.tsx
│ │ │ ├── (auth)/login|register/
│ │ │ ├── (dashboard)/bookings|calendar|resources|users|institutions/
│ │ │ └── pending/
│ │ ├── components/ (layout, ui, dashboard)
│ │ ├── hooks/ (useAuth)
│ │ ├── lib/ (api, cn)
│ │ └── types/ (auth)

About

About Campus Resource Management System (CRMS) designed for academic evaluation, featuring role-based access control, real-time scheduling, and object-oriented design principles with implemented State, Strategy, and Observer patterns using Next.js, Express, Prisma, and PostgreSQL.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages