Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "dotenv -e .env.test -- jest",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
Expand All @@ -23,7 +23,7 @@
"docker:up": "docker-compose -f docker-compose.yaml up -d",
"docker:down": "docker-compose -f docker-compose.yaml down -v",
"migrate:test": "dotenv -e .env.test -- npx prisma migrate deploy",
"seed:test": "dotenv -e .env.test -- npx prisma db seed"
"seed:test": "npx prisma db seed"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

seed:test 스크립트에서 dotenv -e .env.test --가 제거되었습니다. migrate:test 스크립트에는 남아있는데, 이로 인해 seed:test 실행 시 .env.test 파일의 환경 변수를 읽지 못할 수 있습니다. prisma/seed.tsDATABASE_URL 같은 환경 변수에 의존한다면, 테스트 시드 데이터 생성에 실패할 수 있습니다. 일관성을 위해 seed:test 스크립트에도 dotenv-cli를 사용하거나, Jest 설정 등 다른 방식으로 환경 변수를 주입하는 것을 고려해 보세요.

Suggested change
"seed:test": "npx prisma db seed"
"seed:test": "dotenv -e .env.test -- npx prisma db seed"

},
"dependencies": {
"@nestjs/common": "^10.0.0",
Expand All @@ -33,6 +33,8 @@
"@nestjs/swagger": "^8.1.0",
"@nestjs/typeorm": "^10.0.2",
"@prisma/client": "^6.1.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"cross-env": "^7.0.3",
"dotenv": "^16.4.7",
"mysql2": "^3.9.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ CREATE TABLE `order_item` (
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`updated_at` TIMESTAMP(0) NOT NULL,

UNIQUE INDEX `order_item_product_id_key`(`product_id`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Expand Down Expand Up @@ -70,6 +69,7 @@ CREATE TABLE `product` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`price` INTEGER NOT NULL,
`status` BOOLEAN NOT NULL DEFAULT true,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`updated_at` TIMESTAMP(0) NOT NULL,

Expand Down
4 changes: 2 additions & 2 deletions prisma/schema/coupon.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ model Coupon {
name String @db.VarChar(50)
discountType String @map("discount_type") @db.VarChar(10)
discountValue Int @map("discount_value") @db.Int
status Boolean @default(true)
status String @default("AVAILABLE")
startAt DateTime @map("start_at") @db.Timestamp(0)
endAt DateTime @map("end_at") @db.Timestamp(0)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamp(0)
couponQuantity CouponQuantity?
UserCoupon UserCoupon?
userCoupon UserCoupon?

@@map("coupon")
}
2 changes: 1 addition & 1 deletion prisma/schema/order-item.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ model OrderItem {
order Order @relation(fields: [orderId], references: [id])
orderId Int @map("order_id")
product Product @relation(fields: [productId], references: [id])
productId Int @unique @map("product_id")
productId Int @map("product_id")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

productId 필드에서 @unique 제약조건을 제거한 것은 올바른 수정입니다. 하지만 일반적으로 하나의 주문에 동일한 상품이 여러 항목으로 들어가는 것을 방지하기 위해 orderIdproductId에 대한 복합 고유 키(composite unique key)를 설정하는 것이 좋습니다. 모델 하단에 @@unique([orderId, productId])를 추가하는 것을 고려해 보세요.

quantity Int
price Int
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
Expand Down
5 changes: 3 additions & 2 deletions prisma/schema/product.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ model Product {
id Int @id @default(autoincrement())
name String @db.VarChar(50)
price Int @db.Int
status String @default("IN_STOCK")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamp(0)
orderItem OrderItem?
ProductQuantity ProductQuantity?
orderItem OrderItem[]
productQuantity ProductQuantity?

@@map("product")
}
2 changes: 1 addition & 1 deletion prisma/schema/user-coupon.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ model UserCoupon {
usedAt DateTime @map("used_at") @db.Timestamp(0)
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamp(0)
Order Order?
order Order?

@@map("user_coupon")
}
2 changes: 1 addition & 1 deletion prisma/schema/user.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ model User {
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime @updatedAt @map("updated_at") @db.Timestamp(0)
order Order[]
UserCoupon UserCoupon?
userCoupon UserCoupon?

@@map("user")
}
51 changes: 45 additions & 6 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,53 @@ async function initTable() {
}

async function createMockData() {
await prisma.user.create({
data: { balance: 10000 },
});
await Promise.all(
Array.from({ length: 10 }, () =>
prisma.user.create({
data: { balance: 10000 },
}),
),
);

//사용자 생성
await Promise.all(
Array.from({ length: 10 }, () =>
prisma.user.create({
data: { balance: 10000 },
}),
),
);
Comment on lines +30 to +37

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

사용자 생성 코드가 중복되어 있습니다. 22-28 라인과 31-37 라인에서 동일한 로직으로 사용자를 생성하고 있습니다. 중복된 코드를 제거하여 스크립트를 간결하게 유지하는 것이 좋습니다.


//상품 생성 및 재고 생성
for (const index of [...Array(30).keys()]) {
await prisma.product.create({
data: {
name: `테스트상품${index + 1}`,
price: Math.floor(Math.random() * 90001) + 10000, // 10000 ~ 100000 사이 랜덤 가격
ProductQuantity: {
create: {
quantity: 10,
remainingQuantity: 10,
},
},
},
});
}

await prisma.product.create({
//쿠폰 생성 및 재고 생성
await prisma.coupon.create({
data: {
name: '테스트 상품2',
price: 50000,
name: '테스트쿠폰',
discountType: 'PERCENT',
discountValue: 10,
startAt: new Date(),
endAt: new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 1),
couponQuantity: {
create: {
quantity: 10,
remainingQuantity: 10,
},
},
},
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/database/prisma/prisma.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class PrismaService extends PrismaClient implements OnModuleInit {
}

prismaLog() {
if (this.configService.get('NODE_ENV') === 'dev') {
if (this.configService.get('NODE_ENV') !== 'prod') {
(this.$on as any)('query', (e: Prisma.QueryEvent) => {
this.logger.debug(`Query: ${e.query}`);
this.logger.debug(`Duration: ${e.duration}ms`);
Expand Down
3 changes: 3 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { PrismaService } from './database/prisma/prisma.service';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
const app = await NestFactory.create(AppModule);

app.useGlobalPipes(new ValidationPipe({ transform: true }));

const prismaService = app.get(PrismaService);
await prismaService.enableShutdownHooks();

Expand Down
1 change: 0 additions & 1 deletion src/product/application/product.Irepository.ts

This file was deleted.

8 changes: 8 additions & 0 deletions src/product/application/product.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Product } from '../domain/product';
import { GetProductsQueryDTO } from '../presentation/dto/product.request.dto';

export interface ProductRepository {
getProducts(query: GetProductsQueryDTO): Promise<Product[]>;
}

export const PRODUCT_REPOSITORY = Symbol('PRODUCT_REPOSITORY');
16 changes: 14 additions & 2 deletions src/product/application/product.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import { Injectable } from '@nestjs/common';
import { Inject, Injectable } from '@nestjs/common';
import { PRODUCT_REPOSITORY, ProductRepository } from './product.repository';
import { GetProductsQueryDTO } from '../presentation/dto/product.request.dto';
import { ProductResponseDto } from '../presentation/dto/product.response.dto';

@Injectable()
export class ProductService {}
export class ProductService {
constructor(
@Inject(PRODUCT_REPOSITORY) private readonly productRepository: ProductRepository,
) {}

async getProducts(query: GetProductsQueryDTO): Promise<ProductResponseDto[]> {
const products = await this.productRepository.getProducts(query);
return products.map((product) => ProductResponseDto.of(product));
}
}
4 changes: 4 additions & 0 deletions src/product/domain/product.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApiProperty } from '@nestjs/swagger';
import { ProductQuantity } from './product-quantity';

export class Product {
@ApiProperty({ example: 1, description: '상품 ID' })
Expand All @@ -18,4 +19,7 @@ export class Product {

@ApiProperty({ example: '2025-01-01', description: '수정일' })
updatedAt: Date;

@ApiProperty({ type: ProductQuantity, description: '상품 수량' })
ProductQuantity: ProductQuantity;
}
1 change: 0 additions & 1 deletion src/product/infrastructure/product.repository.ts

This file was deleted.

20 changes: 20 additions & 0 deletions src/product/infrastructure/product.typeorm.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PrismaService } from 'src/database/prisma/prisma.service';
import { GetProductsQueryDTO } from '../presentation/dto/product.request.dto';
import { Injectable } from '@nestjs/common';
import { ProductRepository } from '../application/product.repository';
import { Product } from '../domain/product';

@Injectable()
export class ProductTypeOrmRepository implements ProductRepository {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

파일명과 클래스명이 ProductTypeOrmRepository로 되어 있지만, 실제 구현은 Prisma를 사용하고 있습니다. 이는 다른 개발자에게 혼동을 줄 수 있습니다. ProductPrismaRepository와 같이 실제 사용하는 기술을 명시하는 이름으로 변경하는 것을 권장합니다.

Suggested change
export class ProductTypeOrmRepository implements ProductRepository {
export class ProductPrismaRepository implements ProductRepository {

constructor(private readonly prisma: PrismaService) {}

async getProducts(query: GetProductsQueryDTO): Promise<Product[]> {
return await this.prisma.product.findMany({
include: {
ProductQuantity: true,
},
skip: query.offset,
take: query.size,
});
}
}
21 changes: 21 additions & 0 deletions src/product/presentation/dto/product.request.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsNumber, Min } from 'class-validator';

export class GetProductsQueryDTO {
@ApiProperty({ example: 1, description: '페이지 번호' })
@IsNumber()
@Transform(({ value }) => parseInt(value))
@Min(1)
page: number = 1;

@ApiProperty({ example: 10, description: '페이지 크기' })
@Transform(({ value }) => parseInt(value))
@IsNumber()
@Min(10)
size: number = 10;

get offset() {
return (this.page - 1) * this.size;
}
}
Loading