Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…anner-BE into release
  • Loading branch information
ji-woong-song committed Apr 2, 2024
2 parents fab675b + 5e3d35c commit a00c6e4
Show file tree
Hide file tree
Showing 35 changed files with 674 additions and 108 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.umc5th.muffler.domain.dailyplan.repository;

import com.umc5th.muffler.entity.DailyPlan;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
@RequiredArgsConstructor
public class DailyPlanJdbcRepository {

private final JdbcTemplate jdbcTemplate;

public void batchInsert(List<DailyPlan> dailyPlans) {
String sql = "INSERT INTO daily_plan (date, budget, is_zero_day, total_cost, goal_id) VALUES (?, ?, ?, ?, ?)";

jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
DailyPlan dailyPlan = dailyPlans.get(i);
ps.setDate(1, Date.valueOf(dailyPlan.getDate()));
ps.setLong(2, dailyPlan.getBudget());
ps.setBoolean(3, dailyPlan.getIsZeroDay());
ps.setLong(4, dailyPlan.getTotalCost());
ps.setLong(5, dailyPlan.getGoal().getId());
}

@Override
public int getBatchSize() {
return dailyPlans.size();
}
});
}

public void batchUpdateBudget(List<DailyPlan> dailyPlans, List<Long> dailyBudgets) {
String sql = "UPDATE daily_plan SET budget = ? WHERE id = ?";

jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
DailyPlan dailyPlan = dailyPlans.get(i);
Long budget = dailyBudgets.get(i);
ps.setLong(1, budget);
ps.setLong(2, dailyPlan.getId());
}

