Skip to content

Commit

Permalink
feat: ✨ daily team close records 추가를 통한 home team close records last 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
jpham005 committed Nov 13, 2023
1 parent 2299260 commit c3a5ffd
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 52 deletions.
8 changes: 8 additions & 0 deletions app/src/dailyTeamCloseCount/dailyTeamCloseCount.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { DateRange } from 'src/dateRange/dtos/dateRange.dto';

export type FindTeamCloseCountByDateInput = DateRange;

export type FindTeamCloseCountByDateOutput = {
date: Date;
count: number;
};
23 changes: 23 additions & 0 deletions app/src/dailyTeamCloseCount/dailyTeamCloseCount.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { DailyTeamCloseCountService } from './dailyTeamCloseCount.service';
import { DailyTeamCloseClountDaoImpl } from './db/dailyTeamCloseCount.database.dao';
import {
dailyTeamCloseCountSchema,
mv_daily_team_close_counts,
} from './db/dailyTeamCloseCount.database.schema';

@Module({
imports: [
MongooseModule.forFeature([
{
name: mv_daily_team_close_counts.name,
schema: dailyTeamCloseCountSchema,
},
]),
],
providers: [DailyTeamCloseCountService, DailyTeamCloseClountDaoImpl],
exports: [DailyTeamCloseCountService],
})
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class DailyTeamCloseCountModule {}
24 changes: 24 additions & 0 deletions app/src/dailyTeamCloseCount/dailyTeamCloseCount.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Injectable } from '@nestjs/common';
import { DailyTeamCloseClountDaoImpl } from './db/dailyTeamCloseCount.database.dao';
import type { IntRecord } from 'src/common/models/common.valueRecord.model';
import type { DateRange } from 'src/dateRange/dtos/dateRange.dto';

@Injectable()
export class DailyTeamCloseCountService {
constructor(
private readonly dailyTeamCloseCountDao: DailyTeamCloseClountDaoImpl,
) {}

async teamCloseCountRecords({ start, end }: DateRange): Promise<IntRecord[]> {
const teamCloseCounts =
await this.dailyTeamCloseCountDao.findTeamCloseCountsByDate({
start,
end,
});

return teamCloseCounts.map(({ date, count }) => ({
at: date,
value: count,
}));
}
}
44 changes: 44 additions & 0 deletions app/src/dailyTeamCloseCount/db/dailyTeamCloseCount.database.dao.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { InjectModel } from '@nestjs/mongoose';
import type {
FindTeamCloseCountByDateInput,
FindTeamCloseCountByDateOutput,
} from '../dailyTeamCloseCount.dto';
import { mv_daily_team_close_counts } from './dailyTeamCloseCount.database.schema';
import type { Model } from 'mongoose';

export type DailyTeamCloseCountDao = {
findTeamCloseCountsByDate: (
args: FindTeamCloseCountByDateInput,
) => Promise<FindTeamCloseCountByDateOutput[]>;
};

