learning
This commit is contained in:
+3
-1
@@ -20,6 +20,7 @@ import { FormBuilderModule } from './modules/form-builder/form-builder.module';
|
||||
import { RequestModule } from './modules/request/request.module';
|
||||
import { InvoiceModule } from './modules/invoice/invoice.module';
|
||||
import { OrderModule } from './modules/order/order.module';
|
||||
import { LearningModule } from './modules/learnings/learning.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -47,7 +48,8 @@ import { OrderModule } from './modules/order/order.module';
|
||||
FormBuilderModule,
|
||||
RequestModule,
|
||||
InvoiceModule,
|
||||
OrderModule
|
||||
OrderModule,
|
||||
LearningModule,
|
||||
],
|
||||
controllers: [],
|
||||
providers: [],
|
||||
|
||||
@@ -119,6 +119,24 @@ export const enum TicketMessageEnum {
|
||||
OPENED = "تیکت با موفقیت باز شد",
|
||||
}
|
||||
|
||||
export const enum LearningMessage {
|
||||
NOT_FOUND = 'آموزش مورد نظر یافت نشد',
|
||||
CATEGORY_NOT_FOUND = 'دستهبندی مورد نظر یافت نشد',
|
||||
CATEGORY_NAME_EXIST = 'دستهبندی با این نام قبلاً وجود دارد',
|
||||
CATEGORY_MUST_BE_ID = 'شناسه دستهبندی الزامی است',
|
||||
CATEGORY_MUST_BE_UUID = 'شناسه دستهبندی باید معتبر باشد',
|
||||
NAME_REQUIRED = 'نام دستهبندی الزامی است',
|
||||
NAME_STRING = 'نام دستهبندی باید رشته باشد',
|
||||
TITLE_REQUIRED = 'عنوان الزامی است',
|
||||
TITLE_STRING = 'عنوان باید رشته باشد',
|
||||
DESCRIPTION_REQUIRED = 'توضیحات الزامی است',
|
||||
DESCRIPTION_STRING = 'توضیحات باید رشته باشد',
|
||||
COVER_URL_REQUIRED = 'آدرس تصویر جلد الزامی است',
|
||||
COVER_URL_INVALID = 'آدرس تصویر جلد نامعتبر است',
|
||||
VIDEO_URL_INVALID = 'آدرس ویدیو نامعتبر است',
|
||||
VIDEO_DURATION_INVALID = 'مدت زمان ویدیو نامعتبر است',
|
||||
}
|
||||
|
||||
export const enum productMessage {
|
||||
NOT_FOUND = 'کالایی با این مشخصات یافت نشد',
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ export enum PermissionEnum {
|
||||
|
||||
MANAGE_PRINT = 'view_print',
|
||||
|
||||
MANAGE_LEARNINGS = 'manage_learnings',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,5 +76,6 @@ export const PermissionTitles: Record<PermissionEnum, string> = {
|
||||
[PermissionEnum.DELETE_INVOICE]: "",
|
||||
[PermissionEnum.DELETE_ORDER]: "",
|
||||
[PermissionEnum.CREATE_PRINT]: "ایجاد فرم چاپ برای سفارش",
|
||||
[PermissionEnum.MANAGE_PRINT]: "مدیریت فرم چاپ"
|
||||
[PermissionEnum.MANAGE_PRINT]: "مدیریت فرم چاپ",
|
||||
[PermissionEnum.MANAGE_LEARNINGS]: "مدیریت آموزشها"
|
||||
};
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsString } from "class-validator";
|
||||
|
||||
import { LearningMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
export class CreateLearningCategoryDto {
|
||||
@ApiProperty({ description: "name of the learning category", maxLength: 200 })
|
||||
@IsString({ message: LearningMessage.NAME_STRING })
|
||||
@IsNotEmpty({ message: LearningMessage.NAME_REQUIRED })
|
||||
name: string;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsNotEmpty, IsNumberString, IsOptional, IsString, IsUrl } from "class-validator";
|
||||
|
||||
import { LearningMessage } from "../../../common/enums/message.enum";
|
||||
|
||||
export class CreateLearningDto {
|
||||
@IsNotEmpty({ message: LearningMessage.CATEGORY_MUST_BE_ID })
|
||||
@IsString({ message: LearningMessage.CATEGORY_MUST_BE_UUID })
|
||||
@ApiProperty({ description: "Category ID", example: "01ARZ3NDEKTSV4RRFFQ69G5FAV" })
|
||||
categoryId: string;
|
||||
|
||||
@ApiProperty({ description: "Title of the learning", maxLength: 200 })
|
||||
@IsString({ message: LearningMessage.TITLE_STRING })
|
||||
@IsNotEmpty({ message: LearningMessage.TITLE_REQUIRED })
|
||||
title: string;
|
||||
|
||||
@IsNotEmpty({ message: LearningMessage.DESCRIPTION_REQUIRED })
|
||||
@IsString({ message: LearningMessage.DESCRIPTION_STRING })
|
||||
@ApiProperty({ description: "Description of the learning" })
|
||||
description: string;
|
||||
|
||||
@IsNotEmpty({ message: LearningMessage.COVER_URL_REQUIRED })
|
||||
@IsUrl({ protocols: ["http", "https"], require_protocol: true }, { message: LearningMessage.COVER_URL_INVALID })
|
||||
@IsString({ message: LearningMessage.COVER_URL_INVALID })
|
||||
@ApiProperty({ description: "Cover image URL" })
|
||||
coverUrl: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString({ message: LearningMessage.VIDEO_URL_INVALID })
|
||||
@IsUrl({ protocols: ["http", "https"], require_protocol: true }, { message: LearningMessage.VIDEO_URL_INVALID })
|
||||
@ApiProperty({ description: "Video URL", required: false })
|
||||
videoUrl?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsNumberString({ no_symbols: true }, { message: LearningMessage.VIDEO_DURATION_INVALID })
|
||||
@ApiProperty({ description: "Video Duration", required: false })
|
||||
videoDuration?: string;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { PartialType } from "@nestjs/swagger";
|
||||
|
||||
import { CreateLearningCategoryDto } from "./create-learning-category.dto";
|
||||
|
||||
export class UpdateLearningCategoryDto extends PartialType(CreateLearningCategoryDto) {}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
import { PartialType } from "@nestjs/swagger";
|
||||
|
||||
import { CreateLearningDto } from "./create-learning.dto";
|
||||
|
||||
export class UpdateLearningDto extends PartialType(CreateLearningDto) {}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Collection, Entity, OneToMany, Property, OptionalProps } from '@mikro-orm/core';
|
||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||
import { Learning } from './learning.entity';
|
||||
|
||||
@Entity({ tableName: 'learning_categories' })
|
||||
export class LearningCategory extends BaseEntity {
|
||||
[OptionalProps]?: 'createdAt' | 'deletedAt';
|
||||
|
||||
@Property({ type: 'varchar', length: 100, unique: true })
|
||||
name: string;
|
||||
|
||||
@OneToMany(() => Learning, (learning) => learning.category)
|
||||
learnings = new Collection<Learning>(this);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Entity, ManyToOne, Property, OptionalProps } from '@mikro-orm/core';
|
||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||
import { Learning } from './learning.entity';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
|
||||
@Entity({ tableName: 'learning_progress' })
|
||||
export class LearningProgress extends BaseEntity {
|
||||
[OptionalProps]?: 'createdAt' | 'deletedAt';
|
||||
|
||||
@ManyToOne(() => User)
|
||||
user: User;
|
||||
|
||||
@ManyToOne(() => Learning)
|
||||
learning: Learning;
|
||||
|
||||
@Property({ type: 'timestamptz', defaultRaw: 'CURRENT_TIMESTAMP' })
|
||||
watchedAt: Date;
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import { Collection, Entity, ManyToOne, OneToMany, Property, OptionalProps } from '@mikro-orm/core';
|
||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||
import { LearningCategory } from './learning-category.entity';
|
||||
import { LearningProgress } from './learning-progress.entity';
|
||||
|
||||
@Entity({ tableName: 'learnings' })
|
||||
export class Learning extends BaseEntity {
|
||||
[OptionalProps]?: 'createdAt' | 'deletedAt';
|
||||
|
||||
@Property({ type: 'varchar', length: 200 })
|
||||
title: string;
|
||||
|
||||
@Property({ type: 'text' })
|
||||
description: string;
|
||||
|
||||
@Property({ type: 'text' })
|
||||
coverUrl: string;
|
||||
|
||||
@Property({ type: 'text', nullable: true })
|
||||
videoUrl?: string;
|
||||
|
||||
@Property({ type: 'varchar', length: 200, nullable: true })
|
||||
videoDuration?: string;
|
||||
|
||||
@ManyToOne(() => LearningCategory)
|
||||
category: LearningCategory;
|
||||
|
||||
@OneToMany(() => LearningProgress, (learningProgress) => learningProgress.learning)
|
||||
learningProgress = new Collection<LearningProgress>(this);
|
||||
}
|
||||
Executable
+114
@@ -0,0 +1,114 @@
|
||||
import { Body, Controller, Delete, Get, Param, Patch, Post, UseGuards } from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
import { CreateLearningCategoryDto } from './DTO/create-learning-category.dto';
|
||||
import { CreateLearningDto } from './DTO/create-learning.dto';
|
||||
import { UpdateLearningCategoryDto } from './DTO/update-learning-category.dto';
|
||||
import { UpdateLearningDto } from './DTO/update-learning.dto';
|
||||
import { LearningService } from './providers/learning.service';
|
||||
import { AuthGuard } from '../auth/guards/auth.guard';
|
||||
import { AdminAuthGuard } from '../auth/guards/adminAuth.guard';
|
||||
import { Permissions } from 'src/common/decorators/permissions.decorator';
|
||||
import { UserId } from 'src/common/decorators';
|
||||
import { PermissionEnum } from 'src/common/enums/permission.enum';
|
||||
|
||||
@ApiTags('Learning')
|
||||
@ApiBearerAuth()
|
||||
@Controller('learnings')
|
||||
export class LearningController {
|
||||
constructor(private readonly learningService: LearningService) {}
|
||||
|
||||
// ----------------- Admin routes -----------------
|
||||
|
||||
@Post()
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
|
||||
@ApiOperation({ summary: 'Create learning video' })
|
||||
createLearningVideo(@Body() createDto: CreateLearningDto) {
|
||||
return this.learningService.createLearningVideo(createDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
|
||||
@ApiOperation({ summary: 'Delete learning video by id' })
|
||||
deleteLearningVideoById(@Param('id') id: string) {
|
||||
return this.learningService.deleteLearningVideoById(id);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
|
||||
@ApiOperation({ summary: 'Update learning video by id' })
|
||||
updateLearningVideoById(@Param('id') id: string, @Body() updateDto: UpdateLearningDto) {
|
||||
return this.learningService.updateLearningVideo(id, updateDto);
|
||||
}
|
||||
|
||||
@Post('category')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
|
||||
@ApiOperation({ summary: 'Create learning category' })
|
||||
createCategory(@Body() createDto: CreateLearningCategoryDto) {
|
||||
return this.learningService.createLearningCategory(createDto);
|
||||
}
|
||||
|
||||
@Patch('category/:id')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
|
||||
@ApiOperation({ summary: 'Update learning category' })
|
||||
updateLearningCategory(@Param('id') id: string, @Body() updateDto: UpdateLearningCategoryDto) {
|
||||
return this.learningService.updateLearningCategory(id, updateDto);
|
||||
}
|
||||
|
||||
@Delete('category/:id')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.MANAGE_LEARNINGS)
|
||||
@ApiOperation({ summary: 'Delete category by id' })
|
||||
deleteCategoryById(@Param('id') id: string) {
|
||||
return this.learningService.deleteCategoryById(id);
|
||||
}
|
||||
|
||||
// ----------------- Public / User routes -----------------
|
||||
|
||||
@Get()
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Find learnings video' })
|
||||
findAllLearnings() {
|
||||
return this.learningService.findLearningsVideos();
|
||||
}
|
||||
|
||||
@Get('category')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Find learning categories' })
|
||||
findCategories() {
|
||||
return this.learningService.findCategories();
|
||||
}
|
||||
|
||||
@Get('category/:id')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Find one learning category by id' })
|
||||
findCategoryById(@Param('id') id: string) {
|
||||
return this.learningService.findCategoryById(id);
|
||||
}
|
||||
|
||||
@Get('progress')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Get current user learning progress' })
|
||||
getUserProgress(@UserId() userId: string) {
|
||||
return this.learningService.getUserProgress(userId);
|
||||
}
|
||||
|
||||
@Post(':learningId/progress')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Track learning progress' })
|
||||
trackProgress(@UserId() userId: string, @Param('learningId') learningId: string) {
|
||||
return this.learningService.trackProgress(userId, learningId);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Find learning video by id' })
|
||||
findLearningVideoById(@Param('id') id: string) {
|
||||
return this.learningService.findLearningVideoById(id);
|
||||
}
|
||||
}
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { MikroOrmModule } from '@mikro-orm/nestjs';
|
||||
|
||||
import { Learning } from './entities/learning.entity';
|
||||
import { LearningCategory } from './entities/learning-category.entity';
|
||||
import { LearningProgress } from './entities/learning-progress.entity';
|
||||
import { LearningController } from './learning.controller';
|
||||
import { LearningService } from './providers/learning.service';
|
||||
import { LearningCategoryRepository } from './repositories/learning-category.repository';
|
||||
import { LearningProgressRepository } from './repositories/learning-progress.repository';
|
||||
import { LearningRepository } from './repositories/learning.repository';
|
||||
import { UserModule } from '../user/user.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MikroOrmModule.forFeature([Learning, LearningCategory, LearningProgress]),
|
||||
UserModule,
|
||||
],
|
||||
providers: [
|
||||
LearningService,
|
||||
LearningRepository,
|
||||
LearningCategoryRepository,
|
||||
LearningProgressRepository,
|
||||
],
|
||||
controllers: [LearningController],
|
||||
exports: [LearningService],
|
||||
})
|
||||
export class LearningModule {}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { CommonMessage, LearningMessage } from '../../../common/enums/message.enum';
|
||||
import { UserService } from '../../user/providers/user.service';
|
||||
import { CreateLearningCategoryDto } from '../DTO/create-learning-category.dto';
|
||||
import { CreateLearningDto } from '../DTO/create-learning.dto';
|
||||
import { UpdateLearningCategoryDto } from '../DTO/update-learning-category.dto';
|
||||
import { UpdateLearningDto } from '../DTO/update-learning.dto';
|
||||
import { LearningCategoryRepository } from '../repositories/learning-category.repository';
|
||||
import { LearningProgressRepository } from '../repositories/learning-progress.repository';
|
||||
import { LearningRepository } from '../repositories/learning.repository';
|
||||
|
||||
@Injectable()
|
||||
export class LearningService {
|
||||
constructor(
|
||||
private readonly learningRepository: LearningRepository,
|
||||
private readonly learningProgressRepository: LearningProgressRepository,
|
||||
private readonly learningCategoryRepository: LearningCategoryRepository,
|
||||
private readonly userService: UserService,
|
||||
private readonly em: EntityManager,
|
||||
) {}
|
||||
|
||||
async createLearningVideo(createDto: CreateLearningDto) {
|
||||
const { category } = await this.findCategoryById(createDto.categoryId);
|
||||
|
||||
const learning = this.learningRepository.create({ ...createDto, category });
|
||||
await this.em.persistAndFlush(learning);
|
||||
|
||||
return {
|
||||
message: CommonMessage.CREATED,
|
||||
learning,
|
||||
};
|
||||
}
|
||||
|
||||
async updateLearningVideo(learningId: string, updateDto: UpdateLearningDto) {
|
||||
const { learning } = await this.findLearningVideoById(learningId);
|
||||
|
||||
if (updateDto.categoryId) {
|
||||
const { category } = await this.findCategoryById(updateDto.categoryId);
|
||||
learning.category = category;
|
||||
}
|
||||
|
||||
this.em.assign(learning, updateDto);
|
||||
await this.em.flush();
|
||||
|
||||
return {
|
||||
message: CommonMessage.UPDATE_SUCCESS,
|
||||
learning,
|
||||
};
|
||||
}
|
||||
|
||||
async deleteLearningVideoById(learningId: string) {
|
||||
const { learning } = await this.findLearningVideoById(learningId);
|
||||
learning.deletedAt = new Date();
|
||||
await this.em.flush();
|
||||
|
||||
return {
|
||||
message: CommonMessage.DELETED,
|
||||
};
|
||||
}
|
||||
|
||||
async findLearningsVideos() {
|
||||
const learnings = await this.learningRepository.findAll();
|
||||
|
||||
return { learnings };
|
||||
}
|
||||
|
||||
async findLearningVideoById(id: string) {
|
||||
const learning = await this.learningRepository.findOne({ id });
|
||||
if (!learning) throw new BadRequestException(LearningMessage.NOT_FOUND);
|
||||
|
||||
return { learning };
|
||||
}
|
||||
|
||||
async createLearningCategory(createDto: CreateLearningCategoryDto) {
|
||||
const existCategory = await this.learningCategoryRepository.findOne({
|
||||
name: createDto.name,
|
||||
});
|
||||
if (existCategory) throw new BadRequestException(LearningMessage.CATEGORY_NAME_EXIST);
|
||||
|
||||
const category = this.learningCategoryRepository.create(createDto);
|
||||
await this.em.persistAndFlush(category);
|
||||
|
||||
return { category };
|
||||
}
|
||||
|
||||
async updateLearningCategory(categoryId: string, updateDto: UpdateLearningCategoryDto) {
|
||||
const category = await this.learningCategoryRepository.findOne({ id: categoryId });
|
||||
if (!category) throw new BadRequestException(LearningMessage.CATEGORY_NOT_FOUND);
|
||||
|
||||
if (updateDto.name) {
|
||||
const existCategory = await this.learningCategoryRepository.findOne({
|
||||
name: updateDto.name,
|
||||
id: { $ne: categoryId },
|
||||
});
|
||||
if (existCategory) throw new BadRequestException(LearningMessage.CATEGORY_NAME_EXIST);
|
||||
category.name = updateDto.name;
|
||||
}
|
||||
|
||||
await this.em.flush();
|
||||
|
||||
return {
|
||||
message: CommonMessage.UPDATE_SUCCESS,
|
||||
category,
|
||||
};
|
||||
}
|
||||
|
||||
async deleteCategoryById(categoryId: string) {
|
||||
await this.findCategoryById(categoryId);
|
||||
|
||||
const category = await this.learningCategoryRepository.findOneOrFail({ id: categoryId });
|
||||
category.deletedAt = new Date();
|
||||
await this.em.flush();
|
||||
|
||||
return {
|
||||
message: CommonMessage.DELETED,
|
||||
};
|
||||
}
|
||||
|
||||
async findCategories() {
|
||||
const categories = await this.learningCategoryRepository.findAll({
|
||||
filters: ['notDeleted'],
|
||||
});
|
||||
|
||||
return { categories };
|
||||
}
|
||||
|
||||
async findCategoryById(id: string) {
|
||||
const category = await this.learningCategoryRepository.findOne(
|
||||
{ id },
|
||||
{ filters: ['notDeleted'] },
|
||||
);
|
||||
if (!category) throw new BadRequestException(LearningMessage.CATEGORY_NOT_FOUND);
|
||||
|
||||
return { category };
|
||||
}
|
||||
|
||||
async trackProgress(userId: string, learningId: string) {
|
||||
const user = await this.userService.findOrFail(userId);
|
||||
const { learning } = await this.findLearningVideoById(learningId);
|
||||
|
||||
const progress = this.learningProgressRepository.create({
|
||||
user,
|
||||
learning,
|
||||
watchedAt: new Date(),
|
||||
});
|
||||
await this.em.persistAndFlush(progress);
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
async getUserProgress(userId: string) {
|
||||
return this.learningProgressRepository.find(
|
||||
{ user: { id: userId } },
|
||||
{ populate: ['learning'] },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
||||
import { LearningCategory } from '../entities/learning-category.entity';
|
||||
|
||||
@Injectable()
|
||||
export class LearningCategoryRepository extends EntityRepository<LearningCategory> {
|
||||
constructor(readonly em: EntityManager) {
|
||||
super(em, LearningCategory);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
||||
import { LearningProgress } from '../entities/learning-progress.entity';
|
||||
|
||||
@Injectable()
|
||||
export class LearningProgressRepository extends EntityRepository<LearningProgress> {
|
||||
constructor(readonly em: EntityManager) {
|
||||
super(em, LearningProgress);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
||||
import { Learning } from '../entities/learning.entity';
|
||||
|
||||
@Injectable()
|
||||
export class LearningRepository extends EntityRepository<Learning> {
|
||||
constructor(readonly em: EntityManager) {
|
||||
super(em, Learning);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Entity, Index, Property, OneToMany, Collection, Cascade, PrimaryKey, OptionalProps } from '@mikro-orm/core';
|
||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||
import { LearningProgress } from '../../learnings/entities/learning-progress.entity';
|
||||
// import { Order } from 'src/modules/order/entities/order.entity';
|
||||
import { normalizePhone } from '../../util/phone.util';
|
||||
import { ulid } from 'ulid';
|
||||
@@ -8,6 +9,9 @@ import { ulid } from 'ulid';
|
||||
export class User extends BaseEntity {
|
||||
[OptionalProps]?: 'createdAt' | 'deletedAt'
|
||||
|
||||
@OneToMany(() => LearningProgress, (lp) => lp.user)
|
||||
learningProgress = new Collection<LearningProgress>(this);
|
||||
|
||||
// @OneToMany(() => Order, order => order.user)
|
||||
// orders = new Collection<Order>(this);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user