diff --git a/book-rent/src/main/java/com/example/demo/controller/AdminLoanController.java b/book-rent/src/main/java/com/example/demo/controller/AdminLoanController.java index 0c53e5d..1ff68d7 100644 --- a/book-rent/src/main/java/com/example/demo/controller/AdminLoanController.java +++ b/book-rent/src/main/java/com/example/demo/controller/AdminLoanController.java @@ -1,5 +1,4 @@ package com.example.demo.controller; - import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -37,7 +36,7 @@ public class AdminLoanController { public String approvalConfirm(@PathVariable Integer id, Model model, RedirectAttributes ra) { try { model.addAttribute("r", loanService.getView(id, Const.STATUS_WAITING)); - return "approvalConfirm"; + return "approvalConfilm"; } catch (BusinessException e) { ra.addFlashAttribute("errorMessage", e.getMessage()); return "redirect:/admin/applications"; @@ -50,7 +49,7 @@ public class AdminLoanController { try { loanService.approve(id, admin); ra.addFlashAttribute("message", "書籍貸出申請を承認しました。"); - return "redirect:/admin/approval/complete"; + return "approvalComplete"; } catch (BusinessException e) { ra.addFlashAttribute("errorMessage", e.getMessage()); return "redirect:/admin/applications"; @@ -63,7 +62,7 @@ public class AdminLoanController { try { loanService.reject(id, admin); ra.addFlashAttribute("message", "書籍貸出申請を却下しました。"); - return "redirect:/admin/approval/complete"; + return "approvalRejected"; } catch (BusinessException e) { ra.addFlashAttribute("errorMessage", e.getMessage()); return "redirect:/admin/applications"; @@ -116,3 +115,4 @@ public class AdminLoanController { return "complete"; } } + diff --git a/book-rent/src/main/java/com/example/demo/controller/EmployeeController.java b/book-rent/src/main/java/com/example/demo/controller/EmployeeController.java index 71bd363..b358d4e 100644 --- a/book-rent/src/main/java/com/example/demo/controller/EmployeeController.java +++ b/book-rent/src/main/java/com/example/demo/controller/EmployeeController.java @@ -1,5 +1,178 @@ package com.example.demo.controller; -public class EmployeeController { +import java.util.List; +import java.util.Optional; +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.RequestParam; +import org.springframework.web.bind.annotation.SessionAttribute; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import com.example.demo.common.BusinessException; +import com.example.demo.common.Const; +import com.example.demo.common.LoginUser; +import com.example.demo.entity.Employee; +import com.example.demo.form.EmployeeForm; +import com.example.demo.service.EmployeeService; + +/** + * EMP-01 社員登録(管理者のみ:/admin/** で拒否) + * EMP-02 社員編集(管理者:メールアドレスで検索して全項目 / 一般:自分のパスワードのみ) + */ +@Controller +public class EmployeeController { + private static final String NEW = "/admin/employees/new"; + private static final String EDIT = "/employees/edit"; + + private final EmployeeService employeeService; + + public EmployeeController(EmployeeService employeeService) { + this.employeeService = employeeService; + } + + // ===== EMP-01 社員登録 ===== + @GetMapping(NEW) + public String registInput(Model model) { + return registView(new EmployeeForm(), List.of(), model); + } + + @PostMapping(NEW + "/input") + public String registBack(@ModelAttribute("form") EmployeeForm form, Model model) { + return registView(form, List.of(), model); + } + + @PostMapping(NEW + "/confirm") + public String registConfirm(@ModelAttribute("form") EmployeeForm form, Model model) { + List errors = employeeService.validateRegist(form); + if (!errors.isEmpty()) + return registView(form, errors, model); + return "employeeRegistConfirm"; + } + + @PostMapping(NEW + "/execute") + public String registExecute(@ModelAttribute("form") EmployeeForm form, + @SessionAttribute(Const.SESSION_LOGIN_USER) LoginUser admin, + Model model, RedirectAttributes ra) { + try { + employeeService.register(form, admin); + } catch (BusinessException e) { + return registView(form, List.of(e.getMessage()), model); + } + ra.addFlashAttribute("message", "社員登録が完了しました。"); + return "redirect:" + NEW + "/complete"; + } + + @GetMapping(NEW + "/complete") + public String registComplete(Model model) { + return complete(model); + } + + private String registView(EmployeeForm form, List errors, Model model) { + model.addAttribute("form", form); + model.addAttribute("errors", errors); + return "employeeRegistInput"; + } + + // ===== EMP-02 社員編集 ===== + + /** メニュー「社員編集」:管理者は検索画面へ、一般ユーザーは検索せず自分の編集画面へ */ + @GetMapping("/employees/search") + public String search(@SessionAttribute(Const.SESSION_LOGIN_USER) LoginUser user) { + return user.isAdmin() ? "employeeSearch" : "redirect:" + EDIT; + } + + @PostMapping("/employees/search") + public String doSearch(@RequestParam(defaultValue = "") String mailAddress, + @SessionAttribute(Const.SESSION_LOGIN_USER) LoginUser user, Model model) { + if (!user.isAdmin()) + return "redirect:/menu"; + Optional e = employeeService.findByMail(mailAddress); + if (e.isEmpty()) { + model.addAttribute("mailAddress", mailAddress); + model.addAttribute("errorMessage", "該当する社員が見つかりません。"); + return "employeeSearch"; + } + return "redirect:" + EDIT + "?idEmployee=" + e.get().getIdEmployee(); + } + + @GetMapping(EDIT) + public String editInput(@RequestParam(required = false) Integer idEmployee, + @SessionAttribute(Const.SESSION_LOGIN_USER) LoginUser user, + Model model, RedirectAttributes ra) { + // 一般ユーザーは常に自分自身(リクエストの社員IDは使わない) + Integer target = user.isAdmin() ? idEmployee : user.getIdEmployee(); + if (target == null) + return "redirect:/employees/search"; + try { + return editView(employeeService.toForm(employeeService.find(target)), List.of(), user, model); + } catch (BusinessException e) { + ra.addFlashAttribute("errorMessage", e.getMessage()); + return "redirect:/menu"; + } + } + + @PostMapping(EDIT + "/input") + public String editBack(@ModelAttribute("form") EmployeeForm form, + @SessionAttribute(Const.SESSION_LOGIN_USER) LoginUser user, Model model) { + fixTarget(form, user); + return editView(form, List.of(), user, model); + } + + @PostMapping(EDIT + "/confirm") + public String editConfirm(@ModelAttribute("form") EmployeeForm form, + @SessionAttribute(Const.SESSION_LOGIN_USER) LoginUser user, Model model) { + fixTarget(form, user); + List errors = user.isAdmin() + ? employeeService.validateUpdateByAdmin(form) + : employeeService.validateUpdateBySelf(form); + if (!errors.isEmpty()) + return editView(form, errors, user, model); + model.addAttribute("admin", user.isAdmin()); + return "employeeUpdateConfirm"; + } + + @PostMapping(EDIT + "/execute") + public String editExecute(@ModelAttribute("form") EmployeeForm form, + @SessionAttribute(Const.SESSION_LOGIN_USER) LoginUser user, + Model model, RedirectAttributes ra) { + fixTarget(form, user); + try { + if (user.isAdmin()) + employeeService.updateByAdmin(form, user); + else + employeeService.updateBySelf(form, user); + } catch (BusinessException e) { + return editView(form, List.of(e.getMessage()), user, model); + } + ra.addFlashAttribute("message", "社員編集が完了しました。"); + return "redirect:" + EDIT + "/complete"; + } + + @GetMapping(EDIT + "/complete") + public String editComplete(Model model) { + return complete(model); + } + + /** 一般ユーザーの対象は常にセッションの社員ID(URL/フォーム値の書き換えを無視) */ + private static void fixTarget(EmployeeForm form, LoginUser user) { + if (!user.isAdmin()) + form.setIdEmployee(user.getIdEmployee()); + } + + private String editView(EmployeeForm form, List errors, LoginUser user, Model model) { + model.addAttribute("form", form); + model.addAttribute("errors", errors); + model.addAttribute("admin", user.isAdmin()); + return "employeeUpdateInput"; + } + + private String complete(Model model) { + model.addAttribute("backUrl", "/menu"); + model.addAttribute("backLabel", "メニューに戻る"); + return "complete"; + } } diff --git a/book-rent/src/main/java/com/example/demo/service/BookAdminService.java b/book-rent/src/main/java/com/example/demo/service/BookAdminService.java index 2988e02..17f56d1 100644 --- a/book-rent/src/main/java/com/example/demo/service/BookAdminService.java +++ b/book-rent/src/main/java/com/example/demo/service/BookAdminService.java @@ -1,8 +1,5 @@ package com.example.demo.service; - - - import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -18,6 +15,7 @@ import com.example.demo.form.BookForm; import com.example.demo.repository.BookCollectionRepository; /** BOOK-02:書籍登録、BOOK-03:書籍編集 */ + @Service public class BookAdminService { private final BookCollectionRepository bookRepository; @@ -83,6 +81,7 @@ public class BookAdminService { if (!errors.isEmpty()) throw new BusinessException(String.join(" ", errors)); } + private static void apply(BookCollection b, BookForm f) { b.setIsbn(f.getIsbn()); b.setNmBook(f.getNmBook()); @@ -90,4 +89,5 @@ public class BookAdminService { b.setPublisher(f.getPublisher().isEmpty() ? null : f.getPublisher()); b.setNote(f.getNote().isEmpty() ? null : f.getNote()); } + } diff --git a/book-rent/src/main/resources/templates/approvalComplete.html b/book-rent/src/main/resources/templates/approvalComplete.html new file mode 100644 index 0000000..bedbc40 --- /dev/null +++ b/book-rent/src/main/resources/templates/approvalComplete.html @@ -0,0 +1,31 @@ + + + + + + 書籍貸出申請 + + + +

+     +
+ ログイン者名: + +
+

+

書籍貸出申請を承認しました。

+ + +
+ +
+ +
+
+ 承認待ち一覧に戻る + メニューに戻る + + + + \ No newline at end of file diff --git a/book-rent/src/main/resources/templates/approvalConfilm.html b/book-rent/src/main/resources/templates/approvalConfilm.html new file mode 100644 index 0000000..1202633 --- /dev/null +++ b/book-rent/src/main/resources/templates/approvalConfilm.html @@ -0,0 +1,84 @@ + + + + + + 書籍貸出承認確認 + + + + +

+ 書籍貸出承認確認    +
+ ログイン者名: + +
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
申請ID
申請者名
申請日
ISBN
書籍名
出版社
特記事項
貸出日
返却予定日
+ +
+ +
+ +
+ + +
+ +
+
+ +
+ 承認待ち一覧へ戻る + + + + + \ No newline at end of file diff --git a/book-rent/src/main/resources/templates/approvalRejected.html b/book-rent/src/main/resources/templates/approvalRejected.html new file mode 100644 index 0000000..0555880 --- /dev/null +++ b/book-rent/src/main/resources/templates/approvalRejected.html @@ -0,0 +1,31 @@ + + + + + + 書籍貸出申請 + + + +

+     +
+ ログイン者名: + +
+

+

書籍貸出申請を却下しました。

+ + +
+ +
+ +
+
+ 承認待ち一覧に戻る + メニューに戻る + + + + \ No newline at end of file diff --git a/book-rent/src/main/resources/templates/lendingList.html b/book-rent/src/main/resources/templates/lendingList.html new file mode 100644 index 0000000..d4e58c1 --- /dev/null +++ b/book-rent/src/main/resources/templates/lendingList.html @@ -0,0 +1,34 @@ + + + + + 貸出中書籍一覧 + + + +
+
+

貸出中書籍一覧

+
+
+
+

貸出中の書籍はありません。

+ + + + + + + + + + + + + +
申請ID申請者名書籍名申請日貸出日返却予定日操作
返却
+
+

メニューに戻る

+
+ +