mirror of
https://github.com/sergeyyarkov/educt-server.git
synced 2026-10-11 18:29:15 +03:00
feat: added course service
This commit is contained in:
parent
e6880e3e0e
commit
1db5656d67
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
build
|
||||||
|
node_modules
|
||||||
|
.git
|
||||||
|
*.log
|
||||||
|
.env
|
||||||
|
Dockerfile
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { Exception } from '@adonisjs/core/build/standalone';
|
import { Exception, inject, Ioc } from '@adonisjs/core/build/standalone';
|
||||||
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,6 +11,7 @@ import Role from 'App/Datatypes/Enums/RoleEnum';
|
|||||||
*/
|
*/
|
||||||
import Course from 'App/Models/Course';
|
import Course from 'App/Models/Course';
|
||||||
import User from 'App/Models/User';
|
import User from 'App/Models/User';
|
||||||
|
import CourseService from 'App/Services/CourseService';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validators
|
* Validators
|
||||||
@ -20,12 +21,19 @@ import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
|
|||||||
import DelCourseFromUserValidator from 'App/Validators/Course/DelCourseFromUserValidator';
|
import DelCourseFromUserValidator from 'App/Validators/Course/DelCourseFromUserValidator';
|
||||||
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
import UpdateCourseValidator from 'App/Validators/Course/UpdateCourseValidator';
|
||||||
|
|
||||||
export default class CoursesController {
|
import BaseController from '../../BaseController';
|
||||||
|
|
||||||
|
@inject()
|
||||||
|
export default class CoursesController extends BaseController {
|
||||||
|
private courseService: CourseService;
|
||||||
|
|
||||||
private readonly Course: typeof Course;
|
private readonly Course: typeof Course;
|
||||||
|
|
||||||
private readonly User: typeof User;
|
private readonly User: typeof User;
|
||||||
|
|
||||||
constructor() {
|
constructor(courseService: CourseService) {
|
||||||
|
super();
|
||||||
|
this.courseService = courseService;
|
||||||
this.Course = Course;
|
this.Course = Course;
|
||||||
this.User = User;
|
this.User = User;
|
||||||
}
|
}
|
||||||
@ -34,144 +42,113 @@ export default class CoursesController {
|
|||||||
* List of all Courses
|
* List of all Courses
|
||||||
* GET /courses
|
* GET /courses
|
||||||
*/
|
*/
|
||||||
public async list({ response }: HttpContextContract) {
|
public async list(ctx: HttpContextContract) {
|
||||||
const courses = await this.Course.query().preload('teacher').preload('category').preload('lessons');
|
const result = await this.courseService.fetchCourses();
|
||||||
|
|
||||||
return response.ok({
|
if (!result.success && result.error) {
|
||||||
message: 'Fetched all courses.',
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
data: courses,
|
}
|
||||||
});
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Course by "id"
|
* Show Course by "id"
|
||||||
* GET /courses/:id
|
* GET /courses/:id
|
||||||
*/
|
*/
|
||||||
public async show({ response, params }: HttpContextContract) {
|
public async show(ctx: HttpContextContract) {
|
||||||
const course = await this.Course.query()
|
const result = await this.courseService.fetchCourse(ctx.params.id);
|
||||||
.preload('teacher')
|
|
||||||
.preload('category')
|
|
||||||
.preload('lessons')
|
|
||||||
.where('id', params.id)
|
|
||||||
.firstOrFail();
|
|
||||||
|
|
||||||
return response.ok({
|
if (!result.success && result.error) {
|
||||||
message: `Fetched course with id: "${course.id}"`,
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
data: course,
|
}
|
||||||
});
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Teacher of Course with "id"
|
* Show Teacher of Course with "id"
|
||||||
* GET /courses/:id/teacher
|
* GET /courses/:id/teacher
|
||||||
*/
|
*/
|
||||||
public async showTeacher({ response, params }: HttpContextContract) {
|
public async showTeacher(ctx: HttpContextContract) {
|
||||||
const course = await this.Course.query()
|
const result = await this.courseService.fetchCourseTeacher(ctx.params.id);
|
||||||
.select('teacher_id')
|
|
||||||
.preload('teacher', user => user.preload('contacts').preload('roles'))
|
|
||||||
.where('id', params.id)
|
|
||||||
.firstOrFail();
|
|
||||||
|
|
||||||
return response.ok({
|
if (!result.success && result.error) {
|
||||||
message: `Fetched teacher by courseId: "${params.id}"`,
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
data: course.teacher,
|
}
|
||||||
});
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Category of Course with "id"
|
* Show Category of Course with "id"
|
||||||
* GET /courses/:id/category
|
* GET /courses/:id/category
|
||||||
*/
|
*/
|
||||||
public async showCategory({ response, params }: HttpContextContract) {
|
public async showCategory(ctx: HttpContextContract) {
|
||||||
const course = await this.Course.query()
|
const result = await this.courseService.fetchCourseCategory(ctx.params.id);
|
||||||
.select('category_id')
|
|
||||||
.preload('category')
|
|
||||||
.where('id', params.id)
|
|
||||||
.firstOrFail();
|
|
||||||
|
|
||||||
return response.ok({
|
if (!result.success && result.error) {
|
||||||
message: `Fetched category by courseId: "${params.id}"`,
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
data: course.category,
|
}
|
||||||
});
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Lessons of ourse with "id"
|
* Show Lessons of ourse with "id"
|
||||||
* GET /courses/:id/lessons
|
* GET /courses/:id/lessons
|
||||||
*/
|
*/
|
||||||
public async showLessons({ response, params }: HttpContextContract) {
|
public async showLessons(ctx: HttpContextContract) {
|
||||||
const course = await this.Course.query().select('id').preload('lessons').where('id', params.id).firstOrFail();
|
const result = await this.courseService.fetchCourseLessons(ctx.params.id);
|
||||||
|
|
||||||
return response.ok({
|
if (!result.success && result.error) {
|
||||||
message: `Fetched lessons by courseId: "${params.id}"`,
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
data: course.lessons,
|
}
|
||||||
});
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show Students of Course with "id"
|
* Show Students of Course with "id"
|
||||||
* GET /courses/:id/students
|
* GET /courses/:id/students
|
||||||
*/
|
*/
|
||||||
public async showStudents({ response, params }: HttpContextContract) {
|
public async showStudents(ctx: HttpContextContract) {
|
||||||
const course = await this.Course.query().preload('students').where('id', params.id).firstOrFail();
|
const result = await this.courseService.fetchCourseStudents(ctx.params.id);
|
||||||
|
|
||||||
return response.ok({
|
if (!result.success && result.error) {
|
||||||
message: `Fetched students from course with id: "${course.id}"`,
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
data: course.students,
|
}
|
||||||
});
|
|
||||||
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new Course in a system
|
* Create new Course in a system
|
||||||
* POST /courses
|
* POST /courses
|
||||||
*/
|
*/
|
||||||
public async create({ response, request }: HttpContextContract) {
|
public async create(ctx: HttpContextContract) {
|
||||||
const payload = await request.validate(CreateCourseValidator);
|
const payload = await ctx.request.validate(CreateCourseValidator);
|
||||||
|
const result = await this.courseService.createCourse(payload);
|
||||||
|
|
||||||
const teacher = await this.User.findOrFail(payload.teacher_id);
|
if (!result.success && result.error) {
|
||||||
await teacher.load('roles');
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
|
|
||||||
/**
|
|
||||||
* Check user on role Teacher
|
|
||||||
*/
|
|
||||||
const roles = teacher.roles.map(r => r.slug);
|
|
||||||
if (!roles.includes(Role.TEACHER)) {
|
|
||||||
throw new Exception(`User with id "${teacher.id}" not teacher.`, 400, 'ERR_USER_NOT_TEACHER');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const course = await this.Course.create({
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
title: payload.title,
|
|
||||||
description: payload.description,
|
|
||||||
teacher_id: teacher.id,
|
|
||||||
category_id: payload.category_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
await course.save();
|
|
||||||
|
|
||||||
return response.created({
|
|
||||||
message: 'Course has been created',
|
|
||||||
data: course,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete Course by "id"
|
* Delete Course by "id"
|
||||||
* DELETE /courses/:id
|
* DELETE /courses/:id
|
||||||
*/
|
*/
|
||||||
public async delete({ response, params }: HttpContextContract) {
|
public async delete(ctx: HttpContextContract) {
|
||||||
const course = await this.Course.query()
|
const result = await this.courseService.deleteCourse(ctx.params.id);
|
||||||
.preload('teacher')
|
|
||||||
.preload('category')
|
|
||||||
.preload('lessons')
|
|
||||||
.where('id', params.id)
|
|
||||||
.firstOrFail();
|
|
||||||
|
|
||||||
await course.delete();
|
if (!result.success && result.error) {
|
||||||
|
throw new Exception(result.message, result.status, result.error.code);
|
||||||
|
}
|
||||||
|
|
||||||
return response.ok({
|
return this.sendResponse(ctx, result.data, result.message, result.status);
|
||||||
message: `Course with id "${params.id}" has been deleted.`,
|
|
||||||
data: course,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -256,3 +233,5 @@ export default class CoursesController {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new Ioc().make(CoursesController);
|
||||||
|
|||||||
24
app/Helpers/RoleHelper.ts
Normal file
24
app/Helpers/RoleHelper.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import RoleEnum from 'App/Datatypes/Enums/RoleEnum';
|
||||||
|
import type Role from 'App/Models/Role';
|
||||||
|
|
||||||
|
export default class RoleHelper {
|
||||||
|
/**
|
||||||
|
* If the user roles is not found in the array of roles
|
||||||
|
* then return false
|
||||||
|
*
|
||||||
|
* @param userRoles Roles of existing user
|
||||||
|
* @param roles Roles to check
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
public static userHasRoles(userRoles: Role[], roles: RoleEnum[]): boolean {
|
||||||
|
for (let i = 0; i < roles.length; i += 1) {
|
||||||
|
if (!userRoles.map(r => r.slug).includes(roles[i])) {
|
||||||
|
/**
|
||||||
|
* Unable to find current role in user roles
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
app/Repositories/CategoryRepository.ts
Normal file
23
app/Repositories/CategoryRepository.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Models
|
||||||
|
*/
|
||||||
|
import Category from 'App/Models/Category';
|
||||||
|
|
||||||
|
export default class CategoryRepository {
|
||||||
|
private Category: typeof Category;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.Category = Category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get category by id
|
||||||
|
*
|
||||||
|
* @param id Category id
|
||||||
|
* @returns Caregory or null
|
||||||
|
*/
|
||||||
|
public async getById(id: string | number): Promise<Category | null> {
|
||||||
|
const category = await this.Category.query().where('id', id).first();
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
}
|
||||||
129
app/Repositories/CourseRepository.ts
Normal file
129
app/Repositories/CourseRepository.ts
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* Models
|
||||||
|
*/
|
||||||
|
import Category from 'App/Models/Category';
|
||||||
|
import Course from 'App/Models/Course';
|
||||||
|
import Lesson from 'App/Models/Lesson';
|
||||||
|
import User from 'App/Models/User';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validators
|
||||||
|
*/
|
||||||
|
import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
|
||||||
|
|
||||||
|
export default class CourseRepository {
|
||||||
|
private Course: typeof Course;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.Course = Course;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all courses
|
||||||
|
*
|
||||||
|
* @returns List of courses
|
||||||
|
*/
|
||||||
|
public async getAll(): Promise<Course[]> {
|
||||||
|
const courses = await this.Course.query().preload('teacher').preload('category').preload('lessons');
|
||||||
|
return courses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get course by id
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Course or null
|
||||||
|
*/
|
||||||
|
public async getById(id: string | number): Promise<Course | null> {
|
||||||
|
const course = await this.Course.query()
|
||||||
|
.preload('teacher')
|
||||||
|
.preload('category')
|
||||||
|
.preload('lessons')
|
||||||
|
.where('id', id)
|
||||||
|
.first();
|
||||||
|
|
||||||
|
return course;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get teacher of course
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns User or null
|
||||||
|
*/
|
||||||
|
public async getTeacher(id: string | number): Promise<User | null> {
|
||||||
|
const course = await this.Course.query()
|
||||||
|
.select('teacher_id')
|
||||||
|
.preload('teacher', user => user.preload('contacts').preload('roles'))
|
||||||
|
.where('id', id)
|
||||||
|
.first();
|
||||||
|
|
||||||
|
return course && course.teacher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get category of course
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Category or null
|
||||||
|
*/
|
||||||
|
public async getCategory(id: string | number): Promise<Category | null> {
|
||||||
|
const course = await this.Course.query().select('category_id').preload('category').where('id', id).first();
|
||||||
|
return course && course.category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get lessons of course
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns List of lessons or null
|
||||||
|
*/
|
||||||
|
public async getLessons(id: string | number): Promise<Lesson[] | null> {
|
||||||
|
const course = await this.Course.query().select('id').preload('lessons').where('id', id).first();
|
||||||
|
return course && course.lessons;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get students of cours
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns List of users or null
|
||||||
|
*/
|
||||||
|
public async getStudents(id: string | number): Promise<User[] | null> {
|
||||||
|
const course = await this.Course.query().preload('students').where('id', id).first();
|
||||||
|
return course && course.students;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create course
|
||||||
|
*
|
||||||
|
* @param data Data input
|
||||||
|
* @returns Created course
|
||||||
|
*/
|
||||||
|
public async create(data: CreateCourseValidator['schema']['props']): Promise<Course> {
|
||||||
|
const createdCourse = await this.Course.create(data);
|
||||||
|
return createdCourse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete course
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Deleted course
|
||||||
|
*/
|
||||||
|
public async delete(id: string | number): Promise<Course | null> {
|
||||||
|
const course = await this.Course.query()
|
||||||
|
.preload('teacher')
|
||||||
|
.preload('category')
|
||||||
|
.preload('lessons')
|
||||||
|
.where('id', id)
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (course) {
|
||||||
|
await course.delete();
|
||||||
|
return course;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -99,6 +99,10 @@ export default class UserRepository {
|
|||||||
*/
|
*/
|
||||||
public async create(data: CreateUserValidator['schema']['props']): Promise<User> {
|
public async create(data: CreateUserValidator['schema']['props']): Promise<User> {
|
||||||
const createdUser = await this.User.create(data);
|
const createdUser = await this.User.create(data);
|
||||||
|
|
||||||
|
await createdUser.load('contacts');
|
||||||
|
await createdUser.load('roles');
|
||||||
|
|
||||||
return createdUser;
|
return createdUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
299
app/Services/CourseService.ts
Normal file
299
app/Services/CourseService.ts
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
import { inject, Ioc } from '@adonisjs/core/build/standalone';
|
||||||
|
import RoleEnum from 'App/Datatypes/Enums/RoleEnum';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Datatypes
|
||||||
|
*/
|
||||||
|
import StatusCodeEnum from 'App/Datatypes/Enums/StatusCodeEnum';
|
||||||
|
import IResponse from 'App/Datatypes/Interfaces/IResponse';
|
||||||
|
import RoleHelper from 'App/Helpers/RoleHelper';
|
||||||
|
import CategoryRepository from 'App/Repositories/CategoryRepository';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repositories
|
||||||
|
*/
|
||||||
|
import CourseRepository from 'App/Repositories/CourseRepository';
|
||||||
|
import UserRepository from 'App/Repositories/UserRepository';
|
||||||
|
import CreateCourseValidator from 'App/Validators/Course/CreateCourseValidator';
|
||||||
|
|
||||||
|
@inject()
|
||||||
|
export default class CourseService {
|
||||||
|
private courseRepository: CourseRepository;
|
||||||
|
|
||||||
|
private userRepository: UserRepository;
|
||||||
|
|
||||||
|
private categoryRepository: CategoryRepository;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
courseRepository: CourseRepository,
|
||||||
|
userRepository: UserRepository,
|
||||||
|
categoryRepository: CategoryRepository
|
||||||
|
) {
|
||||||
|
this.courseRepository = courseRepository;
|
||||||
|
this.userRepository = userRepository;
|
||||||
|
this.categoryRepository = categoryRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch list of courses
|
||||||
|
*
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async fetchCourses(): Promise<IResponse> {
|
||||||
|
const data = await this.courseRepository.getAll();
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: StatusCodeEnum.OK,
|
||||||
|
message: 'Fetched all courses.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch one course by id
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async fetchCourse(id: string | number): Promise<IResponse> {
|
||||||
|
const data = await this.courseRepository.getById(id);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.NOT_FOUND,
|
||||||
|
message: 'Course not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: StatusCodeEnum.OK,
|
||||||
|
message: 'Fetched course.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch teacher by course id
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async fetchCourseTeacher(id: string | number): Promise<IResponse> {
|
||||||
|
const data = await this.courseRepository.getTeacher(id);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.NOT_FOUND,
|
||||||
|
message: 'Course not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: StatusCodeEnum.OK,
|
||||||
|
message: 'Fetched course teacher.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch category by course id
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async fetchCourseCategory(id: string | number): Promise<IResponse> {
|
||||||
|
const data = await this.courseRepository.getCategory(id);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.NOT_FOUND,
|
||||||
|
message: 'Course not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: StatusCodeEnum.OK,
|
||||||
|
message: 'Fetched course category.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch lessons by course id
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async fetchCourseLessons(id: string | number): Promise<IResponse> {
|
||||||
|
const data = await this.courseRepository.getLessons(id);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.NOT_FOUND,
|
||||||
|
message: 'Course not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: StatusCodeEnum.OK,
|
||||||
|
message: 'Fetched course lessons.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch students by course id
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async fetchCourseStudents(id: string | number): Promise<IResponse> {
|
||||||
|
const data = await this.courseRepository.getStudents(id);
|
||||||
|
|
||||||
|
if (!data) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.NOT_FOUND,
|
||||||
|
message: 'Course not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: StatusCodeEnum.OK,
|
||||||
|
message: 'Fetched course students.',
|
||||||
|
data,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create course
|
||||||
|
*
|
||||||
|
* @param data Data input
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async createCourse(data: CreateCourseValidator['schema']['props']): Promise<IResponse> {
|
||||||
|
/**
|
||||||
|
* Find course teacher
|
||||||
|
*/
|
||||||
|
const teacher = await this.userRepository.getById(data.teacher_id);
|
||||||
|
|
||||||
|
if (!teacher) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.NOT_FOUND,
|
||||||
|
message: 'Teacher not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check teacher on role
|
||||||
|
*/
|
||||||
|
const isTeacher = RoleHelper.userHasRoles(teacher.roles, [RoleEnum.TEACHER]);
|
||||||
|
|
||||||
|
if (!isTeacher) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.BAD_REQUEST,
|
||||||
|
message: `User with id "${teacher.id}" not teacher.`,
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_BAD_REQUEST',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find course category
|
||||||
|
*/
|
||||||
|
const category = await this.categoryRepository.getById(data.category_id);
|
||||||
|
|
||||||
|
if (!category) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.NOT_FOUND,
|
||||||
|
message: 'Category not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creating new course
|
||||||
|
*/
|
||||||
|
const course = await this.courseRepository.create(data);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: StatusCodeEnum.CREATED,
|
||||||
|
message: 'Course created.',
|
||||||
|
data: course,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete course
|
||||||
|
*
|
||||||
|
* @param id Course id
|
||||||
|
* @returns Response
|
||||||
|
*/
|
||||||
|
public async deleteCourse(id: string | number): Promise<IResponse> {
|
||||||
|
const course = await this.courseRepository.delete(id);
|
||||||
|
|
||||||
|
if (!course) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
status: StatusCodeEnum.NOT_FOUND,
|
||||||
|
message: 'Course not found.',
|
||||||
|
data: {},
|
||||||
|
error: {
|
||||||
|
code: 'E_NOT_FOUND',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
status: StatusCodeEnum.OK,
|
||||||
|
message: 'Course deleted.',
|
||||||
|
data: course,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Ioc().make(CourseService);
|
||||||
@ -5,7 +5,7 @@ export default class CreateCourseValidator {
|
|||||||
constructor(protected ctx: HttpContextContract) {}
|
constructor(protected ctx: HttpContextContract) {}
|
||||||
|
|
||||||
public schema = schema.create({
|
public schema = schema.create({
|
||||||
title: schema.string({}, [rules.unique({ table: 'courses', column: 'title' })]),
|
title: schema.string(),
|
||||||
description: schema.string(),
|
description: schema.string(),
|
||||||
teacher_id: schema.string({}, [rules.exists({ table: 'users', column: 'id' })]),
|
teacher_id: schema.string({}, [rules.exists({ table: 'users', column: 'id' })]),
|
||||||
category_id: schema.string({}, [rules.exists({ table: 'categories', column: 'id' })]),
|
category_id: schema.string({}, [rules.exists({ table: 'categories', column: 'id' })]),
|
||||||
|
|||||||
@ -5,7 +5,7 @@ export default class UpdateCourseValidator {
|
|||||||
constructor(protected ctx: HttpContextContract) {}
|
constructor(protected ctx: HttpContextContract) {}
|
||||||
|
|
||||||
public schema = schema.create({
|
public schema = schema.create({
|
||||||
title: schema.string.optional({}, [rules.unique({ table: 'courses', column: 'title' })]),
|
title: schema.string.optional(),
|
||||||
description: schema.string.optional(),
|
description: schema.string.optional(),
|
||||||
teacher_id: schema.string.optional({}, [rules.exists({ table: 'users', column: 'id' })]),
|
teacher_id: schema.string.optional({}, [rules.exists({ table: 'users', column: 'id' })]),
|
||||||
category_id: schema.string.optional({}, [rules.exists({ table: 'categories', column: 'id' })]),
|
category_id: schema.string.optional({}, [rules.exists({ table: 'categories', column: 'id' })]),
|
||||||
|
|||||||
@ -16,4 +16,10 @@ import { Ignitor } from '@adonisjs/core/build/standalone';
|
|||||||
|
|
||||||
sourceMapSupport.install({ handleUncaughtExceptions: false });
|
sourceMapSupport.install({ handleUncaughtExceptions: false });
|
||||||
|
|
||||||
new Ignitor(__dirname).httpServer().start();
|
const server = new Ignitor(__dirname).httpServer();
|
||||||
|
|
||||||
|
server.start().catch(error => {
|
||||||
|
throw new Error(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('SIGINT', () => server.kill(10));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user