Skip to content

Commit

Permalink
Issue/55/planner (#62)
Browse files Browse the repository at this point in the history
* feat: add DTOs for planner

* feat: add types for planners

* feat: add basics for planner

* feat: add serializers for planner

* feat: add union type checker

* feat: add union type narrower

* feat: implement serializer of item and track

* fix: fix typo

* fix: fix miscellaneous bugs

* feat: implement /api/tracks

* feat: implement post

* feat: add query param id checker

* refactor: refactor maps

* fix: snake to camel

* fix: fix planner item query logic

---------

Co-authored-by: ddungiii <ggcc503@gmail.com>
  • Loading branch information
duncan020313 and ddungiii authored Mar 6, 2024
1 parent 411d424 commit be17a1f
Show file tree
Hide file tree
Showing 24 changed files with 909 additions and 8 deletions.
4 changes: 4 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ import { DepartmentsModule } from './modules/departments/departments.module';
import { FeedsModule } from './modules/feeds/feeds.module';
import { LecturesModule } from './modules/lectures/lectures.module';
import { NoticesModule } from './modules/notices/notices.module';
import { PlannersModule } from './modules/planners/planners.module';
import { ReviewsModule } from './modules/reviews/reviews.module';
import { SemestersModule } from './modules/semesters/semesters.module';
import { SessionModule } from './modules/session/session.module';
import { StatusModule } from './modules/status/status.module';
import { TimetablesModule } from './modules/timetables/timetables.module';
import { TracksModule } from './modules/tracks/tracks.module';
import { UserModule } from './modules/user/user.module';
import { WishlistModule } from './modules/wishlist/wishlist.module';
import { PrismaModule } from './prisma/prisma.module';
Expand All @@ -36,6 +38,8 @@ import { PrismaModule } from './prisma/prisma.module';
NoticesModule,
SessionModule,
DepartmentsModule,
PlannersModule,
TracksModule,
],
controllers: [AppController],
providers: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { generationUnionTypeChecker } from 'src/common/utils/method.utils';

const types = ['DOUBLE', 'MINOR', 'ADVANCED', 'INTERDISCIPLINARY'] as const;
export type AdditionalTrackType = (typeof types)[number];
export const AddtionalTrackTypeNarrower = generationUnionTypeChecker(...types);
58 changes: 58 additions & 0 deletions src/common/interfaces/dto/planner/planner.request.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Transform, Type } from 'class-transformer';
import {
IsArray,
IsBoolean,
IsInt,
IsNumber,
IsOptional,
IsString,
} from 'class-validator';
import {
OrderDefaultValidator,
_PROHIBITED_FIELD_PATTERN,
} from '../../../decorators/validators.decorator';
export class PlannerQueryDto {
@IsOptional()
@Transform(({ value }) => (typeof value === 'string' ? [value] : value))
@IsArray()
@IsString({ each: true })
@OrderDefaultValidator(_PROHIBITED_FIELD_PATTERN)
order?: string[];

@IsOptional()
@IsNumber()
@Type(() => Number)
offset?: number;

@IsOptional()
@IsNumber()
@Type(() => Number)
limit?: number;
}

export class PlannerBodyDto {
@IsInt()
start_year!: number;
@IsInt()
end_year!: number;
@IsInt()
general_track!: number;
@IsInt()
major_track!: number;
@IsOptional()
@IsArray()
@IsInt({ each: true })
additional_tracks?: number[];
@IsOptional()
@IsBoolean()
should_update_taken_semesters?: boolean;
@IsArray()
@IsInt({ each: true })
taken_items_to_copy!: number[];
@IsArray()
@IsInt({ each: true })
future_items_to_copy!: number[];
@IsArray()
@IsInt({ each: true })
arbitrary_items_to_copy!: number[];
}
19 changes: 19 additions & 0 deletions src/common/interfaces/dto/planner/planner.response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ArbitraryPlannerItemResponseDto } from '../planner_item/arbitrary.response.dto';
import { FuturePlannerItemResponseDto } from '../planner_item/future.reponse.dto';
import { TakenPlannerItemResponseDto } from '../planner_item/taken.response.dto';
import { AdditionalTrackResponseDto } from '../track/additional.response.dto';
import { GeneralTrackResponseDto } from '../track/general.response.dto';
import { MajorTrackResponseDto } from '../track/major.response.dto';

