feat: add employee fields (birthDate, education, residence) + emergency contacts
This commit is contained in:
@@ -9,6 +9,7 @@ import com.srsystem.dto.PortfolioResponse;
|
||||
import com.srsystem.dto.UpdateAchievementsRequest;
|
||||
import com.srsystem.entity.DispatchHistory;
|
||||
import com.srsystem.entity.Employee;
|
||||
import com.srsystem.entity.EmployeeEmergencyContact;
|
||||
import com.srsystem.entity.enums.EmpStatus;
|
||||
import com.srsystem.service.DispatchHistoryService;
|
||||
import com.srsystem.service.EmployeeService;
|
||||
@@ -152,6 +153,39 @@ public class EmployeeController {
|
||||
return ResponseEntity.ok(ApiResponse.ok("성과가 저장되었습니다", null));
|
||||
}
|
||||
|
||||
// ---- Emergency Contacts ----
|
||||
|
||||
@Operation(summary = "비상연락망 목록 조회", description = "직원의 비상연락망 목록을 조회합니다")
|
||||
@PreAuthorize("hasAnyRole('EMPLOYEE', 'MANAGER', 'ADMIN')")
|
||||
@GetMapping("/{empId}/emergency-contacts")
|
||||
public ResponseEntity<ApiResponse<List<EmployeeEmergencyContact>>> getEmergencyContacts(@PathVariable Long empId) {
|
||||
return ResponseEntity.ok(ApiResponse.ok(employeeService.getEmergencyContacts(empId)));
|
||||
}
|
||||
|
||||
@Operation(summary = "비상연락망 추가", description = "직원의 비상연락망을 추가합니다")
|
||||
@PreAuthorize("hasAnyRole('MANAGER', 'ADMIN')")
|
||||
@PostMapping("/{empId}/emergency-contacts")
|
||||
public ResponseEntity<ApiResponse<EmployeeEmergencyContact>> createEmergencyContact(
|
||||
@PathVariable Long empId, @RequestBody EmployeeEmergencyContact contact) {
|
||||
return ResponseEntity.ok(ApiResponse.ok("비상연락망이 추가되었습니다", employeeService.createEmergencyContact(empId, contact)));
|
||||
}
|
||||
|
||||
@Operation(summary = "비상연락망 수정", description = "비상연락망 정보를 수정합니다")
|
||||
@PreAuthorize("hasAnyRole('MANAGER', 'ADMIN')")
|
||||
@PutMapping("/{empId}/emergency-contacts/{contactId}")
|
||||
public ResponseEntity<ApiResponse<EmployeeEmergencyContact>> updateEmergencyContact(
|
||||
@PathVariable Long empId, @PathVariable Long contactId, @RequestBody EmployeeEmergencyContact contact) {
|
||||
return ResponseEntity.ok(ApiResponse.ok("비상연락망이 수정되었습니다", employeeService.updateEmergencyContact(contactId, contact)));
|
||||
}
|
||||
|
||||
@Operation(summary = "비상연락망 삭제", description = "비상연락망을 삭제합니다")
|
||||
@PreAuthorize("hasAnyRole('MANAGER', 'ADMIN')")
|
||||
@DeleteMapping("/{empId}/emergency-contacts/{contactId}")
|
||||
public ResponseEntity<ApiResponse<Void>> deleteEmergencyContact(@PathVariable Long empId, @PathVariable Long contactId) {
|
||||
employeeService.deleteEmergencyContact(contactId);
|
||||
return ResponseEntity.ok(ApiResponse.ok("비상연락망이 삭제되었습니다", null));
|
||||
}
|
||||
|
||||
@Operation(summary = "비밀번호 변경", description = "현재 사용자의 비밀번호를 변경합니다")
|
||||
@PreAuthorize("hasAnyRole('EMPLOYEE', 'MANAGER', 'ADMIN')")
|
||||
@PutMapping("/me/password")
|
||||
|
||||
@@ -15,5 +15,10 @@ public record EmployeeSummary(
|
||||
EmpStatus empStatus,
|
||||
DispatchStatus dispatchStatus,
|
||||
LocalDate joinedDate,
|
||||
LocalDate leftDate
|
||||
LocalDate leftDate,
|
||||
LocalDate birthDate,
|
||||
String education,
|
||||
String major,
|
||||
LocalDate graduationDate,
|
||||
String residence
|
||||
) {}
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.hibernate.annotations.SQLDelete;
|
||||
import org.hibernate.annotations.SQLRestriction;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "tb_employee")
|
||||
@@ -60,4 +61,23 @@ public class Employee extends BaseEntity {
|
||||
|
||||
@Column(name = "left_date")
|
||||
private LocalDate leftDate;
|
||||
|
||||
@Column(name = "birth_date")
|
||||
private LocalDate birthDate;
|
||||
|
||||
@Column(name = "education", length = 20)
|
||||
private String education;
|
||||
|
||||
@Column(name = "major", length = 100)
|
||||
private String major;
|
||||
|
||||
@Column(name = "graduation_date")
|
||||
private LocalDate graduationDate;
|
||||
|
||||
@Column(name = "residence", length = 255)
|
||||
private String residence;
|
||||
|
||||
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@OrderBy("sortOrder ASC")
|
||||
private List<EmployeeEmergencyContact> emergencyContacts;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.srsystem.entity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.SQLDelete;
|
||||
import org.hibernate.annotations.SQLRestriction;
|
||||
|
||||
@Entity
|
||||
@Table(name = "tb_employee_emergency_contact")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@SQLDelete(sql = "UPDATE tb_employee_emergency_contact SET is_deleted = 'Y' WHERE id = ?")
|
||||
@SQLRestriction("is_deleted = 'N'")
|
||||
public class EmployeeEmergencyContact extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sq_employee_emergency_contacts")
|
||||
@SequenceGenerator(name = "sq_employee_emergency_contacts", sequenceName = "sq_employee_emergency_contacts", allocationSize = 50)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "emp_id", nullable = false)
|
||||
@JsonIgnore
|
||||
private Employee employee;
|
||||
|
||||
@Column(name = "name", nullable = false, length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "relation", length = 50)
|
||||
private String relation;
|
||||
|
||||
@Column(name = "phone", length = 20)
|
||||
private String phone;
|
||||
|
||||
@Column(name = "sort_order")
|
||||
private Integer sortOrder;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.srsystem.repository;
|
||||
|
||||
import com.srsystem.entity.EmployeeEmergencyContact;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import java.util.List;
|
||||
|
||||
public interface EmployeeEmergencyContactRepository extends JpaRepository<EmployeeEmergencyContact, Long> {
|
||||
List<EmployeeEmergencyContact> findByEmployeeEmpIdOrderBySortOrderAsc(Long empId);
|
||||
void deleteByEmployeeEmpId(Long empId);
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public class AuthService {
|
||||
private final EmployeeRepository employeeRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private final EmployeeService employeeService;
|
||||
|
||||
@Transactional
|
||||
public LoginResponse login(LoginRequest request) {
|
||||
@@ -36,17 +37,7 @@ public class AuthService {
|
||||
String accessToken = jwtTokenProvider.generateAccessToken(employee.getLoginId(), employee.getRoleCode().name());
|
||||
String refreshToken = jwtTokenProvider.generateRefreshToken(employee.getLoginId());
|
||||
|
||||
EmployeeSummary summary = new EmployeeSummary(
|
||||
employee.getEmpId(),
|
||||
employee.getName(),
|
||||
employee.getEmail(),
|
||||
employee.getPhone(),
|
||||
employee.getRoleCode(),
|
||||
employee.getEmpStatus(),
|
||||
employee.getDispatchStatus(),
|
||||
employee.getJoinedDate(),
|
||||
employee.getLeftDate()
|
||||
);
|
||||
EmployeeSummary summary = employeeService.toSummary(employee);
|
||||
|
||||
return new LoginResponse(accessToken, refreshToken, summary);
|
||||
}
|
||||
@@ -64,17 +55,7 @@ public class AuthService {
|
||||
String newAccessToken = jwtTokenProvider.generateAccessToken(employee.getLoginId(), employee.getRoleCode().name());
|
||||
String newRefreshToken = jwtTokenProvider.generateRefreshToken(employee.getLoginId());
|
||||
|
||||
EmployeeSummary summary = new EmployeeSummary(
|
||||
employee.getEmpId(),
|
||||
employee.getName(),
|
||||
employee.getEmail(),
|
||||
employee.getPhone(),
|
||||
employee.getRoleCode(),
|
||||
employee.getEmpStatus(),
|
||||
employee.getDispatchStatus(),
|
||||
employee.getJoinedDate(),
|
||||
employee.getLeftDate()
|
||||
);
|
||||
EmployeeSummary summary = employeeService.toSummary(employee);
|
||||
|
||||
return new LoginResponse(newAccessToken, newRefreshToken, summary);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@ import com.srsystem.dto.ChangePasswordRequest;
|
||||
import com.srsystem.dto.EmployeeSearchResult;
|
||||
import com.srsystem.dto.EmployeeSummary;
|
||||
import com.srsystem.entity.Employee;
|
||||
import com.srsystem.entity.EmployeeEmergencyContact;
|
||||
import com.srsystem.entity.enums.EmpStatus;
|
||||
import com.srsystem.exception.BusinessException;
|
||||
import com.srsystem.exception.ErrorCode;
|
||||
import com.srsystem.repository.DispatchHistoryRepository;
|
||||
import com.srsystem.repository.EmployeeEmergencyContactRepository;
|
||||
import com.srsystem.repository.EmployeeRepository;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Page;
|
||||
@@ -28,6 +30,7 @@ public class EmployeeService {
|
||||
|
||||
private final EmployeeRepository employeeRepository;
|
||||
private final DispatchHistoryRepository dispatchHistoryRepository;
|
||||
private final EmployeeEmergencyContactRepository emergencyContactRepository;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
public Page<Employee> findAll(EmpStatus status, Pageable pageable) {
|
||||
@@ -101,6 +104,11 @@ public class EmployeeService {
|
||||
employee.setDispatchStatus(updateRequest.getDispatchStatus());
|
||||
employee.setJoinedDate(updateRequest.getJoinedDate());
|
||||
employee.setLeftDate(updateRequest.getLeftDate());
|
||||
employee.setBirthDate(updateRequest.getBirthDate());
|
||||
employee.setEducation(updateRequest.getEducation());
|
||||
employee.setMajor(updateRequest.getMajor());
|
||||
employee.setGraduationDate(updateRequest.getGraduationDate());
|
||||
employee.setResidence(updateRequest.getResidence());
|
||||
|
||||
if (updateRequest.getPassword() != null && !updateRequest.getPassword().isBlank()) {
|
||||
employee.setPassword(passwordEncoder.encode(updateRequest.getPassword()));
|
||||
@@ -130,10 +138,48 @@ public class EmployeeService {
|
||||
employee.getEmpStatus(),
|
||||
employee.getDispatchStatus(),
|
||||
employee.getJoinedDate(),
|
||||
employee.getLeftDate()
|
||||
employee.getLeftDate(),
|
||||
employee.getBirthDate(),
|
||||
employee.getEducation(),
|
||||
employee.getMajor(),
|
||||
employee.getGraduationDate(),
|
||||
employee.getResidence()
|
||||
);
|
||||
}
|
||||
|
||||
// ---- Emergency Contact CRUD ----
|
||||
|
||||
public List<EmployeeEmergencyContact> getEmergencyContacts(Long empId) {
|
||||
return emergencyContactRepository.findByEmployeeEmpIdOrderBySortOrderAsc(empId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public EmployeeEmergencyContact createEmergencyContact(Long empId, EmployeeEmergencyContact contact) {
|
||||
Employee employee = findById(empId);
|
||||
contact.setEmployee(employee);
|
||||
if (contact.getSortOrder() == null) contact.setSortOrder(0);
|
||||
return emergencyContactRepository.save(contact);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public EmployeeEmergencyContact updateEmergencyContact(Long contactId, EmployeeEmergencyContact update) {
|
||||
EmployeeEmergencyContact contact = emergencyContactRepository.findById(contactId)
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.CODE_NOT_FOUND));
|
||||
if (update.getName() != null) contact.setName(update.getName());
|
||||
if (update.getRelation() != null) contact.setRelation(update.getRelation());
|
||||
if (update.getPhone() != null) contact.setPhone(update.getPhone());
|
||||
if (update.getSortOrder() != null) contact.setSortOrder(update.getSortOrder());
|
||||
return emergencyContactRepository.save(contact);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteEmergencyContact(Long contactId) {
|
||||
EmployeeEmergencyContact contact = emergencyContactRepository.findById(contactId)
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.CODE_NOT_FOUND));
|
||||
contact.setIsDeleted('Y');
|
||||
emergencyContactRepository.save(contact);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void changePassword(Long empId, ChangePasswordRequest request) {
|
||||
Employee employee = findById(empId);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
ALTER TABLE tb_employee ADD COLUMN birth_date DATE;
|
||||
ALTER TABLE tb_employee ADD COLUMN education VARCHAR(20);
|
||||
ALTER TABLE tb_employee ADD COLUMN major VARCHAR(100);
|
||||
ALTER TABLE tb_employee ADD COLUMN graduation_date DATE;
|
||||
ALTER TABLE tb_employee ADD COLUMN residence VARCHAR(255);
|
||||
|
||||
CREATE SEQUENCE sq_employee_emergency_contacts INCREMENT BY 50;
|
||||
|
||||
CREATE TABLE tb_employee_emergency_contact (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
emp_id BIGINT NOT NULL REFERENCES tb_employee(id),
|
||||
name VARCHAR(100) NOT NULL,
|
||||
relation VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
sort_order INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP,
|
||||
updated_at TIMESTAMP,
|
||||
is_deleted CHAR(1) DEFAULT 'N'
|
||||
);
|
||||
|
||||
CREATE INDEX idx_emergency_contact_emp_id ON tb_employee_emergency_contact(emp_id);
|
||||
|
||||
INSERT INTO tb_common_code (id, group_code, code_value, code_name, sort_order, is_active, created_at, updated_at)
|
||||
SELECT nextval('sq_common_codes'), 'EDUCATION_LEVEL', 'HIGH_SCHOOL', '고졸', 1, 'Y', NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM tb_common_code WHERE group_code = 'EDUCATION_LEVEL' AND code_value = 'HIGH_SCHOOL');
|
||||
|
||||
INSERT INTO tb_common_code (id, group_code, code_value, code_name, sort_order, is_active, created_at, updated_at)
|
||||
SELECT nextval('sq_common_codes'), 'EDUCATION_LEVEL', 'COLLEGE', '전문대', 2, 'Y', NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM tb_common_code WHERE group_code = 'EDUCATION_LEVEL' AND code_value = 'COLLEGE');
|
||||
|
||||
INSERT INTO tb_common_code (id, group_code, code_value, code_name, sort_order, is_active, created_at, updated_at)
|
||||
SELECT nextval('sq_common_codes'), 'EDUCATION_LEVEL', 'BACHELOR', '학사', 3, 'Y', NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM tb_common_code WHERE group_code = 'EDUCATION_LEVEL' AND code_value = 'BACHELOR');
|
||||
|
||||
INSERT INTO tb_common_code (id, group_code, code_value, code_name, sort_order, is_active, created_at, updated_at)
|
||||
SELECT nextval('sq_common_codes'), 'EDUCATION_LEVEL', 'MASTER', '석사', 4, 'Y', NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM tb_common_code WHERE group_code = 'EDUCATION_LEVEL' AND code_value = 'MASTER');
|
||||
|
||||
INSERT INTO tb_common_code (id, group_code, code_value, code_name, sort_order, is_active, created_at, updated_at)
|
||||
SELECT nextval('sq_common_codes'), 'EDUCATION_LEVEL', 'DOCTOR', '박사', 5, 'Y', NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM tb_common_code WHERE group_code = 'EDUCATION_LEVEL' AND code_value = 'DOCTOR');
|
||||
Reference in New Issue
Block a user