get orders, get order

김종민·2022년 7월 7일
0

Nuber-Server

목록 보기
28/34


들어가기
order를 확인하는 API
role에 따라 defensive를 해줘야 해서 햇갈릴 수 있으니 집중
get order와 get orders를 같이 다룬다.

1. orders/dto/ get-order, get-orders

1-1.get-order.dto.ts

import { Field, InputType, ObjectType, PickType } from '@nestjs/graphql';
import { MutationOutput } from 'src/common/dtos/output.dto';
import { Order } from '../entities/order.entity';

@InputType()
export class GetOrderInput extends PickType(Order, ['id']) {}
///Order entity의 id만 pick한다

@ObjectType()
export class GetOrderOutput extends MutationOutput {
  @Field(() => Order, { nullable: true })
  order?: Order;
}
///order를 return 받는다.

1-2.get-orders.dto.ts

import { Field, InputType, ObjectType } from '@nestjs/graphql';
import { MutationOutput } from 'src/common/dtos/output.dto';
import { Order, OrderStatus } from '../entities/order.entity';

@InputType()
export class GetOrdersInput {
  @Field(() => OrderStatus, { nullable: true })
  status?: OrderStatus;
}
///get Orders는 status(Pending, Cooking, Cooked등으로 분류할 수 있게 설정)

@ObjectType()
export class GetOrdersOutput extends MutationOutput {
  @Field(() => [Order], { nullable: true })
  orders?: Order[];
}
///Order배열을 return 받는다.

2. orders.resolver.ts

  @Query(() => GetOrdersOutput)
  @Role(['Any'])
  async getOrders(
    @AuthUser() user: User,
    @Args('input') getOrdersInput: GetOrdersInput,
  ): Promise<GetOrdersOutput> {
    return this.ordersService.getOrders(user, getOrdersInput);
  }
  ///user(loggedInUser)와 getOrdersInput을 입력받는다
  ///Role은 loggedInUser는 다 볼수 있게 Any로

  @Query(() => GetOrderOutput)
  @Role(['Any'])
  async getOrder(
    @AuthUser() user: User,
    @Args('input') getOrderInput: GetOrderInput,
  ): Promise<GetOrderOutput> {
    return this.ordersService.getOrder(user, getOrderInput);
  }
  ///user(loggedInUser)와 getOrdersInput을 입력받는다
  ///Role은 loggedInUser는 다 볼수 있게 Any로

3. orders.service.ts

    async getOrders(
    user: User,
    { status }: GetOrdersInput,
  ): Promise<GetOrdersOutput> {
    try {
      let orders: Order[];
      if (user.role === UserRole.Client) {
        orders = await this.orders.find({
          where: {
            customer: user,
            ...(status && { status }),
          },
        });
        ///orders를 let으로 배열로 일단 선언해 놓는다.
        ///input받은 user의 role이 Client이면,
        ///where:{ customer이 user인 곳에서 order를 찾는다.
        ///이어서 status(orderStatus)를 입력 받았으면,
        ///그에 맞는 status의 order만 분류한다.(pending, cooking, cooked...)
        
      } else if (user.role === UserRole.Delivery) {
        orders = await this.orders.find({
          where: {
            driver: user,
            ...(status && { status }),
          },
        });
        ///input받은 user의 role이 Delivery,
        ///where:{ driver가 user인 곳에서 order를 찾는다.
        ///이어서 status(orderStatus)를 입력 받았으면,
        ///그에 맞는 status의 order만 분류한다.(pending, cooking, cooked...)
        
      } else if (user.role === UserRole.Owner) {
        const restaurants = await this.restaurants.find({
          where: {
            owner: user,
          },
          relations: ['orders'],
        });
        ///loggedInUser가 owner이면, 식당을 찾는다, 그리고 relations로
        ///식당과 relation된 orders repository를 불러들인다.
        
        orders = restaurants.map((restaurant) => restaurant.orders).flat(1);
        ///owner가 식당을 여러개 가지고 있을 수 있기때문에,
        ///식당 여러개의 배열, 즉, 식당배열에 각 식당에 대한 order배열..
        ///2차원 배열을 .flat(1) 명령어로 orders를 1차원화 시킨다.
        
        if (status) {
          orders = orders.filter((order) => order.status === status);
        }
        ///위에서 찾은 orders에서, status가 같이 입력됬다면, 
        ///위에서 찾은 order에서 order.status가 입력된 status와 같은
        ///것만 filter한다.
      }
      return {
        ok: true,
        orders,
      };
      ///마지막으로 위애서 찾은 orders들을 return해준다.
      
    } catch {
      return {
        ok: false,
        error: 'Could not got orders',
      };
    }
  }

  canSeeOrder(user: User, order: Order): boolean {
    let canSee = true;
    if (user.role === UserRole.Client && order.customnerId !== user.id) {
      canSee = false;
    }
    if (user.role === UserRole.Delivery && order.driverId !== user.id) {
      canSee = false;
    }
    if (user.role === UserRole.Owner && order.restaurant.ownerId !== user.id) {
      canSee = false;
    }
    return canSee;
  }
  ///getOrder에서 사용하기 위해 만든 API
  /// user와 order를 압력받아서 조건에 따라 true, false를 return함.
  ///order의 customerId, driverId, restaurant.ownerId 와 loggedInUser와
  ///같은 사람만 true를 return받게~
  ///order Entity에 customerId, driverId를 relationId로 설정해준다.
  
  
 ______________________________________________order.entity.ts
  export class Order extends CoreEntity {
  @Field(() => User, { nullable: true })
  @ManyToOne(() => User, (user) => user.orders, {
    onDelete: 'SET NULL',
    nullable: true,
  })
  customer?: User;

  @RelationId((order: Order) => order.customer)
  customnerId: number;

  @Field(() => User, { nullable: true })
  @ManyToOne(() => User, (user) => user.rides, {
    onDelete: 'SET NULL',
    nullable: true,
  })
  driver?: User;

  @RelationId((order: Order) => order.driver)
  driverId: number; 
______________________________________________________________
  
  

  async getOrder(
    user: User,
    { id: orderId }: GetOrderInput,
  ): Promise<GetOrderOutput> {
    try {
      const order = await this.orders.findOne(orderId, {
        relations: ['restaurant'],
      });
      ///입력받은 id로 order를 찾고, 관련된 restaurant를 불러준다.
      
      if (!order) {
        return {
          ok: false,
          error: 'Order not found',
        };
      }

      if (!this.canSeeOrder(user, order)) {
        return {
          ok: false,
          error: 'You can not see that!',
        };
      }
      ///canSeeOrder API에 user와 order를 보내주어서
      ///false를 받는다면 if(!this.canSeeOrder(user, order))
      ///return{ ok:fasle }로 error를 보낸다.
      
      return {
        ok: true,
        order,
      };
      ///canSeeOrder가 !가 아니라면, ok:true, order를 return한다.
      
    } catch {
      return {
        ok: false,
        error: 'Could not load order',
      };
    }
  }

어렵지만, 힘내자!!!!!!!!!!!

profile
코딩하는초딩쌤

0개의 댓글