Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions apps/backend/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
moduleFileExtensions: ['js', 'json', 'ts'],
rootDir: 'src',
testRegex: '.*\\.spec\\.ts$',
transform: {
'^.+\\.(t|j)s$': 'ts-jest',
},
collectCoverageFrom: ['**/*.(t|j)s'],
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

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

collectCoverageFrom: ['**/*.(t|j)s'] is not a valid glob for Jest’s micromatch patterns, so coverage collection may silently skip files. Use a supported pattern such as ['**/*.{ts,js}'] (and optionally exclude .d.ts, main.ts, etc.).

Suggested change
collectCoverageFrom: ['**/*.(t|j)s'],
collectCoverageFrom: ['**/*.{ts,js}'],

Copilot uses AI. Check for mistakes.
coverageDirectory: '../coverage',
testEnvironment: 'node',
};
7 changes: 6 additions & 1 deletion apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main"
"start:prod": "node dist/main",
"test:backend": "jest"
},
"dependencies": {
"@kir-dev/passport-authsch": "^2.2.2",
Expand All @@ -37,11 +38,15 @@
"devDependencies": {
"@nestjs/cli": "^10.3.2",
"@nestjs/schematics": "^10.1.1",
"@nestjs/testing": "^11.1.17",
"@types/express": "^4.17.21",
"@types/jest": "^30.0.0",
"@types/node": "^20.12.7",
"@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^7.7.1",
"jest": "^30.3.0",
"source-map-support": "^0.5.21",
"ts-jest": "^29.4.6",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.2",
"tsconfig-paths": "4.2.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- AlterEnum
ALTER TYPE "ReservationStatus" ADD VALUE 'SANCTIONED';

-- AlterTable
ALTER TABLE "Period" ADD COLUMN "isOpen" BOOLEAN NOT NULL DEFAULT false;

-- AlterTable
ALTER TABLE "User" ADD COLUMN "sanctionPoints" INTEGER NOT NULL DEFAULT 0;

-- CreateTable
CREATE TABLE "Settings" (
"id" SERIAL NOT NULL,
"maxHoursPerWeek" DOUBLE PRECISION NOT NULL DEFAULT 8.0,
"maxHoursPerDay" DOUBLE PRECISION NOT NULL DEFAULT 4.0,
"minReservationMinutes" INTEGER NOT NULL DEFAULT 30,
"maxReservationMinutes" INTEGER NOT NULL DEFAULT 180,
"sanctionHourPenaltyPerPoint" DOUBLE PRECISION NOT NULL DEFAULT 1.0,

CONSTRAINT "Settings_pkey" PRIMARY KEY ("id")
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Reservation" ADD COLUMN "needToBeLetIn" BOOLEAN NOT NULL DEFAULT false;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Warnings:

- You are about to drop the column `sanctionPoints` on the `User` table. All the data in the column will be lost.

*/
-- AlterTable
ALTER TABLE "User" DROP COLUMN "sanctionPoints";

-- CreateTable
CREATE TABLE "SanctionRecord" (
"id" SERIAL NOT NULL,
"userId" INTEGER,
"bandId" INTEGER,
"points" INTEGER NOT NULL,
"reason" TEXT NOT NULL,
"awardedBy" INTEGER NOT NULL,
"awardedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

CONSTRAINT "SanctionRecord_pkey" PRIMARY KEY ("id")
);

-- AddForeignKey
ALTER TABLE "SanctionRecord" ADD CONSTRAINT "SanctionRecord_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "SanctionRecord" ADD CONSTRAINT "SanctionRecord_bandId_fkey" FOREIGN KEY ("bandId") REFERENCES "Band"("id") ON DELETE SET NULL ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "SanctionRecord" ADD CONSTRAINT "SanctionRecord_awardedBy_fkey" FOREIGN KEY ("awardedBy") REFERENCES "ClubMembership"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- CreateEnum
CREATE TYPE "GateKeeperPriority" AS ENUM ('PRIMARY', 'SECONDARY');

-- AlterTable
ALTER TABLE "Reservation" ADD COLUMN "gateKeeperPriority" "GateKeeperPriority";
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
Warnings:

- The values [SANCTIONED] on the enum `ReservationStatus` will be removed. If these variants are still used in the database, this will fail.

*/
-- AlterEnum
BEGIN;
CREATE TYPE "ReservationStatus_new" AS ENUM ('NORMAL', 'OVERTIME', 'ADMINMADE');
ALTER TABLE "Reservation" ALTER COLUMN "status" TYPE "ReservationStatus_new" USING ("status"::text::"ReservationStatus_new");
ALTER TYPE "ReservationStatus" RENAME TO "ReservationStatus_old";
ALTER TYPE "ReservationStatus_new" RENAME TO "ReservationStatus";
DROP TYPE "ReservationStatus_old";
COMMIT;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- AlterTable
ALTER TABLE "Settings" ADD COLUMN "banSanctionPointThreshold" INTEGER NOT NULL DEFAULT 5,
ADD COLUMN "maxTotalHoursPerWeek" DOUBLE PRECISION NOT NULL DEFAULT 12.0,
ADD COLUMN "sanctionTotalHourPenaltyPerPoint" DOUBLE PRECISION NOT NULL DEFAULT 2.0;

-- CreateTable
CREATE TABLE "OpenedWeek" (
"id" SERIAL NOT NULL,
"monday" TIMESTAMP(3) NOT NULL,
"isOpen" BOOLEAN NOT NULL DEFAULT false,

CONSTRAINT "OpenedWeek_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "OpenedWeek_monday_key" ON "OpenedWeek"("monday");
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
Warnings:

- You are about to drop the `ReservationConfig` table. If the table is not empty, all the data it contains will be lost.
- You are about to drop the `SanctionTier` table. If the table is not empty, all the data it contains will be lost.

*/
-- DropForeignKey
ALTER TABLE "SanctionTier" DROP CONSTRAINT "SanctionTier_configId_fkey";

-- DropTable
DROP TABLE "ReservationConfig";

-- DropTable
DROP TABLE "SanctionTier";
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- AlterTable
ALTER TABLE "SanctionRecord" ADD COLUMN "reservationId" INTEGER;

-- AddForeignKey
ALTER TABLE "SanctionRecord" ADD CONSTRAINT "SanctionRecord_reservationId_fkey" FOREIGN KEY ("reservationId") REFERENCES "Reservation"("id") ON DELETE SET NULL ON UPDATE CASCADE;
102 changes: 64 additions & 38 deletions apps/backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,26 @@ enum BandMembershipStatus {
ACCEPTED
}

enum GateKeeperPriority {
PRIMARY
SECONDARY
}

model User {
id Int @id @default(autoincrement())
email String @unique
phone String? @unique
role Role @default(USER)
authSchId String? @unique
id Int @id @default(autoincrement())
email String @unique
phone String? @unique
role Role @default(USER)
authSchId String? @unique
fullName String
clubMembershipUpdatedAt DateTime?
bandMemberships BandMembership[]
clubMembership ClubMembership?
DormResidency DormResidency?
Post Post[]
profilePicture ProfilePicture?
reservations Reservation[] @relation("Reservations")
reservations Reservation[] @relation("Reservations")
sanctionRecords SanctionRecord[] @relation("UserSanctions")
}

model ProfilePicture {
Expand Down Expand Up @@ -70,17 +76,19 @@ model ClubMembership {
isGateKeeper Boolean
user User @relation(fields: [userId], references: [id])
gateKeepingRecords Reservation[] @relation("GateKeeping")
sanctionsAwarded SanctionRecord[] @relation("GateKeeperSanctions")
}

model Band {
id Int @id @default(autoincrement())
name String
email String?
webPage String?
description String?
genres String[]
members BandMembership[]
reservations Reservation[]
id Int @id @default(autoincrement())
name String
email String?
webPage String?
description String?
genres String[]
members BandMembership[]
reservations Reservation[]
sanctionRecords SanctionRecord[] @relation("BandSanctions")
}

model BandMembership {
Expand All @@ -95,16 +103,19 @@ model BandMembership {
}

model Reservation {
id Int @id @default(autoincrement())
id Int @id @default(autoincrement())
userId Int?
bandId Int?
startTime DateTime
endTime DateTime
gateKeeperId Int?
status ReservationStatus
band Band? @relation(fields: [bandId], references: [id])
gateKeeper ClubMembership? @relation("GateKeeping", fields: [gateKeeperId], references: [id])
user User? @relation("Reservations", fields: [userId], references: [id])
gateKeeperId Int?
gateKeeperPriority GateKeeperPriority?
status ReservationStatus
needToBeLetIn Boolean @default(false)
band Band? @relation(fields: [bandId], references: [id])
gateKeeper ClubMembership? @relation("GateKeeping", fields: [gateKeeperId], references: [id])
user User? @relation("Reservations", fields: [userId], references: [id])
sanctionRecords SanctionRecord[]
}

model Comment {
Expand All @@ -119,6 +130,7 @@ model Period {
id Int @id @default(autoincrement())
startDate DateTime
endDate DateTime
isOpen Boolean @default(false)
}

model Post {
Expand All @@ -131,22 +143,36 @@ model Post {
User User @relation(fields: [authorId], references: [id])
}

model ReservationConfig {
id Int @id @default(autoincrement())
userDailyHours Float @default(4)
userWeeklyHours Float @default(8)
bandDailyHours Float @default(6)
bandWeeklyHours Float @default(12)
sanctionTiers SanctionTier[]
}

model SanctionTier {
id Int @id @default(autoincrement())
configId Int
config ReservationConfig @relation(fields: [configId], references: [id])
minPoints Int
userDailyHours Float
userWeeklyHours Float
bandDailyHours Float
bandWeeklyHours Float
model Settings {
id Int @id @default(autoincrement())
maxHoursPerWeek Float @default(8.0)
maxHoursPerDay Float @default(4.0)
minReservationMinutes Int @default(30)
maxReservationMinutes Int @default(180)
sanctionHourPenaltyPerPoint Float @default(1.0)
maxTotalHoursPerWeek Float @default(12.0)
sanctionTotalHourPenaltyPerPoint Float @default(2.0)
banSanctionPointThreshold Int @default(5)
}

model OpenedWeek {
id Int @id @default(autoincrement())
monday DateTime @unique
isOpen Boolean @default(false)
}

model SanctionRecord {
id Int @id @default(autoincrement())
userId Int?
bandId Int?
reservationId Int?
points Int
reason String
awardedBy Int
awardedAt DateTime @default(now())

user User? @relation("UserSanctions", fields: [userId], references: [id])
band Band? @relation("BandSanctions", fields: [bandId], references: [id])
reservation Reservation? @relation(fields: [reservationId], references: [id])
gateKeeper ClubMembership @relation("GateKeeperSanctions", fields: [awardedBy], references: [id])
}
34 changes: 0 additions & 34 deletions apps/backend/src/admin/admin.controller.ts

This file was deleted.

10 changes: 0 additions & 10 deletions apps/backend/src/admin/admin.module.ts

This file was deleted.

Loading
Loading