super basic queue system

This commit is contained in:
2025-10-23 13:45:51 +07:00
parent 1641a4a9c6
commit bee6fef5e2
9 changed files with 119 additions and 10 deletions

View File

@@ -25,4 +25,9 @@ public class ExceptionHandling {
return ResponseMessage.of(HttpStatus.BAD_REQUEST, errors); return ResponseMessage.of(HttpStatus.BAD_REQUEST, errors);
} }
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<ResponseMessage> handleIllegalArgumentException(IllegalArgumentException ex) {
return ResponseMessage.of(HttpStatus.BAD_REQUEST, ex.getCause(), ex.getMessage());
}
} }

View File

@@ -52,4 +52,11 @@ public class LocationController {
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@GetMapping("/nextQueue/{locationId}")
public ResponseEntity<ResponseMessage> nextQueue(@PathVariable String locationId) {
locationService.nextQueue(locationId);
return ResponseMessage.of(HttpStatus.OK, null, "Next Queue");
}
} }

View File

@@ -1,6 +1,7 @@
package id.luxic.mai_queue.controller; package id.luxic.mai_queue.controller;
import id.luxic.mai_queue.request.queue.QueueInsertSoloRequest; import id.luxic.mai_queue.request.queue.QueueInsertSoloRequest;
import id.luxic.mai_queue.request.queue.ReorderQueueRequest;
import id.luxic.mai_queue.response.ResponseMessage; import id.luxic.mai_queue.response.ResponseMessage;
import id.luxic.mai_queue.service.QueueService; import id.luxic.mai_queue.service.QueueService;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@@ -33,4 +34,19 @@ public class QueueController {
return ResponseMessage.of(HttpStatus.OK, queueService.getQueueByLocation(id), "Find by location id"); return ResponseMessage.of(HttpStatus.OK, queueService.getQueueByLocation(id), "Find by location id");
} }
@PostMapping("/reorder")
public ResponseEntity<ResponseMessage> reorderQueue(@RequestBody ReorderQueueRequest request) {
queueService.reorderQueue(request.getLocationId(), request.getFrom(), request.getTo());
return ResponseMessage.of(HttpStatus.OK, null, "Success Reorder");
}
@DeleteMapping("/delete/{id}")
public ResponseEntity<ResponseMessage> deleteQueue(@PathVariable Integer id) {
queueService.deleteQueue(id);
return ResponseMessage.of(HttpStatus.OK, null, "Success Delete");
}
} }

View File

@@ -1,7 +1,6 @@
package id.luxic.mai_queue.model; package id.luxic.mai_queue.model;
import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import jakarta.persistence.*; import jakarta.persistence.*;
import lombok.*; import lombok.*;

View File

@@ -4,4 +4,5 @@ import id.luxic.mai_queue.model.Location;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
public interface LocationRepository extends JpaRepository<Location, String> { public interface LocationRepository extends JpaRepository<Location, String> {
} }

View File

@@ -13,15 +13,23 @@ public interface QueueRepository extends JpaRepository<Queue, Integer> {
@Query("SELECT MAX(q.order) FROM Queue q WHERE q.location.id = :locationId") @Query("SELECT MAX(q.order) FROM Queue q WHERE q.location.id = :locationId")
Integer findLastOrderByLocationId(@Param("locationId") String locationId); Integer findLastOrderByLocationId(@Param("locationId") String locationId);
@Query("SELECT q FROM Queue q WHERE q.location.id = :locationId ORDER BY order ASC") @Query("SELECT q FROM Queue q WHERE q.location.id = :locationId AND q.order >= q.location.currentQueue ORDER BY order ASC")
List<Queue> findByLocationId(@Param("locationId") String locationId); List<Queue> findByLocationId(@Param("locationId") String locationId);
@Modifying @Modifying
@Query(""" @Query("""
UPDATE Queue q UPDATE Queue q
set q.order = q.order + 1 SET q.order = q.order + 1
where q.location.id = :locationId and q.order > :targetOrder WHERE q.location.id = :locationId AND q.order > :targetOrder
""") """)
void reorderQueue(@Param("locationId") String locationId, Integer targetOrder); void reorderQueue(@Param("locationId") String locationId, Integer targetOrder);
@Query (value = """
SELECT q."order" FROM queue q JOIN location l ON q.location_id = l.id WHERE q.location_id = :locationId AND q."order" >= l.current ORDER BY q."order" ASC OFFSET :offset LIMIT 1
""", nativeQuery = true)
Integer nextQueueByLocation(@Param("locationId") String locationId, @Param("offset") Integer offset);
@Query("SELECT q FROM Queue q WHERE q.location.id = :locationId AND order = :order")
Queue findByLocationIdAndOrder(@Param("locationId") String locationId, @Param("order") Integer order);
} }

