Skip to content

Commit edf3fd4

Browse files
authored
Merge pull request #72 from UMC-AlbaLog/feat/ALBA_71
[FEATURE] 전 월 대비 수입 증감률 조회 추가
2 parents 1cc58b4 + 68fde32 commit edf3fd4

3 files changed

Lines changed: 43 additions & 9 deletions

File tree

src/DTO/income_dashboard_dto.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ export interface IncomeDashboardResponseDTO {
2121

2222
/** 브랜드별 실제 수입 분해표 (actualIncome 대상) */
2323
breakdown: IncomeBrandBreakdownDTO[];
24+
25+
incomeChangeRate: number; // 전월 대비 증감률 (%)
2426
}

src/controller/income_dashboard_controller.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export class IncomeDashboardController extends Controller {
2424
* - incomeGoal: 사용자 수입 목표
2525
* - expectedIncome: 근무시간 × 시급 (정산 여부 무관)
2626
* - actualIncome: 정산 완료된 수입
27+
* - incomeChangeRate: 전월 대비 수입 증감률 (%)
2728
* - breakdown: 브랜드별 실제 수입
2829
*
2930
* @param month 조회 월 (YYYY-MM), 생략 시 이번 달

src/service/income_dashboard_service.ts

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ export class IncomeDashboardService {
99

1010
const { start, end, normalizedMonth } = this.getMonthRange(month);
1111

12-
const [workLogs, userAlbas, user] = await Promise.all([
12+
// 전월 month + range 계산
13+
const previousMonth = this.getPreviousMonth(normalizedMonth);
14+
const { start: prevStart, end: prevEnd } = this.getMonthRange(previousMonth);
15+
16+
const [workLogs, prevWorkLogs, userAlbas, user] = await Promise.all([
1317
incomeDashboardRepository.findWorkLogsForMonth(userIdBin, start, end),
18+
incomeDashboardRepository.findWorkLogsForMonth(userIdBin, prevStart, prevEnd),
1419
incomeDashboardRepository.findUserAlbaSettlementStatuses(userIdBin),
1520
incomeDashboardRepository.findUserIncomeGoal(userIdBin),
1621
]);
@@ -22,6 +27,31 @@ export class IncomeDashboardService {
2227
settlementMap.set(Buffer.from(ua.alba_id).toString('hex'), ua.settlement_status ?? null);
2328
}
2429

30+
const current = this.calculateMonthlyIncome(workLogs, settlementMap);
31+
const prev = this.calculateMonthlyIncome(prevWorkLogs, settlementMap);
32+
33+
// 전월 대비 증감률(%)
34+
// 전월 actualIncome이 0이면 0으로
35+
const incomeChangeRate =
36+
prev.actualIncome > 0
37+
? ((current.actualIncome - prev.actualIncome) / prev.actualIncome) * 100
38+
: 0;
39+
40+
return {
41+
month: normalizedMonth,
42+
incomeGoal,
43+
expectedIncome: current.expectedIncome,
44+
actualIncome: current.actualIncome,
45+
breakdown: current.breakdown,
46+
incomeChangeRate,
47+
};
48+
}
49+
50+
// 월별 expected/actual/breakdown 계산 공통 함수
51+
private calculateMonthlyIncome(
52+
workLogs: any[],
53+
settlementMap: Map<string, user_alba_settlement_status | null>,
54+
) {
2555
let expectedIncome = 0;
2656
let actualIncome = 0;
2757

@@ -37,7 +67,6 @@ export class IncomeDashboardService {
3767
expectedIncome += income;
3868

3969
const settlement = settlementMap.get(Buffer.from(log.alba_id).toString('hex')) ?? null;
40-
4170
const isCompleted = settlement === user_alba_settlement_status.paid;
4271
if (!isCompleted) continue;
4372

@@ -53,13 +82,15 @@ export class IncomeDashboardService {
5382
.map(([key, income]) => ({ key, income }))
5483
.sort((a, b) => b.income - a.income);
5584

56-
return {
57-
month: normalizedMonth,
58-
incomeGoal,
59-
expectedIncome,
60-
actualIncome,
61-
breakdown,
62-
};
85+
return { expectedIncome, actualIncome, breakdown };
86+
}
87+
88+
private getPreviousMonth(month: string): string {
89+
const [year, mon] = month.split('-').map(Number);
90+
const date = new Date(year, mon - 2); // 전월
91+
const y = date.getFullYear();
92+
const m = String(date.getMonth() + 1).padStart(2, '0');
93+
return `${y}-${m}`;
6394
}
6495

6596
private getMonthRange(month?: string) {

0 commit comments

Comments
 (0)