No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Resolviendo la relación muchos a muchos personalizada en el controlador

26/33
Recursos

Aportes 9

Preguntas 2

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

Un curso de pruebas unitarias para Nest estaría increíble! 🤩.
Sería un PLUS para aprender todas las bases 😎.

Yo sí que quiero un curso de pruebas unitarias en Nest

Un curso de TDD (Test Driven Development) con NestJS estaría genial.

Mis apuntes

nest g s users/services/orders --flat
nest g co users/controllers/orders --flat
nest g co users/services/order-item --flat
nest g co users/controllers/order-item --flat
// src\users\dtos\order.dto.ts
import { ApiProperty, PartialType } from "@nestjs/swagger";
import { IsNotEmpty, IsPositive } from "class-validator";

export class CreateOrderDto {
  @IsPositive()
  @IsNotEmpty()
  @ApiProperty()
  readonly customerId: number;

}

export class UpdateOrderDto extends PartialType(CreateOrderDto){}
// src\users\services\orders.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateOrderDto, UpdateOrderDto } from '../dtos/order.dto';
import { Customer } from '../entities/customer.entity';
import { Order } from '../entities/order.entity';

@Injectable()
export class OrdersService {
  constructor(
    @InjectRepository(Order) private orderRepo:Repository<Order>,
    @InjectRepository(Customer) private customerRepo:Repository<Customer>
  ){}

  findAll(){
    return this.orderRepo.find();
  }

  async findOne(id: number){
    const order = await this.orderRepo.findOne(id);
    if(!order) {
      throw new NotFoundException(`order ${id} not found`);
    } 
    return order;
  }

  async create(data: CreateOrderDto){
    const order = new Order();
    if (data.customerId) {
      const customer = await this.customerRepo.findOne(data.customerId);
      order.customer = customer;
    }
    return this.orderRepo.save(order);
  }

  async update(id:number, changes:UpdateOrderDto){
    const order = await this.orderRepo.findOne(id);
    if (changes.customerId) {
      const customer = await this.customerRepo.findOne(changes.customerId);
      order.customer = customer;
    }
    return this.orderRepo.save(order);
  }

  delete(id:number){
    return this.orderRepo.delete(id);
  }
}
// src\users\controllers\orders.controller.ts
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Post, Put } from '@nestjs/common';
import { CreateOrderDto, UpdateOrderDto } from '../dtos/order.dto';
import { OrdersService } from '../services/orders.service';

@Controller('orders')
export class OrdersController {
  
  constructor(private ordersService: OrdersService){}

  @Get('')
  findAll(){
    return this.ordersService.findAll();
  }

  @Get(':id')
  findOne(
    @Param('id', ParseIntPipe) id: number
  ){
    return this.ordersService.findOne(id);
  }

  @Post('')
  create(@Body() payload: CreateOrderDto){
    return this.ordersService.create(payload);
  }

  @Put(':id')
  update(
    @Param('id', ParseIntPipe) id:number,
    @Body() payload: UpdateOrderDto
  ){
    return this.ordersService.update(id, payload);
  }

  @Delete(':id')
  delete(@Param('id') id: number){
    return this.ordersService.delete(id);
  }
}
// src\users\dtos\order-item.dto.ts
import { ApiProperty, PartialType } from "@nestjs/swagger";
import { IsNotEmpty, IsNumber, IsPositive } from "class-validator";

export class CreateOrderItemDto {
  @IsNumber()
  @IsPositive()
  @IsNotEmpty()
  @ApiProperty()
  readonly orderId: number;

  @IsNumber()
  @IsPositive()
  @IsNotEmpty()
  @ApiProperty()
  readonly productId: number;

  @IsNumber()
  @IsPositive()
  @IsNotEmpty()
  @ApiProperty()
  readonly quantity: number;
}

export class UpdateOrderItemDto extends PartialType(CreateOrderItemDto){}
// src\products\products.module.ts
@Module({
  ...
  exports: [..., TypeOrmModule], // export TypeOrmModule
})
export class ProductsModule {}
// src\users\services\order-item.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Product } from 'src/products/entities/product.entity';
import { Repository } from 'typeorm';
import { CreateOrderItemDto, UpdateOrderItemDto } from '../dtos/order-item.dto';
import { OrderItem } from '../entities/order-item.entity';
import { Order } from '../entities/order.entity';

