6 Commits

24 changed files with 514 additions and 385 deletions

View File

@@ -1,5 +1,7 @@
package com.example.rhizome.app.domain.model; package com.example.rhizome.app.domain.model;
import java.time.LocalDate;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@@ -37,5 +39,9 @@ public class Employee {
* 部署ID * 部署ID
*/ */
private final Integer idDepartment; private final Integer idDepartment;
/**
* 入社年月日
*/
private final LocalDate dateHired;
} }

View File

@@ -6,6 +6,8 @@
*/ */
package com.example.rhizome.app.domain.model; package com.example.rhizome.app.domain.model;
import java.time.Period;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@@ -25,4 +27,9 @@ public class EmployeeInfo {
*/ */
private final Department department; private final Department department;
/**
* 勤続年数
*/
private final Period lengthOfService;
} }

View File

@@ -1,5 +1,7 @@
package com.example.rhizome.app.domain.model; package com.example.rhizome.app.domain.model;
import java.time.LocalDate;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@@ -40,6 +42,11 @@ public class LoginUser {
*/ */
private final Integer idDepartment; private final Integer idDepartment;
/**
* 入社年月日
*/
private final LocalDate dateHired;
/** /**
* ログインユーザが管理者か * ログインユーザが管理者か
* *

View File

@@ -1,16 +1,20 @@
package com.example.rhizome.app.domain.service.impl; package com.example.rhizome.app.domain.service.impl;
import java.time.LocalDate;
import java.time.Period;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.rhizome.app.domain.model.EmployeeInfo; import com.example.rhizome.app.domain.model.EmployeeInfo;
import com.example.rhizome.app.domain.model.SearchConditionEmployee; import com.example.rhizome.app.domain.model.SearchConditionEmployee;
import com.example.rhizome.app.domain.service.SearchEmployeeInfo; import com.example.rhizome.app.domain.service.SearchEmployeeInfo;
import com.example.rhizome.app.infra.entity.EmployeeDepartmentEntity; import com.example.rhizome.app.infra.entity.EmployeeDepartmentEntity;
import com.example.rhizome.app.infra.repository.EmployeeInfoRepository; import com.example.rhizome.app.infra.repository.EmployeeInfoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/** /**
* SearchEmployeeInfoImpl (employee join department) 検索系の機能を集約させるサービスクラスです * SearchEmployeeInfoImpl (employee join department) 検索系の機能を集約させるサービスクラスです
@@ -26,7 +30,6 @@ public class SearchEmployeeInfoImpl implements SearchEmployeeInfo {
this.employeeInfoRepository = employeeInfoRepository; this.employeeInfoRepository = employeeInfoRepository;
} }
/** /**
* EmployeeInfo (employee join department) のレコードを全件取得 * EmployeeInfo (employee join department) のレコードを全件取得
* *
@@ -34,7 +37,14 @@ public class SearchEmployeeInfoImpl implements SearchEmployeeInfo {
*/ */
public List<EmployeeInfo> selectAll() { public List<EmployeeInfo> selectAll() {
return EmployeeDepartmentEntity.createEmployeeInfoList(employeeInfoRepository.findAll()); List<EmployeeDepartmentEntity> entityList = employeeInfoRepository.findAll();
List<Period> lengthOfServiceList = new ArrayList<>();
for (EmployeeDepartmentEntity entity : entityList) {
lengthOfServiceList.add(Period.between(entity.getDateHired(), LocalDate.now()));
}
return EmployeeDepartmentEntity.createEmployeeInfoList(entityList, lengthOfServiceList);
} }
@@ -47,16 +57,21 @@ public class SearchEmployeeInfoImpl implements SearchEmployeeInfo {
public List<EmployeeInfo> searchBy(SearchConditionEmployee searchConditionEmployee) { public List<EmployeeInfo> searchBy(SearchConditionEmployee searchConditionEmployee) {
// 動的に検索条件を絞り込む // 動的に検索条件を絞り込む
// Specification は Criteria API の Predicate をラップしたもの // Specification は Criteria API の Predicate をラップしたもの
return EmployeeDepartmentEntity List<EmployeeDepartmentEntity> entityList = employeeInfoRepository.findAll(Specification
.createEmployeeInfoList(
employeeInfoRepository.findAll(Specification
.where(EmployeeInfoRepository.idEmployeeEqual(searchConditionEmployee.getIdEmployee())) .where(EmployeeInfoRepository.idEmployeeEqual(searchConditionEmployee.getIdEmployee()))
.and(EmployeeInfoRepository.nmEmployeeEqual(searchConditionEmployee.getNmEmployee())) .and(EmployeeInfoRepository.nmEmployeeEqual(searchConditionEmployee.getNmEmployee()))
.and(EmployeeInfoRepository.knEmployeeEqual(searchConditionEmployee.getKnEmployee())) .and(EmployeeInfoRepository.knEmployeeEqual(searchConditionEmployee.getKnEmployee()))
.and(EmployeeInfoRepository.mailAddressEqual(searchConditionEmployee.getMailAddress())) .and(EmployeeInfoRepository.mailAddressEqual(searchConditionEmployee.getMailAddress()))
.and(EmployeeInfoRepository.idDepartmentEqual(searchConditionEmployee.getIdDepartment())) .and(EmployeeInfoRepository.idDepartmentEqual(searchConditionEmployee.getIdDepartment())));
)
); List<Period> lengthOfServiceList = new ArrayList<>();
for (EmployeeDepartmentEntity entity : entityList) {
lengthOfServiceList.add(Period.between(entity.getDateHired(), LocalDate.now()));
}
return EmployeeDepartmentEntity.createEmployeeInfoList(entityList, lengthOfServiceList);
} }
} }

