File

packages/server/src/modules/order/order.service.ts

Index

Methods

Constructor

constructor(em: EntityManager, repo: Repository, repoCate: Repository<OrderCategoryEntity>, repoPro: Repository<OrderProductEntity>, customerService: CustomerService, request)
Parameters :
Name Type Optional
em EntityManager No
repo Repository<OrderEntity> No
repoCate Repository<OrderCategoryEntity> No
repoPro Repository<OrderProductEntity> No
customerService CustomerService No
request No

Methods

Async all
all(query: OrderQuery, user: ActiveUserData)
Parameters :
Name Type Optional
query OrderQuery No
user ActiveUserData No
Returns : Promise<literal type>
Async changeStatus
changeStatus(id: number, body: OrderStatusRequest)
Parameters :
Name Type Optional
id number No
body OrderStatusRequest No
Returns : Promise<OrderEntity>
Async create
create(body: OrderRequest, user: ActiveUserData)
Parameters :
Name Type Optional
body OrderRequest No
user ActiveUserData No
Returns : Promise<OrderEntity>
Async getById
getById(id?: number)
Parameters :
Name Type Optional
id number Yes
Returns : Promise<OrderEntity | null>
Async getByIdWithCategories
getByIdWithCategories(id?: number)
Parameters :
Name Type Optional
id number Yes
Returns : unknown
Async getByIdWithError
getByIdWithError(id?: number)
Parameters :
Name Type Optional
id number Yes
Returns : Promise<OrderEntity>
Async remove
remove(id: number)
Parameters :
Name Type Optional
id number No
Returns : unknown
Async saveData
saveData(child: OrderEntity, body: OrderRequest, remove)
Parameters :
Name Type Optional Default value
child OrderEntity No
body OrderRequest No
remove No false
Returns : unknown
Async update
update(id: number, body: OrderRequest)
Parameters :
Name Type Optional
id number No
body OrderRequest No
Returns : Promise<OrderEntity>
import * as _ from "lodash";
import {
  Between,
  EntityManager,
  In,
  LessThan,
  MoreThan,
  Repository,
} from "typeorm";
import { ApiStatusCode } from "@bill/database";
import {
  OrderCategoryEntity,
  OrderEntity,
  OrderProductEntity,
  ProductCategoryEntity,
  ProductEntity,
  UserEntity,
} from "@bill/database/dist/entities";
import { OrderStatus } from "@bill/database/dist/enums/OrderStatus";
import { HttpStatus, Inject, Injectable } from "@nestjs/common";
import { REQUEST } from "@nestjs/core";
import { InjectRepository } from "@nestjs/typeorm";

import { ApiException } from "@/common/exception/api.exception";
import { ActiveUserData } from "@/common/interfaces/active-user-data.interface";
import dataFilter from "@/common/utils/dataFilter";

import { CustomerService } from "../customer/customer.service";
import {
  OrderProduct,
  OrderQuery,
  OrderRequest,
  OrderStatusRequest,
} from "./order.interface";

@Injectable()
export class OrderService {
  constructor(
    private em: EntityManager,
    @InjectRepository(OrderEntity) private repo: Repository<OrderEntity>,
    @InjectRepository(OrderCategoryEntity)
    private repoCate: Repository<OrderCategoryEntity>,
    @InjectRepository(OrderProductEntity)
    private repoPro: Repository<OrderProductEntity>,
    private customerService: CustomerService,
    @Inject(REQUEST) private request: Request & { userEntity: UserEntity }
  ) {}

  async all(
    query: OrderQuery,
    user: ActiveUserData
  ): Promise<{ rows: OrderEntity[]; count: number }> {
    const { startDate, endDate, ...rest } = query.where ?? {};
    const whereClause = {
      ...rest,

      ...(startDate && endDate
        ? {
            createTime: Between(startDate, endDate),
          }
        : {}),

      ...dataFilter(this.request.userEntity),
    };
    const [rows, count] = await this.repo.findAndCount({
      skip: query.skip,
      take: query.take,
      where: whereClause,
      relations: {
        customer: true,
      },
    });

    return {
      rows,
      count,
    };
  }

  async getById(id?: number): Promise<OrderEntity | null> {
    const data = await this.repo.findOne({
      where: {
        id,
      },
    });

    return data || null;
  }

