From cbed4e911d7a8d300855f03428b29561fbba2e0b Mon Sep 17 00:00:00 2001 From: n-kawahito Date: Thu, 10 Sep 2026 15:21:43 +0900 Subject: [PATCH] =?UTF-8?q?[ADD]=E9=83=A8=E7=BD=B2=E5=90=8D=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E6=A9=9F=E8=83=BD=E3=81=AE=E5=AE=9F=E6=96=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/domain/service/UpdateDepartment.java | 8 + .../service/impl/UpdateDepartmentImpl.java | 56 +++++++ .../UpdateDepartmentController.java | 105 +++++++++++++ .../UpdateDepartmentResultController.java | 146 ++++++++++++++++++ .../form/UpdateDepartmentForm.java | 95 ++++++++++++ .../templates/updateDepartmentInput.html | 92 +++++++++++ src/main/webapp/updateDepartmentInput.html | 87 +++++++++++ 7 files changed, 589 insertions(+) create mode 100644 src/main/java/com/example/rhizome/app/domain/service/UpdateDepartment.java create mode 100644 src/main/java/com/example/rhizome/app/domain/service/impl/UpdateDepartmentImpl.java create mode 100644 src/main/java/com/example/rhizome/app/presentation/controller/UpdateDepartmentController.java create mode 100644 src/main/java/com/example/rhizome/app/presentation/controller/UpdateDepartmentResultController.java create mode 100644 src/main/java/com/example/rhizome/app/presentation/form/UpdateDepartmentForm.java create mode 100644 src/main/resources/templates/updateDepartmentInput.html create mode 100644 src/main/webapp/updateDepartmentInput.html diff --git a/src/main/java/com/example/rhizome/app/domain/service/UpdateDepartment.java b/src/main/java/com/example/rhizome/app/domain/service/UpdateDepartment.java new file mode 100644 index 0000000..c775568 --- /dev/null +++ b/src/main/java/com/example/rhizome/app/domain/service/UpdateDepartment.java @@ -0,0 +1,8 @@ +package com.example.rhizome.app.domain.service; + +import com.example.rhizome.app.domain.model.Department; + +public interface UpdateDepartment { + void updateDepartment(Department beforeDepartment, Department updateDepartment); + +} diff --git a/src/main/java/com/example/rhizome/app/domain/service/impl/UpdateDepartmentImpl.java b/src/main/java/com/example/rhizome/app/domain/service/impl/UpdateDepartmentImpl.java new file mode 100644 index 0000000..281e6d5 --- /dev/null +++ b/src/main/java/com/example/rhizome/app/domain/service/impl/UpdateDepartmentImpl.java @@ -0,0 +1,56 @@ +package com.example.rhizome.app.domain.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.example.rhizome.app.domain.model.Department; +import com.example.rhizome.app.domain.service.UpdateDepartment; +import com.example.rhizome.app.infra.entity.DepartmentEntity; +import com.example.rhizome.app.infra.repository.DepartmentRepository; + +/** + * employee の更新系の機能を集約させるサービスクラスです。 + */ +@Service +@Transactional +public class UpdateDepartmentImpl implements UpdateDepartment { + + DepartmentRepository departmentRepository; + + @Autowired + public UpdateDepartmentImpl(DepartmentRepository departmentRepository) { + this.departmentRepository = departmentRepository; + } + + /** + * Department の情報を元に Department table のレコードを更新する + * + * @param beforeDepartment 更新前のデータ + * @param updateDepartment 更新後のデータ + */ + public void updateDepartment(Department beforeDepartment, Department updateDepartment) { + + departmentRepository.save(DepartmentEntity.convertFrom(mergeDepartment(beforeDepartment, updateDepartment))); + + } + + /** + * 更新前のデータと更新対象のデータをマージする + * + * @param beforeDepartment 更新前のデータ + * @param updateDepartment 更新対象のデータ + * @return マージしたデータ + */ + private Department mergeDepartment(Department beforeDepartment, Department updateDepartment) { + // 更新対象のデータのパスワードが空文字の場合は、更新前のパスワードを使用する + // 更新対象のデータの管理者権限が null の場合は、更新前の管理者権限を使用する + // 更新対象のデータの部署IDが null の場合は、更新前の部署IDを使用する + return new Department( + updateDepartment.getIdDepartment(), + updateDepartment.getNmDepartment() + ); + + } + +} diff --git a/src/main/java/com/example/rhizome/app/presentation/controller/UpdateDepartmentController.java b/src/main/java/com/example/rhizome/app/presentation/controller/UpdateDepartmentController.java new file mode 100644 index 0000000..87beaf8 --- /dev/null +++ b/src/main/java/com/example/rhizome/app/presentation/controller/UpdateDepartmentController.java @@ -0,0 +1,105 @@ +package com.example.rhizome.app.presentation.controller; + +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import com.example.rhizome.aop.aspect.PermissionCheck; +import com.example.rhizome.aop.aspect.SessionCheck; +import com.example.rhizome.app.domain.model.Department; +import com.example.rhizome.app.domain.model.SearchConditionDepartment; +import com.example.rhizome.app.domain.service.SearchDepartment; +import com.example.rhizome.app.presentation.controller.pageproperty.PageReturnAttributeKeyword; +import com.example.rhizome.app.presentation.controller.pageproperty.TransitionTargetPageNameKeyword; +import com.example.rhizome.app.presentation.form.DepartmentForm; +import com.example.rhizome.app.presentation.form.MessageForm; +import com.example.rhizome.app.presentation.form.SearchConditionDepartmentForm; +import com.example.rhizome.app.presentation.form.UpdateDepartmentForm; + +/** + * 更新対象の department が存在するか確認する為のコントローラ + */ +@Controller +public class UpdateDepartmentController { + + // ログ出力用インスタンス + private final static Logger LOGGER = Logger.getLogger(UpdateDepartmentController.class.getName()); + // エラーメッセージ用の定数フィールド + private final static String SEVERE_ERROR_MESSAGE = "エラーが発生しました!"; + + HttpSession httpSession; + SearchDepartment searchDepartment; + + + @Autowired + public UpdateDepartmentController(HttpSession httpSession, SearchDepartment searchDepartment) { + this.httpSession = httpSession; + this.searchDepartment = searchDepartment; + } + + @ModelAttribute + public SearchConditionDepartmentForm searchConditionDepartmentForm() { + return new SearchConditionDepartmentForm(); + } + + /** + * 更新対象の department が存在するか確認する為のコントローラ + * + * @param idDepartment 更新対象の department の id + * @param model ビューにデータを渡すためのコンテナ + * @return 遷移先の画面 + */ + @PermissionCheck + @SessionCheck + @RequestMapping(value = TransitionTargetPageNameKeyword.SHOW_UPDATE_DEPARTMENT, method = RequestMethod.POST) + public String showUpdateDepartment(@RequestParam("idDepartment") Integer idDepartment, Model model) { + final String UPDATE_TARGET_ID_NOT_FOUND = "更新対象のデータが見つかりません。"; + + try { + // 部署一覧を取得し画面に返す値としてセット + model.addAttribute(PageReturnAttributeKeyword.DEPARTMENT_FORM_LIST, DepartmentForm.convertFrom(searchDepartment.selectAll())); + + // id を条件に更新対象のレコードを検索、取得する + List departmentList = searchDepartment.searchBy( + new SearchConditionDepartment(idDepartment, + null + )); + + // DBに更新対象のデータがあるか + if (departmentList.isEmpty()) { + // ない場合はエラーメッセージをセットして検索画面に戻る + model.addAttribute(PageReturnAttributeKeyword.MESSAGE_ERROR, new MessageForm(UPDATE_TARGET_ID_NOT_FOUND)); + return "forward:" + TransitionTargetPageNameKeyword.SELECT_DEPARTMENT_INFO; + } + + // 更新画面に遷移 + model.addAttribute(PageReturnAttributeKeyword.UPDATE_DEPARTMENT_INFO_FORM, UpdateDepartmentForm.convertFrom(departmentList.get(0))); + + // Update画面に遷移 + return TransitionTargetPageNameKeyword.UPDATE_DEPARTMENT_INPUT_HTML; + + + } catch (Exception e) { + // ログイン情報の破棄 + httpSession.invalidate(); + + e.printStackTrace(); + + // エラーログ出力 + LOGGER.log(Level.SEVERE, SEVERE_ERROR_MESSAGE, e); + // エラー画面遷移 + return TransitionTargetPageNameKeyword.ERROR_HTML; + + } + } +} diff --git a/src/main/java/com/example/rhizome/app/presentation/controller/UpdateDepartmentResultController.java b/src/main/java/com/example/rhizome/app/presentation/controller/UpdateDepartmentResultController.java new file mode 100644 index 0000000..cd82c0c --- /dev/null +++ b/src/main/java/com/example/rhizome/app/presentation/controller/UpdateDepartmentResultController.java @@ -0,0 +1,146 @@ +package com.example.rhizome.app.presentation.controller; + +import java.util.List; +import java.util.Objects; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.http.HttpSession; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import com.example.rhizome.aop.aspect.PermissionCheck; +import com.example.rhizome.aop.aspect.SessionCheck; +import com.example.rhizome.app.domain.model.Department; +import com.example.rhizome.app.domain.service.SearchDepartment; +import com.example.rhizome.app.domain.service.SearchEmployee; +import com.example.rhizome.app.domain.service.UpdateDepartment; +import com.example.rhizome.app.presentation.controller.pageproperty.PageReturnAttributeKeyword; +import com.example.rhizome.app.presentation.controller.pageproperty.SessionKeyword; +import com.example.rhizome.app.presentation.controller.pageproperty.TransitionTargetPageNameKeyword; +import com.example.rhizome.app.presentation.form.DepartmentForm; +import com.example.rhizome.app.presentation.form.LoginUserForm; +import com.example.rhizome.app.presentation.form.MessageForm; +import com.example.rhizome.app.presentation.form.UpdateDepartmentForm; + +@Controller +public class UpdateDepartmentResultController { + + // ログ出力用インスタンス + private final static Logger LOGGER = Logger.getLogger(UpdateEmployeeController.class.getName()); + // エラーメッセージ用の定数フィールド + private final static String SEVERE_ERROR_MESSAGE = "エラーが発生しました!"; + + HttpSession httpSession; + SearchDepartment searchDepartment; + SearchEmployee searchEmployee; + UpdateDepartment updateDepartment; + + @Autowired + public UpdateDepartmentResultController(HttpSession httpSession, SearchDepartment searchDepartment, + SearchEmployee searchEmployee, UpdateDepartment updateDepartment) { + this.httpSession = httpSession; + this.searchDepartment = searchDepartment; + this.searchEmployee = searchEmployee; + this.updateDepartment = updateDepartment; + } + + /** + * 部署名の重複チェック + * + * @param departmentList 元の departmentList + * @param updateDepartmentForm 更新対象のデータ + * @return true:重複無し false:重複あり + */ + private static boolean checkDuplicateNmDepartment(List departmentList, UpdateDepartmentForm updateDepartmentForm) { + // メールアドレスが既に使われていた場合 + if (!departmentList.isEmpty()) { + // 重複が有った場合に、同一人物のものであれば上書きOKとする + return Objects.equals(departmentList.get(0).getIdDepartment(), updateDepartmentForm.getIdDepartment()); + } + return true; + } + + /** + * 更新結果画面表示処理 + * + * @param updateEmployeeInfoForm 更新画面のフォーム + * @param model ビューにデータを渡すためのコンテナ + * @return 遷移先の画面 + */ + @PermissionCheck + @SessionCheck + @RequestMapping(value = TransitionTargetPageNameKeyword.UPDATE_DEPARTMENT_RESULT, method = RequestMethod.POST) + public String employeeUpdateResult(@ModelAttribute UpdateDepartmentForm updateDepartmentForm, Model model) { + + final String NOTHING = "項目が空欄です。"; + final String NO_TARGET = "更新対象のデータが見つかりません。"; + final String DUPLICATION = "既に同名の部署が存在するか、値が変更されていません。"; + final String UPDATE_COMPLETE = "更新が完了しました。"; + + try { + + // 部署一覧取得 + model.addAttribute(PageReturnAttributeKeyword.DEPARTMENT_FORM_LIST, + DepartmentForm.convertFrom(searchDepartment.selectAll())); + + // 部署名を元に検索 + List departmentList = searchDepartment.searchByNmDepartment(updateDepartmentForm.getNmDepartment()); + + // 既に登録済みの部署名が存在するか + if (!checkDuplicateNmDepartment(departmentList, updateDepartmentForm)) { + // 存在する場合はエラーメッセージを設定して更新入力画面に遷移 + model.addAttribute(PageReturnAttributeKeyword.MESSAGE_ERROR, new MessageForm(DUPLICATION)); + model.addAttribute(PageReturnAttributeKeyword.UPDATE_DEPARTMENT_INFO_FORM, updateDepartmentForm); + + return TransitionTargetPageNameKeyword.UPDATE_DEPARTMENT_INPUT_HTML; + } + + // session 情報からログイン者の情報を取得 + LoginUserForm loginUserForm = (LoginUserForm) httpSession.getAttribute(SessionKeyword.LOGIN_USER); + + // 画面から渡ってきた値が必須を満たしているか + if (!UpdateDepartmentForm.hasErrorParameter(updateDepartmentForm)) { + model.addAttribute(PageReturnAttributeKeyword.MESSAGE_ERROR, new MessageForm(NOTHING)); + model.addAttribute(PageReturnAttributeKeyword.UPDATE_DEPARTMENT_INFO_FORM, updateDepartmentForm); + + return TransitionTargetPageNameKeyword.UPDATE_DEPARTMENT_INPUT_HTML; + } + + // 更新前のデータを取得 + Department beforeDepartment = searchDepartment.searchByIdDepartment(updateDepartmentForm.getIdDepartment()); + if (beforeDepartment.getIdDepartment() == null) { + model.addAttribute(PageReturnAttributeKeyword.MESSAGE_ERROR, new MessageForm(NO_TARGET)); + model.addAttribute(PageReturnAttributeKeyword.UPDATE_EMPLOYEE_INFO_FORM, updateDepartmentForm); + + return TransitionTargetPageNameKeyword.UPDATE_DEPARTMENT_INPUT_HTML; + } + + // 画面用の型からビジネスロジック用のモデルに変換し、Updateを実行 + updateDepartment.updateDepartment(beforeDepartment, UpdateDepartmentForm.convertTo(updateDepartmentForm)); + + // 更新結果のメッセージを画面にセットし一覧画面に遷移 + model.addAttribute(PageReturnAttributeKeyword.MESSAGE_INFO, new MessageForm(UPDATE_COMPLETE)); + + // forward 先で不用意な動作をしないために UpdateDepartmentInfoForm をクリア + return "forward:" + TransitionTargetPageNameKeyword.SELECT_DEPARTMENT_INFO_FORM_EMPTY; + + } catch (Exception e) { + // ログイン情報の破棄 + httpSession.invalidate(); + + e.printStackTrace(); + // エラーログ出力 + LOGGER.log(Level.SEVERE, SEVERE_ERROR_MESSAGE, e); + // エラー画面遷移 + return TransitionTargetPageNameKeyword.ERROR_HTML; + } + + } + +} diff --git a/src/main/java/com/example/rhizome/app/presentation/form/UpdateDepartmentForm.java b/src/main/java/com/example/rhizome/app/presentation/form/UpdateDepartmentForm.java new file mode 100644 index 0000000..bef03a6 --- /dev/null +++ b/src/main/java/com/example/rhizome/app/presentation/form/UpdateDepartmentForm.java @@ -0,0 +1,95 @@ +package com.example.rhizome.app.presentation.form; + +import java.util.List; + +import com.example.rhizome.app.domain.model.Department; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 画面から渡ってきた更新内容をまとめ、再度画面に表示する為のクラス + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class UpdateDepartmentForm { + + /** + * 社員ID + */ + private Integer idDepartment; + /** + * 社員名 + */ + private String nmDepartment; + + /** + * business 層の EmployeeInfo クラスから画面用(presentation 層)の UpdateEmployeeInfoForm に + * 変換します。 + * + * @param department business 層の EmployeeInfo インスタンス + * @return 画面用(presentation 層)の UpdateEmployeeInfoForm インスタンス + */ + public static UpdateDepartmentForm convertFrom(Department department) { + return new UpdateDepartmentForm( + department.getIdDepartment(), + department.getNmDepartment() + ); + } + + /** + * business 層の EmployeeInfo クラスから画面用(presentation 層)の UpdateEmployeeInfoForm に + * 変換します。(リスト版) + * + * @param employeeInfoList business 層の EmployeeInfo インスタンスのリスト + * @return 画面用(presentation 層)の UpdateEmployeeInfoForm インスタンスのリスト + */ + public static List convertFrom(List departmentList) { + return departmentList.stream().map(UpdateDepartmentForm::convertFrom).toList(); + } + + /** + * 画面用(presentation 層)の UpdateEmployeeInfoForm クラスから business 層の Employee クラスに + * 変換します。 + * + * @param updateEmployeeInfoForm 画面用(presentation 層)の UpdateEmployeeInfoForm インスタンス + * @return business 層の Employee インスタンス + */ + public static Department convertTo(UpdateDepartmentForm updateDepartmentInfoForm) { + return new Department( + updateDepartmentInfoForm.getIdDepartment(), + updateDepartmentInfoForm.getNmDepartment() + ); + } + + /** + * 画面から渡ってきたパラメータのチェック + * + * @param updateEmployeeInfoForm 画面から渡ってきたパラメータ + * @return true: エラー無し false:エラーあり(必須を満たしていない) + */ + public static boolean hasErrorParameter(UpdateDepartmentForm updateDepartmentInfoForm) { + + boolean errorFlag = !isNullOrBlank(updateDepartmentInfoForm.getNmDepartment()); + + return errorFlag; + } + + + + /** + * 仮引数を null or 空 判定する + * + * @param str 判定対象の文字列 + * @return true:null or 空 false:null or 空 では無い + */ + private static boolean isNullOrBlank(String str) { + if (null == str) { + return true; + } + return str.isBlank(); + } + +} diff --git a/src/main/resources/templates/updateDepartmentInput.html b/src/main/resources/templates/updateDepartmentInput.html new file mode 100644 index 0000000..88ce0ac --- /dev/null +++ b/src/main/resources/templates/updateDepartmentInput.html @@ -0,0 +1,92 @@ + + + + + + + + + + 部署情報更新 + + + +

+ 部署情報更新    +
+ ログイン者名: + +
+

+ +
+ +
+ +
+ + + + + + + + + + + + + + + +
部署ID + +
部署名 + +
+ +
+
+ + 一覧に戻る + + + + diff --git a/src/main/webapp/updateDepartmentInput.html b/src/main/webapp/updateDepartmentInput.html new file mode 100644 index 0000000..5ebb8b8 --- /dev/null +++ b/src/main/webapp/updateDepartmentInput.html @@ -0,0 +1,87 @@ + + + + + + + + + + 部署情報更新 + + + +

+ 部署情報更新    +
+ ログイン者名: + +
+

+ +
+ +
+ +
+ + + + + + + + + + + +
部署ID + +
部署名 + +
+
+ + 一覧に戻る + + + + + \ No newline at end of file