[NestJS] Seeder 모듈 및 App 제작

도도·2021년 8월 1일
0

기술Velog

목록 보기
8/28

NestJS- Seeder

Ref Docs

STAR

S 상황

  • 기본 프리셋 전략의 값은 반드시 시드 데이터가 있어야 한다.
  • Readonly 테이블과 비슷하다.

T 과제

  • seed역할을 수행하는 모듈을 만들고
  • createApplicationContext 을 이용해
  • 시드서비스를 호출하자.

A 액션

  • seeder 모듈 제작
  • seeder 서비스 제작
  • seed data 제작
  • ssed Application 제작

R 결과

seed.ts

import { NestFactory } from '@nestjs/core';
import { SeederModule } from './seeder.module';
import { SeederService } from './seeder.service';

async function bootstrap() {
  const appContext = await NestFactory.createApplicationContext(SeederModule);
  const seederService = appContext.get(SeederService);
  await seederService.seedBaseTradingStrategy();
  // await seederService.seedScenario01();
}
bootstrap();

data.ts

import { StrategyName } from 'src/trading/constant/strategy-setting';
import { BaseTradingStrategy } from 'src/trading/entities';

export const preSet__BaseTradingStrategy_List: BaseTradingStrategy[] = [
  {
    trading_strategy_code: 0,
    trading_strategy_name: StrategyName.None,
    setting_json: {},
  },
  {
    trading_strategy_code: 1,
    trading_strategy_name: StrategyName.GoldenCross,
    setting_json: {
      GoldenCross: {
        pfast: 5,
        pslow: 10,
      },
    },
  },
  {
    trading_strategy_code: 2,
    trading_strategy_name: StrategyName.SMA,
    setting_json: {
      SMA: { SMA_A: 5 },
    },
  },
];

seeder.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as Chance from 'chance';
import { Logger } from '@nestjs/common';
import {
  AccumulateProfitRateChart,
  BacktestDetailInfo,
  BacktestMontlyProfitRateChart,
  BacktestQueue,
  BacktestWinRatio,
  History,
  InvestProfitInfo,
} from 'src/backtest/entities';
import {
  Category,
  CategoryList,
  Corporation,
  DailyStock,
} from 'src/finance/entities';
import {
  LookupMemberList,
  MemberInfo,
  OperationMemberList,
} from 'src/member/entities';
import {
  Hash,
  HashList,
  MemberStrategy,
  // StockList,
} from 'src/strategy/entities';
import {
  BaseTradingStrategy,
  // CustomTradingStrategy,
  SimpleBacktest,
  Universal,
} from 'src/trading/entities';
import { UploadedObject } from 'src/upload/entities/uploaded-object.entity';
import { UserRole } from 'src/member/entities/member-info.entity';
import { InvestType } from 'src/strategy/entities/member-strategy.entity';
import { preSet__BaseTradingStrategy_List } from './pre-settings/data';
/*
CategoryList
Category
Corporation
DailyStock
CustomTradingStrategy
BaseTradingStrategy
Hash
HashList
MemberStrategy
StockList
AccumulateProfitRateChart
BacktestDetailInfo
BacktestMontlyProfitRateChart
BacktestQueue
BacktestWinRatio
History
InvestProfitInfo
LookupMemberList
MemberInfo
OperationMemberList
UploadedObject
*/
@Injectable()
export class SeederService {
  private readonly logger = new Logger(SeederService.name);
  constructor(
    @InjectRepository(CategoryList)
    private readonly CategoryList: Repository<CategoryList>,
    @InjectRepository(Category)
    private readonly Category: Repository<Category>,
    @InjectRepository(Corporation)
    private readonly Corporation: Repository<Corporation>,
    @InjectRepository(DailyStock)
    private readonly DailyStock: Repository<DailyStock>,
    // @InjectRepository(CustomTradingStrategy)
    // private readonly CustomTradingStrategy: Repository<CustomTradingStrategy>,
    @InjectRepository(BaseTradingStrategy)
    private readonly BaseTradingStrategy: Repository<BaseTradingStrategy>,
    @InjectRepository(SimpleBacktest)
    private readonly SimpleBacktest: Repository<SimpleBacktest>,
    @InjectRepository(Universal)
    private readonly Universal: Repository<Universal>,
    @InjectRepository(Hash)
    private readonly Hash: Repository<Hash>,
    @InjectRepository(HashList)
    private readonly HashList: Repository<HashList>,
    @InjectRepository(MemberStrategy)
    private readonly MemberStrategy: Repository<MemberStrategy>,
    // @InjectRepository(StockList)
    // private readonly StockList: Repository<StockList>,
    @InjectRepository(AccumulateProfitRateChart)
    private readonly AccumulateProfitRateChart: Repository<AccumulateProfitRateChart>,
    @InjectRepository(BacktestDetailInfo)
    private readonly BacktestDetailInfo: Repository<BacktestDetailInfo>,
    @InjectRepository(BacktestMontlyProfitRateChart)
    private readonly BacktestMontlyProfitRateChart: Repository<BacktestMontlyProfitRateChart>,
    @InjectRepository(BacktestQueue)
    private readonly BacktestQueue: Repository<BacktestQueue>,
    @InjectRepository(BacktestWinRatio)
    private readonly BacktestWinRatio: Repository<BacktestWinRatio>,
    @InjectRepository(History)
    private readonly History: Repository<History>,
    @InjectRepository(InvestProfitInfo)
    private readonly InvestProfitInfo: Repository<InvestProfitInfo>,
    @InjectRepository(LookupMemberList)
    private readonly LookupMemberList: Repository<LookupMemberList>,
    @InjectRepository(MemberInfo)
    private readonly MemberInfo: Repository<MemberInfo>,
    @InjectRepository(OperationMemberList)
    private readonly OperationMemberList: Repository<OperationMemberList>,
    @InjectRepository(UploadedObject)
    private readonly UploadedObject: Repository<UploadedObject>,
  ) {}