  async getByIdWithError(id?: number): Promise<OrderEntity> {
    const order = await this.getById(id);

    if (!order) {
      throw new ApiException(
        "can not find record",
        ApiStatusCode.KEY_NOT_EXIST,
        HttpStatus.OK,
        {
          id: id,
          type: "OrderEntity",
        }
      );
    }

    return order;
  }

  async getByIdWithCategories(id?: number) {
    await this.getByIdWithError(id);

    const categories = (await this.repoCate.find({
      where: {
        orderId: id,
      },
      relations: {
        category: true,
      },
    })) as (OrderCategoryEntity & {
      products: OrderProduct[];
    })[];

    const categoryProducts = await this.repoPro.find({
      where: {
        orderCategory: {
          id: In(categories.map((c) => c.id)),
        },
      },
      relations: {
        orderCategory: true,
        product: {
          unit: true,
        },
      },
    });

    const categoryMap = _.keyBy(categories, "id");

    for (const cp of categoryProducts) {
      const category = categoryMap[cp.orderCategory.id];

      if (category) {
        if (!category.products) {
          category.products = [];
        }
        category.products.push(cp);
      }
    }

    return categories;
  }

  async saveData(child: OrderEntity, body: OrderRequest, remove = false) {
    const customer = await this.customerService.getByIdWithError(
      body.customerId
    );
    return await this.em.transaction(async (entityManager: EntityManager) => {
      const order = await entityManager.save(OrderEntity, {
        ...child,
        totalPrice: 0,
        no: body.no,
        discount: customer.discount,
        status: OrderStatus.UNPAYED,
        customer: customer,
      });
      const categories: Promise<unknown>[] = [];
      const products: Promise<unknown>[] = [];

      if (remove) {
        await this.repoPro.delete({
          orderId: order.id,
        });
        await this.repoCate.delete({
          orderId: order.id,
        });
      }

      order.totalPrice = 0;

      for (const c of body.categories) {
        const productCategory =
          await entityManager.findOneByOrFail<ProductCategoryEntity>(
            ProductCategoryEntity,
            {
              id: c.productCategoryId,
            }
          );

        const orderCategory = new OrderCategoryEntity().extend({
          category: productCategory,
          orderId: order.id,
          name: c.name,
        });
        categories.push(entityManager.save(orderCategory));

        for (const p of c.products) {
          const product = await entityManager.findOneByOrFail(ProductEntity, {
            id: p.productId,
          });

          const orderProduct = new OrderProductEntity().extend({
            productId: p.productId,
            name: product.name,
            price: p.price,
            discount: p.discount,
            count: p.count,
            orderCategory: orderCategory,
            orderId: order.id,
            totalPrice: p.count * p.price * (p.discount / 100),
          });

          order.totalPrice += orderProduct.totalPrice;

          products.push(entityManager.save(orderProduct));
        }
      }
      await entityManager.save(OrderEntity, order);
      await Promise.all([
        ...categories,
        ...products,
        // entityManager.save(order),
      ]).catch((e) => {
        throw e;
      });

      return order;
    });
  }

  async create(body: OrderRequest, user: ActiveUserData): Promise<OrderEntity> {
    const { categories, ...rest } = body;
    const order = new OrderEntity().extend({
      ...rest,
      companyId: user.companyId,
      userId: user.id,
    });

    return this.saveData(order, body);
  }

  async update(id: number, body: OrderRequest): Promise<OrderEntity> {
    const order = await this.getByIdWithError(id);
    const { categories, ...rest } = body;

    order.extend(rest);

    return this.saveData(order, body, true);
  }

  async changeStatus(
    id: number,
    body: OrderStatusRequest
  ): Promise<OrderEntity> {
    const order = await this.getByIdWithError(id);

    if (order.status !== OrderStatus.UNPAYED) {
      throw new ApiException(
        "Status has been closed.",
        ApiStatusCode.UNKOWN_ERROR,
        HttpStatus.OK
      );
    }

    if (body.status === OrderStatus.UNPAYED) {
      return order;
    }

    order.extend(body);

    return this.em.save(OrderEntity, order);
  }

  async remove(id: number) {
    const customer = await this.getByIdWithError(id);

    return this.repo.softRemove(customer);
  }
}

results matching ""

    No results matching ""