chore: update
This commit is contained in:
+33
-14
@@ -15,18 +15,40 @@ permissions:
|
|||||||
checks: write
|
checks: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-and-test:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Install dependencies with Proxy
|
- name: Install JDK and Maven
|
||||||
env:
|
run: |
|
||||||
http_proxy: "http://host.docker.internal:3142"
|
# Kiểm tra proxy có hoạt động không
|
||||||
https_proxy: "http://host.docker.internal:3142"
|
echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends --no-install-suggests \
|
||||||
|
openjdk-25-jdk-headless docker-cli docker-buildx zstd maven
|
||||||
|
|
||||||
|
- name: Cache Maven packages
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.m2/repository
|
||||||
|
**/target/native-image-cache
|
||||||
|
**/target/reports
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: ${{ runner.os }}-maven-
|
||||||
|
|
||||||
|
- name: Build native with Maven
|
||||||
|
run: |
|
||||||
|
mvn -B clean install -DskipTests -Pnative \
|
||||||
|
-Dquarkus.container-image.push=false
|
||||||
|
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Install JDK and Maven
|
||||||
run: |
|
run: |
|
||||||
# Kiểm tra proxy có hoạt động không
|
# Kiểm tra proxy có hoạt động không
|
||||||
echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy
|
echo "Acquire::http::Proxy \"$http_proxy\";" > /etc/apt/apt.conf.d/80proxy
|
||||||
@@ -46,16 +68,13 @@ jobs:
|
|||||||
**/target/native-image-cache
|
**/target/native-image-cache
|
||||||
**/target/reports
|
**/target/reports
|
||||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
restore-keys: |
|
restore-keys: ${{ runner.os }}-maven-
|
||||||
${{ runner.os }}-maven-
|
|
||||||
|
|
||||||
- name: Build and Test all module
|
- name: Run Tests
|
||||||
env:
|
env:
|
||||||
TESTCONTAINERS_RYUK_DISABLED: true
|
TESTCONTAINERS_RYUK_DISABLED: true
|
||||||
run: |
|
run: |
|
||||||
mvn -B clean install -Pnative \
|
mvn clean test -Dquarkus.main.run-tests=true
|
||||||
-Dquarkus.container-image.push=false \
|
|
||||||
-Dquarkus.container-image.registry=git.demonkernel.io.vn
|
|
||||||
|
|
||||||
- name: Publish Test Report
|
- name: Publish Test Report
|
||||||
uses: dorny/test-reporter@v3
|
uses: dorny/test-reporter@v3
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class StaffService extends BaseService<StaffEntity> {
|
|||||||
|
|
||||||
return Response.status(Response.Status.CREATED)
|
return Response.status(Response.Status.CREATED)
|
||||||
.header(InternalValue.userId, staff.id.toString())
|
.header(InternalValue.userId, staff.id.toString())
|
||||||
|
.header(InternalValue.managerId, manager.id.toString())
|
||||||
.header(InternalValue.role, Role.Staff)
|
.header(InternalValue.role, Role.Staff)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
@@ -64,6 +65,7 @@ public class StaffService extends BaseService<StaffEntity> {
|
|||||||
|
|
||||||
return Response.accepted()
|
return Response.accepted()
|
||||||
.header(InternalValue.userId, staff.id.toString())
|
.header(InternalValue.userId, staff.id.toString())
|
||||||
|
.header(InternalValue.managerId, staff.serve.id.toString())
|
||||||
.header(InternalValue.role, Role.Staff)
|
.header(InternalValue.role, Role.Staff)
|
||||||
.entity(staff)
|
.entity(staff)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package com.drinkool.dtos;
|
|||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import org.eclipse.microprofile.graphql.NonNull;
|
import org.eclipse.microprofile.graphql.NonNull;
|
||||||
|
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
public class CreateShift {
|
public class CreateShift {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
@@ -27,6 +27,13 @@ public class EateryEntity extends BaseEntity {
|
|||||||
)
|
)
|
||||||
public List<MenuItemEntity> menuItems = new ArrayList<>();
|
public List<MenuItemEntity> menuItems = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
mappedBy = "eatery",
|
||||||
|
cascade = CascadeType.ALL,
|
||||||
|
orphanRemoval = true
|
||||||
|
)
|
||||||
|
public List<ShiftEntity> shifts = new ArrayList<>();
|
||||||
|
|
||||||
public EateryEntity() {}
|
public EateryEntity() {}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
|||||||
@@ -3,13 +3,21 @@ package com.drinkool.entities;
|
|||||||
import com.drinkool.lib.entities.BaseEntity;
|
import com.drinkool.lib.entities.BaseEntity;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table
|
@Table
|
||||||
public class ShiftEntity extends BaseEntity {
|
public class ShiftEntity extends BaseEntity {
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "eatery_id")
|
||||||
|
public EateryEntity eatery;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
public String name;
|
public String name;
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import com.drinkool.InternalValue;
|
|||||||
import com.drinkool.Role;
|
import com.drinkool.Role;
|
||||||
import com.drinkool.dtos.CreateShift;
|
import com.drinkool.dtos.CreateShift;
|
||||||
import com.drinkool.dtos.RegisterShift;
|
import com.drinkool.dtos.RegisterShift;
|
||||||
|
import com.drinkool.entities.EateryEntity;
|
||||||
import com.drinkool.entities.ShiftEntity;
|
import com.drinkool.entities.ShiftEntity;
|
||||||
import com.drinkool.entities.ShiftRegistrationEntity;
|
import com.drinkool.entities.ShiftRegistrationEntity;
|
||||||
|
|
||||||
import io.vertx.core.http.HttpServerRequest;
|
import io.vertx.core.http.HttpServerRequest;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
@@ -58,9 +58,17 @@ public class ShiftService {
|
|||||||
@Name("registration") RegisterShift registration
|
@Name("registration") RegisterShift registration
|
||||||
) throws GraphQLException {
|
) throws GraphQLException {
|
||||||
String userIdStr = request.getHeader(InternalValue.userId);
|
String userIdStr = request.getHeader(InternalValue.userId);
|
||||||
|
String managerIdStr = request.getHeader(InternalValue.managerId);
|
||||||
UUID staffId = UUID.fromString(userIdStr);
|
UUID staffId = UUID.fromString(userIdStr);
|
||||||
|
|
||||||
ShiftEntity shift = ShiftEntity.findById(registration.shiftId);
|
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");
|
if (shift == null) throw new GraphQLException("NotFoundShift");
|
||||||
|
|
||||||
List<ShiftRegistrationEntity> overlappingShifts =
|
List<ShiftRegistrationEntity> overlappingShifts =
|
||||||
@@ -94,8 +102,13 @@ public class ShiftService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public ShiftEntity createShift(@Name("shiftInput") CreateShift input)
|
public ShiftEntity createShift(@Name("shiftInput") CreateShift input)
|
||||||
throws GraphQLException {
|
throws GraphQLException {
|
||||||
|
String ownerId = request.getHeader(InternalValue.userId);
|
||||||
|
|
||||||
|
EateryEntity eatery = EateryEntity.findByOwnerId(ownerId);
|
||||||
|
if (eatery == null) return null;
|
||||||
|
|
||||||
ShiftEntity shift = new ShiftEntity();
|
ShiftEntity shift = new ShiftEntity();
|
||||||
|
shift.eatery = eatery;
|
||||||
shift.name = input.name;
|
shift.name = input.name;
|
||||||
shift.startTime = input.startTime;
|
shift.startTime = input.startTime;
|
||||||
shift.endTime = input.endTime;
|
shift.endTime = input.endTime;
|
||||||
@@ -120,6 +133,11 @@ public class ShiftService {
|
|||||||
ShiftEntity shift = ShiftEntity.findById(id);
|
ShiftEntity shift = ShiftEntity.findById(id);
|
||||||
if (shift == null) throw new GraphQLException("NotFoundShift");
|
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.name = input.name;
|
||||||
shift.startTime = input.startTime;
|
shift.startTime = input.startTime;
|
||||||
shift.endTime = input.endTime;
|
shift.endTime = input.endTime;
|
||||||
@@ -137,6 +155,22 @@ public class ShiftService {
|
|||||||
@RolesAllowed(Role.Manager)
|
@RolesAllowed(Role.Manager)
|
||||||
@Transactional
|
@Transactional
|
||||||
public boolean deleteShift(@Name("id") Long id) throws GraphQLException {
|
public boolean deleteShift(@Name("id") Long 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);
|
long count = ShiftRegistrationEntity.count("shift.id", id);
|
||||||
if (count > 0) throw new GraphQLException(
|
if (count > 0) throw new GraphQLException(
|
||||||
"CannotDeleteShiftWithRegistrations"
|
"CannotDeleteShiftWithRegistrations"
|
||||||
|
|||||||
@@ -4,11 +4,15 @@ import static io.restassured.RestAssured.given;
|
|||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
import com.drinkool.InternalValue;
|
import com.drinkool.InternalValue;
|
||||||
|
import com.drinkool.Role;
|
||||||
|
import com.drinkool.entities.EateryEntity;
|
||||||
import com.drinkool.entities.ShiftEntity;
|
import com.drinkool.entities.ShiftEntity;
|
||||||
import com.drinkool.entities.ShiftRegistrationEntity;
|
import com.drinkool.entities.ShiftRegistrationEntity;
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -44,16 +48,28 @@ public class ShiftServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testCreateShift_AsManager() {
|
void testCreateShift_AsManager() {
|
||||||
String mutation =
|
String query = """
|
||||||
"mutation { createShift(shiftInput: { " +
|
mutation Create($input: CreateShiftInput!)
|
||||||
"name: \"Ca Chiều\", " +
|
{ createShift(shiftInput: $input) { id name } }""";
|
||||||
"startTime: \"13:00:00\", " +
|
|
||||||
"endTime: \"17:00:00\", " +
|
Map<String, Object> input = new HashMap<>();
|
||||||
"maxStaff: 3 }) { id name } }";
|
input.put("name", "Ca Sáng");
|
||||||
|
input.put("startTime", "08:00:00");
|
||||||
|
input.put("endTime", "12:00:00");
|
||||||
|
input.put("maxStaff", 5);
|
||||||
|
|
||||||
|
Map<String, Object> body = new HashMap<>();
|
||||||
|
body.put("query", query);
|
||||||
|
body.put("variables", Map.of("input", input));
|
||||||
|
|
||||||
|
UUID ownerId = createMockOwner();
|
||||||
|
createMockEatery(ownerId);
|
||||||
|
|
||||||
given()
|
given()
|
||||||
.contentType("application/json")
|
.contentType("application/json")
|
||||||
.body("{ \"query\": \"" + mutation + "\" }")
|
.header(InternalValue.role, Role.Manager)
|
||||||
|
.header(InternalValue.userId, ownerId)
|
||||||
|
.body(body)
|
||||||
.when()
|
.when()
|
||||||
.post("/graphql")
|
.post("/graphql")
|
||||||
.then()
|
.then()
|
||||||
@@ -136,7 +152,6 @@ public class ShiftServiceTest {
|
|||||||
@Transactional
|
@Transactional
|
||||||
ShiftEntity createMockShift(String name, String start, String end) {
|
ShiftEntity createMockShift(String name, String start, String end) {
|
||||||
ShiftEntity shift = new ShiftEntity();
|
ShiftEntity shift = new ShiftEntity();
|
||||||
shift.id = UUID.randomUUID();
|
|
||||||
shift.name = name;
|
shift.name = name;
|
||||||
shift.startTime = LocalTime.parse(start);
|
shift.startTime = LocalTime.parse(start);
|
||||||
shift.endTime = LocalTime.parse(end);
|
shift.endTime = LocalTime.parse(end);
|
||||||
@@ -148,9 +163,24 @@ public class ShiftServiceTest {
|
|||||||
@Transactional
|
@Transactional
|
||||||
void registerStaffToShift(UUID staffId, ShiftEntity shift) {
|
void registerStaffToShift(UUID staffId, ShiftEntity shift) {
|
||||||
ShiftRegistrationEntity reg = new ShiftRegistrationEntity();
|
ShiftRegistrationEntity reg = new ShiftRegistrationEntity();
|
||||||
reg.id = UUID.randomUUID();
|
|
||||||
reg.staffId = staffId;
|
reg.staffId = staffId;
|
||||||
reg.shift = shift;
|
reg.shift = shift;
|
||||||
reg.persist();
|
reg.persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public UUID createMockOwner() {
|
||||||
|
return UUID.randomUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public EateryEntity createMockEatery(UUID ownerId) {
|
||||||
|
EateryEntity eatery = new EateryEntity();
|
||||||
|
eatery.name = "Nhà hàng " + ownerId.toString().substring(0, 5);
|
||||||
|
eatery.ownerId = ownerId;
|
||||||
|
eatery.persist();
|
||||||
|
|
||||||
|
EateryEntity.getEntityManager().flush();
|
||||||
|
return eatery;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ public class InternalValue {
|
|||||||
public static final String headerId = "X-Internal-";
|
public static final String headerId = "X-Internal-";
|
||||||
public static final String userId = headerId + "UserId";
|
public static final String userId = headerId + "UserId";
|
||||||
public static final String role = headerId + "Role";
|
public static final String role = headerId + "Role";
|
||||||
|
public static final String managerId = headerId + "ManagerId";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user