feat: approval workflow with approver/backupApprover
This commit is contained in:
@@ -65,6 +65,11 @@ public class EmployeeService {
|
||||
return results;
|
||||
}
|
||||
|
||||
public List<EmployeeSearchResult> getApprovers() {
|
||||
return employeeRepository.findByRoleCodeIn(List.of(RoleCode.MANAGER, RoleCode.ADMIN))
|
||||
.stream().map(this::toSearchResult).toList();
|
||||
}
|
||||
|
||||
private EmployeeSearchResult toSearchResult(Employee e) {
|
||||
return new EmployeeSearchResult(
|
||||
e.getEmpId(),
|
||||
@@ -107,6 +112,8 @@ public class EmployeeService {
|
||||
employee.setProfileImage(updateRequest.getProfileImage());
|
||||
employee.setSchoolName(updateRequest.getSchoolName());
|
||||
employee.setPosition(updateRequest.getPosition());
|
||||
employee.setManagerId(updateRequest.getManagerId());
|
||||
employee.setBackupManagerId(updateRequest.getBackupManagerId());
|
||||
|
||||
return employee;
|
||||
}
|
||||
|
||||
@@ -59,13 +59,20 @@ public class TicketService {
|
||||
Employee requester = employeeRepository.findById(requesterId)
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.EMPLOYEE_NOT_FOUND));
|
||||
|
||||
boolean needsApproval = switch (request.category()) {
|
||||
case VACATION, EXPENSE, EQUIPMENT_REQUEST, GENERAL -> true;
|
||||
default -> false;
|
||||
};
|
||||
|
||||
TicketStatus initialStatus = needsApproval ? TicketStatus.PENDING_APPROVAL : TicketStatus.OPEN;
|
||||
|
||||
Ticket.TicketBuilder builder = Ticket.builder()
|
||||
.requester(requester)
|
||||
.category(request.category())
|
||||
.priority(request.priority())
|
||||
.title(request.title())
|
||||
.description(request.description())
|
||||
.status(TicketStatus.OPEN)
|
||||
.status(initialStatus)
|
||||
.slaWarnFlag('N')
|
||||
.attachmentUrl(request.attachmentUrl())
|
||||
.attachmentName(request.attachmentName());
|
||||
@@ -76,6 +83,15 @@ public class TicketService {
|
||||
builder.project(project);
|
||||
}
|
||||
|
||||
if (needsApproval) {
|
||||
Long approverId = request.approverId() != null ? request.approverId() : requester.getManagerId();
|
||||
builder.approverId(approverId);
|
||||
Long backupId = request.backupApproverId() != null ? request.backupApproverId() : requester.getBackupManagerId();
|
||||
if (backupId != null && !backupId.equals(approverId)) {
|
||||
builder.backupApproverId(backupId);
|
||||
}
|
||||
}
|
||||
|
||||
Ticket saved = ticketRepository.save(builder.build());
|
||||
return toIssueTicket(saved);
|
||||
}
|
||||
@@ -185,6 +201,39 @@ public class TicketService {
|
||||
ticketRepository.delete(ticket);
|
||||
}
|
||||
|
||||
public List<IssueTicket> getPendingApprovals(Long approverId) {
|
||||
List<TicketStatus> statuses = List.of(TicketStatus.PENDING_APPROVAL);
|
||||
List<Ticket> tickets = ticketRepository.findByStatusInAndApproverIdOrBackupApproverId(statuses, approverId);
|
||||
return tickets.stream().map(this::toIssueTicket).toList();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public IssueTicket approveTicket(Long ticketId, Long approverId) {
|
||||
Ticket ticket = ticketRepository.findById(ticketId)
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.TICKET_NOT_FOUND));
|
||||
if (ticket.getStatus() != TicketStatus.PENDING_APPROVAL) {
|
||||
throw new BusinessException(ErrorCode.INVALID_STATUS);
|
||||
}
|
||||
ticket.setStatus(TicketStatus.APPROVED);
|
||||
ticket.setApprovedBy(approverId);
|
||||
ticket.setApprovedAt(LocalDateTime.now());
|
||||
return toIssueTicket(ticketRepository.save(ticket));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public IssueTicket rejectTicket(Long ticketId, Long approverId, String reason) {
|
||||
Ticket ticket = ticketRepository.findById(ticketId)
|
||||
.orElseThrow(() -> new BusinessException(ErrorCode.TICKET_NOT_FOUND));
|
||||
if (ticket.getStatus() != TicketStatus.PENDING_APPROVAL) {
|
||||
throw new BusinessException(ErrorCode.INVALID_STATUS);
|
||||
}
|
||||
ticket.setStatus(TicketStatus.REJECTED);
|
||||
ticket.setResolutionNote(reason);
|
||||
ticket.setApprovedBy(approverId);
|
||||
ticket.setApprovedAt(LocalDateTime.now());
|
||||
return toIssueTicket(ticketRepository.save(ticket));
|
||||
}
|
||||
|
||||
private IssueTicket toIssueTicket(Ticket ticket) {
|
||||
return new IssueTicket(
|
||||
ticket.getTicketId(),
|
||||
@@ -202,7 +251,11 @@ public class TicketService {
|
||||
ticket.getSlaWarnFlag() == 'Y',
|
||||
ticket.getCreatedAt(),
|
||||
ticket.getAttachmentUrl(),
|
||||
ticket.getAttachmentName()
|
||||
ticket.getAttachmentName(),
|
||||
ticket.getApproverId(),
|
||||
ticket.getBackupApproverId(),
|
||||
ticket.getApprovedBy(),
|
||||
ticket.getApprovedAt()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user