33 Commits

Author SHA1 Message Date
kkazuya
9259a53bad [EDIT] コースのコントローラとビュー、ユーザーサービスを修正しました。 2026-09-18 14:16:00 +09:00
s-choi
ad1121d694 [FIX] 日付の設定をデフォルト値を設定しました。 2026-09-18 14:06:57 +09:00
s-choi
6ca5a9eeec [STYLE] 家計簿関連ページのスタイルを修正しました。 2026-09-18 14:03:54 +09:00
709f5e14da [EDIT]画面の上下に空白を作りました 2026-09-18 14:00:20 +09:00
6197b12ac4 [EDIT]ヘッダーを固定化しました 2026-09-18 13:59:50 +09:00
18faec044e Merge branch 's-choi' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into n-kawahito 2026-09-18 13:59:17 +09:00
s-choi
b49c9156a1 [FIX] 全体的な整合性を確認しました。 2026-09-18 13:58:12 +09:00
6b4ae5bd96 Merge branch 'k-oshita' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into s-morimto 2026-09-18 13:58:07 +09:00
s-choi
9cdf7b7767 [EDIT] 収支一覧にデザインを追加しました。 2026-09-18 13:57:51 +09:00
s-choi
6dd182ed0b [ADD] 収支編集画面を作成しました。 2026-09-18 13:57:30 +09:00
s-choi
04d62956f7 [EDIT] 日付が自動で記入されるように変更しました。 2026-09-18 13:57:08 +09:00
s-choi
a5c9ab9abe [EDIT] 該当テーブルの収支の情報を取得するメソッドを追加しました。 2026-09-18 13:56:27 +09:00
s-choi
200ebe2a61 [EDIT] 収支IDでカテゴリエンティティを取得するメソッドを作成しました。 2026-09-18 13:55:32 +09:00
s-choi
2300aa3644 [EDIT] 収支詳細画面のデザインを作成しました。 2026-09-18 13:54:32 +09:00
s-choi
d415bf1ad5 [EDIT] 収支詳細に編集ボタンを追加しました。 2026-09-18 13:53:27 +09:00
s-choi
12550c5b1d [STYLE] menuのデザインを変更しました。 2026-09-18 13:51:59 +09:00
15bf2949bc [EDIT] 目標を表示する機能を追加しました。 2026-09-18 13:32:14 +09:00
be9abffeaa Merge branch 'n-kawahito' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into k-oshita 2026-09-18 13:30:15 +09:00
cb7a3f542b Merge branch 'k-kobayashi' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into k-oshita
# Conflicts:
#	src/main/java/com/example/demo/app/domain/service/impl/CourseInfoServiceImpl.java
2026-09-18 11:11:19 +09:00
702dd24d2e Merge branch 'n-kawahito' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into k-oshita
# Conflicts:
#	src/main/java/com/example/demo/app/presentation/form/AnalysisForm.java
#	src/main/java/com/example/demo/app/presentation/form/CategoryAnalysisForm.java
2026-09-18 11:04:06 +09:00
d71194659b [FIX]ゴールモデルのバグ修正 2026-09-18 11:02:42 +09:00
44ceb0ca07 Merge branch 'k-kobayashi' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into k-oshita
# Conflicts:
#	src/main/java/com/example/demo/app/domain/model/GoalModel.java
#	src/main/java/com/example/demo/app/domain/service/CourseInfoService.java
2026-09-18 11:01:21 +09:00
614533e2b0 Merge remote-tracking branch 'origin/k-kobayashi' into k-oshita
# Conflicts:
#	src/main/java/com/example/demo/app/domain/service/CourseService.java
2026-09-18 10:57:42 +09:00
2da75305fd Merge remote-tracking branch 'origin/k-kobayashi' into k-oshita
# Conflicts:
#	src/main/java/com/example/demo/app/domain/service/impl/CourseServiceImpl.java
2026-09-18 10:56:22 +09:00
f55ece4dc7 「STYLE] 目標名を追記しました。 2026-09-18 10:55:37 +09:00
0a63c81712 Merge branch 's-morimto' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into k-oshita 2026-09-18 10:39:13 +09:00
571fcc6d90 [add]余分なファイルをコミットしました 2026-09-18 10:16:49 +09:00
15185672c4 s-choiブランチとのマージ完了 2026-09-18 10:08:41 +09:00
3833689759 [ADD]目標を管理するため機能の追加 2026-09-18 10:05:15 +09:00
0bec7b3b3b [EDIT]目標モデルの改行 2026-09-17 16:52:56 +09:00
662e3433d2 [EDIT]目標のModelの変換部分の修正 2026-09-17 16:12:15 +09:00
60d4ebd74f Merge branch 's-choi' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into k-oshita 2026-09-17 15:13:57 +09:00
49af15f939 Merge branch 's-choi' of https://gitea.it-college.co.jp/2026_09_5H_Spring_KIZAKI/Monegement into k-oshita 2026-09-17 14:36:29 +09:00
29 changed files with 862 additions and 150 deletions

1
.gitignore vendored
View File

@@ -31,3 +31,4 @@ build/
### VS Code ###
.vscode/
/bin/

