Skip to content

Commit

Permalink
Merge branch 'dev' into feat/#198
Browse files Browse the repository at this point in the history
  • Loading branch information
ryogaeng authored Nov 28, 2024
2 parents 7f02e61 + 1d7d2f7 commit 19e44af
Show file tree
Hide file tree
Showing 62 changed files with 1,486 additions and 1,168 deletions.
84 changes: 46 additions & 38 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,67 +1,75 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.7'
id 'io.spring.dependency-management' version '1.1.5'
id 'com.google.cloud.tools.jib' version '3.4.3'
id 'java'
id 'org.springframework.boot' version '3.2.7'
id 'io.spring.dependency-management' version '1.1.5'
id 'com.google.cloud.tools.jib' version '3.4.3'
}

group = 'com.bbteam'
version = '0.0.1-SNAPSHOT'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-security' // security
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' //Swagger
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-security' // security
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' //Swagger

implementation 'net.nurigo:sdk:4.2.7' // 문자메시지 대행 서비스
implementation 'net.nurigo:sdk:4.2.7' // 문자메시지 대행 서비스

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-cache' // cache

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly('io.jsonwebtoken:jjwt-jackson:0.11.5') // jackson으로 jwt 파싱

// querydsl 관련
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform()
}

jib {
from {
image = 'openjdk:17-alpine'
platforms {
platform {
architecture = 'amd64'
os = 'linux'
}
}
}
to {
image = 'binjumeoniz1/binjumeoniz:latest'
}
container {
jvmFlags = ['-Dspring.profiles.active=dev']
}
from {
image = 'openjdk:17-alpine'
platforms {
platform {
architecture = 'amd64'
os = 'linux'
}
}
}
to {
image = 'binjumeoniz1/binjumeoniz:latest'
}
container {
jvmFlags = ['-Dspring.profiles.active=dev']
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableJpaAuditing
@EnableAsync
@EnableCaching
public class BudgetbuddiesApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public enum ErrorStatus implements BaseErrorCode {


_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON5000", "서버에러"),
_INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON5000", "서버 에러. 관리자에게 문의하세요."),
_BAD_REQUEST(HttpStatus.BAD_REQUEST, "COMMON4000", "잘못된 요청"),
_USER_NOT_FOUND(HttpStatus.BAD_REQUEST, "USER4001", "사용자가 없습니다."),
_COMMENT_NOT_FOUND(HttpStatus.BAD_REQUEST, "COMMENT4001", "해당 댓글이 없습니다.") ,
Expand All @@ -27,7 +27,9 @@ public enum ErrorStatus implements BaseErrorCode {

_OTP_NOT_VALID(HttpStatus.BAD_REQUEST, "OTP4001", "인증번호가 유효하지 않습니다."),
_PHONE_NUMBER_NOT_VALID(HttpStatus.BAD_REQUEST, "AUTH4001", "전화번호 형식이 유효하지 않습니다. (예: 01012341234)"),
_FAQ_NOT_FOUND(HttpStatus.NOT_FOUND, "FAQ4004", "해당 FAQ가 존재하지 않습니다.");
_FAQ_NOT_FOUND(HttpStatus.NOT_FOUND, "FAQ4004", "해당 FAQ가 존재하지 않습니다."),
_SEARCH_KEYWORD_NOT_FOUND(HttpStatus.NOT_FOUND, "SEARCH_KEYWORD4004", "해당 SearchKeyword가 존재하지 않습니다."),
_FAQ_KEYWORD_NOT_FOUND(HttpStatus.NOT_FOUND, "FAQ_KEYWORD4004", "해당 FaqKeyword가 존재하지 않습니다.");


private HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ public interface CategoryService {

List<CategoryResponseDto> getUserCategories(Long userId);

Category handleCategoryChange(Expense expense, ExpenseUpdateRequestDto request, User user);

void deleteCategory(Long id, Long userId);

Category getCategory(Long categoryId);

List<Category> getUserCategoryList(Long userId);
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import java.util.Optional;
import java.util.stream.Collectors;

import com.bbteam.budgetbuddies.domain.expense.repository.ExpenseRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -16,9 +15,8 @@
import com.bbteam.budgetbuddies.domain.category.repository.CategoryRepository;
import com.bbteam.budgetbuddies.domain.consumptiongoal.entity.ConsumptionGoal;
import com.bbteam.budgetbuddies.domain.consumptiongoal.repository.ConsumptionGoalRepository;
import com.bbteam.budgetbuddies.domain.consumptiongoal.service.ConsumptionGoalService;
import com.bbteam.budgetbuddies.domain.expense.dto.ExpenseUpdateRequestDto;
import com.bbteam.budgetbuddies.domain.expense.entity.Expense;
import com.bbteam.budgetbuddies.domain.expense.repository.ExpenseRepository;
import com.bbteam.budgetbuddies.domain.user.entity.User;
import com.bbteam.budgetbuddies.domain.user.repository.UserRepository;

Expand All @@ -30,7 +28,6 @@
public class CategoryServiceImpl implements CategoryService {

private final CategoryRepository categoryRepository;
private final ConsumptionGoalService consumptionGoalService;
private final UserRepository userRepository;
private final CategoryConverter categoryConverter;
private final ConsumptionGoalRepository consumptionGoalRepository;
Expand All @@ -40,11 +37,11 @@ public class CategoryServiceImpl implements CategoryService {
@Transactional
public CategoryResponseDto createCategory(Long userId, CategoryRequestDto categoryRequestDto) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("Invalid user ID"));
.orElseThrow(() -> new IllegalArgumentException("Invalid user ID"));

// 동일한 이름의 삭제된 카테고리가 존재하는지 확인
Optional<Category> existingCategory = categoryRepository.findByNameAndUserIdAndDeletedTrue(
categoryRequestDto.getName(), userId);
categoryRequestDto.getName(), userId);

if (existingCategory.isPresent()) {
// 삭제된 카테고리가 존재하면 복구 (deleted = false)
Expand All @@ -54,7 +51,7 @@ public CategoryResponseDto createCategory(Long userId, CategoryRequestDto catego

// 해당 카테고리의 삭제된 ConsumptionGoal도 복구
Optional<ConsumptionGoal> existingConsumptionGoal = consumptionGoalRepository.findByUserAndCategoryAndDeletedTrue(
user, categoryToRestore);
user, categoryToRestore);

if (existingConsumptionGoal.isPresent()) {
ConsumptionGoal consumptionGoalToRestore = existingConsumptionGoal.get();
Expand All @@ -65,13 +62,13 @@ public CategoryResponseDto createCategory(Long userId, CategoryRequestDto catego
} else {
// ConsumptionGoal이 존재하지 않으면 새로 생성
ConsumptionGoal newConsumptionGoal = ConsumptionGoal.builder()
.user(user)
.category(categoryToRestore)
.goalMonth(LocalDate.now().withDayOfMonth(1)) // 현재 달로 목표 설정
.consumeAmount(0L)
.goalAmount(0L)
.deleted(false) // 생성할 때 삭제 상태가 아니도록
.build();
.user(user)
.category(categoryToRestore)
.goalMonth(LocalDate.now().withDayOfMonth(1)) // 현재 달로 목표 설정
.consumeAmount(0L)
.goalAmount(0L)
.deleted(false) // 생성할 때 삭제 상태가 아니도록
.build();
consumptionGoalRepository.save(newConsumptionGoal);
}

Expand All @@ -83,13 +80,13 @@ public CategoryResponseDto createCategory(Long userId, CategoryRequestDto catego

// 새로운 카테고리에 대한 ConsumptionGoal도 생성
ConsumptionGoal newConsumptionGoal = ConsumptionGoal.builder()
.user(user)
.category(newCategory)
.goalMonth(LocalDate.now().withDayOfMonth(1)) // 현재 달로 목표 설정
.consumeAmount(0L)
.goalAmount(0L)
.deleted(false) // 생성할 때 삭제 상태가 아니도록
.build();
.user(user)
.category(newCategory)
.goalMonth(LocalDate.now().withDayOfMonth(1)) // 현재 달로 목표 설정
.consumeAmount(0L)
.goalAmount(0L)
.deleted(false) // 생성할 때 삭제 상태가 아니도록
.build();
consumptionGoalRepository.save(newConsumptionGoal);

return categoryConverter.toCategoryResponseDto(newCategory);
Expand All @@ -100,21 +97,15 @@ public CategoryResponseDto createCategory(Long userId, CategoryRequestDto catego
public List<CategoryResponseDto> getUserCategories(Long userId) {

userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("User not found with id: " + userId));
.orElseThrow(() -> new IllegalArgumentException("User not found with id: " + userId));

List<Category> categories = categoryRepository.findUserCategoryByUserId(userId);
return categories.stream().map(categoryConverter::toCategoryResponseDto).collect(Collectors.toList());
}

@Override
@Transactional(readOnly = true)
public Category handleCategoryChange(Expense expense, ExpenseUpdateRequestDto request, User user) {
Category categoryToReplace = categoryRepository.findById(request.getCategoryId())
.orElseThrow(() -> new IllegalArgumentException("Not found category"));

consumptionGoalService.recalculateConsumptionAmount(expense, request, user);

return categoryToReplace;
public Category getCategory(Long id) {
return categoryRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Not found category"));
}

@Override
Expand All @@ -131,15 +122,15 @@ public void deleteCategory(Long categoryId, Long userId) {

// 현재 월에 해당하는 삭제되지 않은 Expense 조회 (deleted = false)
List<Expense> currentMonthExpenses = expenseRepository.findByCategoryIdAndUserIdAndExpenseDateBetweenAndDeletedFalse(
categoryId, userId, startOfMonth.atStartOfDay(), endOfMonth.atTime(23, 59, 59));
categoryId, userId, startOfMonth.atStartOfDay(), endOfMonth.atTime(23, 59, 59));

long totalAmount = currentMonthExpenses.stream()
.mapToLong(Expense::getAmount)
.sum();
.mapToLong(Expense::getAmount)
.sum();

// category_id = 10(기타 카테고리)의 소비 목표 업데이트 (custom 카테고리 삭제로 인한 소비 내역은 삭제되지 않고 기타 카테고리로..)
ConsumptionGoal goal = consumptionGoalRepository.findByCategoryIdAndUserId(10L, userId)
.orElseThrow(() -> new IllegalArgumentException("No consumption goal found for category_id 10."));
.orElseThrow(() -> new IllegalArgumentException("No consumption goal found for category_id 10."));
goal.setConsumeAmount(goal.getConsumeAmount() + totalAmount);
consumptionGoalRepository.save(goal);

Expand All @@ -161,4 +152,8 @@ public void deleteCategory(Long categoryId, Long userId) {
});
}

@Override
public List<Category> getUserCategoryList(Long userId) {
return categoryRepository.findUserCategoryByUserId(userId);
}
}
Loading

0 comments on commit 19e44af

Please sign in to comment.