View File

@@ -0,0 +1,14 @@
package id.luxic.mai_queue.request.queue;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ReorderQueueRequest {
private String locationId;
private Integer from;
private Integer to;
}

View File

@@ -1,22 +1,25 @@
package id.luxic.mai_queue.service; package id.luxic.mai_queue.service;
import id.luxic.mai_queue.model.Location; import id.luxic.mai_queue.model.Location;
import id.luxic.mai_queue.model.Queue;
import id.luxic.mai_queue.repository.LocationRepository; import id.luxic.mai_queue.repository.LocationRepository;
import id.luxic.mai_queue.repository.QueueRepository;
import id.luxic.mai_queue.request.location.NewLocationRequest; import id.luxic.mai_queue.request.location.NewLocationRequest;
import id.luxic.mai_queue.tools.IdGenerator; import id.luxic.mai_queue.tools.IdGenerator;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant;
import java.util.List; import java.util.List;
@Service @Service
public class LocationService { public class LocationService {
private final LocationRepository locationRepository; private final LocationRepository locationRepository;
private final QueueRepository queueRepository;
public LocationService(LocationRepository locationRepository) { public LocationService(LocationRepository locationRepository, QueueRepository queueRepository) {
this.locationRepository = locationRepository; this.locationRepository = locationRepository;
this.queueRepository = queueRepository;
} }
public List<Location> getAllLocation() { public List<Location> getAllLocation() {
@@ -43,4 +46,34 @@ public class LocationService {
locationRepository.deleteById(id); locationRepository.deleteById(id);
} }
public void nextQueue(String locationId) {
Location location = locationRepository.findById(locationId).orElse(null);
if (location == null) {
throw new IllegalArgumentException("Location not found");
}
Queue queue = queueRepository.findByLocationIdAndOrder(location.getId(), location.getCurrentQueue());
if (queue == null) {
throw new IllegalArgumentException("There's no one here");
}
Integer offset = 2;
if (queue.isSolo()) offset = 1;
Integer nextOrder = queueRepository.nextQueueByLocation(locationId, offset);
Integer lastOrder = queueRepository.findLastOrderByLocationId(locationId);
if (nextOrder == null || nextOrder.equals(lastOrder)) nextOrder = lastOrder + 1;
location.setCurrentQueue(nextOrder);
// TODO: Use FCM to push notification
locationRepository.save(location);
}
} }

View File

@@ -56,11 +56,37 @@ public class QueueService {
return queueRepository.findByLocationId(locationId); return queueRepository.findByLocationId(locationId);
} }
public void reorderQueue(String locationId, Queue source, Integer targetOrder) { @Transactional
// Source must be higher order than target public void reorderQueue(String locationId, Integer from, Integer to) {
queueRepository.reorderQueue(locationId, targetOrder); // From must be higher order than target
Location location = locationRepository.findById(locationId).orElse(null);
source.setOrder(targetOrder+1); // Make sure from is higher order than target
if (to > from) {
int temp = to;
to = from;
from = temp;
}
System.out.println("to: " + to + ", from: " + from);
if (to < location.getCurrentQueue()) {
throw new IllegalArgumentException("Target queue is lower than current queue");
}
Queue source = queueRepository.findById(from).orElse(null);
if (source == null) {
throw new IllegalArgumentException("Queue not found");
}
queueRepository.reorderQueue(locationId, to);
source.setOrder(to+1);
queueRepository.save(source); queueRepository.save(source);
} }
public void deleteQueue(Integer id) {
queueRepository.deleteById(id);
}
} }