Skip to content

Commit

Permalink
Merge pull request #113 from boostcampwm-2024/feature/api/execute-#53
Browse files Browse the repository at this point in the history
[BE] 7.07 거래 체결 기능 구현 (WebSocket) #53
  • Loading branch information
sieunie authored Nov 14, 2024
2 parents 0965f2d + 712cabd commit ad6afbc
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 13 deletions.
4 changes: 2 additions & 2 deletions BE/src/stock/order/stock-order-socket.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export class StockOrderSocketService {

const totalPrice = order.price * order.amount;
const fee = this.calculateFee(totalPrice);
await this.stockOrderRepository.updateOrderAndAssetWhenBuy(
await this.stockOrderRepository.updateOrderAndAssetAndUserStockWhenBuy(
order,
totalPrice + fee,
);
Expand All @@ -100,7 +100,7 @@ export class StockOrderSocketService {

const totalPrice = order.price * order.amount;
const fee = this.calculateFee(totalPrice);
await this.stockOrderRepository.updateOrderAndAssetWhenSell(
await this.stockOrderRepository.updateOrderAndAssetAndUserStockWhenSell(
order,
totalPrice - fee,
);
Expand Down
8 changes: 7 additions & 1 deletion BE/src/stock/order/stock-order.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ import { StockOrderRepository } from './stock-order.repository';
import { SocketModule } from '../../websocket/socket.module';
import { AssetModule } from '../../asset/asset.module';
import { StockOrderSocketService } from './stock-order-socket.service';
import { UserStockModule } from '../../userStock/user-stock.module';

@Module({
imports: [TypeOrmModule.forFeature([Order]), SocketModule, AssetModule],
imports: [
TypeOrmModule.forFeature([Order]),
SocketModule,
AssetModule,
UserStockModule,
],
controllers: [StockOrderController],
providers: [StockOrderService, StockOrderRepository, StockOrderSocketService],
})
Expand Down
47 changes: 37 additions & 10 deletions BE/src/stock/order/stock-order.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { Order } from './stock-order.entity';
import { StatusType } from './enum/status-type';
import { Asset } from '../../asset/asset.entity';
import { UserStock } from '../../userStock/user-stock.entity';

@Injectable()
export class StockOrderRepository extends Repository<Order> {
Expand All @@ -17,7 +18,7 @@ export class StockOrderRepository extends Repository<Order> {
.getRawMany();
}

async updateOrderAndAssetWhenBuy(order, realPrice) {
async updateOrderAndAssetAndUserStockWhenBuy(order, realPrice) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.startTransaction();

Expand All @@ -32,14 +33,32 @@ export class StockOrderRepository extends Repository<Order> {
.createQueryBuilder()
.update(Asset)
.set({
cash_balance: () => 'cash_balance - :realPrice',
total_asset: () => 'total_asset - :realPrice',
total_profit: () => 'total_profit - :realPrice',
cash_balance: () => `cash_balance - ${realPrice}`,
total_asset: () => `total_asset - ${realPrice}`,
total_profit: () => `total_profit - ${realPrice}`,
total_profit_rate: () => `total_profit / 10000000`,
last_updated: new Date(),
})
.where({ user_id: order.user_id })
.setParameter('realPrice', realPrice)
.execute();

await queryRunner.manager
.createQueryBuilder()
.insert()
.into(UserStock)
.values({
user_id: order.user_id,
stock_code: order.stock_code,
quantity: order.amount,
avg_price: order.price,
})
.orUpdate(
[
`quantity = quantity + ${order.amount}`,
`avg_price = ((avg_price * quantity + ${order.price} * ${order.amount}) / (quantity + ${order.amount}))`,
],
['user_id', 'stock_code'],
)
.execute();

await queryRunner.commitTransaction();
Expand All @@ -51,7 +70,7 @@ export class StockOrderRepository extends Repository<Order> {
}
}

async updateOrderAndAssetWhenSell(order, realPrice) {
async updateOrderAndAssetAndUserStockWhenSell(order, realPrice) {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.startTransaction();

Expand All @@ -66,14 +85,22 @@ export class StockOrderRepository extends Repository<Order> {
.createQueryBuilder()
.update(Asset)
.set({
cash_balance: () => 'cash_balance + :realPrice',
total_asset: () => 'total_asset + :realPrice',
total_profit: () => 'total_profit + :realPrice',
cash_balance: () => `cash_balance + ${realPrice}`,
total_asset: () => `total_asset + ${realPrice}`,
total_profit: () => `total_profit + ${realPrice}`,
total_profit_rate: () => `total_profit / 10000000`,
last_updated: new Date(),
})
.where({ user_id: order.user_id })
.setParameter('realPrice', realPrice)
.execute();

await queryRunner.manager
.createQueryBuilder()
.update(UserStock)
.set({
quantity: () => `quantity - ${order.amount}`,
})
.where({ user_id: order.user_id, stock_code: order.stock_code })
.execute();

await queryRunner.commitTransaction();
Expand Down
11 changes: 11 additions & 0 deletions BE/src/stock/order/stock-order.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
BadRequestException,
ConflictException,
ForbiddenException,
Injectable,
Expand All @@ -9,12 +10,14 @@ import { StockOrderRepository } from './stock-order.repository';
import { TradeType } from './enum/trade-type';
import { StatusType } from './enum/status-type';
import { StockOrderSocketService } from './stock-order-socket.service';
import { UserStockRepository } from '../../userStock/user-stock.repository';

@Injectable()
export class StockOrderService {
constructor(
private readonly stockOrderRepository: StockOrderRepository,
private readonly stockOrderSocketService: StockOrderSocketService,
private readonly userStockRepository: UserStockRepository,
) {}

async buy(userId: number, stockOrderRequest: StockOrderRequestDto) {
Expand All @@ -32,6 +35,14 @@ export class StockOrderService {
}

async sell(userId: number, stockOrderRequest: StockOrderRequestDto) {
const userStock = await this.userStockRepository.findOneBy({
user_id: userId,
stock_code: stockOrderRequest.stock_code,
});

if (!userStock || userStock.quantity === 0)
throw new BadRequestException('주식을 매도 수만큼 가지고 있지 않습니다.');

const order = this.stockOrderRepository.create({
user_id: userId,
stock_code: stockOrderRequest.stock_code,
Expand Down
6 changes: 6 additions & 0 deletions BE/src/userStock/user-stock.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Controller } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';

@Controller('/api/userStock')
@ApiTags('사용자 보유 주식 API')
export class UserStockController {}
27 changes: 27 additions & 0 deletions BE/src/userStock/user-stock.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {
Column,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';

@Entity('user_stocks')
export class UserStock {
@PrimaryGeneratedColumn()
id: number;

@Column({ nullable: false })
user_id: number;

@Column({ nullable: false })
stock_code: string;

@Column({ nullable: false })
quantity: number;

@Column('decimal', { nullable: false, precision: 10, scale: 5 })
avg_price: number;

@UpdateDateColumn()
last_updated: Date;
}
14 changes: 14 additions & 0 deletions BE/src/userStock/user-stock.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UserStock } from './user-stock.entity';
import { UserStockController } from './user-stock.controller';
import { UserStockRepository } from './user-stock.repository';
import { UserStockService } from './user-stock.service';

@Module({
imports: [TypeOrmModule.forFeature([UserStock])],
controllers: [UserStockController],
providers: [UserStockRepository, UserStockService],
exports: [UserStockRepository],
})
export class UserStockModule {}
11 changes: 11 additions & 0 deletions BE/src/userStock/user-stock.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Injectable } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import { DataSource, Repository } from 'typeorm';
import { UserStock } from './user-stock.entity';

@Injectable()
export class UserStockRepository extends Repository<UserStock> {
constructor(@InjectDataSource() private dataSource: DataSource) {
super(UserStock, dataSource.createEntityManager());
}
}
4 changes: 4 additions & 0 deletions BE/src/userStock/user-stock.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';

@Injectable()
export class UserStockService {}

0 comments on commit ad6afbc

Please sign in to comment.