Skip to content

Commit

Permalink
feat: 장부 내역 조회 api v2를 추가한다. (#77)
Browse files Browse the repository at this point in the history
* feat: 내정보 조회 api에 provider field를 추가한다.

* feat: 특정 기간의 장부를 반환하는 메소드를 추가한다.

* feat: LedgerReader의 공통 코드를 메소드 분리한다.

* feat: LedgerControllerV2, RequestV2를 추가한다.
  • Loading branch information
rlarltj authored Apr 24, 2024
1 parent 822d9ba commit 5232cd4
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 25 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.moneymong.domain.ledger.api;

import com.moneymong.domain.ledger.api.request.*;
import com.moneymong.domain.ledger.api.response.ledger.LedgerInfoView;
import com.moneymong.domain.ledger.service.reader.LedgerReader;
import com.moneymong.global.security.token.dto.jwt.JwtAuthentication;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

@Tag(name = "5. [장부 V2]")
@RequestMapping("/api/v2/ledger")
@RestController
@RequiredArgsConstructor
public class LedgerControllerV2 {
private final LedgerReader ledgerReader;

@Operation(summary = " 장부 내역 조회 API")
@GetMapping("/{id}")
public LedgerInfoView search(
@AuthenticationPrincipal JwtAuthentication user,
@PathVariable("id") final Long ledgerId,
@ParameterObject @Valid final SearchLedgerRequestV2 searchLedgerRequest
) {
return ledgerReader.searchLedgersByPeriod(
user.getId(),
ledgerId,
searchLedgerRequest.getStartYear(),
searchLedgerRequest.getStartMonth(),
searchLedgerRequest.getEndYear(),
searchLedgerRequest.getEndMonth(),
searchLedgerRequest.getPage(),
searchLedgerRequest.getLimit()
);
}

@Operation(summary = "장부 내역 필터별 조회 API")
@GetMapping("/{id}/filter")
public LedgerInfoView searchByFilter(
@AuthenticationPrincipal JwtAuthentication user,
@PathVariable("id") final Long ledgerId,
@ParameterObject @Valid final SearchLedgerFilterRequestV2 searchLedgerFilterRequest
) {
return ledgerReader.searchLedgersByPeriodAndFundType(
user.getId(),
ledgerId,
searchLedgerFilterRequest.getStartYear(),
searchLedgerFilterRequest.getStartMonth(),
searchLedgerFilterRequest.getEndYear(),
searchLedgerFilterRequest.getEndMonth(),
searchLedgerFilterRequest.getPage(),
searchLedgerFilterRequest.getLimit(),
searchLedgerFilterRequest.getFundType()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.moneymong.domain.ledger.api.request;

import com.moneymong.domain.ledger.entity.enums.FundType;
import jakarta.validation.constraints.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class SearchLedgerFilterRequestV2 {
@Positive(message = "startYear를 입력해주세요.")
private int startYear;

@Positive(message = "endYear를 입력해주세요.")
private int endYear;

@Min(value = 1, message = "month 1 이상 입력해주세요.")
@Max(value = 12, message = "month 12 이하 입력해주세요.")
private int startMonth;

@Min(value = 1, message = "month 1 이상 입력해주세요.")
@Max(value = 12, message = "month 12 이하 입력해주세요.")
private int endMonth;

@PositiveOrZero(message = "page 0이상 입력해주세요.")
private int page;

@Max(value= 300, message = "limit를 입력해주세요.")
private int limit;

@NotNull(message = "fundType(INCOME, EXPENSE)를 입력해주세요.")
private FundType fundType;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.moneymong.domain.ledger.api.request;

import jakarta.validation.constraints.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class SearchLedgerRequestV2 {

@Positive(message = "startYear를 입력해주세요.")
private int startYear;

@Positive(message = "endYear를 입력해주세요.")
private int endYear;

@Min(value = 1, message = "month 1 이상 입력해주세요.")
@Max(value = 12, message = "month 12 이하 입력해주세요.")
private int startMonth;

@Min(value = 1, message = "month 1 이상 입력해주세요.")
@Max(value = 12, message = "month 12 이하 입력해주세요.")
private int endMonth;

@PositiveOrZero(message = "page 0이상 입력해주세요.")
private int page;

@Max(value= 300, message = "limit를 입력해주세요.")
private int limit;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ List<LedgerDetail> searchByFundType(
PageRequest pageable
);

List<LedgerDetail> searchByPeriod(
Ledger ledger,
ZonedDateTime from,
ZonedDateTime to,
PageRequest pageable
);

List<LedgerDetail> searchByPeriodAndFundType(
Ledger ledger,
ZonedDateTime from,
ZonedDateTime to,
FundType fundType,
PageRequest pageable
);

void bulkUpdateLedgerDetailBalance(
Ledger ledger,
ZonedDateTime paymentDate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public List<LedgerDetail> search(
ZonedDateTime to,
Pageable pageable
) {

return jpaQueryFactory.selectFrom(ledgerDetail)
.where(ledgerDetail.ledger.eq(ledger))
.where(ledgerDetail.paymentDate.between(from, to))
Expand All @@ -46,7 +45,40 @@ public List<LedgerDetail> searchByFundType(
FundType fundType,
PageRequest pageable
) {
return jpaQueryFactory.selectFrom(ledgerDetail)
.where(ledgerDetail.ledger.eq(ledger))
.where(ledgerDetail.fundType.eq(fundType))
.where(ledgerDetail.paymentDate.between(from, to))
.orderBy(ledgerDetail.paymentDate.desc())
.offset((long) pageable.getPageNumber() * pageable.getPageSize())
.limit(pageable.getPageSize())
.fetch();
}

@Override
public List<LedgerDetail> searchByPeriod(
Ledger ledger,
ZonedDateTime from,
ZonedDateTime to,
PageRequest pageable
) {
return jpaQueryFactory.selectFrom(ledgerDetail)
.where(ledgerDetail.ledger.eq(ledger))
.where(ledgerDetail.paymentDate.between(from, to))
.orderBy(ledgerDetail.paymentDate.desc())
.offset((long) pageable.getPageNumber() * pageable.getPageSize())
.limit(pageable.getPageSize())
.fetch();
}

@Override
public List<LedgerDetail> searchByPeriodAndFundType(
Ledger ledger,
ZonedDateTime from,
ZonedDateTime to,
FundType fundType,
PageRequest pageable
) {
return jpaQueryFactory.selectFrom(ledgerDetail)
.where(ledgerDetail.ledger.eq(ledger))
.where(ledgerDetail.fundType.eq(fundType))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import static com.moneymong.domain.agency.entity.enums.AgencyUserRole.isBlockedUser;
import static java.util.stream.Collectors.toList;

@Transactional(readOnly = true)
@RequiredArgsConstructor
@Service
public class LedgerReader {
Expand All @@ -36,7 +37,64 @@ public class LedgerReader {
private final LedgerRepository ledgerRepository;
private final LedgerDetailRepository ledgerDetailRepository;

@Transactional(readOnly = true)
public LedgerInfoView searchLedgersByPeriod(
long userId,
long ledgerId,
int startYear,
int startMonth,
int endYear,
int endMonth,
int page,
int limit
) {
Ledger ledger = getLedger(ledgerId);
AgencyUser agencyUser = getAgencyUser(userId, ledger);

ensureAgencyUserNotBlocked(agencyUser.getAgencyUserRole());

ZonedDateTime from = ZonedDateTime.of(startYear, startMonth, 1, 0, 0, 0, 0, ZoneId.systemDefault());
ZonedDateTime to = ZonedDateTime.of(endYear, endMonth, 1, 0, 0, 0, 0, ZoneId.systemDefault());

List<LedgerDetail> ledgerDetails = ledgerDetailRepository.searchByPeriod(
ledger,
from,
to,
PageRequest.of(page, limit)
);

return LedgerInfoView.from(ledger, convertToLedgerInfoViewDetail(ledgerDetails));
}

public LedgerInfoView searchLedgersByPeriodAndFundType(
long userId,
long ledgerId,
int startYear,
int startMonth,
int endYear,
int endMonth,
int page,
int limit,
FundType fundType
) {
Ledger ledger = getLedger(ledgerId);
AgencyUser agencyUser = getAgencyUser(userId, ledger);

ensureAgencyUserNotBlocked(agencyUser.getAgencyUserRole());

ZonedDateTime from = ZonedDateTime.of(startYear, startMonth, 1, 0, 0, 0, 0, ZoneId.systemDefault());
ZonedDateTime to = ZonedDateTime.of(endYear, endMonth, 1, 0, 0, 0, 0, ZoneId.systemDefault());

List<LedgerDetail> ledgerDetails = ledgerDetailRepository.searchByPeriodAndFundType(
ledger,
from,
to,
fundType,
PageRequest.of(page, limit)
);

return LedgerInfoView.from(ledger, convertToLedgerInfoViewDetail(ledgerDetails));
}

public LedgerInfoView search(
final Long userId,
final Long ledgerId,
Expand All @@ -46,19 +104,13 @@ public LedgerInfoView search(
final Integer limit
) {
// === 유저 ===
User user = userRepository
.findById(userId)
.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
User user = getUser(userId);

// === 장부 ===
Ledger ledger = ledgerRepository.findById(ledgerId).orElseThrow(
() -> new NotFoundException(ErrorCode.LEDGER_NOT_FOUND)
);
Ledger ledger = getLedger(ledgerId);

// === 소속 ===
AgencyUser agencyUser = agencyUserRepository
.findByUserIdAndAgencyId(userId, ledger.getAgency().getId())
.orElseThrow(() -> new NotFoundException(ErrorCode.AGENCY_NOT_FOUND));
AgencyUser agencyUser = getAgencyUser(userId, ledger);

ensureAgencyUserNotBlocked(agencyUser.getAgencyUserRole());

Expand All @@ -74,7 +126,6 @@ public LedgerInfoView search(
return LedgerInfoView.from(ledger, convertToLedgerInfoViewDetail(ledgerDetailPage));
}

@Transactional(readOnly = true)
public LedgerInfoView searchByFilter(
final Long userId,
final Long ledgerId,
Expand All @@ -85,19 +136,13 @@ public LedgerInfoView searchByFilter(
final FundType fundType
) {
// === 유저 ===
User user = userRepository
.findById(userId)
.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
User user = getUser(userId);

// === 장부 ===
Ledger ledger = ledgerRepository.findById(ledgerId).orElseThrow(
() -> new NotFoundException(ErrorCode.LEDGER_NOT_FOUND)
);
Ledger ledger = getLedger(ledgerId);

// === 소속 ===
AgencyUser agencyUser = agencyUserRepository
.findByUserIdAndAgencyId(userId, ledger.getAgency().getId())
.orElseThrow(() -> new NotFoundException(ErrorCode.AGENCY_NOT_FOUND));
AgencyUser agencyUser = getAgencyUser(userId, ledger);

ensureAgencyUserNotBlocked(agencyUser.getAgencyUserRole());

Expand All @@ -114,7 +159,6 @@ public LedgerInfoView searchByFilter(
return LedgerInfoView.from(ledger, convertToLedgerInfoViewDetail(ledgerDetailPage));
}


public LedgerInfoView searchByAgency(
final Long userId,
final Long agencyId,
Expand All @@ -124,9 +168,7 @@ public LedgerInfoView searchByAgency(
final Integer limit
) {
// === 유저 ===
User user = userRepository
.findById(userId)
.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
User user = getUser(userId);

// === 장부 ===
Ledger ledger = ledgerRepository.findByAgencyId(agencyId).orElseThrow(
Expand Down Expand Up @@ -160,6 +202,24 @@ public boolean exists(Long agencyId) {
return ledgerDetailRepository.existsByLedger(ledger);
}

private User getUser(Long userId) {
return userRepository
.findById(userId)
.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
}

private Ledger getLedger(Long ledgerId) {
return ledgerRepository.findById(ledgerId).orElseThrow(
() -> new NotFoundException(ErrorCode.LEDGER_NOT_FOUND)
);
}

private AgencyUser getAgencyUser(Long userId, Ledger ledger) {
return agencyUserRepository
.findByUserIdAndAgencyId(userId, ledger.getAgency().getId())
.orElseThrow(() -> new NotFoundException(ErrorCode.AGENCY_NOT_FOUND));
}

private void ensureAgencyUserNotBlocked(AgencyUserRole role) {
if (isBlockedUser(role)) {
throw new BadRequestException(ErrorCode.BLOCKED_AGENCY_USER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
public class UserProfileResponse {
private Long id;
private String userToken;
private String provider;
private String nickname;
private String email;
private String universityName;
Expand All @@ -21,6 +22,7 @@ public static UserProfileResponse from(User user, UserUniversity userUniversity)
return UserProfileResponse.builder()
.id(user.getId())
.userToken(user.getUserToken())
.provider(user.getProvider())
.nickname(user.getNickname())
.email(user.getEmail())
.universityName(userUniversity.getUniversityName())
Expand Down

0 comments on commit 5232cd4

Please sign in to comment.