export interface PlannerResponseDto {
id: number;
start_year: number;
end_year: number;
general_track: GeneralTrackResponseDto;
major_track: MajorTrackResponseDto;
additional_tracks: AdditionalTrackResponseDto[];
taken_items: TakenPlannerItemResponseDto[];
future_items: FuturePlannerItemResponseDto[];
arbitrary_items: ArbitraryPlannerItemResponseDto[];
arrange_order: number;
}
14 changes: 14 additions & 0 deletions src/common/interfaces/dto/planner_item/arbitrary.response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { DepartmentResponseDto } from '../department/department.response.dto';

export interface ArbitraryPlannerItemResponseDto {
id: number;
item_type: 'ARBITRARY';
is_excluded: boolean;
year: number;
semester: number;
department: DepartmentResponseDto | null;
type: string;
type_en: string;
credit: number;
credit_au: number;
}
10 changes: 10 additions & 0 deletions src/common/interfaces/dto/planner_item/future.reponse.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { CourseResponseDto } from '../course/course.response.dto';

export interface FuturePlannerItemResponseDto {
id: number;
item_type: 'FUTURE';
is_excluded: boolean;
year: number;
semester: number;
course: CourseResponseDto;
}
10 changes: 10 additions & 0 deletions src/common/interfaces/dto/planner_item/taken.response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { CourseResponseDto } from '../course/course.response.dto';
import { LectureResponseDto } from '../lecture/lecture.response.dto';

export interface TakenPlannerItemResponseDto {
id: number;
item_type: 'TAKEN';
is_excluded: boolean;
lecture: LectureResponseDto;
course: CourseResponseDto;
}
12 changes: 12 additions & 0 deletions src/common/interfaces/dto/track/additional.response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { AdditionalTrackType } from '../../constants/additional.track.response.dto';
import { DepartmentResponseDto } from '../department/department.response.dto';

export interface AdditionalTrackResponseDto {
id: number;
start_year: number;
end_year: number;
type: AdditionalTrackType;
department: DepartmentResponseDto | null;
major_required: number;
major_elective: number;
}
16 changes: 16 additions & 0 deletions src/common/interfaces/dto/track/general.response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface GeneralTrackResponseDto {
id: number;
start_year: number;
end_year: number;
is_foreign: boolean;
total_credit: number;
total_au: number;
basic_required: number;
basic_elective: number;
thesis_study: number;
thesis_study_doublemajor: number;
general_required_credit: number;
general_required_au: number;
humanities: number;
humanities_doublemajor: number;
}
11 changes: 11 additions & 0 deletions src/common/interfaces/dto/track/major.response.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DepartmentResponseDto } from '../department/department.response.dto';

export interface MajorTrackResponseDto {
id: number;
start_year: number;
end_year: number;
department: DepartmentResponseDto;
basic_elective_doublemajor: number;
major_required: number;
major_elective: number;
}
70 changes: 70 additions & 0 deletions src/common/interfaces/serializer/planner.item.serializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {
ArbitraryPlannerItem,
FuturePlannerItem,
TakenPlannerItem,
} from 'src/common/schemaTypes/types';
import { ArbitraryPlannerItemResponseDto } from '../dto/planner_item/arbitrary.response.dto';
import { FuturePlannerItemResponseDto } from '../dto/planner_item/future.reponse.dto';
import { TakenPlannerItemResponseDto } from '../dto/planner_item/taken.response.dto';
import { toJsonCourse } from './course.serializer';
import { toJsonDepartment } from './department.serializer';
import { toJsonLecture } from './lecture.serializer';

export const toJsonTakenItem = (
taken_item: TakenPlannerItem,
): TakenPlannerItemResponseDto => {
return {
id: taken_item.id,
item_type: 'TAKEN',
is_excluded: taken_item.is_excluded,
lecture: toJsonLecture(taken_item.subject_lecture, false),
course: toJsonCourse(
taken_item.subject_lecture.course,
taken_item.subject_lecture,
taken_item.subject_lecture.course.subject_course_professors.map(
(x) => x.professor,
),
false,
),
};
};

export const toJsonArbitraryItem = (
arbitrary_item: ArbitraryPlannerItem,
): ArbitraryPlannerItemResponseDto => {
return {
id: arbitrary_item.id,
item_type: 'ARBITRARY',
is_excluded: arbitrary_item.is_excluded,
year: arbitrary_item.year,
semester: arbitrary_item.semester,
department:
arbitrary_item.subject_department !== null
? toJsonDepartment(arbitrary_item.subject_department)
: null,
type: arbitrary_item.type,
type_en: arbitrary_item.type_en,
credit: arbitrary_item.credit,
credit_au: arbitrary_item.credit_au,
};
};