View File

@@ -2,6 +2,9 @@ package com.example.demo.app.domain.model;
import java.time.LocalDate;
import com.example.demo.app.infra.entity.GoalEntity;
import com.example.demo.app.presentation.form.GoalForm;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -21,4 +24,35 @@ public class GoalModel {
private Integer goalComplete;
public static GoalModel convertFrom(GoalEntity goalEntity) {
return new GoalModel(
goalEntity.getGoalId(),
goalEntity.getGoalTitle(),
goalEntity.getGoalSubtitle(),
goalEntity.getTargetAmount(),
goalEntity.getDeadline(),
goalEntity.getGoalComplete());
}
public static GoalEntity convertTo(GoalModel goalModel) {
return new GoalEntity(
goalModel.getGoalId(),
goalModel.getGoalTitle(),
goalModel.getGoalSubtitle(),
goalModel.getTargetAmount(),
goalModel.getDeadline(),
goalModel.getGoalComplete(),
null);
}
public static GoalModel convertFrom(GoalForm goalForm) {
return new GoalModel(
goalForm.getGoalId(),
goalForm.getGoalTitle(),
goalForm.getGoalSubtitle(),
goalForm.getTargetAmount(),
goalForm.getDeadline(),
goalForm.getGoalComplete());
}
}

View File

@@ -11,4 +11,6 @@ public interface CategoryService {
public CategoryModel findOne(Long categoryId);
public CategoryModel findOneByCategoryName(String categoryName);
public CategoryModel findByTransactionId(Long transactionId);
}

View File

@@ -0,0 +1,17 @@
package com.example.demo.app.domain.service;
import com.example.demo.app.domain.model.GoalModel;
public interface GoalService {
GoalModel getGoalById(Long goalId);
GoalModel getGoalByUserId(Long userId);
GoalModel createGoal(GoalModel goalModel);
GoalModel updateGoal(GoalModel goalModel);
// void deleteGoal(Long goalId);
}

View File

