Skip to content

Commit

Permalink
feat: ✨ daily logtime module 추가를 통해 logtimeRecords 의 last 지원 범위 증가
Browse files Browse the repository at this point in the history
  • Loading branch information
jpham005 committed Nov 10, 2023
1 parent acfca3b commit 6cc0ab5
Show file tree
Hide file tree
Showing 9 changed files with 167 additions and 42 deletions.
14 changes: 14 additions & 0 deletions app/src/dailyLogtime/dailyLogtime.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { DateRange } from 'src/dateRange/dtos/dateRange.dto';

export type UserLogtimeRecordsByDateRangeInput = {
userId: number;
} & DateRange;

export type UserLogtimeRecordByDateRangeOutput = {
/**
*
* @description %Y-%m Date 형식
*/
at: string;
value: number;
};
20 changes: 20 additions & 0 deletions app/src/dailyLogtime/dailyLogtime.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { DailyLogtimeService } from './dailyLogtime.service';
import { DailyLogtimeDaoImpl } from './db/dailyLogtime.database.dao';
import {
dailyLogtimeSchema,
daily_logtimes,
} from './db/dailyLogtime.database.schema';

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

@Injectable()
export class DailyLogtimeService {
constructor(private readonly dailyLogtimeDao: DailyLogtimeDaoImpl) {}

async userLogtimeRecordsByDateRange(
userId: number,
{ start, end }: DateRange,
): Promise<IntRecord[]> {
const userLogtimeRecords =
await this.dailyLogtimeDao.userLogtimeRecordsByDateRange({
userId,
start,
end,
});

return userLogtimeRecords.map(({ at, value }) => ({
at: new Date(at),
value,
}));
}
}
58 changes: 58 additions & 0 deletions app/src/dailyLogtime/db/dailyLogtime.database.dao.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Injectable } from '@nestjs/common';
import type {
UserLogtimeRecordsByDateRangeInput,
UserLogtimeRecordByDateRangeOutput,
} from '../dailyLogtime.dto';
import { InjectModel } from '@nestjs/mongoose';
import { daily_logtimes } from './dailyLogtime.database.schema';
import type { Model } from 'mongoose';

export type DailyLogtimeDao = {
userLogtimeRecordsByDateRange: (
args: UserLogtimeRecordsByDateRangeInput,
) => Promise<UserLogtimeRecordByDateRangeOutput[]>;
};

@Injectable()
export class DailyLogtimeDaoImpl implements DailyLogtimeDao {
constructor(
@InjectModel(daily_logtimes.name)
private readonly dailyLogtime: Model<daily_logtimes>,
) {}

async userLogtimeRecordsByDateRange({
userId,
start,
end,
}: UserLogtimeRecordsByDateRangeInput): Promise<
UserLogtimeRecordByDateRangeOutput[]
> {
return await this.dailyLogtime
.aggregate<UserLogtimeRecordByDateRangeOutput>()
.match({
userId,
date: {
$gte: start,
$lte: end,
},
})
.group({
_id: {
$dateToString: {
date: '$date',
format: '%Y-%m',
timezone: 'Asia/Seoul',
},
},
value: {
$sum: '$value',
},
})
.sort({ _id: 1 })
.project({
_id: 0,
at: '$_id',
value: 1,
});
}
}
13 changes: 11 additions & 2 deletions app/src/page/personal/general/models/personal.general.model.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Field, Float, ObjectType } from '@nestjs/graphql';
import { ArgsType, Field, Float, ObjectType } from '@nestjs/graphql';
import { Max, Min } from 'class-validator';
import { ProjectPreview } from 'src/common/models/common.project.model';
import { IntRecord } from 'src/common/models/common.valueRecord.model';
import { DateRanged } from 'src/dateRange/models/dateRange.model';
import { TeamStatus } from 'src/page/teamInfo/models/teamInfo.status.model';
import { DailyActivity } from './personal.general.dailyActivity.model';
import { Character } from '../character/models/personal.general.character.model';
import { DailyActivity } from './personal.general.dailyActivity.model';
import { UserProfile } from './personal.general.userProfile.model';

@ObjectType()
Expand Down Expand Up @@ -97,6 +98,14 @@ export class UserScoreInfo {
rankInTotal: number;
}

@ArgsType()
export class GetLogtimeRecordsArgs {
@Min(1)
@Max(120)
@Field()
last: number;
}

export type PersonalGeneralRoot = Pick<
PersonalGeneral,
'userProfile' | 'beginAt' | 'blackholedAt' | 'wallet'
Expand Down
2 changes: 2 additions & 0 deletions app/src/page/personal/general/personal.general.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ScaleTeamModule } from 'src/api/scaleTeam/scaleTeam.module';
import { ScoreModule } from 'src/api/score/score.module';
import { TeamModule } from 'src/api/team/team.module';
import { DailyActivityModule } from 'src/dailyActivity/dailyActivity.module';
import { DailyLogtimeModule } from 'src/dailyLogtime/dailyLogtime.module';
import { DateRangeModule } from 'src/dateRange/dateRange.module';
import { PersonalUtilModule } from '../util/personal.util.module';
import { PersonalGeneralCharacterModule } from './character/persoanl.general.character.module';
Expand All @@ -30,6 +31,7 @@ import { PersonalGeneralService } from './personal.general.service';
CoalitionsUserModule,
DailyActivityModule,
DateRangeModule,
DailyLogtimeModule,
],
providers: [PersonalGeneralResolver, PersonalGeneralService],
})
Expand Down
29 changes: 24 additions & 5 deletions app/src/page/personal/general/personal.general.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import { UseFilters, UseGuards } from '@nestjs/common';
import { Args, Query, ResolveField, Resolver, Root } from '@nestjs/graphql';
import { MyUserId } from 'src/auth/myContext';
import { StatAuthGuard } from 'src/auth/statAuthGuard';
import { CacheUtilService } from 'src/cache/cache.util.service';
import { IntRecord } from 'src/common/models/common.valueRecord.model';
import { DailyActivityService } from 'src/dailyActivity/dailyActivity.service';
import { DailyLogtimeService } from 'src/dailyLogtime/dailyLogtime.service';
import { DateRangeService } from 'src/dateRange/dateRange.service';
import { DateTemplateArgs } from 'src/dateRange/dtos/dateRange.dto';
import { DateWrapper } from 'src/dateWrapper/dateWrapper';
Expand All @@ -16,6 +18,7 @@ import {
GetDailyActivitiesArgs,
} from './models/personal.general.dailyActivity.model';
import {
GetLogtimeRecordsArgs,
LevelRecord,
PersonalGeneral,
PersonalGeneralRoot,
Expand All @@ -25,7 +28,6 @@ import {
UserTeamInfo,
} from './models/personal.general.model';
import { PersonalGeneralService } from './personal.general.service';
import { CacheUtilService } from 'src/cache/cache.util.service';

@UseFilters(HttpExceptionFilter)
@UseGuards(StatAuthGuard)
Expand All @@ -37,6 +39,7 @@ export class PersonalGeneralResolver {
private readonly personalGeneralCharacterService: PersonalGeneralCharacterService,
private readonly dateRangeService: DateRangeService,
private readonly dailyActiviyService: DailyActivityService,
private readonly dailyLogtimeService: DailyLogtimeService,
private readonly cacheUtilService: CacheUtilService,
) {}

Expand Down Expand Up @@ -64,15 +67,31 @@ export class PersonalGeneralResolver {
return await this.personalGeneralService.scoreInfo(root.userProfile.id);
}

@ResolveField((_returns) => [IntRecord], { description: '1 ~ 24 개월' })
@ResolveField((_returns) => [IntRecord], { description: '1 ~ 120 개월' })
async logtimeRecords(
@Root() root: PersonalGeneralRoot,
@Args('last') last: number,
@Args() { last }: GetLogtimeRecordsArgs,
): Promise<IntRecord[]> {
return await this.personalGeneralService.logtimeRecords(
const currMonth = DateWrapper.currMonth().toDate();
const startMonth = new DateWrapper(currMonth).moveMonth(-last + 1).toDate();

const cacheKey = `logtimeRecords:${
root.userProfile.id
}:${startMonth.toISOString()}:${currMonth.toISOString()}`;

const cached = await this.cacheUtilService.get<IntRecord[]>(cacheKey);
if (cached) {
return cached;
}

const result = await this.dailyLogtimeService.userLogtimeRecordsByDateRange(
root.userProfile.id,
Math.max(1, Math.min(last, 24)),
{ start: startMonth, end: currMonth },
);

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

return result;
}

@ResolveField((_returns) => PreferredTimeDateRanged)
Expand Down
23 changes: 0 additions & 23 deletions app/src/page/personal/general/personal.general.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { ScoreCacheService } from 'src/api/score/score.cache.service';
import { TeamService } from 'src/api/team/team.service';
import { CacheOnReturn } from 'src/cache/decrators/onReturn/cache.decorator.onReturn.symbol';
import type { IntDateRanged } from 'src/common/models/common.dateRanaged.model';
import { IntRecord } from 'src/common/models/common.valueRecord.model';
import { DateRangeService } from 'src/dateRange/dateRange.service';
import { DateTemplate, type DateRange } from 'src/dateRange/dtos/dateRange.dto';
import { DateWrapper } from 'src/dateWrapper/dateWrapper';
Expand Down Expand Up @@ -139,28 +138,6 @@ export class PersonalGeneralService {
return await this.logtimeByDateRange(userId, dateRange);
}

async logtimeRecords(userId: number, last: number): Promise<IntRecord[]> {
const ret: IntRecord[] = [];
const startDate = new DateWrapper().startOfMonth().moveMonth(1 - last);

for (let i = 0; i < last; i++) {
const currStartDate = startDate.moveMonth(i).toDate();
const currEndDate = startDate.moveMonth(i + 1).toDate();

const [curr] = await this.locationService.logtimeRanking(
{
start: currStartDate,
end: currEndDate,
},
{ 'user.id': userId },
);

ret.push({ at: currStartDate, value: curr?.value ?? 0 });
}

return ret;
}

private async preferredTime(
userId: number,
filter: FilterQuery<location>,
Expand Down
24 changes: 12 additions & 12 deletions app/src/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,18 @@ type LeaderboardScore {
byDateTemplate(pageSize: Int! = 10, pageNumber: Int! = 1, promo: Int, coalitionId: Int, dateTemplate: DateTemplate!): LeaderboardElementDateRanged!
}

type CharacterType {
name: String!
description: String!
color: String!
}

type Character {
name: String!
types: [CharacterType!]!
imgUrl: String!
}

type DailyActivity {
date: DateTime!
records: [DailyActivityRecord!]!
Expand All @@ -333,18 +345,6 @@ type DailyDefaultRecord {
at: DateTime!
}

type CharacterType {
name: String!
description: String!
color: String!
}

type Character {
name: String!
types: [CharacterType!]!
imgUrl: String!
}

type UserTeam {
id: Int!
name: String!
Expand Down

0 comments on commit 6cc0ab5

Please sign in to comment.