Advertisement
dangl1n

Untitled

Apr 9th, 2025
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
TypeScript 5.10 KB | Source Code | 0 0
  1. import { Injectable, Controller, Post, Body, Get, Param, UseGuards, BadRequestException, NotFoundException, UnauthorizedException, Module } from '@nestjs/common';
  2. import { InjectRepository } from '@nestjs/typeorm';
  3. import { Repository, Entity, Column, PrimaryGeneratedColumn, ManyToOne } from 'typeorm';
  4. import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
  5. import { JwtService } from '@nestjs/jwt';
  6. import { AuthGuard } from '@nestjs/passport';
  7. import { validate } from 'class-validator';
  8. import * as bcrypt from 'bcrypt';
  9. import { IsString, IsEmail, MinLength, IsNumber, IsPositive } from 'class-validator';
  10. import { InjectQueue } from '@nestjs/bull';
  11. import { Queue } from 'bull';
  12.  
  13. @Entity()
  14. export class User {
  15.   @PrimaryGeneratedColumn()
  16.   id: number;
  17.  
  18.   @Column()
  19.   @IsString()
  20.   name: string;
  21.  
  22.   @Column({ unique: true })
  23.   @IsEmail()
  24.   email: string;
  25.  
  26.   @Column()
  27.   @IsString()
  28.   @MinLength(8)
  29.   password: string;
  30. }
  31.  
  32. @Entity()
  33. export class Order {
  34.   @PrimaryGeneratedColumn()
  35.   id: number;
  36.  
  37.   @ManyToOne(() => User, (user) => user.id)
  38.   user: User;
  39.  
  40.   @Column()
  41.   @IsNumber()
  42.   @IsPositive()
  43.   totalPrice: number;
  44.  
  45.   @Column({ default: 'pending' })
  46.   status: string;
  47. }
  48.  
  49.  
  50. export class CreateOrderDto {
  51.   @IsNumber()
  52.   @IsPositive()
  53.   totalPrice: number;
  54. }
  55.  
  56. @Injectable()
  57. export class OrderService {
  58.   private readonly saltRounds = 10;
  59.  
  60.   constructor(
  61.     @InjectRepository(User)
  62.     private readonly userRepository: Repository<User>,
  63.     @InjectRepository(Order)
  64.     private readonly orderRepository: Repository<Order>,
  65.     private readonly jwtService: JwtService,
  66.     @InjectQueue('notifications')
  67.     private readonly notificationQueue: Queue,
  68.   ) {}
  69.  
  70.   async register(name: string, email: string, password: string): Promise<{ accessToken: string }> {
  71.     const existingUser = await this.userRepository.findOne({ where: { email } });
  72.     if (existingUser) {
  73.       throw new BadRequestException('Email уже занят');
  74.     }
  75.  
  76.     const hashedPassword = await bcrypt.hash(password, this.saltRounds);
  77.     const user = this.userRepository.create({ name, email, password: hashedPassword });
  78.     await this.userRepository.save(user);
  79.  
  80.     const payload = { sub: user.id, email: user.email };
  81.     return { accessToken: this.jwtService.sign(payload) };
  82.   }
  83.  
  84.   async createOrder(userId: number, createOrderDto: CreateOrderDto): Promise<Order> {
  85.     const user = await this.userRepository.findOne({ where: { id: userId } });
  86.     if (!user) {
  87.       throw new NotFoundException('Пользователь не найден');
  88.     }
  89.  
  90.     const errors = await validate(createOrderDto);
  91.     if (errors.length > 0) {
  92.       throw new BadRequestException('Некорректные данные заказа');
  93.     }
  94.  
  95.     let { totalPrice } = createOrderDto;
  96.  
  97.     if (totalPrice > 1000) {
  98.       totalPrice *= 0.9; // скидка
  99.     }
  100.  
  101.     const order = this.orderRepository.create({ user, totalPrice, status: 'pending' });
  102.     await this.orderRepository.save(order);
  103.  
  104.     await this.notificationQueue.add('sendOrderConfirmation', {
  105.       userId: user.id,
  106.       orderId: order.id,
  107.       email: user.email,
  108.     });
  109.  
  110.     return order;
  111.   }
  112.  
  113.   async getOrderStatus(orderId: number): Promise<string> {
  114.     const order = await this.orderRepository.findOne({ where: { id: orderId } });
  115.     if (!order) {
  116.       throw new NotFoundException('Заказ не найден');
  117.     }
  118.     return order.status;
  119.   }
  120.  
  121.   async updateOrderStatus(orderId: number, status: string): Promise<void> {
  122.     const order = await this.orderRepository.findOne({ where: { id: orderId } });
  123.     if (!order) {
  124.       throw new NotFoundException('Заказ не найден');
  125.     }
  126.  
  127.     order.status = status;
  128.     await this.orderRepository.save(order);
  129.  
  130.     if (status === 'completed') {
  131.       await this.notificationQueue.add('sendOrderCompleted', {
  132.         orderId: order.id,
  133.         email: order.user.email,
  134.       });
  135.     }
  136.   }
  137. }
  138.  
  139. @ApiTags('orders')
  140. @Controller('orders')
  141. export class OrderController {
  142.   constructor(private readonly orderService: OrderService) {}
  143.  
  144.   @Post('register')
  145.   async register(@Body() body: { name: string; email: string; password: string }) {
  146.     return this.orderService.register(body.name, body.email, body.password);
  147.   }
  148.  
  149.   @Post()
  150.   @UseGuards(AuthGuard('jwt'))
  151.   @ApiBearerAuth()
  152.   async createOrder(@Body() createOrderDto: CreateOrderDto, @Param('userId') userId: number) {
  153.     return this.orderService.createOrder(userId, createOrderDto);
  154.   }
  155.  
  156.   @Get(':orderId/status')
  157.   @UseGuards(AuthGuard('jwt'))
  158.   @ApiBearerAuth()
  159.   async getOrderStatus(@Param('orderId') orderId: string) {
  160.     return this.orderService.getOrderStatus(+orderId);
  161.   }
  162.  
  163.   @Post(':orderId/status')
  164.   @UseGuards(AuthGuard('jwt'))
  165.   @ApiBearerAuth()
  166.   async updateOrderStatus(@Param('orderId') orderId: string, @Body('status') status: string) {
  167.     await this.orderService.updateOrderStatus(+orderId, status);
  168.     return { message: 'Статус обновлен' };
  169.   }
  170. }
  171.  
  172. @Module({
  173.   providers: [OrderService],
  174.   controllers: [OrderController],
  175. })
  176. export class AppModule {}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement