Search code examples
typescriptormnestjsnode.js-typeormnestjs-typeorm

How establish typeorm relation between orders & products?


I am using TypeOrm. This is my Orders Entity file:

@Entity('orders')
export class OrdersEntity {
  @PrimaryGeneratedColumn('uuid') id: string;

  @CreateDateColumn() created: Date;

  @UpdateDateColumn() updated: Date;

  @Column('text', { default: StatusEnum.PROCESSING }) status: string;

  // relationships

  @ManyToOne(type => UsersEntity, customer => customer.orders)
  customer: UsersEntity;

  @OneToMany(type => ProductsEntity, products => products.order, {cascade: true})
  products: ProductsEntity[];
}

This is my Products Entity:

export class ProductsEntity {
  @PrimaryGeneratedColumn('uuid') id: string;

  @CreateDateColumn() created: Date;

  @UpdateDateColumn() updated: Date;

  @Column({ type: 'text', unique: true }) name: string;

  @Column('text') description: string;

  @Column('integer') unitsOnStock: number;

  @Column('numeric', { precision: 10, scale: 2 }) price: number;

  // relationships

  @ManyToOne(type => CategoriesEntity, category => category.products)
  category: CategoriesEntity;

  @ManyToOne(type => OrdersEntity, order => order.products)
  order: OrdersEntity;
}

and there is a function in orders.service.ts to create new order:

  async create(data: OrdersDto, userId: string) {
    const { productsArray } = data;
    // const products2: ProductWithQuantity[] = [];
    const products: ProductsEntity[] = [];
    for (const productItem of productsArray) {
      const product = await this.productsRepository.findOne({
        where: { id: productItem.productId },
      });
      if (!product) {
        throw new HttpException("Product's ID not found", HttpStatus.NOT_FOUND);
      }
      if (product.unitsOnStock - productItem.quantity < 0) {
        throw new HttpException('Insufficient stock', HttpStatus.BAD_REQUEST);
      } else {
        // products2.push({ product, quantity: productItem.quantity });
        products.push({ ...product });
      }
    }
    const user = await this.usersRepository.findOne({ where: { id: userId } });

    for (const productItem of productsArray) {
      const product = await this.productsRepository.findOne({
        where: { id: productItem.productId },
      });
      await this.productsRepository.update(product.id, {
        unitsOnStock: product.unitsOnStock - productItem.quantity,
      });
    }

    const order = await this.ordersRepository.create({
      products,
      customer: user,
    });

    await this.ordersRepository.save(order);
    return order;
  }

I want in orders table to have another column with array which would contain objects {productId: string, quantity: string} for each order.

I tried using @JoingTable but it didnt work...

I will be glad for any ideas, thanks in advance!


Solution

  • There is no point in doing this the way you described. Proper approach would be creating another table for actual products that are placed in order. I suggest something like this

    @Entity('order_items')
    export class OrderItemEntity {
    @PrimaryGeneratedColumn('uuid')
    id: string;
    
    @Column('uuid')
    productId: string;
    
    @Column()
    quantity: number;
    
    @ManyToOne(() => OrdersEntity, order => order.orderItems)
    order: OrdersEntity;
    }