@@ -10,6 +10,8 @@ import com.example.demo.app.presentation.form.Income;
public interface TransactionService {
public TransactionModel findByTransactionId(Long transactionId);
public Map<LocalDate, List<TransactionModel>> findAllByDate(LocalDate startDate, LocalDate endDate, Long userId);
public List<TransactionModel> findByUserIdAndDate(LocalDate todayDate, Long userId);
@@ -18,6 +20,8 @@ public interface TransactionService {
public int findTotalExpense(LocalDate startDate, LocalDate endDate, Long userId);
public int findMoneyRecord(Long transactionId);
public int createTransaction(TransactionModel transactionModel);
public int updateTransaction(TransactionModel transactionModel);

View File

@@ -3,5 +3,8 @@ package com.example.demo.app.domain.service;
import com.example.demo.app.presentation.form.UserForm;
public interface UserService {
void register(UserForm userForm);
void register(UserForm userForm);
public void updateCourse(Long userId, Long courseId);
}

View File

@@ -48,4 +48,9 @@ public class CategoryServiceImpl implements CategoryService {
}
public CategoryModel findByTransactionId(Long transactionId) {
return CategoryModel.convertFrom(categoryRepository.findByTransactionId(transactionId));
}
}

View File

@@ -0,0 +1,55 @@
package com.example.demo.app.domain.service.impl;
import org.springframework.stereotype.Service;
import com.example.demo.app.domain.model.GoalModel;
import com.example.demo.app.domain.service.GoalService;
import com.example.demo.app.infra.entity.GoalEntity;
import com.example.demo.app.infra.entity.UserEntity;
import com.example.demo.app.infra.repository.GoalRepository;
import com.example.demo.app.infra.repository.UserRepository;
import lombok.RequiredArgsConstructor;
@Service
@RequiredArgsConstructor
public class GoalServiceImpl implements GoalService {
private final GoalRepository goalRepository;
private final UserRepository userRepository;
@Override
public GoalModel getGoalById(Long goalId) {
GoalEntity goalEntity = goalRepository.findById(goalId).orElse(null);
return GoalModel.convertFrom(goalEntity);
}
@Override
public GoalModel getGoalByUserId(Long userId) {
UserEntity userEntity = userRepository.findById(userId).orElseThrow();
GoalEntity goalEntity = userEntity.getGoalEntity();
return GoalModel.convertFrom(goalEntity);
}
@Override
public GoalModel createGoal(GoalModel goalModel) {
GoalEntity goalEntity = GoalModel.convertTo(goalModel);
GoalEntity savedGoalEntity = goalRepository.save(goalEntity);
return GoalModel.convertFrom(savedGoalEntity);
}
@Override
public GoalModel updateGoal(GoalModel goalModel) {
GoalEntity goalEntity = GoalModel.convertTo(goalModel);
GoalEntity updatedGoalEntity = goalRepository.save(goalEntity);
return GoalModel.convertFrom(updatedGoalEntity);
}
}

View File

@@ -29,6 +29,13 @@ public class TransactionServiceImpl implements TransactionService {
private final UserRepository userRepository;
private final CategoryRepository categoryRepository;
public TransactionModel findByTransactionId(Long transactionId) {
return TransactionModel.convertFrom(transactionRepository.findById(transactionId).get());
}
public Map<LocalDate, List<TransactionModel>> findAllByDate(
LocalDate startDate,
LocalDate endDate,
@@ -92,6 +99,11 @@ public class TransactionServiceImpl implements TransactionService {
return TransactionModel.convertFrom(transactionRepository.findByUserIdAndDate(todayDate, userId));
}
public int findMoneyRecord(Long transactionId) {
return transactionRepository.findMoneyRecord(transactionId);
}
public int createTransaction(TransactionModel transactionModel) {

View File

@@ -57,6 +57,18 @@ public class UserServiceImpl implements UserService {
userRepository.save(userEntity);
}
@Override
public void updateCourse(Long userId, Long courseId) {
UserEntity userEntity = userRepository.findById(userId).orElseThrow();
CourseEntity courseEntity = courseRepository.findById(courseId).orElseThrow();
userEntity.setCourseEntity(courseEntity);
userRepository.save(userEntity);
}
}

View File

@@ -38,7 +38,7 @@ public class GoalEntity {
@Column(name = "deadline", nullable = false)
private LocalDate deadline;
@Column(name = "goal_complete", nullable = false)
@Column(name = "goal_complete", nullable = true)
private Integer goalComplete;
@OneToOne(mappedBy = "goalEntity")

View File

@@ -12,4 +12,7 @@ public interface CategoryRepository extends JpaRepository<CategoryEntity, Long>
@Query("select c from CategoryEntity c where c.categoryName = :categoryName")
public CategoryEntity findByCategoryName(@Param("categoryName") String categoryName);
@Query("select c from CategoryEntity c inner join TransactionEntity t on c.categoryId = t.categoryEntity.categoryId where t.transactionId = :transactionId")
public CategoryEntity findByTransactionId(Long transactionId);
}

View File

@@ -33,5 +33,7 @@ public interface TransactionRepository extends JpaRepository<TransactionEntity,
@Query("select new com.example.demo.app.presentation.form.Income(t.transactionDate, coalesce(sum(t.amount), 0)) from TransactionEntity t inner join CategoryEntity c on t.categoryEntity.categoryId = c.categoryId where (t.userEntity.userId = :userId and t.transactionDate between :startDate and :endDate) and c.transactionType = 1 group by t.transactionDate order by t.transactionDate asc")
public List<Income> findTotalIncomeList(LocalDate startDate, LocalDate endDate, Long userId);
@Query("select coalesce(t.amount, 0) from TransactionEntity t where t.transactionId = :transactionId")
public Integer findMoneyRecord(Long transactionId);
}

View File

@@ -1,13 +1,22 @@
package com.example.demo.app.presentation.controller;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.example.demo.app.domain.model.LoginModel;
import com.example.demo.app.domain.model.UserModel;
import com.example.demo.app.domain.service.CourseInfoService;
import com.example.demo.app.domain.service.CourseService;
import com.example.demo.app.domain.service.UserService;
import com.example.demo.app.presentation.form.CourseForm;
import com.example.demo.app.presentation.form.CourseInfoForm;
@@ -15,6 +24,7 @@ import lombok.RequiredArgsConstructor;
@Controller
@RequestMapping("/course")
@RequiredArgsConstructor
public class CourseController {
@@ -22,31 +32,70 @@ public class CourseController {
// エラーメッセージ用の定数フィールド
private final static String SEVERE_ERROR_MESSAGE = "エラーが発生しました!";
// private final HttpSession httpSession;
private final HttpSession httpSession;
private final CourseService courseService;
private final CourseInfoService courseInfoService;
private final UserService userService;
@GetMapping("/select-course")
public String select(Model model) {
@PostMapping("/select/register")
public String showSelectCourse(@ModelAttribute UserModel userModel, Model model) {
//try {
try {
model.addAttribute("mode", "select");
model.addAttribute("courseList", CourseForm.convertFrom(courseService.findAll()));
model.addAttribute("courseInfoList", CourseInfoForm.convertFrom(courseInfoService.findAll()));
return "select_course";
//} catch (Exception e) {
// // ログイン情報の破棄
// httpSession.invalidate();
//
// e.printStackTrace();
//
// // エラーログ出力
// LOGGER.log(Level.SEVERE, SEVERE_ERROR_MESSAGE, e);
// // エラー画面遷移
// return null;
// }
} catch (Exception e) {
// ログイン情報の破棄
httpSession.invalidate();
e.printStackTrace();
// エラーログ出力
LOGGER.log(Level.SEVERE, SEVERE_ERROR_MESSAGE, e);
// エラー画面遷移
return null;
}
}
@PostMapping("/select/change")
public String showChangeCourse(Model model) {
try {
model.addAttribute("mode", "change");
model.addAttribute("courseList", CourseForm.convertFrom(courseService.findAll()));
model.addAttribute("courseInfoList", CourseInfoForm.convertFrom(courseInfoService.findAll()));
return "select_course";
} catch (Exception e) {
// ログイン情報の破棄
httpSession.invalidate();
e.printStackTrace();
// エラーログ出力
LOGGER.log(Level.SEVERE, SEVERE_ERROR_MESSAGE, e);
// エラー画面遷移
return null;
}
}
@PostMapping("/change")
public String changeCourse(@RequestParam Long courseId) {
LoginModel loginUser = (LoginModel) httpSession.getAttribute("loginUser");
userService.updateCourse(loginUser.getUserId(), courseId);
return "redirect:/menu";
}
}

View File

@@ -0,0 +1,81 @@
package com.example.demo.app.presentation.controller;
import jakarta.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.demo.app.domain.model.GoalModel;
import com.example.demo.app.domain.model.LoginModel;
import com.example.demo.app.domain.service.GoalService;
import com.example.demo.app.presentation.form.GoalForm;
import lombok.RequiredArgsConstructor;
@Controller
@RequiredArgsConstructor
@RequestMapping("/goal")
public class GoalController {
private final GoalService goalService;
@GetMapping("")
public String getGoal(Model model, HttpSession session) {
LoginModel loginUser = (LoginModel) session.getAttribute("loginUser");
Long userId = loginUser.getUserId();
//テスト用
// Long userId = 1L;
GoalModel goalModel = goalService.getGoalByUserId(userId);
GoalForm goalForm = GoalForm.convertFrom(goalModel);
model.addAttribute("goalForm", goalForm);
return "goal_view";
}
@GetMapping("/edit")
public String editGoal(Model model, HttpSession session) {
LoginModel loginUser = (LoginModel) session.getAttribute("loginUser");
Long userId = loginUser.getUserId();
//テスト用
// Long userId = 1L;
GoalModel goalModel = goalService.getGoalByUserId(userId);
GoalForm goalForm = GoalForm.convertFrom(goalModel);
model.addAttribute("goalForm", goalForm);
return "goal_edit";
}
@PostMapping("/update")
public String updateGoal(@ModelAttribute GoalForm goalForm, HttpSession session) {
LoginModel loginUser = (LoginModel) session.getAttribute("loginUser");
Long userId = loginUser.getUserId();
//テスト用
// Long userId = 1L;
// 本人の目標かどうかを確認してから更新する
GoalModel currentGoal = goalService.getGoalByUserId(userId);
if (!currentGoal.getGoalId().equals(goalForm.getGoalId())) {
return "redirect:/goal"; // 他人のデータを更新しようとしたら弾く
}
GoalModel goalModel = GoalModel.convertFrom(goalForm);
goalService.updateGoal(goalModel);
return "redirect:/goal";
}
}

View File

@@ -2,6 +2,7 @@ package com.example.demo.app.presentation.controller;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -65,9 +66,7 @@ public class TransactionController {
}).collect(Collectors.toList());
transactionFormMap.put(date, transactionFormList);
});
model.addAttribute("transactionFormMap", transactionFormMap);
return "transaction_list";
@@ -78,21 +77,45 @@ public class TransactionController {
public String findOne(@RequestParam(required = false) LocalDate todayDates, Model model, HttpSession session) {
LocalDate todayDate = (todayDates == null) ? LocalDate.now() : todayDates;
LoginModel loginUser = (LoginModel) session.getAttribute("loginUser");
List<TransactionForm> transactionFormList = transactionService
.findByUserIdAndDate(todayDate, loginUser.getUserId()).stream()
.map(transaction -> {
TransactionForm transactionForm = TransactionForm.convertFrom(
transaction,
CategoryForm.convertFrom(categoryService.findOne(transaction.getCategoryId()))
.getCategoryName(),
transactionService.findTotalExpense(todayDate, todayDate, loginUser.getUserId()),
transactionService.findTotalIncome(todayDate, todayDate, loginUser.getUserId()),
CategoryForm.convertFrom(categoryService.findOne(transaction.getCategoryId()))
.getTransactionType());
int type = CategoryForm.convertFrom(categoryService.findOne(transaction.getCategoryId()))
.getTransactionType();
TransactionForm transactionForm;
if (type == 1) {
transactionForm = TransactionForm.convertFrom(
transaction,
CategoryForm.convertFrom(categoryService.findOne(transaction.getCategoryId()))
.getCategoryName(),
0,
transactionService.findMoneyRecord(transaction.getTransactionId()),
type);
} else if (type == 0) {
transactionForm = TransactionForm.convertFrom(
transaction,
CategoryForm.convertFrom(categoryService.findOne(transaction.getCategoryId()))
.getCategoryName(),
transactionService.findMoneyRecord(transaction.getTransactionId()),
0,
type);
} else {
transactionForm = TransactionForm.convertFrom(
transaction,
CategoryForm.convertFrom(categoryService.findOne(transaction.getCategoryId()))
.getCategoryName(),
0,
0,
type);
}
return transactionForm;
}).collect(Collectors.toList());
@@ -103,102 +126,146 @@ public class TransactionController {
}
@GetMapping("/transaction/create")
public String createOneGet(@ModelAttribute TransactionForm transactionForm, @RequestParam LocalDate today, Model model) {
public String createOneGet(@RequestParam(defaultValue = "") LocalDate today,
Model model) {
if (today == null) {
today = LocalDate.now();
}
List<CategoryForm> categoryFormList = CategoryForm.convertFrom(categoryService.findAll());
TransactionForm transactionForm = new TransactionForm();
transactionForm.setTransactionDate(today);
System.out.println(transactionForm.getCategoryName() + " " + transactionForm.getAmount());
model.addAttribute("transactionForm", transactionForm);
model.addAttribute("categoryFormList", categoryFormList);
model.addAttribute("today", today);
model.addAttribute("today", today.format(DateTimeFormatter.ISO_LOCAL_DATE));
return "transaction_create";
}
@PostMapping("/transaction/create")
public String createOnePost(@ModelAttribute TransactionForm transactionForm, @RequestParam LocalDate today, Model model, HttpSession session) {
public String createOnePost(@ModelAttribute TransactionForm transactionForm, @RequestParam LocalDate today,
Model model,
HttpSession session) {
LoginModel loginUser = (LoginModel) session.getAttribute("loginUser");
transactionForm.setUserId(loginUser.getUserId());
transactionForm.setTransactionDate(today);
if (transactionService.createTransaction(TransactionForm.convertTo(transactionForm)) != 0) {
return "error";
}
return "redirect:/transaction/detail?todayDates=" + today;
return "redirect:/transaction/detail?todayDates=" + transactionForm.getTransactionDate();
}
@GetMapping("/transaction/update")
public String updateOneGet(@ModelAttribute TransactionForm transactionForm) {
public String updateOneGet(@RequestParam Long transactionId, @RequestParam(defaultValue = "") LocalDate today,
Model model) {
if (today == null) {
today = LocalDate.now();
}
List<CategoryForm> categoryFormList = CategoryForm.convertFrom(categoryService.findAll());
TransactionForm transactionForm = TransactionForm.convertFrom(
transactionService.findByTransactionId(transactionId),
CategoryForm.convertFrom(categoryService.findByTransactionId(transactionId)).getCategoryName(),
transactionService.findMoneyRecord(transactionId),
transactionService.findMoneyRecord(transactionId),
CategoryForm.convertFrom(categoryService.findByTransactionId(transactionId)).getTransactionType());
System.out.println("category: " + transactionForm.getCategoryId() + "金額: " + transactionForm.getAmount());
model.addAttribute("transactionId", transactionId);
model.addAttribute("transactionForm", transactionForm);
model.addAttribute("categoryFormList", categoryFormList);
model.addAttribute("today", today);
return "transaction_update";
return "";
}
@PostMapping("/transaction/update")
public String updateOnePost(@ModelAttribute TransactionForm transactionForm, Model model) {
public String updateOnePost(@RequestParam Long transactionId, @ModelAttribute TransactionForm transactionForm, @RequestParam LocalDate today, Model model,
HttpSession session) {
LoginModel loginUser = (LoginModel) session.getAttribute("loginUser");
transactionForm.setUserId(loginUser.getUserId());
transactionForm.setTransactionId(transactionId);
if (transactionService.updateTransaction(TransactionForm.convertTo(transactionForm)) != 0) {
return "error";
}
return "";
return "redirect:/transaction/detail?todayDates=" + transactionForm.getTransactionDate();
}
@PostMapping("/transaction/delete")
public String deleteOne(@RequestParam Long transactionId, @RequestParam LocalDate today) {
transactionService.deleteTransaction(transactionId);
return "redirect:/transaction/detail?todayDates=" + today;
}
@GetMapping("/menu")
public String menu(HttpSession session, Model model, @RequestParam(required = false, defaultValue = "0") String years, @RequestParam(required = false, defaultValue = "0") String months) {
public String menu(HttpSession session, Model model,
@RequestParam(required = false, defaultValue = "0") String years,
@RequestParam(required = false, defaultValue = "0") String months) {
LoginModel loginUser = (LoginModel) session.getAttribute("loginUser");
LocalDate today = LocalDate.now();
int year = (years.equals("0")) ? today.getYear() : Integer.parseInt(years);
int month = (months.equals("0")) ? today.getMonthValue() : Integer.parseInt(months);
System.out.println("year : " + year + "month : " + month);
YearMonth yearMonth = YearMonth.of(year, month);
int lastDay = yearMonth.lengthOfMonth();
int firstDayOfWeek =
yearMonth.atDay(1).getDayOfWeek().getValue() % 7;
YearMonth yearMonth = YearMonth.of(year, month);
model.addAttribute("year", year);
model.addAttribute("month", month);
model.addAttribute("day", today.getDayOfMonth());
int lastDay = yearMonth.lengthOfMonth();
model.addAttribute("lastDay", lastDay);
model.addAttribute("firstDayOfWeek", firstDayOfWeek);
int firstDayOfWeek = yearMonth.atDay(1).getDayOfWeek().getValue() % 7;
LocalDate startDate = LocalDate.now().withDayOfMonth(1);
model.addAttribute("year", year);
model.addAttribute("month", month);
model.addAttribute("day", today.getDayOfMonth());
model.addAttribute("lastDay", lastDay);
model.addAttribute("firstDayOfWeek", firstDayOfWeek);
LocalDate startDate = LocalDate.now().withDayOfMonth(1);
LocalDate endDate = LocalDate.now().withDayOfMonth(LocalDate.now().lengthOfMonth());
List<Income> incomeList = transactionService.findTotalIncomeList(startDate, endDate, loginUser.getUserId());
List<Expense> expenseList = transactionService.findTotalExpenseList(startDate, endDate, loginUser.getUserId());
model.addAttribute("incomeList", incomeList);
model.addAttribute("expenseList", expenseList);
int totalIncome = transactionService.findTotalIncome(startDate, endDate, loginUser.getUserId());
int totalExpense= transactionService.findTotalExpense(startDate, endDate, loginUser.getUserId());
int totalExpense = transactionService.findTotalExpense(startDate, endDate, loginUser.getUserId());
model.addAttribute("totalIncome", totalIncome);
model.addAttribute("totalExpense", totalExpense);
return "menu";
}
return "menu";
}
}

View File

@@ -0,0 +1,42 @@
package com.example.demo.app.presentation.form;
import java.time.LocalDate;
import com.example.demo.app.domain.model.GoalModel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GoalForm {
private Long goalId;
private String goalTitle;
private String goalSubtitle;
private Integer targetAmount;
private LocalDate deadline;
private Integer goalComplete;
public static GoalForm convertFrom(GoalModel goalModel) {
return new GoalForm(
goalModel.getGoalId(),
goalModel.getGoalTitle(),
goalModel.getGoalSubtitle(),
goalModel.getTargetAmount(),
goalModel.getDeadline(),
goalModel.getGoalComplete());
}
// public static List<GoalForm> convertFrom(List<GoalModel> goalModelList) {
// return goalModelList.stream().map(GoalForm::convertFrom).toList();
// }
}

View File

@@ -1,15 +1,80 @@
table, th, td {border: 1px solid black; border-collapse: collapse;}
body {
margin: 0;
padding: 0;
}
td:hover{background-color: lightblue;}
#calendar {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th{font-weight: bold; height: 50px;}
#calendar th,
#calendar td {
border: 1px solid black;
}
td{text-align: left; vertical-align: text-top; width: 200px; height: 100px; padding: 10px}
th {
font-weight: bold;
height: 35px;
font-size: 13px;
text-align: center;
}
.holiday{color: red;}
td {
width: 14.28%;
height: 70px;
padding: 5px;
text-align: left;
vertical-align: top;
}
#today{font-weight: bold; background-color: bisque;}
td:hover {
background-color: lightblue;
}
.year{font-size: 30px;}
.holiday {
color: red;
}
.month{font-size: 50px; font-weight: bold;}
#today {
font-weight: bold;
background-color: bisque;
}
.year {
font-size: 20px;
}
.month {
font-size: 30px;
font-weight: bold;
}
.calendar-title {
margin: 15px 10px;
}
.date {
font-size: 13px;
font-weight: bold;
}
.income {
color: blue;
font-size: 10px;
}
.expense {
color: red;
font-size: 10px;
}
.total {
margin: 15px 10px;
padding: 10px;
border-top: 1px solid #ddd;
font-size: 16px;
text-align: right;
}

View File

@@ -0,0 +1,15 @@
.transaction-item {
display: flex;
align-items: center;
justify-content: space-between;
}
.transaction-buttons {
display: flex;
gap: 10px;
margin-right: 20px;
}
.transaction-buttons form {
margin: 0;
}

View File

@@ -5,11 +5,12 @@
<title>分析画面</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<body class="pb-5 pt-5">
<div th:replace="~{header :: header}">
</div>
<div class="container mt-4">
<h2 class="text-center">支出分析</h2>
<table class="table text-center">
@@ -81,6 +82,8 @@
</tbody>
</table>
</div>
<div th:replace="~{footer :: footer}">
</div>

View File

@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>目標編集</title>
</head>
<body>
<h1>目標編集</h1>
<form th:action="@{/goal/update}" th:object="${goalForm}" method="post">
<input type="hidden" th:field="*{goalId}">
<div>
<label>目標名</label>
<input type="text" th:field="*{goalTitle}">
</div>
<div>
<label>目標説明</label>
<textarea th:field="*{goalSubtitle}"></textarea>
</div>
<div>
<label>目標金額</label>
<input type="number" th:field="*{targetAmount}">
</div>
<div>
<label>目標達成期限</label>
<input type="date" th:field="*{deadline}">
</div>
<button type="submit">更新する</button>
</form>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>目標詳細</title>
</head>
<body>
<h1>目標詳細</h1>
<table>
<tr>
<th>目標名</th>
<td th:text="${goalForm.goalTitle}"></td>
</tr>
<tr>
<th>目標説明</th>
<td th:text="${goalForm.goalSubtitle}"></td>
</tr>
<tr>
<th>目標金額</th>
<td th:text="${goalForm.targetAmount}"></td>
</tr>
<tr>
<th>目標達成期限</th>
<td th:text="${goalForm.deadline}"></td>
</tr>
</table>
<a th:href="@{/goal/edit}">編集する</a>
</body>
</html>

View File

@@ -7,7 +7,7 @@
</head>
<body>
<header th:fragment="header">
<header th:fragment="header" class="fixed-top">
<nav class="navbar" style="background-color: #e3f2fd;" data-bs-theme="light">
<div class="container-fluid">

View File

@@ -2,71 +2,107 @@
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Calendar</title>
<link rel="stylesheet" th:href="@{/css/menu.css}">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Calendar</title>
<link rel="stylesheet" th:href="@{/css/menu.css}">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<span class="year" th:text="|${year}年|"></span>
<span class="month" th:text="|${month}月|"></span>
<div th:replace="~{header :: header}"></div>
<table id="calendar">
<thead>
<tr>
<th class="holiday">日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th>土</th>
</tr>
</thead>
<div class="calendar-title">
<tbody>
<span class="year" th:text="|${year}年|">
</span>
<tr th:each="week : ${#numbers.sequence(0, 5)}">
<span class="month" th:text="|${month}月|">
</span>
<td th:each="weekDay : ${#numbers.sequence(0, 6)}">
</div>
<div th:if="${week * 7 + weekDay - firstDayOfWeek + 1 >= 1 and week * 7 + weekDay - firstDayOfWeek + 1 <= lastDay}">
<div class="date" th:text="${week * 7 + weekDay - firstDayOfWeek + 1}">
</div>
<table id="calendar">
<div th:each="income : ${incomeList}"
th:if="${income.date.dayOfMonth == week * 7 + weekDay - firstDayOfWeek + 1}"
class="income"
th:text="|収入 +${income.amount}円|"
style="color: blue;">
</div>
<thead>
<div th:each="expense : ${expenseList}"
th:if="${expense.date.dayOfMonth == week * 7 + weekDay - firstDayOfWeek + 1}"
class="expense"
th:text="|支出 -${expense.amount}円|"
style="color: red;">
</div>
<tr>
<th class="holiday">日</th>
<th>月</th>
<th>火</th>
<th>水</th>
<th>木</th>
<th>金</th>
<th>土</th>
</tr>
</div>
</thead>
</td>
</tr>
<tbody>
</tbody>
</table>
<tr th:each="week : ${#numbers.sequence(0, 5)}">
<div>
<h2>
<span th:text="|収入:${totalIncome}|"></span>
<span th:text="|支出:${totalExpense}|"></span>
</h2>
</div>
<td th:each="weekDay : ${#numbers.sequence(0, 6)}">
<a th:if="${week * 7 + weekDay - firstDayOfWeek + 1 >= 1
and week * 7 + weekDay - firstDayOfWeek + 1 <= lastDay}"
th:href="@{/transaction/detail(
todayDates=${T(java.time.LocalDate).of(year, month, week * 7 + weekDay - firstDayOfWeek + 1)}
)}">
<div th:if="${week * 7 + weekDay - firstDayOfWeek + 1 >= 1 and week * 7 + weekDay - firstDayOfWeek + 1 <= lastDay}">
<div class="date" th:text="${week * 7 + weekDay - firstDayOfWeek + 1}">
</div>
<div th:each="income : ${incomeList}" th:if="${income.date.dayOfMonth == week * 7 + weekDay - firstDayOfWeek + 1}" class="income" th:text="|収入 +${income.amount}円|">
</div>
<div th:each="expense : ${expenseList}" th:if="${expense.date.dayOfMonth == week * 7 + weekDay - firstDayOfWeek + 1}" class="expense" th:text="|支出 -${expense.amount}円|">
</div>
</div>
</a>
</td>
</tr>
</tbody>
</table>
<div class="total">
<div>
<span>収入:</span>
<span th:text="${totalIncome}"></span>
<span>円</span>
</div>
<div>
<span>支出:</span>
<span th:text="${totalExpense}"></span>
<span>円</span>
</div>
</div>
<div th:replace="~{footer :: footer}"></div>
</body>
</html>
</html>

View File

@@ -2,25 +2,41 @@
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
<title>コース選択</title>
</head>
<body>
<h1>コース選択</h1>
<form th:action="@{/user/register}" th:object="${userForm}" method="post">
<input type="hidden" th:field="*{userName}">
<input type="hidden" th:field="*{mailAddress}">
<input type="hidden" th:field="*{birthDate}">
<input type="hidden" th:field="*{password}">
<input type="hidden" th:field="*{secretQuestionId}">
<input type="hidden" th:field="*{secretAnswer}">
<input type="hidden" th:field="*{saving}">
<input type="hidden" th:field="*{annualIncome}">
<input type="hidden" th:field="*{monthlyBudget}">
<input type="hidden" th:field="*{targetAmount}">
<button type="submit">確定</button>
<div class="accordion" id="accordionExample">
<div class="accordion-item" th:each="course:${courseList}">
<h2 class="accordion-header">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
<span th:text="${course.courseName}"></span>
<h2 class="accordion-header d-flex align-items-center">
<input type="radio" name="courseId" th:value="${course.courseId}" class="form-check-input ms-3 me-2">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" th:data-bs-target="'#collapse' + ${course.courseId}" aria-expanded="false" aria-controls="'collapse' + ${course.courseId}">
<span th:text="${course.courseName}"></span>
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse show" data-bs-parent="#accordionExample">
<div th:id="'collapse' + ${course.courseId}" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
<div class="accordion-body">
<span th:text="${course.description}"></span>
<table border="1">
<tr>
<th>カテゴリ名</th><tr>配分(%)</tr>
<th>カテゴリ名</th><th>配分(%)</th>
</tr>
<tr th:each="courseInfo:${courseInfoList}" th:if="course.courseId == courseInfo.courseId">
<tr th:each="courseInfo:${courseInfoList}" th:if="${course.courseId == courseInfo.courseId}">
<td th:text="${courseInfo.categoryName}"></td>
<td th:text="${courseInfo.allocationRatio}"></td>
</tr>
@@ -29,7 +45,8 @@
</div>
</div>
</div>
</form>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@@ -4,16 +4,22 @@
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" th:href="@{/css/menu.css}">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div th:replace="~{header :: header}"></div>
<h1>取引登録</h1>
<form th:action="@{/transaction/create}" th:object="${transactionForm}" method="post">
<div>
<label for="transactionDate">日付</label>
<input type="date" id="transactionDate" th:field="*{transactionDate}">
<input type="date" id="transactionDate" name="transactionDate" th:value="*{transactionDate}">
</div>
<br>
@@ -61,6 +67,7 @@
</form>
<div th:replace="~{footer :: footer}"></div>
</body>

View File

@@ -4,35 +4,60 @@
<head>
<meta charset="UTF-8">
<title>収支詳細</title>
<link rel="stylesheet" th:href="@{/css/transaction_detail.css}">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div th:replace="~{header :: header}"></div>
<h1 th:text="${today}"></h1>
<div>
<ul>
<li th:each="transactionForm : ${transactionFormList}">
<p>カテゴリ名:<span th:text="${transactionForm.categoryName}"></span>
<br>金額:<span th:text="${transactionForm.amount}"></span>
</p>
<form th:action="@{/transaction/delete}" method="post">
<input type="hidden" name="today" id="today" th:value="${today}">
<input type="hidden" name="transactionId" id="transactionId" value="${transactionForm.transactionId}">
<li th:each="transactionForm : ${transactionFormList}" class="transaction-item">
<button type="submit">削除</button>
</form>
<hr />
<div>
<p>
カテゴリ名:
<span th:text="${transactionForm.categoryName}"></span>
<br>
金額:
<span th:text="${transactionForm.amount}"></span>
</p>
</div>
<div class="transaction-buttons">
<form th:action="@{/transaction/delete}" method="post">
<input type="hidden" name="today" th:value="${today}">
<input type="hidden" name="transactionId" th:value="${transactionForm.transactionId}">
<button type="submit">削除</button>
</form>
<form th:action="@{/transaction/update}" method="get">
<input type="hidden" name="today" th:value="${today}">
<input type="hidden" name="transactionId" th:value="${transactionForm.transactionId}">
<button type="submit">編集</button>
</form>
</div>
<hr>
<hr>
</li>
</ul>
</div>
<form th:action="@{/transaction/create}" method="get">
<input type="hidden" name="today" id="today" th:value="${today}">
<button type="submit">新規登録</button>
</form>
<div th:replace="~{footer :: footer}"></div>
</body>
</html>

View File

@@ -4,10 +4,15 @@
<head>
<meta charset="UTF-8">
<title>一覧</title>
<link rel="stylesheet" th:href="@{/css/menu.css}">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div th:replace="~{header :: header}"></div>
<div th:each="transactionForm : ${transactionFormMap}">
<a th:href="@{/transaction/detail(todayDates=${transactionForm.key})}">
@@ -23,6 +28,7 @@
</ul>
</div>
<div th:replace="~{footer :: footer}"></div>
</body>

View File

@@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" th:href="@{/css/menu.css}">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div th:replace="~{header :: header}"></div>
<h1>取引登録</h1>
<form th:action="@{/transaction/update}" th:object="${transactionForm}" method="post">
<input type="hidden" name="transactionId" th:value="${transactionId}">
<div>
<label for="transactionDate">日付</label>
<input type="date" id="transactionDate" name="transactionDate" th:value="*{transactionDate}">
</div>
<br>
<div>
<label for="transactionType">収入・支出</label>
<select id="transactionType" th:field="*{transactionType}">
<option value="">選択してください</option>
<option value="0">支出</option>
<option value="1">収入</option>
</select>
</div>
<br>
<div>
<label for="categoryId">カテゴリ</label>
<select id="categoryId" th:field="*{categoryId}">
<option value="">選択してください</option>
<option th:each="category : ${categoryFormList}" th:value="${category.categoryId}"
th:text="${category.categoryName}">
</option>
</select>
</div>
<br>
<div>
<label for="amount">金額</label>
<input type="number" id="amount" th:field="*{amount}" min="0" placeholder="金額を入力してください">
</div>
<br>
<input type="hidden" name="today" id="today" th:value="${today}">
<button type="submit">登録</button>
</form>
<div th:replace="~{footer :: footer}"></div>
</body>
</html>