@Override
public int getBatchSize() {
return dailyPlans.size();
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
public interface DailyPlanRepository extends JpaRepository<DailyPlan, Long>, DailyPlanRepositoryCustom {
Expand All @@ -23,4 +25,12 @@ public interface DailyPlanRepository extends JpaRepository<DailyPlan, Long>, Dai
+ "WHERE dailyPlan.date = :date "
+ "AND dailyPlan.goal.member.id = :memberId")
Optional<DailyPlan> findDailyPlanWithGoalByDateAndMember(String memberId, LocalDate date);

@Query("SELECT dp.id FROM DailyPlan dp WHERE dp.goal.id = :goalId")
List<Long> findByGoalId(Long goalId);

@Transactional
@Modifying
@Query("DELETE FROM DailyPlan dp WHERE dp.id in :ids")
void deleteByIds(List<Long> ids);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import com.umc5th.muffler.entity.Expense;
import com.umc5th.muffler.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import java.util.List;

import java.time.LocalDate;
import java.util.Optional;
import org.springframework.transaction.annotation.Transactional;

@Repository
public interface ExpenseRepository extends JpaRepository<Expense, Long>, ExpenseRepositoryCustom {
Expand All @@ -27,4 +29,9 @@ public interface ExpenseRepository extends JpaRepository<Expense, Long>, Expense

@Query("SELECT SUM(e.cost) FROM Expense e WHERE e.member.id = :memberId AND e.category.id = :categoryId AND e.date BETWEEN :startDate AND :endDate")
Optional<Long> sumTotalCategoryCostByMemberAndDateBetween(String memberId, Long categoryId, LocalDate startDate, LocalDate endDate);

@Transactional
@Modifying
@Query("DELETE FROM Expense e WHERE e.id in :ids")
void deleteByIds(List<Long> ids);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

import com.umc5th.muffler.entity.Category;
import com.umc5th.muffler.entity.Expense;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import com.umc5th.muffler.entity.Goal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

public interface ExpenseRepositoryCustom {
Map<LocalDate, List<Expense>> findByMemberAndDateRangeGroupedByDate(String memberId, LocalDate startDate, LocalDate endDate);
Expand All @@ -18,4 +17,7 @@ public interface ExpenseRepositoryCustom {
Long sumCategoryExpenseWithinGoal(String memberId, Category category, Goal goal);
Long sumCostByMemberAndDateBetween(String memberId, LocalDate startDate, LocalDate endDate);
Slice<Expense> findByMemberAndTitleContaining(String memberId, String searchKeyword, LocalDate lastDate, Long lastExpenseId, int size, String order);
boolean existsExpense(String memberId, LocalDate startDate, LocalDate endDate);
List<Long> findByMemberIdAndDateRange(String memberId, LocalDate startDate, LocalDate endDate);
Map<LocalDate, Long> findTotalCostDate(String memberId, LocalDate startDate, LocalDate endDate);
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
package com.umc5th.muffler.domain.expense.repository;

import static com.umc5th.muffler.entity.QCategory.category;
import static com.umc5th.muffler.entity.QExpense.expense;

import com.querydsl.core.Tuple;
import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.umc5th.muffler.entity.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.*;

import com.umc5th.muffler.entity.Category;
import com.umc5th.muffler.entity.Expense;
import com.umc5th.muffler.entity.Goal;
import com.umc5th.muffler.entity.QExpense;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.umc5th.muffler.entity.QCategory.category;
import static com.umc5th.muffler.entity.QExpense.expense;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.SliceImpl;
import org.springframework.data.domain.Sort;

@RequiredArgsConstructor
public class ExpenseRepositoryImpl implements ExpenseRepositoryCustom {
Expand Down Expand Up @@ -171,6 +179,50 @@ public Slice<Expense> findByMemberAndTitleContaining(String memberId, String sea
return new SliceImpl<>(results, pageable, hasNext);
}

@Override
public boolean existsExpense(String memberId, LocalDate startDate, LocalDate endDate) {
QExpense expense = QExpense.expense;

return queryFactory.select(expense.id)
.from(expense)
.where(expense.member.id.eq(memberId)
.and(expense.date.between(startDate, endDate)))
.fetchFirst() != null;
}

@Override
public List<Long> findByMemberIdAndDateRange(String memberId, LocalDate startDate, LocalDate endDate) {
QExpense expense = QExpense.expense;

return queryFactory.select(expense.id)
.from(expense)
.where(expense.member.id.eq(memberId)
.and(expense.date.between(startDate, endDate)))
.fetch();
}

@Override
public Map<LocalDate, Long> findTotalCostDate(String memberId, LocalDate startDate, LocalDate endDate) {
QExpense expense = QExpense.expense;

Map<LocalDate, Long> expenseMap = new HashMap<>();
List<Tuple> tuples = queryFactory
.select(expense.date, expense.cost.sum().as("totalCost"))
.from(expense)
.where(expense.date.between(startDate, endDate), expense.member.id.eq(memberId))
.groupBy(expense.date)
.fetch();
for (Tuple tuple : tuples) {
LocalDate date = tuple.get(expense.date);
Long sum = tuple.get(expense.cost.sum());
if (date != null) {
if (sum == null) sum = 0L;
expenseMap.put(date, sum);
}
}
return expenseMap;
}

private BooleanExpression searchTitle(String searchKeyword){
if (searchKeyword != null && !searchKeyword.trim().isEmpty()) {
return expense.title.containsIgnoreCase(searchKeyword);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.umc5th.muffler.domain.goal.controller;

import com.umc5th.muffler.domain.goal.dto.CategoryGoalsRequest;
import com.umc5th.muffler.domain.goal.dto.DailyBudgetsRequest;
import com.umc5th.muffler.domain.goal.dto.GoalConverter;
import com.umc5th.muffler.domain.goal.dto.GoalCreateRequest;
import com.umc5th.muffler.domain.goal.dto.GoalGetResponse;
Expand All @@ -8,7 +10,7 @@
import com.umc5th.muffler.domain.goal.dto.GoalPreviewResponse;
import com.umc5th.muffler.domain.goal.dto.GoalPreviousResponse;
import com.umc5th.muffler.domain.goal.dto.GoalReportResponse;
import com.umc5th.muffler.domain.goal.dto.GoalTitleRequest;
import com.umc5th.muffler.domain.goal.dto.GoalUpdateRequest;
import com.umc5th.muffler.domain.goal.service.GoalCreateService;
import com.umc5th.muffler.domain.goal.service.GoalService;
import com.umc5th.muffler.entity.Goal;
Expand All @@ -21,6 +23,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down Expand Up @@ -53,9 +56,32 @@ public Response<GoalPreviousResponse> getPrevious(Authentication authentication)
return Response.success(GoalConverter.getGoalPreviousResponse(goals));
}

@GetMapping("/restore")
public ResponseEntity<Void> checkRestore(Authentication authentication,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
boolean isExists = goalService.checkRestore(authentication.getName(), startDate, endDate);
if (isExists) {
return ResponseEntity.ok().build();
}
return ResponseEntity.noContent().build();
}

@PatchMapping("/{goalId}")
public Response<Void> updateTitle(@PathVariable Long goalId, @RequestBody @Valid GoalTitleRequest request, Authentication authentication) {
goalService.updateTitle(goalId, request.getTitle(), authentication.getName());
public Response<Void> updateTitleAndIcon(@PathVariable Long goalId, @RequestBody @Valid GoalUpdateRequest request, Authentication authentication) {
goalService.updateTitleAndIcon(goalId, request.getTitle(), request.getIcon(), authentication.getName());
return Response.success();
}

@PatchMapping("/{goalId}/category-goal")
public Response<Void> updateCategoryGoals(@PathVariable Long goalId, @RequestBody @Valid CategoryGoalsRequest request, Authentication authentication) {
goalCreateService.updateCategoryGoals(authentication.getName(), goalId, request.getCategoryGoals());
return Response.success();
}

@PatchMapping("/{goalId}/daily-budgets")
public Response<Void> updateDailyBudgets(@PathVariable Long goalId, @RequestBody @Valid DailyBudgetsRequest request, Authentication authentication) {
goalCreateService.updateDailyBudgets(authentication.getName(), goalId, request.getDailyBudgets());
return Response.success();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
@Getter
@AllArgsConstructor
public class CategoryGoalRequest {
@NotNull
private Long categoryGoalId;
@NotNull
private Long categoryId;
@NotNull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.umc5th.muffler.domain.goal.dto;

import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class CategoryGoalsRequest {
@NotNull @Valid
private List<CategoryGoalRequest> categoryGoals;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.umc5th.muffler.domain.goal.dto;

import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class DailyBudgetsRequest {
@NotNull
private List<Long> dailyBudgets;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.time.LocalDate;
import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
Expand All @@ -14,7 +15,7 @@
@NoArgsConstructor
@Builder
public class GoalCreateRequest {
@NotNull
@NotBlank
private String icon;
@NotBlank
private String title;
Expand All @@ -26,8 +27,13 @@ public class GoalCreateRequest {
private Long totalBudget;

@NotNull
@Valid
private List<CategoryGoalRequest> categoryGoals;

@NotNull
private List<Long> dailyBudgets;

@NotNull
private Boolean canRestore;
private Boolean restore;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class GoalTitleRequest {
public class GoalUpdateRequest {
@NotBlank
private String title;
@NotBlank
private String icon;
}
Loading

0 comments on commit a00c6e4

Please sign in to comment.