export const toJsonFutureItem = (
future_item: FuturePlannerItem,
): FuturePlannerItemResponseDto => {
return {
id: future_item.id,
item_type: 'FUTURE',
is_excluded: future_item.is_excluded,
year: future_item.year,
semester: future_item.semester,
course: toJsonCourse(
future_item.subject_course,
future_item.subject_course.lecture[0],
future_item.subject_course.subject_course_professors.map(
(x) => x.professor,
),
false,
),
};
};
36 changes: 36 additions & 0 deletions src/common/interfaces/serializer/planner.serializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { PlannerDetails } from 'src/common/schemaTypes/types';
import { PlannerResponseDto } from '../dto/planner/planner.response.dto';
import {
toJsonArbitraryItem,
toJsonFutureItem,
toJsonTakenItem,
} from './planner.item.serializer';
import {
toJsonAdditionalTrack,
toJsonGeneralTrack,
toJsonMajorTrack,
} from './track.serializer';

export const toJsonPlanner = (planner: PlannerDetails): PlannerResponseDto => {
return {
id: planner.id,
start_year: planner.start_year,
end_year: planner.end_year,
general_track: toJsonGeneralTrack(planner.graduation_generaltrack),
major_track: toJsonMajorTrack(planner.graduation_majortrack),
additional_tracks: planner.planner_planner_additional_tracks.map(
(additional_track) =>
toJsonAdditionalTrack(additional_track.graduation_additionaltrack),
),
taken_items: planner.planner_takenplanneritem.map((item) =>
toJsonTakenItem(item),
),
future_items: planner.planner_futureplanneritem.map((item) =>
toJsonFutureItem(item),
),
arbitrary_items: planner.planner_arbitraryplanneritem.map((item) =>
toJsonArbitraryItem(item),
),
arrange_order: planner.arrange_order,
};
};
68 changes: 68 additions & 0 deletions src/common/interfaces/serializer/track.serializer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {
AdditionalTrackDetails,
GeneralTrackBasic,
MajorTrackDetails,
} from 'src/common/schemaTypes/types';
import { AddtionalTrackTypeNarrower } from '../constants/additional.track.response.dto';
import { AdditionalTrackResponseDto } from '../dto/track/additional.response.dto';
import { GeneralTrackResponseDto } from '../dto/track/general.response.dto';
import { MajorTrackResponseDto } from '../dto/track/major.response.dto';
import { toJsonDepartment } from './department.serializer';

export const toJsonGeneralTrack = (
generalTrack: GeneralTrackBasic,
): GeneralTrackResponseDto => {
return {
id: generalTrack.id,
start_year: generalTrack.start_year,
end_year: generalTrack.end_year,
is_foreign: generalTrack.is_foreign,
total_credit: generalTrack.total_credit,
total_au: generalTrack.total_au,
basic_required: generalTrack.basic_required,
basic_elective: generalTrack.basic_elective,
thesis_study: generalTrack.thesis_study,
thesis_study_doublemajor: generalTrack.thesis_study_doublemajor,
general_required_credit: generalTrack.general_required_credit,
general_required_au: generalTrack.general_required_au,
humanities: generalTrack.humanities,
humanities_doublemajor: generalTrack.humanities_doublemajor,
};
};

export const toJsonMajorTrack = (
majorTrack: MajorTrackDetails,
): MajorTrackResponseDto => {
return {
id: majorTrack.id,
start_year: majorTrack.start_year,
end_year: majorTrack.end_year,
department: toJsonDepartment(majorTrack.subject_department),
basic_elective_doublemajor: majorTrack.basic_elective_doublemajor,
major_required: majorTrack.major_required,
major_elective: majorTrack.major_elective,
};
};

export const toJsonAdditionalTrack = (
additionalTrack: AdditionalTrackDetails,
): AdditionalTrackResponseDto => {
const type = AddtionalTrackTypeNarrower(additionalTrack.type);

if (type instanceof Error) {
throw type;
}

return {
id: additionalTrack.id,
start_year: additionalTrack.start_year,
end_year: additionalTrack.end_year,
type,
department:
additionalTrack.subject_department === null
? null
: toJsonDepartment(additionalTrack.subject_department),
major_required: additionalTrack.major_required,
major_elective: additionalTrack.major_elective,
};
};
Loading

0 comments on commit be17a1f

Please sign in to comment.