  // seed - entity
  // (1) 사용자 n명을 추가하는 시더
  async seedMemberInfo(n: number) {
    try {
      await Promise.all(
        new Array(n).fill(0).map(async () => {
          return this.MemberInfo.save(this.__createMemberInfo());
        }),
      );
      this.logger.log(`✔ seedMemberInfo ${n} done`);
      return true;
    } catch (error) {
      this.logger.error(`❌ seedMemberInfo fails`);
      return false;
    }
  }
  // (2) 기본 매매전략을 resetting
  async seedBaseTradingStrategy() {
    try {
      const targets = await this.BaseTradingStrategy.find();
      await Promise.all(
        targets.map(async (t) =>
          this.BaseTradingStrategy.delete(t.trading_strategy_code),
        ),
      );
      await Promise.all(
        preSet__BaseTradingStrategy_List.map(async (t) =>
          this.BaseTradingStrategy.save(this.BaseTradingStrategy.create(t)),
        ),
      );
      this.logger.verbose('✔ seedBaseTradingStrategy');
    } catch (error) {
      this.logger.error('❌ seedBaseTradingStrategy', error);
    }
  }

  // seed - relation mapping
  // (1) 시나리오
  async seedScenario01() {
    this.logger.verbose('✔ seedScenario01');
  }

  __createMemberInfo() {
    const email = Chance().email();
    return this.MemberInfo.create({
      email_id: email, //Chance().email(),
      password: email, //Chance().age(),
      member_name: Chance().name(),
    });
  }
}

seeder.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import * as Joi from 'joi';
import {
  AccumulateProfitRateChart,
  BacktestDetailInfo,
  BacktestMontlyProfitRateChart,
  BacktestQueue,
  BacktestWinRatio,
  History,
  InvestProfitInfo,
} from 'src/backtest/entities';
import {
  Category,
  CategoryList,
  Corporation,
  DailyStock,
} from 'src/finance/entities';
import {
  LookupMemberList,
  MemberInfo,
  OperationMemberList,
} from 'src/member/entities';
import { Hash, HashList, MemberStrategy } from 'src/strategy/entities';
import {
  BaseTradingStrategy,
  SimpleBacktest,
  Universal,
} from 'src/trading/entities';
import { UploadedObject } from 'src/upload/entities/uploaded-object.entity';
import { SeederService } from './seeder.service';
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      envFilePath: process.env.NODE_ENV === 'dev' ? '.env.dev' : '.env.test',
      ignoreEnvFile: process.env.NODE_ENV === 'prod',
      validationSchema: Joi.object({
        MAINTAINER: Joi.string().required(),
        PORT: Joi.number().required(),
        DATABASE_URL: Joi.string().required(),
        DATABASE_rejectUnauthorized: Joi.string().required(),
      }),
    }),
    TypeOrmModule.forRoot({
      type: 'postgres',
      url: process.env.DATABASE_URL,
      ...(process.env.DATABASE_rejectUnauthorized === 'false' && {
        ssl: {
          rejectUnauthorized: false,
        },
      }),
      synchronize: false,
      logging: false,
      entities: [
        ...[
          // finance (4/4)
          CategoryList,
          Category,
          Corporation,
          DailyStock,
        ],
        ...[
          // Trading(4/4)
          BaseTradingStrategy,
          SimpleBacktest,
          Universal,
        ],
        ...[
          //
          Hash,
          HashList,
          MemberStrategy,
          // StockList,
        ],
        ...[
          // back test (7/7)
          AccumulateProfitRateChart,
          BacktestDetailInfo,
          BacktestMontlyProfitRateChart,
          BacktestQueue,
          BacktestWinRatio,
          History,
          InvestProfitInfo,
        ],
        ...[
          //member (3/3)
          LookupMemberList,
          MemberInfo,
          OperationMemberList,
        ],
        ...[
          //upload
          UploadedObject,
        ],
      ],
    }),
    TypeOrmModule.forFeature([
      ...[
        // finance (4/4)
        CategoryList,
        Category,
        Corporation,
        DailyStock,
      ],
      ...[
        // Trading(4/4)
        BaseTradingStrategy,
        SimpleBacktest,
        Universal,
      ],
      ...[
        //
        Hash,
        HashList,
        MemberStrategy,
        // StockList,
      ],
      ...[
        // back test (7/7)
        AccumulateProfitRateChart,
        BacktestDetailInfo,
        BacktestMontlyProfitRateChart,
        BacktestQueue,
        BacktestWinRatio,
        History,
        InvestProfitInfo,
      ],
      ...[
        //member (3/3)
        LookupMemberList,
        MemberInfo,
        OperationMemberList,
      ],
      ...[
        //upload
        UploadedObject,
      ],
    ]),
  ],
  controllers: [],
  providers: [SeederService],
  exports: [SeederService],
})
export class SeederModule {}
profile
프론트 주력의 JS 개발자 입니다.! Node.js, React, NestJS 에 관심이 많습니다.

0개의 댓글