55import com .nitrogen .domain .expense .dto .report .summary .MonthlyReportSummaryResponse ;
66import com .nitrogen .domain .expense .dto .report .summary .SummaryRecordResponse ;
77import com .nitrogen .domain .expense .dto .report .summary .WeeklyReportResponse ;
8+ import com .nitrogen .domain .expense .dto .weeklyAndmonthly .TotalOpenStatusResponse ;
89import com .nitrogen .domain .expense .repository .ExpenseRepository ;
910import com .nitrogen .domain .expense .service .inquiry .ExpenseInquiryService ;
1011import com .nitrogen .domain .expense .service .report .DailyRetrospectReportService ;
1112import com .nitrogen .domain .expense .service .report .WeeklyRecordService ;
13+ import com .nitrogen .domain .expense .service .report .TotalOpenStatusService ;
1214import com .nitrogen .domain .expense .service .report .WeeklyDetailRecordService ;
1315import com .nitrogen .domain .user .entity .CustomUserDetails ;
1416import com .nitrogen .global .apiPayload .ApiResponse ;
@@ -40,6 +42,7 @@ public class ExpenseReportController {
4042 private final DailyRetrospectReportService dailyRetrospectReportService ;
4143 private final ExpenseRepository expenseRepository ;
4244 private final ExpenseInquiryService expenseInquiryService ;
45+ private final TotalOpenStatusService totalOpenStatusService ;
4346
4447 @ Operation (summary = "메인화면 분석 리포트 조회" , description = "이번 달 총 소비 금액과 지난주 주간 분석 리포트를 한 번에 조회합니다." )
4548 @ GetMapping ("/summary_record" )
@@ -73,8 +76,10 @@ public ApiResponse<SummaryRecordResponse> getSummaryRecord(@AuthenticationPrinci
7376 while (!checkDate .isAfter (lastAvailableMonday )) {
7477 LocalDate sunday = checkDate .plusDays (6 );
7578
76- if (expenseRepository .existsByUserUserIdAndExpendedAtBetween (userId , checkDate , sunday )) {
77- int weekOfMonth = checkDate .get (WeekFields .ISO .weekOfMonth ());
79+ LocalDate thursday = checkDate .plusDays (3 );
80+ if (thursday .getYear () == nowDate .getYear () && thursday .getMonthValue () == nowDate .getMonthValue ()
81+ && expenseRepository .existsByUserUserIdAndExpendedAtBetween (userId , checkDate , sunday )) {
82+ int weekOfMonth = thursday .get (WeekFields .ISO .weekOfMonth ());
7883 weeklyReports .add (weeklyRecordService .generateWeeklyReport (userId , checkDate , sunday , weekOfMonth ));
7984 }
8085 checkDate = checkDate .plusWeeks (1 );
@@ -83,25 +88,45 @@ public ApiResponse<SummaryRecordResponse> getSummaryRecord(@AuthenticationPrinci
8388 return ApiResponse .onSuccess (new SummaryRecordResponse (monthlyReport , weeklyReports ));
8489 }
8590
86- @ Operation (summary = "주간 분석 상세 리포트 조회" , description = "특정 주차의 감정 분석, 만족도 통계, TOP 3 지출 내역 등 상세 데이터를 조회합니다." )
91+ @ Operation (summary = "주간 분석 상세 리포트 조회" , description = "해당 월의 열람 가능한 모든 주차에 대한 상세 리포트를 리스트로 조회합니다." )
8792 @ GetMapping ("/weekly_detail" )
88- public ApiResponse <WeeklyDetailReportResponse > getWeeklyDetailReport (
93+ public ApiResponse <List < WeeklyDetailReportResponse > > getWeeklyDetailReport (
8994 @ AuthenticationPrincipal CustomUserDetails userDetails ,
90- @ RequestParam ("date" ) @ DateTimeFormat (iso = DateTimeFormat .ISO .DATE ) LocalDate date ) {
95+ @ RequestParam int year ,
96+ @ RequestParam int month ) {
9197
9298 Long userId = userDetails .getUserId ();
99+ LocalDateTime nowDateTime = LocalDateTime .now ();
100+ LocalDate nowDate = nowDateTime .toLocalDate ();
93101
94- LocalDate start = date .with (TemporalAdjusters .previousOrSame (DayOfWeek .MONDAY ));
95- LocalDate end = start .plusDays (6 );
102+ LocalDate startOfMonth = LocalDate .of (year , month , 1 );
96103
97- int month = date .getMonthValue ();
98- int weekOfMonth = date .get (WeekFields .ISO .weekOfMonth ()) + 1 ;
99- String weekRange = String .format ("%d년 %d월 %d주차 분석 리포트" , date .getYear (), month , weekOfMonth );
104+ LocalDateTime thisWeekGenTime = nowDate .with (TemporalAdjusters .previousOrSame (DayOfWeek .MONDAY )).atTime (8 , 0 );
100105
101- WeeklyDetailReportResponse response = weeklyDetailRecordService .generateWeeklyDetailReport (
102- userId , start , end , weekRange );
106+ LocalDate lastAvailableMonday = nowDateTime .isBefore (thisWeekGenTime )
107+ ? nowDate .with (TemporalAdjusters .previousOrSame (DayOfWeek .MONDAY )).minusWeeks (2 )
108+ : nowDate .with (TemporalAdjusters .previousOrSame (DayOfWeek .MONDAY )).minusWeeks (1 );
103109
104- return ApiResponse .onSuccess (response );
110+ LocalDate checkDate = startOfMonth .with (TemporalAdjusters .previousOrSame (DayOfWeek .MONDAY ));
111+
112+ List <WeeklyDetailReportResponse > responses = new ArrayList <>();
113+
114+ while (!checkDate .isAfter (lastAvailableMonday )) {
115+ LocalDate sunday = checkDate .plusDays (6 );
116+
117+ LocalDate thursday = checkDate .plusDays (3 );
118+ if (thursday .getYear () == year && thursday .getMonthValue () == month
119+ && expenseRepository .existsByUserUserIdAndExpendedAtBetween (userId , checkDate , sunday )) {
120+ int weekOfMonth = thursday .get (WeekFields .ISO .weekOfMonth ());
121+ String weekRange = String .format ("%d년 %d월 %d주차 분석 리포트" , thursday .getYear (), thursday .getMonthValue (), weekOfMonth );
122+
123+ responses .add (weeklyDetailRecordService .generateWeeklyDetailReport (
124+ userId , checkDate , sunday , weekRange ));
125+ }
126+ checkDate = checkDate .plusWeeks (1 );
127+ }
128+
129+ return ApiResponse .onSuccess (responses );
105130 }
106131
107132 @ Operation (summary = "일별 종합 소비 만족도 조회" , description = "당일 모든 지출에 대한 회고가 완료된 경우, 전체 만족도 평균을 문구로 반환합니다." )
@@ -127,6 +152,20 @@ public ApiResponse<List<MonthlyReportSummaryResponse>> getMonthlyTotalList(
127152 return ApiResponse .onSuccess (response );
128153 }
129154
155+ @ Operation (summary = "월 + 주차별 open 상태 통합 조회" ,
156+ description = "특정 월의 총 지출액, 주차별 리포트 오픈 여부, 월간 리포트 오픈 여부를 한 번에 조회합니다." )
157+ @ GetMapping ("/total_open_status" )
158+ public ApiResponse <TotalOpenStatusResponse > getTotalOpenStatus (
159+ @ AuthenticationPrincipal CustomUserDetails userDetails ,
160+ @ RequestParam int year ,
161+ @ RequestParam int month ) {
162+
163+ Long userId = userDetails .getUserId ();
164+ TotalOpenStatusResponse response = totalOpenStatusService .getTotalOpenStatus (userId , year , month );
165+
166+ return ApiResponse .onSuccess (response );
167+ }
168+
130169 @ Operation (summary = "분석 리포트 도착 알림 카드 조회" ,
131170 description = "생성한 월별 분석 리포트 알림 카드 목록을 반환합니다. 확인한 리포트는 isChecked=true로\n " +
132171 " 표시됩니다. 이전 달 미확인과 무관하게 최신 리포트도 노출됩니다." )
0 commit comments