Skip to content

Commit b8982b5

Browse files
committed
Merge branch 'main' of github.com:UMC-AlbaLog/Node.JS
2 parents bb3ab77 + edf3fd4 commit b8982b5

13 files changed

Lines changed: 249 additions & 46 deletions

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/DTO/store_review_dto.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,7 @@ export interface StoreReviewResponseDto{
2222
createdAt:Date,
2323
updatedAt:Date
2424
}
25+
26+
export interface StoreReviewDto {
27+
reviews: StoreReviewResponseDto[];
28+
}

src/DTO/user_alba_schedule_dto.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface CreateManualScheduleBody {
77
work_time?: string;
88
day_of_week?: user_alba_schedule_day_of_week; // 실제 enum 타입으로 바꿔도 됨
99
repeat_type?: user_alba_schedule_repeat_type; // 실제 enum 타입으로 바꿔도 됨
10-
repeat_days?: string;
10+
repeat_days?: string | null;
1111
hourly_wage?: number;
1212
memo?: string;
1313
}
@@ -18,7 +18,7 @@ export interface UpdateManualScheduleBody {
1818
work_time?: string;
1919
day_of_week?: user_alba_schedule_day_of_week; // 실제 enum 타입으로 바꿔도 됨
2020
repeat_type?: user_alba_schedule_repeat_type; // 실제 enum 타입으로 바꿔도 됨
21-
repeat_days?: string;
21+
repeat_days?: string | null;
2222
hourly_wage?: number;
2323
memo?: string;
2424
}

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/controller/search_alba_controller.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import {Get,Route,SuccessResponse,Response, Tags, Controller, Queries} from 'tsoa'
1+
import {Get,Route,SuccessResponse,Response,Request,Security, Tags, Controller, Queries} from 'tsoa'
2+
import { Request as ExpressRequest } from 'express';
23
import { SearchAlbaRequestDto,SearchAlbaResponseDto } from '../DTO/search_alba_dto';
34
import { getFilteredAlba } from '../service/search_alba_service';
5+
import { uuidToBuffer } from '../util/uuid_util';
46

57

68
/**
@@ -17,13 +19,19 @@ export class SearchAlbaController extends Controller{
1719
* @returns 조건에 맞는 알바 리스트
1820
*/
1921
@Get('search')
22+
@Security('jwt')
2023
@SuccessResponse('200','조회 성공')
2124
@Response('400','Bad Request')
2225
@Response('500','Internal Error')
2326
public async searchFilteredAlba(
27+
@Request() req:ExpressRequest,
2428
@Queries() params:SearchAlbaRequestDto
2529
): Promise<SearchAlbaResponseDto[]>{
26-
const result = await getFilteredAlba(params)
30+
//UUID 문자열 Buffer로 변환
31+
const userId = (req.user as unknown as { id: string }).id;
32+
const userBuffer=Buffer.from(uuidToBuffer(userId))
33+
34+
const result = await getFilteredAlba(params,userBuffer)
2735

2836
return result
2937
}

src/controller/store_review_controller.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Tags, Route,SuccessResponse,Response,Request, Post, Body, Controller, Security} from 'tsoa';
1+
import { Tags, Route,SuccessResponse,Response,Request,Path, Post, Body, Controller, Security, Get} from 'tsoa';
22
import { Request as ExpressRequest } from 'express';
3-
import {StoreReviewRequestDto,StoreReviewResponseDto} from '../DTO/store_review_dto'
4-
import { addReview } from '../service/store_review_service';
3+
import {StoreReviewDto, StoreReviewRequestDto,StoreReviewResponseDto} from '../DTO/store_review_dto'
4+
import { addReview,getStoreReviewById } from '../service/store_review_service';
55
import { uuidToBuffer } from '../util/uuid_util';
66