export class DailyTeamCloseClountDaoImpl implements DailyTeamCloseCountDao {
constructor(
@InjectModel(mv_daily_team_close_counts.name)
private readonly dailyTeamCloseCount: Model<mv_daily_team_close_counts>,
) {}

async findTeamCloseCountsByDate({
start,
end,
}: FindTeamCloseCountByDateInput): Promise<FindTeamCloseCountByDateOutput[]> {
return await this.dailyTeamCloseCount
.find(
{
date: {
$gte: start,
$lt: end,
},
},
{
_id: 0,
date: 1,
count: 1,
},
{
sort: { _id: 1 },
},
)
.lean();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import type { HydratedDocument } from 'mongoose';

export type DailyTeamCloseCountDocument =
HydratedDocument<mv_daily_team_close_counts>;

@Schema({ collection: 'mv_daily_team_close_counts' })
export class mv_daily_team_close_counts {
@Prop({ required: true })
count: number;

@Prop({ required: true })
date: Date;
}

export const dailyTeamCloseCountSchema = SchemaFactory.createForClass(
mv_daily_team_close_counts,
);
11 changes: 10 additions & 1 deletion app/src/page/home/team/home.team.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,21 @@ import { Module } from '@nestjs/common';
import { ExamModule } from 'src/api/exam/exam.module';
import { ProjectsUserModule } from 'src/api/projectsUser/projectsUser.module';
import { TeamModule } from 'src/api/team/team.module';
import { CacheUtilModule } from 'src/cache/cache.util.module';
import { DailyTeamCloseCountModule } from 'src/dailyTeamCloseCount/dailyTeamCloseCount.module';
import { DateRangeModule } from 'src/dateRange/dateRange.module';
import { HomeTeamResolver } from './home.team.resolver';
import { HomeTeamService } from './home.team.service';

@Module({
imports: [ProjectsUserModule, TeamModule, ExamModule, DateRangeModule],
imports: [
ProjectsUserModule,
TeamModule,
ExamModule,
DateRangeModule,
DailyTeamCloseCountModule,
CacheUtilModule,
],
providers: [HomeTeamResolver, HomeTeamService],
})
// eslint-disable-next-line
Expand Down
41 changes: 34 additions & 7 deletions app/src/page/home/team/home.team.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,60 @@
import { UseFilters, UseGuards } from '@nestjs/common';
import { Args, Query, ResolveField, Resolver } from '@nestjs/graphql';
import { StatAuthGuard } from 'src/auth/statAuthGuard';
import { CacheUtilService } from 'src/cache/cache.util.service';
import { IntRecord } from 'src/common/models/common.valueRecord.model';
import { DailyTeamCloseCountService } from 'src/dailyTeamCloseCount/dailyTeamCloseCount.service';
import { DateWrapper } from 'src/dateWrapper/dateWrapper';
import { HttpExceptionFilter } from 'src/http-exception.filter';
import { RecentExamResultArgs } from './dtos/home.team.dto.recentExamResultArgs';
import { HomeTeamService } from './home.team.service';
import {
ExamResult,
ExamResultDateRanged,
GetHomeTeamCloseRecordsArgs,
HomeTeam,
ProjectRank,
} from './models/home.team.model';
import { IntRecord } from 'src/common/models/common.valueRecord.model';

@UseFilters(HttpExceptionFilter)
@UseGuards(StatAuthGuard)
@Resolver((_of: unknown) => HomeTeam)
export class HomeTeamResolver {
constructor(private readonly homeTeamService: HomeTeamService) {}
constructor(
private readonly homeTeamService: HomeTeamService,
private readonly dailyTeamCloseCountService: DailyTeamCloseCountService,
private readonly cacheUtilService: CacheUtilService,
) {}

@Query((_of) => HomeTeam)
async getHomeTeam() {
return {};
}

@ResolveField((_returns) => [IntRecord], { description: '1 ~ 60 일' })
async teamCloseRecords(@Args('last') last: number): Promise<IntRecord[]> {
return await this.homeTeamService.teamCloseRecords(
Math.max(1, Math.min(last, 60)),
);
@ResolveField((_returns) => [IntRecord], { description: '1 ~ 730 일' })
async teamCloseRecords(
@Args() { last }: GetHomeTeamCloseRecordsArgs,
): Promise<IntRecord[]> {
const nextDay = new DateWrapper().startOfDate().moveDate(1).toDate();
const start = new DateWrapper()
.startOfDate()
.moveDate(1 - last)
.toDate();

const cacheKey = `homeTeamCloseRecords:${start.getTime()}:${nextDay.getTime()}`;
const cached = await this.cacheUtilService.get<IntRecord[]>(cacheKey);
if (cached) {
return cached;
}

const result = await this.dailyTeamCloseCountService.teamCloseCountRecords({
start,
end: nextDay,
});

await this.cacheUtilService.set(cacheKey, result, DateWrapper.MIN);

return result;
}

@ResolveField((_returns) => [ProjectRank])
Expand Down
43 changes: 1 addition & 42 deletions app/src/page/home/team/home.team.service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import type { exam } from 'src/api/exam/db/exam.database.schema';
import { EXAM_PROJECT_IDS, ExamService } from 'src/api/exam/exam.service';
import { ExamService } from 'src/api/exam/exam.service';
import { ProjectsUserService } from 'src/api/projectsUser/projectsUser.service';
import { TeamService } from 'src/api/team/team.service';
import { CacheOnReturn } from 'src/cache/decrators/onReturn/cache.decorator.onReturn.symbol';
import { IntRecord } from 'src/common/models/common.valueRecord.model';
import { DateRangeService } from 'src/dateRange/dateRange.service';
import { DateWrapper } from 'src/dateWrapper/dateWrapper';
import type {
Expand All @@ -22,46 +21,6 @@ export class HomeTeamService {
private readonly dateRangeService: DateRangeService,
) {}

@CacheOnReturn()
async teamCloseRecords(last: number): Promise<IntRecord[]> {
const startDate = new DateWrapper()
.startOfDate()
.moveDate(1 - last)
.toDate();

const teams: { closedAt?: Date }[] = await this.teamService.findAllAndLean({
filter: {
closedAt: { $gte: startDate },
projectId: { $nin: EXAM_PROJECT_IDS },
},
select: { closedAt: 1 },
});

const res = teams.reduce((acc, { closedAt }) => {
if (!closedAt) {
return acc;
}

const date = new DateWrapper(closedAt).startOfDate().toDate().getTime();

const prev = acc.get(date);

acc.set(date, (prev ?? 0) + 1);

return acc;
}, new Map() as Map<number, number>);

const records: IntRecord[] = [];

for (let i = 0; i < last; i++) {
const currDate = new DateWrapper(startDate).moveDate(i).toDate();

records.push({ at: currDate, value: res.get(currDate.getTime()) ?? 0 });
}

return records;
}

@CacheOnReturn()
async currRegisteredCountRanking(limit: number): Promise<ProjectRank[]> {
return await this.projectsUserService.currRegisteredCountRanking(limit);
Expand Down
11 changes: 10 additions & 1 deletion app/src/page/home/team/models/home.team.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Field, ObjectType } from '@nestjs/graphql';
import { ArgsType, Field, ObjectType } from '@nestjs/graphql';
import { Max, Min } from 'class-validator';
import { ProjectPreview } from 'src/common/models/common.project.model';
import { Rate } from 'src/common/models/common.rate.model';
import { IntRecord } from 'src/common/models/common.valueRecord.model';
Expand Down Expand Up @@ -63,3 +64,11 @@ export class HomeTeam {
@Field()
recentExamResult: ExamResultDateRanged;
}

@ArgsType()
export class GetHomeTeamCloseRecordsArgs {
@Min(1)
@Max(730)
@Field({ description: '1 ~ 730 일' })
last: number;
}
5 changes: 4 additions & 1 deletion app/src/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,10 @@ type ExamResultDateRanged {
}

type HomeTeam {
teamCloseRecords(last: Int!): [IntRecord!]!
teamCloseRecords(
"""1 ~ 730 일"""
last: Int!
): [IntRecord!]!
currRegisteredCountRanking(limit: Int! = 3): [ProjectRank!]!
recentExamResult(skip: Int! = 0): ExamResultDateRanged!
}
Expand Down

0 comments on commit c3a5ffd

Please sign in to comment.