View File

@@ -1,12 +1,13 @@
package com.example.rhizome.app.domain.service.impl; 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.Employee; import com.example.rhizome.app.domain.model.Employee;
import com.example.rhizome.app.domain.service.UpdateEmployee; import com.example.rhizome.app.domain.service.UpdateEmployee;
import com.example.rhizome.app.infra.entity.EmployeeEntity; import com.example.rhizome.app.infra.entity.EmployeeEntity;
import com.example.rhizome.app.infra.repository.EmployeeRepository; import com.example.rhizome.app.infra.repository.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/** /**
* employee の更新系の機能を集約させるサービスクラスです。 * employee の更新系の機能を集約させるサービスクラスです。
@@ -52,7 +53,8 @@ public class UpdateEmployeeImpl implements UpdateEmployee {
updateEmployee.getMailAddress(), updateEmployee.getMailAddress(),
updateEmployee.getPassword().isBlank() ? beforeEmployee.getPassword() : updateEmployee.getPassword(), updateEmployee.getPassword().isBlank() ? beforeEmployee.getPassword() : updateEmployee.getPassword(),
updateEmployee.getAdminAuth() == null ? beforeEmployee.getAdminAuth() : updateEmployee.getAdminAuth(), updateEmployee.getAdminAuth() == null ? beforeEmployee.getAdminAuth() : updateEmployee.getAdminAuth(),
updateEmployee.getIdDepartment() == null ? beforeEmployee.getIdDepartment() : updateEmployee.getIdDepartment() updateEmployee.getIdDepartment() == null ? beforeEmployee.getIdDepartment() : updateEmployee.getIdDepartment(),
beforeEmployee.getDateHired()
); );
} }

View File

@@ -1,16 +1,30 @@
package com.example.rhizome.app.infra.entity; package com.example.rhizome.app.infra.entity;
import java.time.LocalDate;
import java.time.Period;
import java.util.List;
import java.util.stream.IntStream;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedEntityGraph;
import javax.persistence.Table;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import com.example.rhizome.app.domain.model.Department; import com.example.rhizome.app.domain.model.Department;
import com.example.rhizome.app.domain.model.Employee; import com.example.rhizome.app.domain.model.Employee;
import com.example.rhizome.app.domain.model.EmployeeInfo; import com.example.rhizome.app.domain.model.EmployeeInfo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import javax.persistence.*;
import java.util.List;
/** /**
* Employee + Department の Join 情報を保持するEntity * Employee + Department の Join 情報を保持するEntity
@@ -71,13 +85,20 @@ public class EmployeeDepartmentEntity {
@Fetch(FetchMode.JOIN) @Fetch(FetchMode.JOIN)
private DepartmentEntity department; private DepartmentEntity department;
/*
* 入社年月日
*/
@Column(name = "date_hired", nullable = false)
private LocalDate dateHired;
/** /**
* EmployeeDepartmentEntity(DataAccess層依存) を EmployeeInfo(BusinessLogic層依存) に変換します。 * EmployeeDepartmentEntity(DataAccess層依存) を EmployeeInfo(BusinessLogic層依存) に変換します。
* *
* @param employeeDepartmentEntity  EmployeeDepartmentEntity のインスタンス * @param employeeDepartmentEntity  EmployeeDepartmentEntity のインスタンス
* @param lengthOfService  勤続年数
* @return EmployeeInfo のインスタンス * @return EmployeeInfo のインスタンス
*/ */
public static EmployeeInfo createEmployeeInfo(EmployeeDepartmentEntity employeeDepartmentEntity) { public static EmployeeInfo createEmployeeInfo(EmployeeDepartmentEntity employeeDepartmentEntity, Period lengthOfService) {
// コンストラクタを使って書くとSetterを使用するより簡略化出来ます。 // コンストラクタを使って書くとSetterを使用するより簡略化出来ます。
// 混乱してしまう人は落ち着いて EmployeeInfo のフィールドを見に行って、 // 混乱してしまう人は落ち着いて EmployeeInfo のフィールドを見に行って、
@@ -90,12 +111,14 @@ public class EmployeeDepartmentEntity {
employeeDepartmentEntity.getMailAddress(), employeeDepartmentEntity.getMailAddress(),
employeeDepartmentEntity.getPassword(), employeeDepartmentEntity.getPassword(),
employeeDepartmentEntity.getAdminAuth(), employeeDepartmentEntity.getAdminAuth(),
employeeDepartmentEntity.getDepartment() == null ? null : employeeDepartmentEntity.getDepartment().getIdDepartment() employeeDepartmentEntity.getDepartment() == null ? null : employeeDepartmentEntity.getDepartment().getIdDepartment(),
employeeDepartmentEntity.getDateHired()
), ),
new Department( new Department(
employeeDepartmentEntity.getDepartment() == null ? null : employeeDepartmentEntity.getDepartment().getIdDepartment(), employeeDepartmentEntity.getDepartment() == null ? null : employeeDepartmentEntity.getDepartment().getIdDepartment(),
employeeDepartmentEntity.getDepartment() == null ? null : employeeDepartmentEntity.getDepartment().getNmDepartment() employeeDepartmentEntity.getDepartment() == null ? null : employeeDepartmentEntity.getDepartment().getNmDepartment()
) ),
lengthOfService
); );
} }
@@ -105,14 +128,25 @@ public class EmployeeDepartmentEntity {
* (リスト版) * (リスト版)
* *
* @param employeeDepartmentEntityList EmployeeDepartmentEntity インスタンスのリスト * @param employeeDepartmentEntityList EmployeeDepartmentEntity インスタンスのリスト
* @param 勤続年数のリスト
* @return EmployeeInfo インスタンスのリスト * @return EmployeeInfo インスタンスのリスト
*/ */
public static List<EmployeeInfo> createEmployeeInfoList(List<EmployeeDepartmentEntity> employeeDepartmentEntityList) { public static List<EmployeeInfo> createEmployeeInfoList(
List<EmployeeDepartmentEntity> employeeDepartmentEntityList,
List<Period> lengthOfServiceList) {
// StreamAPI を使うとこうなります。 if (employeeDepartmentEntityList.size() != lengthOfServiceList.size()) {
return employeeDepartmentEntityList.stream().map(EmployeeDepartmentEntity::createEmployeeInfo).toList(); throw new IllegalArgumentException(
"社員情報と勤続年数の件数が一致しません。");
}
return IntStream.range(0, employeeDepartmentEntityList.size())
.mapToObj(index -> EmployeeDepartmentEntity
.createEmployeeInfo(employeeDepartmentEntityList.get(index), lengthOfServiceList.get(index)))
.toList();
} }
} }