@Injectable()
export class OrderItemService {
  constructor(
    @InjectRepository(Product) private productRepo:Repository<Product>,
    @InjectRepository(Order) private orderRepo:Repository<Order>,
    @InjectRepository(OrderItem) private orderItemRepo: Repository<OrderItem>
  ){}

  async create(data: CreateOrderItemDto){
    const order = await this.orderRepo.findOne(data.orderId);
    const product = await this.productRepo.findOne(data.productId);
    const newOrderItem = new OrderItem();
    newOrderItem.order = order;
    newOrderItem.product = product;
    newOrderItem.quantity = data.quantity;
    return this.orderItemRepo.save(newOrderItem)
  }
}
// src\users\controllers\order-item.controller.ts
import { Body, Controller, Post } from '@nestjs/common';
import { CreateOrderItemDto } from '../dtos/order-item.dto';
import { OrderItemService } from '../services/order-item.service';

@Controller('order-item')
export class OrderItemController {
  
  constructor(private orderItemService: OrderItemService){}
  
  @Post('')
  create(@Body() payload: CreateOrderItemDto){
    return this.orderItemService.create(payload);
  }
}
// src\users\services\orders.service.ts
async findOne(id: number){
    const order = await this.orderRepo.findOne(id, {
      relations: ["items", "items.product"] // Agregamos relacion
    });
    if(!order) {
      throw new NotFoundException(`order ${id} not found`);
    } 
    return order;
  }

Cuando usan el comando generate del CLI pueden pasarle el argumento --no-spec para que no cree los archivos para pruebas unitarias

Mi Solucion al Reto

findAll, findOne, update, delete

// src\users\services\order-item.service.ts
findAll(){
    return this.orderItemRepo.find({
      relations: ['order', 'order.customer']
    });
  }

  findOne(id: number){
    return this.orderItemRepo.findOne(id,{
      relations: ['order', 'product']
    });
  }

async update(id: number, changes: UpdateOrderItemDto){
  const orderItem = await this.orderItemRepo.findOne(id);
  if (changes.orderId) {
    const order = await this.orderRepo.findOne(changes.orderId);
    orderItem.order = order;
  }
  if (changes.productId) {
    const product = await this.productRepo.findOne(changes.productId);
    orderItem.product = product;
  }
  if(changes.quantity){
    orderItem.quantity = changes.quantity;
  }
  return this.orderItemRepo.save(orderItem);
}

delete(id: number){
  return this.orderItemRepo.delete(id);
}
//  src\users\controllers\order-item.controller.ts
@Get('')
findAll(){
  return this.orderItemService.findAll();
}

@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number){
  return this.orderItemService.findOne(id);
}

@Put(':id')
update(
  @Param('id', ParseIntPipe) id: number,
  @Body() payload: UpdateOrderItemDto
){
  return this.orderItemService.update(id, payload);
}

@Delete(':id')
delete(@Param('id') id: number){
  return this.orderItemService.delete(id);
}

Un curso de prueba unitarias en Nest js Por favor

Otro tip, pueden usar nest generate resource <nombre-del-recurso> para autogenerar un CRUD (link):

$ nest g resource users

> ? What transport layer do you use? GraphQL (code first)
> ? Would you like to generate CRUD entry points? Yes
> CREATE src/users/users.module.ts (224 bytes)
> CREATE src/users/users.resolver.spec.ts (525 bytes)
> CREATE src/users/users.resolver.ts (1109 bytes)
> CREATE src/users/users.service.spec.ts (453 bytes)
> CREATE src/users/users.service.ts (625 bytes)
> CREATE src/users/dto/create-user.input.ts (195 bytes)
> CREATE src/users/dto/update-user.input.ts (281 bytes)
> CREATE src/users/entities/user.entity.ts (187 bytes)
> UPDATE src/app.module.ts (312 bytes)

Esta super bien la clase, pero como sujerencia estas deben ser mas cortas. Lo ideal es que duren un maximo de 10 minutos porque de lo contrario es mayor el esfuerzo mental que un alumno debe hacer y facilmente pierda el hilo del tema.