77
/**
@@ -32,4 +32,23 @@ export class StoreReviewController extends Controller{
3232
this.setStatus(201);
3333
return result;
3434
}
35+
36+
/**
37+
* 근무지 평가 조회 API
38+
* @param 쿼리 파라미터로 가게 Id
39+
* @returns 리뷰 정보 + 가게,유저명 반환
40+
*/
41+
@Get('/{storeId}')
42+
@Security('jwt')
43+
@SuccessResponse('200','조회 성공')
44+
@Response('400','Bad Request')
45+
@Response('500','Internal Server Error')
46+
public async getStoreReview(
47+
@Path() storeId: string,
48+
): Promise<StoreReviewDto>{
49+
50+
const result= await getStoreReviewById(storeId)
51+
this.setStatus(201);
52+
return result;
53+
}
3554
}

src/repository/search_alba_repository.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,24 @@ import { SearchAlbaRequestDto, SearchAlbaResponseDto } from "../DTO/search_alba_
33
import { bufferToUuid } from "../util/uuid_util";
44
//id값으로 변경된 storeCategoryId 사용
55
export interface SearchAlbaRepoParams extends SearchAlbaRequestDto{
6-
storeCategoryId?:number
6+
storeCategoryId?:number,
7+
userBuffer?:Buffer
78
}
89
/**
910
* 아르바이트 필터 명시 및 조회
1011
* @param data
1112
* @returns 조건에 맞는 알바 리스트
1213
*/
1314
export const findPostingByFilter = async(data:SearchAlbaRepoParams):Promise<SearchAlbaResponseDto[]>=>{
14-
const {workDate,storeCategoryId,storeName,hourlyRate,} = data
15+
const {workDate,storeCategoryId,storeName,hourlyRate,userBuffer} = data
1516
const result = await prisma.alba_posting.findMany({
1617
where:{
18+
...(userBuffer && {user_alba: {
19+
none: {
20+
user_id: new Uint8Array(userBuffer)
21+
}
22+
}
23+
}),
1724
...(hourlyRate&&{hourly_rate:{gte:hourlyRate}}),
1825
store:{
1926
...(storeCategoryId&&{

src/repository/store_review_repository.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,14 @@ export const createStoreReview = async (userBuffer:Buffer,storeBuffer:Buffer,dat
4545
createdAt: result.created_at, //생성, 수정 시간 추가
4646
updatedAt: result.updated_at
4747
}
48-
}
48+
}
49+
export const findReviewsByStoreId = async (storeId: Buffer) => {
50+
return await prisma.store_review.findMany({
51+
where: { store_id: new Uint8Array(storeId) },
52+
include: {
53+
user:true,
54+
store:true
55+
},
56+
orderBy: { created_at: 'desc' } // 최신순 정렬
57+
});
58+
};

src/repository/user_alba_schedule_repository.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,12 @@ export class UserAlbaScheduleRepository {
5151
public async createWithWorkLog(
5252
userId: string,
5353
input: CreateUserAlbaScheduleRepoInput,
54-
workLogData: { workDate: Date; startTime: Date | null; endTime: Date | null; workMinutes: number | null },
54+
workLogData: {
55+
workDate: Date;
56+
startTime: Date | null;
57+
endTime: Date | null;
58+
workMinutes: number | null;
59+
},
5560
): Promise<Uint8Array> {
5661
const userIdBin = uuidToBin(userId);
5762

@@ -91,6 +96,23 @@ export class UserAlbaScheduleRepository {
9196
return schedule.user_alba_schedule_id;
9297
}
9398

99+
public async findByIdAndUserId(userId: string, scheduleId: string) {
100+
const userIdBin = uuidToBin(userId);
101+
const scheduleIdBin = uuidToBin(scheduleId);
102+
103+
return prisma.user_alba_schedule.findFirst({
104+
where: {
105+
user_id: userIdBin,
106+
user_alba_schedule_id: scheduleIdBin,
107+
},
108+
select: {
109+
repeat_type: true,
110+
repeat_days: true,
111+
// merge 검증에 필요하면 더 추가 가능
112+
},
113+
});
114+
}
115+
94116
public async updateByIdAndUserId(
95117
userId: string,
96118
scheduleId: string,

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)