View File

@@ -7,16 +7,24 @@
package com.example.rhizome.app.infra.entity; package com.example.rhizome.app.infra.entity;
import java.time.LocalDate;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import com.example.rhizome.app.domain.model.Employee; import com.example.rhizome.app.domain.model.Employee;
import com.example.rhizome.app.domain.model.LoginUser; import com.example.rhizome.app.domain.model.LoginUser;
import com.example.rhizome.app.domain.model.SearchConditionEmployee; import com.example.rhizome.app.domain.model.SearchConditionEmployee;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.List;
/** /**
* EmployeeテーブルのEntity * EmployeeテーブルのEntity
* *
@@ -73,6 +81,12 @@ public class EmployeeEntity {
@Column(name = "id_department", nullable = false) @Column(name = "id_department", nullable = false)
private Integer idDepartment; private Integer idDepartment;
/**
* 入社年月日
*/
@Column(name = "date_hired", nullable = false)
private LocalDate dateHired;
/** /**
* Employee(BusinessLogic 依存)を EmployeeEntity(DataAccess層依存)に変換します。 * Employee(BusinessLogic 依存)を EmployeeEntity(DataAccess層依存)に変換します。
@@ -89,7 +103,8 @@ public class EmployeeEntity {
employee.getMailAddress(), employee.getMailAddress(),
employee.getPassword(), employee.getPassword(),
employee.getAdminAuth(), employee.getAdminAuth(),
employee.getIdDepartment() employee.getIdDepartment(),
employee.getDateHired()
); );
} }
@@ -129,7 +144,8 @@ public class EmployeeEntity {
employeeEntity.getMailAddress(), employeeEntity.getMailAddress(),
employeeEntity.getPassword(), employeeEntity.getPassword(),
employeeEntity.getAdminAuth(), employeeEntity.getAdminAuth(),
employeeEntity.getIdDepartment() employeeEntity.getIdDepartment(),
employeeEntity.getDateHired()
); );
} }
@@ -167,7 +183,8 @@ public class EmployeeEntity {
getMailAddress(), getMailAddress(),
getPassword(), getPassword(),
getAdminAuth(), getAdminAuth(),
getIdDepartment() getIdDepartment(),
getDateHired()
); );
} }

View File

@@ -1,5 +1,22 @@
package com.example.rhizome.app.presentation.controller; package com.example.rhizome.app.presentation.controller;
import static com.example.rhizome.app.presentation.controller.pageproperty.TransitionTargetPageNameKeyword.*;
import java.time.LocalDate;
import java.util.ArrayList;
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 com.example.rhizome.aop.aspect.PermissionCheck; import com.example.rhizome.aop.aspect.PermissionCheck;
import com.example.rhizome.aop.aspect.SessionCheck; import com.example.rhizome.aop.aspect.SessionCheck;
import com.example.rhizome.app.domain.service.RegisterEmployee; import com.example.rhizome.app.domain.service.RegisterEmployee;
@@ -11,20 +28,6 @@ import com.example.rhizome.app.presentation.controller.pageproperty.TransitionTa
import com.example.rhizome.app.presentation.form.DepartmentForm; import com.example.rhizome.app.presentation.form.DepartmentForm;
import com.example.rhizome.app.presentation.form.InsertEmployeeForm; import com.example.rhizome.app.presentation.form.InsertEmployeeForm;
import com.example.rhizome.app.presentation.form.MessageForm; import com.example.rhizome.app.presentation.form.MessageForm;
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 javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import static com.example.rhizome.app.presentation.controller.pageproperty.TransitionTargetPageNameKeyword.INSERT_EMPLOYEE;
/** /**
* 新規登録用のコントローラ * 新規登録用のコントローラ
@@ -82,7 +85,8 @@ public class InsertEmployeeController {
insertEmployeeForm.getMailAddress(), insertEmployeeForm.getMailAddress(),
insertEmployeeForm.getPassword(), insertEmployeeForm.getPassword(),
insertEmployeeForm.getAdminAuth(), insertEmployeeForm.getAdminAuth(),
insertEmployeeForm.getIdDepartment() insertEmployeeForm.getIdDepartment(),
insertEmployeeForm.getDateHired()
); );
// エラーが1件以上有る場合 // エラーが1件以上有る場合
@@ -126,7 +130,8 @@ public class InsertEmployeeController {
String mailAddress, String mailAddress,
String password, String password,
Integer management, Integer management,
Integer departmentId Integer departmentId,
LocalDate hireDate
) { ) {
final String EMPLOYEE_NAME_NULL_BLANK = "社員名"; final String EMPLOYEE_NAME_NULL_BLANK = "社員名";
@@ -135,6 +140,7 @@ public class InsertEmployeeController {
final String PASSWORD_NULL_BLANK = "パスワード"; final String PASSWORD_NULL_BLANK = "パスワード";
final String MANAGEMENT_ERROR = "管理者権限指定"; final String MANAGEMENT_ERROR = "管理者権限指定";
final String DEPARTMENT_ID_NULL_BLANK = "所属部署"; final String DEPARTMENT_ID_NULL_BLANK = "所属部署";
final String HIRE_DATE_NULL_BLANK = "入社年月日";
List<String> error = new ArrayList<>(); List<String> error = new ArrayList<>();
@@ -174,6 +180,12 @@ public class InsertEmployeeController {
error.add(DEPARTMENT_ID_NULL_BLANK); error.add(DEPARTMENT_ID_NULL_BLANK);
} }
// null判定
if (hireDate == null) {
//エラー内容を追加
error.add(HIRE_DATE_NULL_BLANK);
}
return error; return error;
} }

View File

@@ -1,5 +1,17 @@
package com.example.rhizome.app.presentation.controller; package com.example.rhizome.app.presentation.controller;
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.PermissionCheck;
import com.example.rhizome.aop.aspect.SessionCheck; import com.example.rhizome.aop.aspect.SessionCheck;
import com.example.rhizome.app.domain.service.SearchDepartment; import com.example.rhizome.app.domain.service.SearchDepartment;
@@ -7,16 +19,6 @@ import com.example.rhizome.app.presentation.controller.pageproperty.PageReturnAt
import com.example.rhizome.app.presentation.controller.pageproperty.TransitionTargetPageNameKeyword; import com.example.rhizome.app.presentation.controller.pageproperty.TransitionTargetPageNameKeyword;
import com.example.rhizome.app.presentation.form.DepartmentForm; import com.example.rhizome.app.presentation.form.DepartmentForm;
import com.example.rhizome.app.presentation.form.SearchConditionDepartmentForm; import com.example.rhizome.app.presentation.form.SearchConditionDepartmentForm;
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 javax.servlet.http.HttpSession;
import java.util.logging.Level;
import java.util.logging.Logger;
/** /**
* 部署検索画面用コントローラ リスト全件表示、検索表示、更新、削除が可能 * 部署検索画面用コントローラ リスト全件表示、検索表示、更新、削除が可能
@@ -60,7 +62,7 @@ public class SelectDepartmentController {
// 作成した部署一覧をセット // 作成した部署一覧をセット
model.addAttribute( model.addAttribute(
PageReturnAttributeKeyword.DEPARTMENT_FORM_LIST, PageReturnAttributeKeyword.DEPARTMENT_FORM_LIST,
DepartmentForm.convertFrom(searchDepartment.searchByWithLike(SearchConditionDepartmentForm.convertTo(searchConditionDepartmentForm))) DepartmentForm.convertFrom(searchDepartment.searchBy(SearchConditionDepartmentForm.convertTo(searchConditionDepartmentForm)))
); );
// 検索ページに遷移 // 検索ページに遷移

View File

@@ -1,13 +1,16 @@
package com.example.rhizome.app.presentation.form; package com.example.rhizome.app.presentation.form;
import java.time.LocalDate;
import java.time.Period;
import java.util.List;
import com.example.rhizome.app.domain.model.EmployeeInfo; import com.example.rhizome.app.domain.model.EmployeeInfo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.List;
/** /**
* 画面に表示するために employee と department を Join した構造を扱うクラス * 画面に表示するために employee と department を Join した構造を扱うクラス
*/ */
@@ -49,6 +52,16 @@ public class EmployeeInfoForm {
*/ */
private String nmDepartment; private String nmDepartment;
/**
* 入社年月日
*/
private LocalDate dateHired;
/**
* 勤続年数
*/
private String lengthOfService;
/** /**
* business 層の EmployeeInfo クラスから画面用(presentation 層)の EmployeeInfoForm に * business 層の EmployeeInfo クラスから画面用(presentation 層)の EmployeeInfoForm に
* 変換します。 * 変換します。
@@ -57,6 +70,11 @@ public class EmployeeInfoForm {
* @return クラスから画面用(presentation 層)の EmployeeInfoForm インスタンス * @return クラスから画面用(presentation 層)の EmployeeInfoForm インスタンス
*/ */
public static EmployeeInfoForm convertFrom(EmployeeInfo employeeInfo) { public static EmployeeInfoForm convertFrom(EmployeeInfo employeeInfo) {
Period period = employeeInfo.getLengthOfService();
String lengthOfService =
period.getYears() + "年" + period.getMonths() + "ヵ月";
return new EmployeeInfoForm( return new EmployeeInfoForm(
employeeInfo.getEmployee().getIdEmployee(), employeeInfo.getEmployee().getIdEmployee(),
employeeInfo.getEmployee().getNmEmployee(), employeeInfo.getEmployee().getNmEmployee(),
@@ -65,7 +83,9 @@ public class EmployeeInfoForm {
employeeInfo.getEmployee().getPassword(), employeeInfo.getEmployee().getPassword(),
employeeInfo.getEmployee().getAdminAuth(), employeeInfo.getEmployee().getAdminAuth(),
employeeInfo.getDepartment().getIdDepartment(), employeeInfo.getDepartment().getIdDepartment(),
employeeInfo.getDepartment().getNmDepartment() employeeInfo.getDepartment().getNmDepartment(),
employeeInfo.getEmployee().getDateHired(),
lengthOfService
); );
} }

View File

@@ -1,13 +1,17 @@
package com.example.rhizome.app.presentation.form; package com.example.rhizome.app.presentation.form;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import org.springframework.format.annotation.DateTimeFormat;
import com.example.rhizome.app.domain.model.Employee; import com.example.rhizome.app.domain.model.Employee;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
/** /**
* 画面から渡ってきた登録内容をまとめ、再度画面に表示する為のクラス * 画面から渡ってきた登録内容をまとめ、再度画面に表示する為のクラス
*/ */
@@ -51,6 +55,13 @@ public class InsertEmployeeForm {
*/ */
private Integer idDepartment; private Integer idDepartment;
/**
* 入社年月日
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate dateHired;
/** /**
* パスワードのValidation * パスワードのValidation
* チェック対象にエラーが有った場合エラーリストに文言を追加する * チェック対象にエラーが有った場合エラーリストに文言を追加する
@@ -106,7 +117,8 @@ public class InsertEmployeeForm {
insertEmployeeForm.getMailAddress(), insertEmployeeForm.getMailAddress(),
insertEmployeeForm.getPassword(), insertEmployeeForm.getPassword(),
insertEmployeeForm.getAdminAuth(), insertEmployeeForm.getAdminAuth(),
insertEmployeeForm.getIdDepartment() insertEmployeeForm.getIdDepartment(),
insertEmployeeForm.getDateHired()
); );
} }
@@ -121,6 +133,7 @@ public class InsertEmployeeForm {
final String MAIL_ADDRESS_NULL_BLANK = "メールアドレス"; final String MAIL_ADDRESS_NULL_BLANK = "メールアドレス";
final String MANAGEMENT_ERROR = "管理者権限指定"; final String MANAGEMENT_ERROR = "管理者権限指定";
final String DEPARTMENT_ID_NULL_BLANK = "所属部署"; final String DEPARTMENT_ID_NULL_BLANK = "所属部署";
final String HIRE_DATE_NULL = "入社年月日";
List<String> error = new ArrayList<>(); List<String> error = new ArrayList<>();
@@ -133,6 +146,9 @@ public class InsertEmployeeForm {
if (isNullOrBlank(mailAddress)) { if (isNullOrBlank(mailAddress)) {
error.add(MAIL_ADDRESS_NULL_BLANK); error.add(MAIL_ADDRESS_NULL_BLANK);
} }
if(dateHired == null) {
error.add(HIRE_DATE_NULL);
}
// パスワードが仕様を満たしているか確認 // パスワードが仕様を満たしているか確認
checkPassword(password, passwordConfirm, error); checkPassword(password, passwordConfirm, error);

View File

@@ -1,7 +1,10 @@
package com.example.rhizome.app.presentation.form; package com.example.rhizome.app.presentation.form;
import java.time.LocalDate;
import com.example.rhizome.app.domain.model.LoginUser; import com.example.rhizome.app.domain.model.LoginUser;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -41,6 +44,11 @@ public class LoginUserForm {
*/ */
private Integer idDepartment; private Integer idDepartment;
/**
* 入社年月日
*/
private LocalDate dateHired;
/** /**
* business 層の LoginUser クラスから画面用(presentation 層)の LoginUserForm に * business 層の LoginUser クラスから画面用(presentation 層)の LoginUserForm に
* 変換します。 * 変換します。
@@ -56,7 +64,8 @@ public class LoginUserForm {
loginUser.getMailAddress(), loginUser.getMailAddress(),
loginUser.getPassword(), loginUser.getPassword(),
loginUser.getAdminAuth(), loginUser.getAdminAuth(),
loginUser.getIdDepartment() loginUser.getIdDepartment(),
loginUser.getDateHired()
); );
} }
@@ -75,7 +84,8 @@ public class LoginUserForm {
loginUserForm.getMailAddress(), loginUserForm.getMailAddress(),
loginUserForm.getPassword(), loginUserForm.getPassword(),
loginUserForm.getAdminAuth(), loginUserForm.getAdminAuth(),
loginUserForm.getIdDepartment() loginUserForm.getIdDepartment(),
loginUserForm.getDateHired()
); );
} }

View File

@@ -1,13 +1,15 @@
package com.example.rhizome.app.presentation.form; package com.example.rhizome.app.presentation.form;
import java.time.LocalDate;
import java.util.List;
import com.example.rhizome.app.domain.model.Employee; import com.example.rhizome.app.domain.model.Employee;
import com.example.rhizome.app.domain.model.EmployeeInfo; import com.example.rhizome.app.domain.model.EmployeeInfo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.List;
/** /**
* 画面から渡ってきた更新内容をまとめ、再度画面に表示する為のクラス * 画面から渡ってきた更新内容をまとめ、再度画面に表示する為のクラス
*/ */
@@ -48,6 +50,10 @@ public class UpdateEmployeeInfoForm {
* 部署ID * 部署ID
*/ */
private Integer idDepartment; private Integer idDepartment;
/**
* 入社年月日
*/
private LocalDate dateHired;
/** /**
* business 層の EmployeeInfo クラスから画面用(presentation 層)の UpdateEmployeeInfoForm に * business 層の EmployeeInfo クラスから画面用(presentation 層)の UpdateEmployeeInfoForm に
@@ -65,7 +71,8 @@ public class UpdateEmployeeInfoForm {
employeeInfo.getEmployee().getPassword(), employeeInfo.getEmployee().getPassword(),
null, null,
employeeInfo.getEmployee().getAdminAuth(), employeeInfo.getEmployee().getAdminAuth(),
employeeInfo.getDepartment().getIdDepartment() employeeInfo.getDepartment().getIdDepartment(),
employeeInfo.getEmployee().getDateHired()
); );
} }
@@ -95,7 +102,8 @@ public class UpdateEmployeeInfoForm {
updateEmployeeInfoForm.getMailAddress(), updateEmployeeInfoForm.getMailAddress(),
updateEmployeeInfoForm.getPassword(), updateEmployeeInfoForm.getPassword(),
updateEmployeeInfoForm.getAdminAuth(), updateEmployeeInfoForm.getAdminAuth(),
updateEmployeeInfoForm.getIdDepartment() updateEmployeeInfoForm.getIdDepartment(),
updateEmployeeInfoForm.getDateHired()
); );
} }

View File

@@ -2,6 +2,7 @@ package com.example.rhizome.app.presentation.form;
import com.example.rhizome.app.domain.model.Employee; import com.example.rhizome.app.domain.model.Employee;
import com.example.rhizome.app.domain.model.LoginUser; import com.example.rhizome.app.domain.model.LoginUser;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@@ -54,6 +55,7 @@ public class UpdatePersonalUserForm {
updatePersonalUserForm.getMailAddress(), updatePersonalUserForm.getMailAddress(),
updatePersonalUserForm.getPassword(), updatePersonalUserForm.getPassword(),
null, null,
null,
null null
); );
} }

View File

@@ -13,17 +13,14 @@
</head> </head>
<body> <body>
<h1>登録内容確認    <h1>登録内容確認   
<div class="rightSection"> <div class="rightSection">
<span class="loginInfo">ログイン者名:<span th:text="${session.loginUser.nmEmployee}"></span></span> <span class="loginInfo">ログイン者名:<span th:text="${session.loginUser.nmEmployee}"></span></span>
<button class="logoutButton" onclick="logoutSubmit()">ログアウト</button> <button class="logoutButton" onclick="logoutSubmit()">ログアウト</button>
</div> </div>
</h1> </h1>
<form action="insertEmployee" <form action="insertEmployee" id="insertForm" method="post" th:object="${insertEmployeeForm}">
id="insertForm"
method="post"
th:object="${insertEmployeeForm}">
<div class="msgBox error" th:if="${messageError != null}"> <div class="msgBox error" th:if="${messageError != null}">
<span class="error" th:each="message : ${messageError.message}" th:text="${message}"></span> <span class="error" th:each="message : ${messageError.message}" th:text="${message}"></span>
@@ -33,11 +30,7 @@
<th class="header">社員ID</th> <th class="header">社員ID</th>
<td> <td>
<label> <label>
<input class="readOnly" <input class="readOnly" name="empId" readonly="readonly" type="text" value="自動で設定されます" />
name="empId"
readonly="readonly"
type="text"
value="自動で設定されます"/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -45,11 +38,8 @@
<th class="header">社員名</th> <th class="header">社員名</th>
<td> <td>
<label> <label>
<input class="readOnly" <input class="readOnly" name="nmEmployee" readonly="readonly" th:value="*{nmEmployee}"
name="nmEmployee" type="text" />
readonly="readonly"
th:value="*{nmEmployee}"
type="text"/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -57,11 +47,8 @@
<th class="header">社員名フリガナ</th> <th class="header">社員名フリガナ</th>
<td> <td>
<label> <label>
<input class="readOnly" <input class="readOnly" name="knEmployee" readonly="readonly" th:value="*{knEmployee}"
name="knEmployee" type="text" />
readonly="readonly"
th:value="*{knEmployee}"
type="text"/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -69,11 +56,8 @@
<th class="header">メールアドレス</th> <th class="header">メールアドレス</th>
<td> <td>
<label> <label>
<input class="readOnly" <input class="readOnly" name="mailAddress" readonly="readonly" th:value="*{mailAddress}"
name="mailAddress" type="text" />
readonly="readonly"
th:value="*{mailAddress}"
type="text"/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -81,11 +65,8 @@
<th class="header">パスワード</th> <th class="header">パスワード</th>
<td> <td>
<label> <label>
<input class="readOnly" <input class="readOnly" name="password" readonly="readonly" th:value="*{password}"
name="password" type="password" />
readonly="readonly"
th:value="*{password}"
type="password"/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -94,14 +75,12 @@
<td> <td>
<label> <label>
<input id="adminAuth1" name="adminAuth" onclick="return false;" <input id="adminAuth1" name="adminAuth" onclick="return false;"
th:checked="${insertEmployeeForm .adminAuth == 1}" type="radio" th:checked="${insertEmployeeForm .adminAuth == 1}" type="radio" value="1"> 管理者権限
value="1"> 管理者権限
</label> </label>
<label> <label>
<input id="adminAuth0" name="adminAuth" onclick="return false;" <input id="adminAuth0" name="adminAuth" onclick="return false;"
th:checked="${insertEmployeeForm.adminAuth == null or insertEmployeeForm.adminAuth == 0}" th:checked="${insertEmployeeForm.adminAuth == null or insertEmployeeForm.adminAuth == 0}"
type="radio" type="radio" value="0">
value="0">
一般権限 一般権限
</label> </label>
</td> </td>
@@ -114,8 +93,7 @@
<th:block th:each="department : ${departmentFormList}"> <th:block th:each="department : ${departmentFormList}">
<th:block <th:block
th:if="${insertEmployeeForm.idDepartment != null && department.idDepartment == insertEmployeeForm.idDepartment}"> th:if="${insertEmployeeForm.idDepartment != null && department.idDepartment == insertEmployeeForm.idDepartment}">
<option th:text="${department.nmDepartment}" <option th:text="${department.nmDepartment}" th:value="${department.idDepartment}">
th:value="${department.idDepartment}">
</option> </option>
</th:block> </th:block>
</th:block> </th:block>
@@ -123,16 +101,25 @@
</label> </label>
</td> </td>
</tr> </tr>
<tr>
<th class="header">入社年月日</th>
<td>
<label>
<input class="readOnly" name="dateHired" readonly="readonly" th:value="*{dateHired}"
type="text" />
</label>
</td>
</tr>
<tr> <tr>
<td class="btnArea" colspan="2"> <td class="btnArea" colspan="2">
<input type="submit" value="登録"/> <input type="submit" value="登録" />
</td> </td>
</tr> </tr>
</table> </table>
<a href="javascript:onClickEdit()">登録内容の編集</a> | <a href="showMenu">メニューに戻る</a> <a href="javascript:onClickEdit()">登録内容の編集</a> | <a href="showMenu">メニューに戻る</a>
</form> </form>
<script type="text/javascript"> <script type="text/javascript">
function onClickEdit() { function onClickEdit() {
const form = document.getElementById('insertForm'); const form = document.getElementById('insertForm');
form.setAttribute('method', 'post'); form.setAttribute('method', 'post');
@@ -151,7 +138,8 @@
form.submit(); form.submit();
} }
</script> </script>
</body> </body>
</html> </html>

View File

@@ -13,16 +13,14 @@
</head> </head>
<body> <body>
<h1> <h1>
社員登録    社員登録   
<div class="rightSection"> <div class="rightSection">
<span class="loginInfo">ログイン者名:<span th:text="${session.loginUser.nmEmployee}"></span></span> <span class="loginInfo">ログイン者名:<span th:text="${session.loginUser.nmEmployee}"></span></span>
<button class="logoutButton" onclick="logoutSubmit()">ログアウト</button> <button class="logoutButton" onclick="logoutSubmit()">ログアウト</button>
</div> </div>
</h1> </h1>
<form action="insertEmployeeConfirm" <form action="insertEmployeeConfirm" method="post" th:object="${insertEmployeeForm}">
method="post"
th:object="${insertEmployeeForm}">
<div class="msgBox error" th:if="${messageError} != null"> <div class="msgBox error" th:if="${messageError} != null">
<span class="error" th:text="${messageError.message}"></span> <span class="error" th:text="${messageError.message}"></span>
@@ -33,11 +31,7 @@
<th class="header">社員ID</th> <th class="header">社員ID</th>
<td> <td>
<label> <label>
<input class="readOnly" <input class="readOnly" readonly="readonly" type="text" value="自動で設定されます" />
readonly="readonly"
type="text"
value="自動で設定されます"
/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -45,12 +39,8 @@
<th class="header">社員名</th> <th class="header">社員名</th>
<td> <td>
<label> <label>
<input maxlength="50" <input maxlength="50" placeholder="社員名" required="required" th:field="*{nmEmployee}"
placeholder="社員名" type="text" />
required="required"
th:field="*{nmEmployee}"
type="text"
/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -58,13 +48,8 @@
<th class="header">社員名フリガナ</th> <th class="header">社員名フリガナ</th>
<td> <td>
<label> <label>
<input maxlength="50" <input maxlength="50" oninput="convertToKatakana(this)" placeholder="フリガナ" required="required"
oninput="convertToKatakana(this)" th:field="*{knEmployee}" type="text" />
placeholder="フリガナ"
required="required"
th:field="*{knEmployee}"
type="text"
/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -72,12 +57,8 @@
<th class="header">メールアドレス</th> <th class="header">メールアドレス</th>
<td> <td>
<label> <label>
<input maxlength="100" <input maxlength="100" placeholder="メールアドレス" required="required" th:field="*{mailAddress}"
placeholder="メールアドレス" type="email" />
required="required"
th:field="*{mailAddress}"
type="email"
/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -85,32 +66,23 @@
<th class="header">パスワード</th> <th class="header">パスワード</th>
<td> <td>
<label> <label>
<input pattern="^(?=.*?[a-zA-Z])(?=.*?\d)[a-zA-Z\d]{3,10}$" <input pattern="^(?=.*?[a-zA-Z])(?=.*?\d)[a-zA-Z\d]{3,10}$" placeholder="パスワード"
placeholder="パスワード" required="required" th:field="*{password}" type="password" />
required="required"
th:field="*{password}"
type="password"
/>
</label> </label>
</td> </td>
</tr> </tr>
<!-- *** Chrome等のブラウザの場合自動でセットされる可能性があるので注意書きを外にも *** --> <!-- *** Chrome等のブラウザの場合自動でセットされる可能性があるので注意書きを外にも *** -->
<tr> <tr>
<th></th> <th></th>
<td><span <td><span style="font-size:8pt; font-weight:bold; color:red;">※半角英数字をそれぞれ1種類以上含む3-10文字</span>
style="font-size:8pt; font-weight:bold; color:red;">※半角英数字をそれぞれ1種類以上含む3-10文字</span>
</td> </td>
</tr> </tr>
<tr> <tr>
<th class="header">パスワード確認用</th> <th class="header">パスワード確認用</th>
<td> <td>
<label> <label>
<input pattern="^(?=.*?[a-zA-Z])(?=.*?\d)[a-zA-Z\d]{3,10}$" <input pattern="^(?=.*?[a-zA-Z])(?=.*?\d)[a-zA-Z\d]{3,10}$" placeholder="パスワード確認用"
placeholder="パスワード確認用" required="required" th:field="*{passwordConfirm}" type="password" />
required="required"
th:field="*{passwordConfirm}"
type="password"
/>
</label> </label>
</td> </td>
</tr> </tr>
@@ -119,14 +91,12 @@
<td> <td>
<label> <label>
<input id="adminAuth1" name="adminAuth" th:checked="${insertEmployeeForm .adminAuth == 1}" <input id="adminAuth1" name="adminAuth" th:checked="${insertEmployeeForm .adminAuth == 1}"
type="radio" type="radio" value="1"> 管理者権限
value="1"> 管理者権限
</label> </label>
<label> <label>
<input id="adminAuth0" name="adminAuth" <input id="adminAuth0" name="adminAuth"
th:checked="${insertEmployeeForm.adminAuth == null or insertEmployeeForm.adminAuth == 0}" th:checked="${insertEmployeeForm.adminAuth == null or insertEmployeeForm.adminAuth == 0}"
type="radio" type="radio" value="0">
value="0">
一般権限 一般権限
</label> </label>
</td> </td>
@@ -139,20 +109,29 @@
<select required="required" th:field="*{idDepartment}"> <select required="required" th:field="*{idDepartment}">
<option th:each="department : ${departmentFormList}" <option th:each="department : ${departmentFormList}"
th:selected="${insertEmployeeForm.idDepartment != null && department.idDepartment == insertEmployeeForm.idDepartment}" th:selected="${insertEmployeeForm.idDepartment != null && department.idDepartment == insertEmployeeForm.idDepartment}"
th:text="${department.nmDepartment}" th:text="${department.nmDepartment}" th:value="${department.idDepartment}">
th:value="${department.idDepartment}">
</option> </option>
</select> </select>
</label> </label>
</td> </td>
</tr> </tr>
<tr>
<th class="header">入社年月日</th>
<td>
<label>
<input required="required" th:field="*{dateHired}"
type="date" />
</label>
</td>
</tr>
<tr> <tr>
<td class="btnArea" colspan="2"> <td class="btnArea" colspan="2">
<input type="submit" value="登録確認"/> <input type="submit" value="登録確認" />
</td> </td>
</tr> </tr>
</table> </table>
</form> </form>
<a href="showMenu">メニューに戻る</a> <a href="showMenu">メニューに戻る</a>
</body> </body>
</html> </html>

View File

@@ -107,7 +107,9 @@
<th style="width: 100px;">パスワード</th> <th style="width: 100px;">パスワード</th>
<th style="width: 70px;">管理者フラグ</th> <th style="width: 70px;">管理者フラグ</th>
<th style="width: 150px;">所属部署</th> <th style="width: 150px;">所属部署</th>
<th style="width: 150px;">操作</th> <th style="width: 80px;">入社年月日</th>
<th style="width: 80px;">勤続年数</th>
<th style="width: 100px;">操作</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -119,6 +121,8 @@
<td th:text="${employeeInfoForm.password}"></td> <td th:text="${employeeInfoForm.password}"></td>
<td th:text="${employeeInfoForm.adminAuth}"></td> <td th:text="${employeeInfoForm.adminAuth}"></td>
<td th:text="${employeeInfoForm.nmDepartment}"></td> <td th:text="${employeeInfoForm.nmDepartment}"></td>
<td th:text="${employeeInfoForm.dateHired}"></td>
<td th:text="${employeeInfoForm.lengthOfService}"></td>
<td> <td>
<!-- 更新フォーム --> <!-- 更新フォーム -->
<form action="showUpdateEmployee" method="post" style="display: inline;"> <form action="showUpdateEmployee" method="post" style="display: inline;">

Binary file not shown.