Files
backend/eatery-service/src/main/java/com/drinkool/services/ShiftService.java
T
TakahashiNguyen 345d4c056c
Release package / release (push) Successful in 26m36s
fix: add shift features (#51)
Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com>
Reviewed-on: #51
2026-05-12 02:14:21 +00:00

207 lines
6.1 KiB
Java

package com.drinkool.services;
import com.drinkool.InternalValue;
import com.drinkool.Role;
import com.drinkool.dtos.CreateShift;
import com.drinkool.dtos.RegisterShift;
import com.drinkool.entities.EateryEntity;
import com.drinkool.entities.ShiftEntity;
import com.drinkool.entities.ShiftRegistrationEntity;
import io.vertx.core.http.HttpServerRequest;
import jakarta.annotation.security.RolesAllowed;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.eclipse.microprofile.graphql.*;
@GraphQLApi
@ApplicationScoped
public class ShiftService {
@Inject
HttpServerRequest request;
// --- QUERIES ---
@Query("allShifts")
@Description("Lấy danh sách tất cả các loại ca trực")
@RolesAllowed({ Role.Staff, Role.Manager })
public List<ShiftEntity> getAllShifts() throws GraphQLException {
String ownerId = request.getHeader(InternalValue.managerId);
if (ownerId == null || ownerId.isEmpty()) {
ownerId = request.getHeader(InternalValue.userId);
}
EateryEntity eatery = EateryEntity.findByOwnerId(ownerId);
return ShiftEntity.list("eatery", eatery);
}
@Query("myRegistrations")
@Description("Lấy danh sách ca trực mà nhân viên hiện tại đã đăng ký")
@RolesAllowed(Role.Staff)
public List<ShiftRegistrationEntity> getMyShifts() {
String userId = request.getHeader(InternalValue.userId);
return ShiftRegistrationEntity.list("staffId", UUID.fromString(userId));
}
@Query("allRegistrations")
@Description("Manager xem toàn bộ danh sách đăng ký của tất cả nhân viên")
@RolesAllowed(Role.Manager)
public List<ShiftRegistrationEntity> getAllRegistrations() {
return ShiftRegistrationEntity.listAll();
}
// --- MUTATIONS ---
@Mutation("registerShift")
@Description("Nhân viên đăng ký vào một ca trực cụ thể")
@RolesAllowed(Role.Staff)
@Transactional
public ShiftRegistrationEntity registerShift(
@Name("registration") RegisterShift registration
) throws GraphQLException {
String userIdStr = request.getHeader(InternalValue.userId);
String managerIdStr = request.getHeader(InternalValue.managerId);
UUID staffId = UUID.fromString(userIdStr);
EateryEntity eatery = EateryEntity.findByOwnerId(managerIdStr);
if (eatery == null) throw new GraphQLException("NotFoundEatery");
ShiftEntity shift = ShiftEntity.find(
"id = ?1 and eatery.id = ?2",
registration.shiftId,
eatery.id
).firstResult();
if (shift == null) throw new GraphQLException("NotFoundShift");
List<ShiftRegistrationEntity> overlappingShifts =
ShiftRegistrationEntity.findOverlappingShifts(staffId, shift);
if (!overlappingShifts.isEmpty()) {
String ids = overlappingShifts
.stream()
.map(reg -> reg.shift.id.toString())
.distinct()
.collect(Collectors.joining(", "));
throw new GraphQLException("OverlappingShift: " + ids);
}
long currentStaffCount = ShiftRegistrationEntity.countByShift(shift.id);
if (shift.maxStaff != null && currentStaffCount >= shift.maxStaff) {
throw new GraphQLException("FulledShift");
}
ShiftRegistrationEntity record = new ShiftRegistrationEntity();
record.staffId = staffId;
record.shift = shift;
record.persist();
return record;
}
@Mutation("createShift")
@Description("Quản lý tạo mới một loại ca trực")
@RolesAllowed(Role.Manager)
@Transactional
public ShiftEntity createShift(@Name("shiftInput") CreateShift input)
throws GraphQLException {
String ownerId = request.getHeader(InternalValue.userId);
EateryEntity eatery = EateryEntity.findByOwnerId(ownerId);
if (eatery == null) return null;
ShiftEntity shift = new ShiftEntity();
shift.eatery = eatery;
shift.name = input.name;
shift.startTime = input.startTime;
shift.endTime = input.endTime;
shift.maxStaff = input.maxStaff;
if (shift.endTime.isBefore(shift.startTime)) {
throw new GraphQLException("InvalidEndTime");
}
shift.persist();
return shift;
}
@Mutation("updateShift")
@Description("Quản lý cập nhật thông tin ca trực")
@RolesAllowed(Role.Manager)
@Transactional
public ShiftEntity updateShift(
@Name("id") UUID id,
@Name("shiftInput") CreateShift input
) throws GraphQLException {
ShiftEntity shift = ShiftEntity.findById(id);
if (shift == null) throw new GraphQLException("NotFoundShift");
String ownerId = request.getHeader(InternalValue.userId);
if (
!shift.eatery.ownerId.toString().equals(ownerId)
) throw new GraphQLException("InvalidShiftId");
shift.name = input.name;
shift.startTime = input.startTime;
shift.endTime = input.endTime;
shift.maxStaff = input.maxStaff;
if (shift.endTime.isBefore(shift.startTime)) {
throw new GraphQLException("InvalidEndTime");
}
return shift;
}
@Mutation("deleteShift")
@Description("Quản lý xóa một ca trực")
@RolesAllowed(Role.Manager)
@Transactional
public boolean deleteShift(@Name("id") UUID id) throws GraphQLException {
String ownerId = request.getHeader(InternalValue.userId);
EateryEntity eatery = EateryEntity.findByOwnerId(ownerId);
if (eatery == null) {
throw new GraphQLException("NotFoundEatery");
}
ShiftEntity shift = ShiftEntity.find(
"id = ?1 and eatery = ?2",
id,
eatery
).firstResult();
if (shift == null) {
throw new GraphQLException("NotFoundShiftOrAccessDenied");
}
long count = ShiftRegistrationEntity.count("shift.id", id);
if (count > 0) throw new GraphQLException(
"CannotDeleteShiftWithRegistrations"
);
return ShiftEntity.deleteById(id);
}
@Mutation("cancelRegistration")
@Description("Nhân viên hủy ca đã đăng ký")
@RolesAllowed(Role.Staff)
@Transactional
public boolean cancelRegistration(@Name("registrationId") UUID id)
throws GraphQLException {
String userId = request.getHeader(InternalValue.userId);
ShiftRegistrationEntity reg = ShiftRegistrationEntity.findById(id);
if (reg == null) throw new GraphQLException("RegistrationNotFound");
if (!reg.staffId.equals(UUID.fromString(userId))) {
throw new GraphQLException("NotYourRegistration");
}
reg.delete();
return true;
}
}