feat: add employee fields (birthDate, education, residence) + emergency contacts

This commit is contained in:
pray4skylark
2026-06-02 18:11:05 +09:00
parent 65a82db0e0
commit d205a447a1
12 changed files with 747 additions and 112 deletions
@@ -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);