Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: #37
This commit was merged in pull request #37.
This commit is contained in:
@@ -45,4 +45,16 @@ public class EateryEntity extends BaseEntity {
|
|||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public static EateryEntity findByOwnerId(String ownerId) {
|
||||||
|
UUID ownerUUID = UUID.fromString(ownerId);
|
||||||
|
|
||||||
|
return EateryEntity.find("ownerId", ownerUUID).firstResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public static EateryEntity findByOwnerId(UUID ownerId) {
|
||||||
|
return EateryEntity.find("ownerId", ownerId).firstResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
package com.drinkool.entities;
|
|
||||||
|
|
||||||
import com.drinkool.lib.entities.BaseEntity;
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table
|
|
||||||
public class EateryInventoryItemEntity extends BaseEntity {
|
|
||||||
|
|
||||||
public double quantity;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "inventory_item_id")
|
|
||||||
public InventoryItemEntity inventoryItem;
|
|
||||||
|
|
||||||
private EateryInventoryItemEntity() {}
|
|
||||||
|
|
||||||
// Create
|
|
||||||
@Transactional
|
|
||||||
public static EateryInventoryItemEntity create(
|
|
||||||
String name,
|
|
||||||
double quantity,
|
|
||||||
String unit
|
|
||||||
) {
|
|
||||||
String itemName = name.toLowerCase();
|
|
||||||
|
|
||||||
InventoryItemEntity item = InventoryItemEntity.find(
|
|
||||||
"name",
|
|
||||||
itemName
|
|
||||||
).firstResult();
|
|
||||||
|
|
||||||
if (item == null || item.unit != unit) {
|
|
||||||
if (unit != null || unit == "") {
|
|
||||||
item = InventoryItemEntity.create(itemName, unit);
|
|
||||||
} else {
|
|
||||||
item = InventoryItemEntity.create(itemName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
EateryInventoryItemEntity eateryInventoryItem =
|
|
||||||
new EateryInventoryItemEntity();
|
|
||||||
|
|
||||||
eateryInventoryItem.quantity = quantity;
|
|
||||||
eateryInventoryItem.inventoryItem = item;
|
|
||||||
|
|
||||||
eateryInventoryItem.persist();
|
|
||||||
|
|
||||||
return eateryInventoryItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package com.drinkool.entities;
|
|
||||||
|
|
||||||
import com.drinkool.lib.entities.BaseEntity;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "inventory_items")
|
|
||||||
public class InventoryItemEntity extends BaseEntity {
|
|
||||||
|
|
||||||
public String name;
|
|
||||||
public String unit;
|
|
||||||
|
|
||||||
private InventoryItemEntity() {}
|
|
||||||
|
|
||||||
// Create
|
|
||||||
@Transactional
|
|
||||||
public static InventoryItemEntity create(String name, String unit) {
|
|
||||||
InventoryItemEntity item = new InventoryItemEntity();
|
|
||||||
|
|
||||||
item.name = name;
|
|
||||||
item.unit = unit;
|
|
||||||
|
|
||||||
item.persist();
|
|
||||||
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public static InventoryItemEntity create(String name) {
|
|
||||||
return InventoryItemEntity.create(name, "unit");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ package com.drinkool.entities;
|
|||||||
import com.drinkool.lib.entities.BaseEntity;
|
import com.drinkool.lib.entities.BaseEntity;
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table
|
@Table
|
||||||
@@ -19,45 +18,19 @@ public class MenuItemEntity extends BaseEntity {
|
|||||||
@JoinColumn(name = "eatery_id")
|
@JoinColumn(name = "eatery_id")
|
||||||
public EateryEntity eatery;
|
public EateryEntity eatery;
|
||||||
|
|
||||||
// Danh sách các nguyên liệu cấu thành món ăn này
|
|
||||||
@OneToMany(
|
|
||||||
mappedBy = "menuItem",
|
|
||||||
cascade = CascadeType.ALL,
|
|
||||||
orphanRemoval = true
|
|
||||||
)
|
|
||||||
public List<MenuItemIngredientEntity> ingredients = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thêm nguyên liệu vào món ăn với định lượng cụ thể
|
|
||||||
*/
|
|
||||||
@Transactional
|
|
||||||
public void addIngredient(
|
|
||||||
EateryInventoryItemEntity inventoryItem,
|
|
||||||
double requiredQty
|
|
||||||
) {
|
|
||||||
MenuItemIngredientEntity ingredient = MenuItemIngredientEntity.create(
|
|
||||||
this,
|
|
||||||
inventoryItem,
|
|
||||||
requiredQty
|
|
||||||
);
|
|
||||||
|
|
||||||
this.ingredients.add(ingredient);
|
|
||||||
|
|
||||||
this.persist();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Phương thức tiện ích để tạo nhanh Menu Item từ tên
|
* Phương thức tiện ích để tạo nhanh Menu Item từ tên
|
||||||
*/
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
public static MenuItemEntity create(String name, double price) {
|
public static MenuItemEntity create(EateryEntity eatery, String name, double price) {
|
||||||
MenuItemEntity menu = new MenuItemEntity();
|
MenuItemEntity menuItem = new MenuItemEntity();
|
||||||
|
|
||||||
menu.name = name;
|
menuItem.name = name;
|
||||||
menu.price = price;
|
menuItem.price = price;
|
||||||
|
menuItem.eatery = eatery;
|
||||||
|
|
||||||
menu.persist();
|
menuItem.persist();
|
||||||
|
|
||||||
return menu;
|
return menuItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
package com.drinkool.entities;
|
|
||||||
|
|
||||||
import com.drinkool.lib.entities.BaseEntity;
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "menu_item_ingredients")
|
|
||||||
public class MenuItemIngredientEntity extends BaseEntity {
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "menu_item_id")
|
|
||||||
public MenuItemEntity menuItem;
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
|
||||||
@JoinColumn(name = "inventory_item_id")
|
|
||||||
public EateryInventoryItemEntity inventoryItem;
|
|
||||||
|
|
||||||
public double requiredQuantity;
|
|
||||||
|
|
||||||
private MenuItemIngredientEntity() {}
|
|
||||||
|
|
||||||
public static MenuItemIngredientEntity create(
|
|
||||||
MenuItemEntity menuItem,
|
|
||||||
EateryInventoryItemEntity inventoryItem,
|
|
||||||
double requiredQuantity
|
|
||||||
) {
|
|
||||||
MenuItemIngredientEntity ingredient = new MenuItemIngredientEntity();
|
|
||||||
|
|
||||||
ingredient.menuItem = menuItem;
|
|
||||||
ingredient.inventoryItem = inventoryItem;
|
|
||||||
ingredient.requiredQuantity = requiredQuantity;
|
|
||||||
|
|
||||||
ingredient.persist();
|
|
||||||
|
|
||||||
return ingredient;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,19 @@
|
|||||||
package com.drinkool.services;
|
package com.drinkool.services;
|
||||||
|
|
||||||
|
import com.drinkool.InternalValue;
|
||||||
|
import com.drinkool.Role;
|
||||||
import com.drinkool.dtos.event.ManagerCreate;
|
import com.drinkool.dtos.event.ManagerCreate;
|
||||||
import com.drinkool.entities.EateryEntity;
|
import com.drinkool.entities.EateryEntity;
|
||||||
|
import com.drinkool.entities.MenuItemEntity;
|
||||||
|
import io.vertx.core.http.HttpServerRequest;
|
||||||
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import org.eclipse.microprofile.graphql.GraphQLApi;
|
import org.eclipse.microprofile.graphql.GraphQLApi;
|
||||||
|
import org.eclipse.microprofile.graphql.Mutation;
|
||||||
import org.eclipse.microprofile.graphql.Name;
|
import org.eclipse.microprofile.graphql.Name;
|
||||||
import org.eclipse.microprofile.graphql.Query;
|
import org.eclipse.microprofile.graphql.Query;
|
||||||
import org.eclipse.microprofile.reactive.messaging.Incoming;
|
import org.eclipse.microprofile.reactive.messaging.Incoming;
|
||||||
@@ -15,6 +22,9 @@ import org.eclipse.microprofile.reactive.messaging.Incoming;
|
|||||||
@GraphQLApi
|
@GraphQLApi
|
||||||
public class EateryService {
|
public class EateryService {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
HttpServerRequest request;
|
||||||
|
|
||||||
@Incoming("manager-in")
|
@Incoming("manager-in")
|
||||||
@Transactional
|
@Transactional
|
||||||
public void consumeManagerSignup(ManagerCreate input) {
|
public void consumeManagerSignup(ManagerCreate input) {
|
||||||
@@ -32,4 +42,32 @@ public class EateryService {
|
|||||||
public EateryEntity getEatery(@Name("id") UUID id) {
|
public EateryEntity getEatery(@Name("id") UUID id) {
|
||||||
return EateryEntity.findById(id);
|
return EateryEntity.findById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mutation("addMenuItem")
|
||||||
|
@RolesAllowed(Role.Manager)
|
||||||
|
@Transactional
|
||||||
|
public MenuItemEntity addMenuItem(
|
||||||
|
@Name("name") String name,
|
||||||
|
@Name("price") double price
|
||||||
|
) {
|
||||||
|
String ownerId = request.getHeader(InternalValue.userId);
|
||||||
|
|
||||||
|
EateryEntity eatery = EateryEntity.findByOwnerId(ownerId);
|
||||||
|
if (eatery == null) return null;
|
||||||
|
|
||||||
|
MenuItemEntity item = MenuItemEntity.create(eatery, name, price);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query("menuItemsByEatery")
|
||||||
|
public List<MenuItemEntity> getMenuItemsByEatery(
|
||||||
|
@Name("eateryId") UUID eateryId
|
||||||
|
) {
|
||||||
|
EateryEntity eatery = EateryEntity.findById(eateryId);
|
||||||
|
|
||||||
|
if (eatery == null) return List.of();
|
||||||
|
|
||||||
|
return MenuItemEntity.list("eatery", eatery);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.drinkool.services;
|
|
||||||
|
|
||||||
import com.drinkool.dtos.AddInventory;
|
|
||||||
import com.drinkool.entities.InventoryItemEntity;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import jakarta.ws.rs.*;
|
|
||||||
import jakarta.ws.rs.core.Response;
|
|
||||||
|
|
||||||
@Path("/api/inventory")
|
|
||||||
public class InventoryService {
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/create")
|
|
||||||
@Transactional
|
|
||||||
public Response create(AddInventory input) {
|
|
||||||
InventoryItemEntity.create(input.name, input.unit);
|
|
||||||
|
|
||||||
return Response.ok().build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package com.drinkool.entities;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
@QuarkusTest
|
|
||||||
public class EateryInventoryItemEntityTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
void testAdd_WhenItemExists_ShouldUseExistingItem() {
|
|
||||||
String itemName = "Coca Cola";
|
|
||||||
int quantity = 10;
|
|
||||||
|
|
||||||
InventoryItemEntity.create(itemName);
|
|
||||||
|
|
||||||
EateryInventoryItemEntity eateryItem = EateryInventoryItemEntity.create(
|
|
||||||
itemName,
|
|
||||||
quantity,
|
|
||||||
""
|
|
||||||
);
|
|
||||||
|
|
||||||
EateryInventoryItemEntity savedEntity = EateryInventoryItemEntity.find(
|
|
||||||
"id",
|
|
||||||
eateryItem.id
|
|
||||||
).firstResult();
|
|
||||||
assertNotNull(savedEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
void testAdd_WhenItemDoesNotExist_ShouldCreateNewItem() {
|
|
||||||
String itemName = "Pepsi";
|
|
||||||
int quantity = 5;
|
|
||||||
String unit = "Bottle";
|
|
||||||
|
|
||||||
EateryInventoryItemEntity eateryItem = EateryInventoryItemEntity.create(
|
|
||||||
itemName,
|
|
||||||
quantity,
|
|
||||||
unit
|
|
||||||
);
|
|
||||||
|
|
||||||
EateryInventoryItemEntity savedEntity = EateryInventoryItemEntity.find(
|
|
||||||
"id",
|
|
||||||
eateryItem.id
|
|
||||||
).firstResult();
|
|
||||||
assertNotNull(savedEntity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package com.drinkool.entities;
|
|
||||||
|
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
@QuarkusTest
|
|
||||||
public class InventoryItemEntityTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
public void testCreateInventoryItem() {
|
|
||||||
// 1. Chuẩn bị dữ liệu (Lưu ý: Không còn biến quantity nữa)
|
|
||||||
String name = "Trà sữa truyền thống";
|
|
||||||
String unit = "Ly";
|
|
||||||
|
|
||||||
// 2. Gọi hàm static create (Không dùng new hay hàm add nữa)
|
|
||||||
// Hàm này vừa tạo object, vừa gán data, vừa gọi persist() luôn
|
|
||||||
InventoryItemEntity item = InventoryItemEntity.create(name, unit);
|
|
||||||
|
|
||||||
// 3. Kiểm chứng
|
|
||||||
Assertions.assertNotNull(item, "Entity tạo ra không được null");
|
|
||||||
Assertions.assertEquals(name, item.name, "Tên không khớp");
|
|
||||||
Assertions.assertEquals(unit, item.unit, "Đơn vị không khớp");
|
|
||||||
Assertions.assertNotNull(
|
|
||||||
item.id,
|
|
||||||
"ID phải được sinh ra tự động sau khi persist"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
public void testCreateWithDefaultUnit() {
|
|
||||||
// 1. Chuẩn bị dữ liệu
|
|
||||||
String name = "Trân châu đen";
|
|
||||||
|
|
||||||
// 2. Gọi hàm static create rút gọn (chỉ truyền name, unit sẽ tự là "unit")
|
|
||||||
InventoryItemEntity item = InventoryItemEntity.create(name);
|
|
||||||
|
|
||||||
// 3. Kiểm chứng
|
|
||||||
Assertions.assertNotNull(item, "Entity tạo ra không được null");
|
|
||||||
Assertions.assertEquals(name, item.name, "Tên không khớp");
|
|
||||||
Assertions.assertEquals("unit", item.unit, "Unit mặc định phải là 'unit'");
|
|
||||||
Assertions.assertNotNull(
|
|
||||||
item.id,
|
|
||||||
"ID phải được sinh ra tự động sau khi persist"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
package com.drinkool.entities;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
@QuarkusTest
|
|
||||||
public class MenuItemEntityTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
public void testCreateMenuItemSuccessfully() {
|
|
||||||
// 1. Chuẩn bị dữ liệu (Arrange)
|
|
||||||
String name = "Cà phê sữa đá";
|
|
||||||
double price = 29000.0;
|
|
||||||
|
|
||||||
// 2. Thực thi (Act) - Gọi hàm tĩnh create
|
|
||||||
MenuItemEntity menuItem = MenuItemEntity.create(name, price);
|
|
||||||
|
|
||||||
// 3. Kiểm chứng (Assert)
|
|
||||||
assertNotNull(menuItem, "Thực thể MenuItem không được null");
|
|
||||||
assertEquals(name, menuItem.name, "Tên món ăn không khớp");
|
|
||||||
assertEquals(price, menuItem.price, "Giá món ăn không khớp");
|
|
||||||
assertNotNull(menuItem.id, "ID phải được tự động sinh ra sau khi persist");
|
|
||||||
assertTrue(
|
|
||||||
menuItem.ingredients.isEmpty(),
|
|
||||||
"Danh sách nguyên liệu ban đầu phải rỗng"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
public void testAddIngredientSuccessfully() {
|
|
||||||
// 1. Chuẩn bị dữ liệu (Arrange)
|
|
||||||
// Tạo món ăn
|
|
||||||
MenuItemEntity menuItem = MenuItemEntity.create(
|
|
||||||
"Trà sữa trân châu",
|
|
||||||
45000.0
|
|
||||||
);
|
|
||||||
|
|
||||||
// Tạo nguyên liệu trong kho (Dùng đúng hàm add() của EateryInventoryItemEntity như đã fix)
|
|
||||||
EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create(
|
|
||||||
"Trân châu đen",
|
|
||||||
50,
|
|
||||||
"kg"
|
|
||||||
);
|
|
||||||
|
|
||||||
double requiredQty = 0.2; // Cần 0.2 kg trân châu cho 1 ly
|
|
||||||
|
|
||||||
// 2. Thực thi (Act) - Thêm nguyên liệu vào món ăn
|
|
||||||
menuItem.addIngredient(inventoryItem, requiredQty);
|
|
||||||
|
|
||||||
// 3. Kiểm chứng (Assert)
|
|
||||||
// Kiểm tra danh sách nguyên liệu của món ăn
|
|
||||||
assertFalse(
|
|
||||||
menuItem.ingredients.isEmpty(),
|
|
||||||
"Danh sách nguyên liệu không được rỗng sau khi thêm"
|
|
||||||
);
|
|
||||||
assertEquals(
|
|
||||||
1,
|
|
||||||
menuItem.ingredients.size(),
|
|
||||||
"Phải có đúng 1 nguyên liệu trong danh sách"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Lấy phần tử nguyên liệu đầu tiên ra để kiểm tra chi tiết các liên kết
|
|
||||||
MenuItemIngredientEntity addedIngredient = menuItem.ingredients.get(0);
|
|
||||||
|
|
||||||
assertNotNull(
|
|
||||||
addedIngredient.id,
|
|
||||||
"ID của Entity trung gian phải được sinh ra"
|
|
||||||
);
|
|
||||||
assertEquals(
|
|
||||||
menuItem.id,
|
|
||||||
addedIngredient.menuItem.id,
|
|
||||||
"Khóa ngoại MenuItem bị sai"
|
|
||||||
);
|
|
||||||
assertEquals(
|
|
||||||
inventoryItem.id,
|
|
||||||
addedIngredient.inventoryItem.id,
|
|
||||||
"Khóa ngoại InventoryItem bị sai"
|
|
||||||
);
|
|
||||||
assertEquals(
|
|
||||||
requiredQty,
|
|
||||||
addedIngredient.requiredQuantity,
|
|
||||||
"Định lượng (requiredQty) không khớp"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
package com.drinkool.entities;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
@QuarkusTest
|
|
||||||
public class MenuItemIngredientEntityTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
void testCreate_ShouldPersistIngredientSuccessfully() {
|
|
||||||
// 1. Chuẩn bị dữ liệu giả định
|
|
||||||
|
|
||||||
String menuItemName = "Milk Tea";
|
|
||||||
double menuItemPrice = 40;
|
|
||||||
|
|
||||||
MenuItemEntity menuItem = MenuItemEntity.create(
|
|
||||||
menuItemName,
|
|
||||||
menuItemPrice
|
|
||||||
);
|
|
||||||
|
|
||||||
String inventoryItemName = "Water";
|
|
||||||
int inventoryItemQuantity = 10; // Đổi thành int cho khớp với kiểu của EateryInventoryItemEntity
|
|
||||||
String inventoryItemUnit = "l";
|
|
||||||
|
|
||||||
// SỬA Ở ĐÂY: Khởi tạo bằng new và dùng hàm add() đúng như cấu trúc class của bạn
|
|
||||||
EateryInventoryItemEntity inventoryItem = EateryInventoryItemEntity.create(
|
|
||||||
inventoryItemName,
|
|
||||||
inventoryItemQuantity,
|
|
||||||
inventoryItemUnit
|
|
||||||
);
|
|
||||||
// Lưu ý: Hàm add() của bạn đã có sẵn lệnh this.persist() bên trong nên không cần gọi lại nữa!
|
|
||||||
|
|
||||||
double requiredQuantity = 0.5;
|
|
||||||
|
|
||||||
// 2. Gọi hàm static create cần test
|
|
||||||
MenuItemIngredientEntity createdIngredient =
|
|
||||||
MenuItemIngredientEntity.create(
|
|
||||||
menuItem,
|
|
||||||
inventoryItem,
|
|
||||||
requiredQuantity
|
|
||||||
);
|
|
||||||
|
|
||||||
// 3. Kiểm tra kết quả
|
|
||||||
assertNotNull(createdIngredient.id, "ID không được null sau khi persist");
|
|
||||||
|
|
||||||
// Truy vấn lại từ Database để đảm bảo dữ liệu đã được lưu đúng
|
|
||||||
MenuItemIngredientEntity savedEntity = MenuItemIngredientEntity.findById(
|
|
||||||
createdIngredient.id
|
|
||||||
);
|
|
||||||
|
|
||||||
assertNotNull(savedEntity);
|
|
||||||
assertEquals(menuItem.id, savedEntity.menuItem.id);
|
|
||||||
assertEquals(inventoryItem.id, savedEntity.inventoryItem.id);
|
|
||||||
assertEquals(requiredQuantity, savedEntity.requiredQuantity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,11 +2,16 @@ package com.drinkool.services;
|
|||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
import static io.restassured.RestAssured.given;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
import static org.hamcrest.CoreMatchers.notNullValue;
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
import static org.hamcrest.Matchers.hasItems;
|
import static org.hamcrest.Matchers.hasItems;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
|
||||||
|
import com.drinkool.InternalValue;
|
||||||
|
import com.drinkool.Role;
|
||||||
import com.drinkool.dtos.event.ManagerCreate;
|
import com.drinkool.dtos.event.ManagerCreate;
|
||||||
import com.drinkool.entities.EateryEntity;
|
import com.drinkool.entities.EateryEntity;
|
||||||
|
import com.drinkool.entities.MenuItemEntity;
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
import io.quarkus.test.junit.QuarkusTest;
|
||||||
import io.restassured.http.ContentType;
|
import io.restassured.http.ContentType;
|
||||||
import io.smallrye.reactive.messaging.memory.InMemoryConnector;
|
import io.smallrye.reactive.messaging.memory.InMemoryConnector;
|
||||||
@@ -54,21 +59,32 @@ public class EateryServiceTest {
|
|||||||
|
|
||||||
private UUID lastSavedId;
|
private UUID lastSavedId;
|
||||||
private String lastSavedName;
|
private String lastSavedName;
|
||||||
|
private UUID lastOwnerId = UUID.randomUUID();
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@Transactional
|
@Transactional
|
||||||
void setup() {
|
void setup() {
|
||||||
|
MenuItemEntity.deleteAll();
|
||||||
EateryEntity.deleteAll();
|
EateryEntity.deleteAll();
|
||||||
|
|
||||||
lastSavedName = faker.restaurant().name();
|
lastSavedName = faker.restaurant().name();
|
||||||
|
|
||||||
EateryEntity eatery = new EateryEntity();
|
EateryEntity eatery = new EateryEntity();
|
||||||
lastSavedId = eatery.create(UUID.randomUUID(), lastSavedName).id;
|
eatery = eatery.create(lastOwnerId, lastSavedName);
|
||||||
|
lastSavedId = eatery.id;
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
EateryEntity e = new EateryEntity();
|
EateryEntity e = new EateryEntity();
|
||||||
e.create(UUID.randomUUID(), faker.restaurant().name());
|
e.create(UUID.randomUUID(), faker.restaurant().name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
MenuItemEntity.create(
|
||||||
|
eatery,
|
||||||
|
faker.food().dish(),
|
||||||
|
faker.number().randomDouble(2, 10, 100)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -106,4 +122,144 @@ public class EateryServiceTest {
|
|||||||
.statusCode(200)
|
.statusCode(200)
|
||||||
.body("data.eateryById.name", is(lastSavedName));
|
.body("data.eateryById.name", is(lastSavedName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddMenuItemSuccess() {
|
||||||
|
String mutation =
|
||||||
|
"mutation addMenuItem($name: String!, $price: Float!) {" +
|
||||||
|
" addMenuItem(name: $name, price: $price) {" +
|
||||||
|
" id" +
|
||||||
|
" name" +
|
||||||
|
" price" +
|
||||||
|
" }" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
java.util.Map<String, Object> variables = new java.util.HashMap<>();
|
||||||
|
variables.put("name", "Trà Sữa");
|
||||||
|
variables.put("price", 30000.0);
|
||||||
|
|
||||||
|
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||||
|
requestBody.put("query", mutation);
|
||||||
|
requestBody.put("variables", variables);
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.header(InternalValue.role, Role.Manager)
|
||||||
|
.header(InternalValue.userId, lastOwnerId) // Thay "x-user-id" bằng InternalValue.userId của bạn
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/graphql")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.body("data.addMenuItem.name", is("Trà Sữa"))
|
||||||
|
.body("data.addMenuItem.id", notNullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddMenuItemFailInvalidRole() {
|
||||||
|
String mutation =
|
||||||
|
"mutation addMenuItem($name: String!, $price: Float!) {" +
|
||||||
|
" addMenuItem(name: $name, price: $price) {" +
|
||||||
|
" id" +
|
||||||
|
" name" +
|
||||||
|
" price" +
|
||||||
|
" }" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
java.util.Map<String, Object> variables = new java.util.HashMap<>();
|
||||||
|
variables.put("name", "Trà Sữa");
|
||||||
|
variables.put("price", 30000.0);
|
||||||
|
|
||||||
|
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||||
|
requestBody.put("query", mutation);
|
||||||
|
requestBody.put("variables", variables);
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.header(InternalValue.role, Role.Customer)
|
||||||
|
.header(InternalValue.userId, lastOwnerId)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/graphql")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.body("data.addMenuItem.name", is("Trà Sữa"))
|
||||||
|
.body("data.addMenuItem.id", notNullValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddMenuItemFailInvalidOwner() {
|
||||||
|
String mutation =
|
||||||
|
"mutation { addMenuItem(name: \"Coffee\", price: 20000.0) { id } }";
|
||||||
|
|
||||||
|
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||||
|
requestBody.put("query", mutation);
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.header(InternalValue.role, Role.Manager)
|
||||||
|
.header(InternalValue.userId, UUID.randomUUID())
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/graphql")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.body("data.addMenuItem", is((Object) null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMenuItemsByEatery_Success() {
|
||||||
|
String query =
|
||||||
|
"query getItems($id: String!) {" +
|
||||||
|
" menuItemsByEatery(eateryId: $id) {" +
|
||||||
|
" id" +
|
||||||
|
" name" +
|
||||||
|
" price" +
|
||||||
|
" }" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
java.util.Map<String, Object> variables = new java.util.HashMap<>();
|
||||||
|
variables.put("id", lastSavedId.toString());
|
||||||
|
|
||||||
|
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||||
|
requestBody.put("query", query);
|
||||||
|
requestBody.put("variables", variables);
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/graphql")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.body("data.menuItemsByEatery", hasSize(not(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMenuItemsByEatery_NotFound() {
|
||||||
|
String randomId = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
String query =
|
||||||
|
"query getItems($id: String!) {" +
|
||||||
|
" menuItemsByEatery(eateryId: $id) {" +
|
||||||
|
" id" +
|
||||||
|
" }" +
|
||||||
|
"}";
|
||||||
|
|
||||||
|
java.util.Map<String, Object> variables = new java.util.HashMap<>();
|
||||||
|
variables.put("id", randomId);
|
||||||
|
|
||||||
|
java.util.Map<String, Object> requestBody = new java.util.HashMap<>();
|
||||||
|
requestBody.put("query", query);
|
||||||
|
requestBody.put("variables", variables);
|
||||||
|
|
||||||
|
given()
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.body(requestBody)
|
||||||
|
.when()
|
||||||
|
.post("/graphql")
|
||||||
|
.then()
|
||||||
|
.statusCode(200)
|
||||||
|
.body("data.menuItemsByEatery", hasSize(0)); // Phải trả về List rỗng như code bạn viết
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.drinkool.services;
|
|
||||||
|
|
||||||
import static io.restassured.RestAssured.given;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
import com.drinkool.dtos.AddInventory;
|
|
||||||
import com.drinkool.entities.InventoryItemEntity;
|
|
||||||
import io.quarkus.test.junit.QuarkusTest;
|
|
||||||
import io.restassured.http.ContentType;
|
|
||||||
import java.util.UUID;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
@QuarkusTest
|
|
||||||
public class InventoryServiceTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void add() {
|
|
||||||
String name = UUID.randomUUID().toString();
|
|
||||||
|
|
||||||
AddInventory input = new AddInventory();
|
|
||||||
input.name = name;
|
|
||||||
|
|
||||||
given()
|
|
||||||
.contentType(ContentType.JSON)
|
|
||||||
.body(input)
|
|
||||||
.when()
|
|
||||||
.post("/api/inventory/create")
|
|
||||||
.then();
|
|
||||||
|
|
||||||
assertEquals(1, InventoryItemEntity.find("name", name).count());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.drinkool.controller;
|
package com.drinkool.controller;
|
||||||
|
|
||||||
|
import com.drinkool.dtos.GraphqlDto;
|
||||||
import io.smallrye.graphql.client.GraphQLClient;
|
import io.smallrye.graphql.client.GraphQLClient;
|
||||||
import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient;
|
import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient;
|
||||||
import jakarta.ws.rs.POST;
|
import jakarta.ws.rs.POST;
|
||||||
@@ -15,10 +16,11 @@ public class EateryController {
|
|||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Path("/graphql")
|
@Path("/graphql")
|
||||||
public Response forward(String query)
|
public Response forward(GraphqlDto gqlRequest)
|
||||||
throws ExecutionException, InterruptedException {
|
throws ExecutionException, InterruptedException {
|
||||||
io.smallrye.graphql.client.Response response = dynamicClient.executeSync(
|
io.smallrye.graphql.client.Response response = dynamicClient.executeSync(
|
||||||
query
|
gqlRequest.query,
|
||||||
|
gqlRequest.variables
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.hasError()) {
|
if (response.hasError()) {
|
||||||
|
|||||||
+6
-1
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project
|
<project
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
@@ -21,6 +21,11 @@
|
|||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-security</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-annotations</artifactId>
|
<artifactId>jackson-annotations</artifactId>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package com.drinkool.dtos;
|
||||||
|
|
||||||
|
public class GraphqlDto {
|
||||||
|
|
||||||
|
public String query;
|
||||||
|
public java.util.Map<String, Object> variables;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.drinkool.lib.utils;
|
||||||
|
|
||||||
|
import com.drinkool.InternalValue;
|
||||||
|
import io.quarkus.security.identity.AuthenticationRequestContext;
|
||||||
|
import io.quarkus.security.identity.IdentityProvider;
|
||||||
|
import io.quarkus.security.identity.SecurityIdentity;
|
||||||
|
import io.quarkus.security.identity.request.TrustedAuthenticationRequest;
|
||||||
|
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
|
||||||
|
import io.smallrye.mutiny.Uni;
|
||||||
|
import io.vertx.core.http.HttpServerRequest;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class HeaderIdentityProvider
|
||||||
|
implements IdentityProvider<TrustedAuthenticationRequest>
|
||||||
|
{
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
HttpServerRequest httpServerRequest;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<TrustedAuthenticationRequest> getRequestType() {
|
||||||
|
return TrustedAuthenticationRequest.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Uni<SecurityIdentity> authenticate(
|
||||||
|
TrustedAuthenticationRequest request,
|
||||||
|
AuthenticationRequestContext context
|
||||||
|
) {
|
||||||
|
String role = httpServerRequest.getHeader(InternalValue.role);
|
||||||
|
|
||||||
|
return Uni.createFrom().item(
|
||||||
|
QuarkusSecurityIdentity.builder().addRole(role).build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user