12 Commits

16 changed files with 445 additions and 125 deletions

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

@@ -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

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

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,
@@ -93,6 +100,11 @@ public class TransactionServiceImpl implements TransactionService {
}
public int findMoneyRecord(Long transactionId) {
return transactionRepository.findMoneyRecord(transactionId);
}
public int createTransaction(TransactionModel transactionModel) {
Optional<UserEntity> userEntityOptional = userRepository.findById(transactionModel.getUserId());

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

@@ -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;
@@ -66,8 +67,6 @@ public class TransactionController {
transactionFormMap.put(date, transactionFormList);
});
model.addAttribute("transactionFormMap", transactionFormMap);
return "transaction_list";
@@ -79,20 +78,44 @@ public class TransactionController {
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(
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(),
transactionService.findTotalExpense(todayDate, todayDate, loginUser.getUserId()),
transactionService.findTotalIncome(todayDate, todayDate, loginUser.getUserId()),
0,
transactionService.findMoneyRecord(transaction.getTransactionId()),
type);
} else if (type == 0) {
transactionForm = TransactionForm.convertFrom(
transaction,
CategoryForm.convertFrom(categoryService.findOne(transaction.getCategoryId()))
.getTransactionType());
.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,43 +126,86 @@ 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) {
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.equals(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();
}
@@ -151,7 +217,9 @@ public class TransactionController {
}
@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");
@@ -166,8 +234,7 @@ public class TransactionController {
int lastDay = yearMonth.lengthOfMonth();
int firstDayOfWeek =
yearMonth.atDay(1).getDayOfWeek().getValue() % 7;
int firstDayOfWeek = yearMonth.atDay(1).getDayOfWeek().getValue() % 7;
model.addAttribute("year", year);
model.addAttribute("month", month);
@@ -180,7 +247,6 @@ public class TransactionController {
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());
@@ -188,17 +254,14 @@ public class TransactionController {
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";
}
}

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

@@ -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,19 +2,38 @@
<html xmlns:th="http://www.thymeleaf.org">
<head>
<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>
<div class="calendar-title">
<span class="year" th:text="|${year}年|">
</span>
<span class="month" th:text="|${month}月|">
</span>
</div>
<table id="calendar">
<thead>
<tr>
<th class="holiday">日</th>
<th>月</th>
@@ -24,49 +43,65 @@
<th>金</th>
<th>土</th>
</tr>
</thead>
<tbody>
<tr th:each="week : ${#numbers.sequence(0, 5)}">
<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}円|"
style="color: blue;">
<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}円|"
style="color: red;">
<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>
<h2>
<span th:text="|収入:${totalIncome}|"></span>
<span th:text="|支出:${totalExpense}|"></span>
</h2>
<span>収入:</span>
<span th:text="${totalIncome}"></span>
<span>円</span>
</div>
<div>
<span>支出:</span>
<span th:text="${totalExpense}"></span>
<span>円</span>
</div>
</div>
</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>

View File

@@ -4,32 +4,56 @@
<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">
<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>
<hr />
<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>

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})}">

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>
</body>
</html>