1. Membuat Order dan List Order
1. Membuat Module, Controller, Service untuk order dan detail_order
terminal
npx nest g module app/order
npx nest g controller app/order
npx nest g service app/order
npx nest g module app/order_detail
npx nest g controller app/order_detail
npx nest g service app/order_detail
2. Membuat Entity order
order.entity.ts
import {
Entity,
BaseEntity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
JoinColumn,
OneToMany,
} from 'typeorm';
import { User } from '../auth/auth.entity';
import { Konsumen } from '../konsumen/konsumen.entity';
import { OrderDetail } from '../order_detail/detail_order.entity';
export enum Status {
BAYAR = 'bayar',
BELUM = 'belum bayar',
}
@Entity()
export class Order extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({ nullable: false })
nomor_order: string;
@Column({ nullable: false })
tanggal_order: Date;
@Column({
type: 'enum',
enum: Status,
default: Status.BELUM,
})
status: Status;
@Column({ type: 'double', precision: 18, scale: 2, nullable: false })
total_bayar: number;
@ManyToOne(() => Konsumen, (v) => v.order, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'konsumen_id' })
konsumen: Konsumen;
@ManyToOne(() => User)
@JoinColumn({ name: 'created_by' })
created_by: User;
@ManyToOne(() => User)
@JoinColumn({ name: 'updated_by' })
updated_by: User;
@OneToMany(() => OrderDetail, (v) => v.order, {
onDelete: 'CASCADE',
cascade: ['insert', 'update'],
})
order_detail: OrderDetail[];
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
created_at: Date;
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
updated_at: Date;
}
Note
@OneToMany(() => OrderDetail, (v) => v.order, {onDelete: 'CASCADE' cascade: ['insert', 'update'],})
Pada kode di atas, kita membuat relasi pada tabel order detail dengan menambkahkan
onDelete: 'CASCADE'
: ketika data di order di hapus , maka semua data yang adda di order_detail yang berelasi akan ikut di hapuscascade: ['insert', 'update']
: ketika insert dan update maka order detail juga akan dipebaharui.
3. Membuat Entity detail_order
order_detail.entity.ts
import {
Entity,
BaseEntity,
PrimaryGeneratedColumn,
Column,
ManyToOne,
JoinColumn,
} from 'typeorm';
import { User } from '../auth/auth.entity';
import { Produk } from '../produk/produk.entity';
import { Order } from '../order/order.entity';
@Entity()
export class OrderDetail extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({ nullable: false })
jumlah: number;
@ManyToOne(() => Produk, (v) => v.order_detail, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'produk_id' })
produk: Produk;
@ManyToOne(() => Order, (v) => v.order_detail, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'order_id' })
order: Order;
@ManyToOne(() => User)
@JoinColumn({ name: 'created_by' })
created_by: User;
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
created_at: Date;
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
updated_at: Date;
}
4. Membuat DTO pada order
order.dto.ts
import { OmitType, PartialType } from '@nestjs/mapped-types';
import { Type } from 'class-transformer';
import {
IsArray,
IsInt,
IsNotEmpty,
IsObject,
IsOptional,
IsString,
ValidateNested,
IsIn,
IsNumber,
IsDate,
} from 'class-validator';
import { PageRequestDto } from 'src/utils/dto/page.dto';
import { Status } from './order.entity';
import { OrderDetailDto } from '../order_detail/detail_order.dto';
export class OrderDto {
@IsInt()
id: number;
@IsString()
@IsOptional()
nomor_order: string;
@IsDate()
@IsNotEmpty()
tanggal_order: Date;
@IsString()
@IsNotEmpty()
@IsIn([Status.BAYAR, Status.BELUM])
status: Status;
@IsNumber()
@IsNotEmpty()
total_bayar: number;
@IsNumber()
@IsNotEmpty()
konsumen_id: number;
@IsObject()
@IsOptional()
updated_by: { id: number };
@IsObject()
@IsOptional()
created_by: { id: number };
@IsArray()
@ValidateNested({ each: true })
@Type(() => OrderDetailDto)
order_detail: OrderDetailDto[];
}
export class CreateOrderDto extends OmitType(OrderDto, ['id', 'updated_by']) {}
export class UpdateOrderDto extends PartialType(OrderDto) {
@IsInt()
@IsNotEmpty()
id: number;
}
export class CreateOrderArrayDto {
@IsArray()
@ValidateNested({ each: true })
@Type(() => CreateOrderDto)
data: CreateOrderDto[];
}
export class findAllOrderDto extends PageRequestDto {
@IsString()
@IsOptional()
nomor_order: string;
@IsString()
@IsOptional()
nama_konsumen: string;
@IsString()
@IsOptional()
dari_order_tanggal: Date;
@IsString()
@IsOptional()
sampai_order_tanggal: Date;
@IsOptional()
@IsNumber()
@Type(() => Number)
dari_total_bayar: number;
@IsOptional()
@IsNumber()
@Type(() => Number)
sampai_total_bayar: number;
@IsString()
@IsOptional()
status: string;
}
5. Membuat DTO pada detail_order
order_detail.dto.ts
import { OmitType } from '@nestjs/mapped-types';
import { IsInt, IsObject, IsOptional, IsNumber } from 'class-validator';
export class OrderDetailDto {
@IsInt()
@IsOptional()
id?: number;
@IsNumber()
jumlah: number;
@IsObject()
produk: { id: number };
@IsObject()
@IsOptional()
updated_by: { id: number };
@IsObject()
@IsOptional()
created_by: { id: number };
}
6. Membuat Endpoint create order
Service create order
order.service.ts
import {
HttpException,
HttpStatus,
Inject,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import BaseResponse from 'src/utils/response/base.response';
import { Between, Like, Repository } from 'typeorm';
import { Order } from './order.entity';
import { ResponsePagination, ResponseSuccess } from 'src/interface/response';
import { CreateOrderDto, UpdateOrderDto, findAllOrderDto } from './order.dto';
import { REQUEST } from '@nestjs/core';
import { Workbook } from 'exceljs';
import { Response } from 'express';
@Injectable()
export class OrderService extends BaseResponse {
constructor(
@InjectRepository(Order)
private readonly orderRepository: Repository<Order>,
@Inject(REQUEST) private req: any,
) {
super();
}
generateInvoice(): string {
return `INV` + new Date().getTime();
}
async createOrder(payload: CreateOrderDto): Promise<ResponseSuccess> {
try {
const invoice = this.generateInvoice();
payload.nomor_order = invoice;
payload.order_detail &&
payload.order_detail.forEach((item) => {
item.created_by = this.req.user.id;
});
await this.orderRepository.save({
...payload,
konsumen: {
id: payload.konsumen_id,
},
});
return this._success('OK');
} catch (err) {
console.log('err', err);
throw new HttpException('Ada Kesalahan', HttpStatus.UNPROCESSABLE_ENTITY);
}
}
}
Controller create order
order.controller.ts
import {
Controller,
Delete,
Get,
Param,
Post,
Put,
Res,
UseGuards,
} from '@nestjs/common';
import { OrderService } from './order.service';
import { JwtGuard } from '../auth/auth.guard';
import { InjectCreatedBy } from 'src/utils/decorator/inject-created_by.decorator';
import { CreateOrderDto, UpdateOrderDto, findAllOrderDto } from './order.dto';
import { Pagination } from 'src/utils/decorator/pagination.decorator';
import { InjectUpdatedBy } from 'src/utils/decorator/inject-updated_by.decorator';
import { Response } from 'express';
@UseGuards(JwtGuard)
@Controller('order')
export class OrderController {
constructor(private readonly orderService: OrderService) {}
@Post('tambah')
async createOrder(@InjectCreatedBy() payload: CreateOrderDto) {
return this.orderService.createOrder(payload);
}
}
Pengujian di Postman
payload
{
"tanggal_order" : "2023-09-01",
"status" : "belum bayar",
"total_bayar" : 200000,
"konsumen_id" : 1,
"order_detail" : [
{
"jumlah" : 10,
"produk" : {
"id" : 1
}
},
{
"jumlah" : 10,
"produk" : {
"id" : 3
}
}
]
}
Setelah success silahkan cek di tabel order dan tabel detail_order
tabel order
tabel order_detail
7. Membuat Endpoint list order
Service list order
order.service.ts
async findAll(query: findAllOrderDto): Promise<ResponsePagination> {
const {
page,
pageSize,
limit,
nomor_order,
dari_order_tanggal,
sampai_order_tanggal,
status,
dari_total_bayar,
sampai_total_bayar,
nama_konsumen,
} = query;
const filterQuery: any = [];
if (nomor_order) {
filterQuery.nomor_order = Like(`%${nomor_order}%`);
}
if (nama_konsumen) {
filterQuery.konsumen = {
nama_konsumen: Like(`%${nama_konsumen}%`),
};
}
if (status) {
filterQuery.status = Like(`%${status}%`);
}
if (dari_total_bayar && sampai_total_bayar) {
filterQuery.total_bayar = Between(dari_total_bayar, sampai_total_bayar);
}
if (dari_total_bayar && !!sampai_total_bayar === false) {
filterQuery.total_bayar = Between(dari_total_bayar, dari_total_bayar);
}
if (dari_order_tanggal && sampai_order_tanggal) {
filterQuery.tanggal_order = Between(
dari_order_tanggal,
sampai_order_tanggal,
);
}
if (dari_order_tanggal && !!sampai_order_tanggal === false) {
filterQuery.tanggal_order = Between(
dari_order_tanggal,
sampai_order_tanggal,
);
}
const total = await this.orderRepository.count({
where: filterQuery,
});
const result = await this.orderRepository.find({
where: filterQuery,
relations: [
'created_by',
'konsumen',
'order_detail',
'order_detail.produk',
],
select: {
id: true,
nomor_order: true,
status: true,
total_bayar: true,
tanggal_order: true,
konsumen: {
id: true,
nama_konsumen: true,
},
created_by: {
id: true,
nama: true,
},
order_detail: {
id: true,
jumlah: true,
produk: {
nama_produk: true,
},
},
},
skip: limit,
take: pageSize,
});
return this._pagination('OK', result, total, page, pageSize);
}
Controller list order
order.controller.ts
@Get('list')
async listOrder(@Pagination() query: findAllOrderDto) {
return this.orderService.findAll(query);
}