Compare commits

...

2 Commits

Author SHA1 Message Date
TakahashiNguyen 43600fc8cf fix: menu items CRUD (#44)
Release package / release (push) Successful in 14m26s
Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com>
Reviewed-on: #44
2026-05-06 15:10:31 +00:00
gitea-actions a6ec0c39c5 chore: release [ci skip] 2026-05-05 04:16:54 +00:00
53 changed files with 453 additions and 111 deletions
+11 -11
View File
@@ -23,6 +23,17 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Install dependencies with Proxy
env:
http_proxy: "http://host.docker.internal:3142"
https_proxy: "http://host.docker.internal:3142"
run: |
# Kiểm tra proxy có hoạt động không
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
- uses: shogo82148/actions-setup-redis@v1 - uses: shogo82148/actions-setup-redis@v1
with: with:
redis-version: "7.x" redis-version: "7.x"
@@ -38,17 +49,6 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-maven- ${{ runner.os }}-maven-
- name: Install dependencies with Proxy
env:
http_proxy: "http://host.docker.internal:3142"
https_proxy: "http://host.docker.internal:3142"
run: |
# Kiểm tra proxy có hoạt động không
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
- name: Build and Test all module - name: Build and Test all module
env: env:
TESTCONTAINERS_RYUK_DISABLED: true TESTCONTAINERS_RYUK_DISABLED: true
-1
View File
@@ -22,7 +22,6 @@ bin/
nb-configuration.xml nb-configuration.xml
# Visual Studio Code # Visual Studio Code
.vscode
.factorypath .factorypath
*.rdb *.rdb
+15
View File
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Attach to Quarkus",
"request": "attach",
"hostName": "localhost",
"port": 5005
}
]
}
+13
View File
@@ -0,0 +1,13 @@
{
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/.DS_Store": true,
"**/Thumbs.db": true,
"**/target": true,
"**/docker": true,
"node_modules": true
},
"explorerExclude.backup": {}
}
+7
View File
@@ -1,3 +1,10 @@
## [1.5.19](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.18...v1.5.19) (2026-05-05)
### Bug Fixes
* better graphql response type for native ([#43](https://git.demonkernel.io.vn/FoodSurf/backend/issues/43)) ([b401627](https://git.demonkernel.io.vn/FoodSurf/backend/commit/b4016275063da592a6990a86cf8652b81a63c068))
## [1.5.18](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.17...v1.5.18) (2026-05-04) ## [1.5.18](https://git.demonkernel.io.vn/FoodSurf/backend/compare/v1.5.17...v1.5.18) (2026-05-04)
+1 -1
View File
@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>com.drinkool</groupId> <groupId>com.drinkool</groupId>
<artifactId>drinkool</artifactId> <artifactId>drinkool</artifactId>
<version>1.5.18</version> <version>1.5.19</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@@ -2,8 +2,8 @@ package com.drinkool.services;
import com.drinkool.Role; import com.drinkool.Role;
import com.drinkool.Url; import com.drinkool.Url;
import com.drinkool.dtos.SmsOtp;
import com.drinkool.entities.ManagerEntity; import com.drinkool.entities.ManagerEntity;
import com.drinkool.lib.dtos.SmsOtp;
import com.drinkool.models.UserModel; import com.drinkool.models.UserModel;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
@@ -1,8 +1,9 @@
package com.drinkool.services; package com.drinkool.services;
import com.drinkool.*; import com.drinkool.*;
import com.drinkool.dtos.*;
import com.drinkool.entities.CustomerEntity; import com.drinkool.entities.CustomerEntity;
import com.drinkool.lib.dtos.*;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
@@ -1,9 +1,10 @@
package com.drinkool.services; package com.drinkool.services;
import com.drinkool.*; import com.drinkool.*;
import com.drinkool.dtos.*;
import com.drinkool.dtos.event.ManagerCreate;
import com.drinkool.entities.ManagerEntity; import com.drinkool.entities.ManagerEntity;
import com.drinkool.lib.dtos.*;
import com.drinkool.lib.dtos.event.ManagerCreate;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
@@ -3,7 +3,8 @@ package com.drinkool.services;
import static io.restassured.RestAssured.*; import static io.restassured.RestAssured.*;
import com.drinkool.*; import com.drinkool.*;
import com.drinkool.dtos.*; import com.drinkool.lib.dtos.*;
import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -4,7 +4,8 @@ import static io.restassured.RestAssured.*;
import static org.hamcrest.CoreMatchers.*; import static org.hamcrest.CoreMatchers.*;
import com.drinkool.*; import com.drinkool.*;
import com.drinkool.dtos.*; import com.drinkool.lib.dtos.*;
import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -4,8 +4,9 @@ import static io.restassured.RestAssured.*;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import com.drinkool.*; import com.drinkool.*;
import com.drinkool.dtos.*;
import com.drinkool.entities.CustomerEntity; import com.drinkool.entities.CustomerEntity;
import com.drinkool.lib.dtos.*;
import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import jakarta.inject.Inject; import jakarta.inject.Inject;
@@ -4,7 +4,8 @@ import static io.restassured.RestAssured.*;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import com.drinkool.*; import com.drinkool.*;
import com.drinkool.dtos.*; import com.drinkool.lib.dtos.*;
import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.kafka.*; import io.quarkus.test.kafka.*;
+31 -1
View File
@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>com.drinkool</groupId> <groupId>com.drinkool</groupId>
<artifactId>drinkool</artifactId> <artifactId>drinkool</artifactId>
<version>1.5.18</version> <version>1.5.19</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@@ -28,6 +28,8 @@
<quarkus.platform.version>3.32.4</quarkus.platform.version> <quarkus.platform.version>3.32.4</quarkus.platform.version>
<skipITs>true</skipITs> <skipITs>true</skipITs>
<surefire-plugin.version>3.5.4</surefire-plugin.version> <surefire-plugin.version>3.5.4</surefire-plugin.version>
<org.mapstruct.version>1.6.3</org.mapstruct.version>
<org.projectlombok.version>1.18.46</org.projectlombok.version>
</properties> </properties>
<dependencyManagement> <dependencyManagement>
@@ -53,6 +55,22 @@
<artifactId>quarkus-security</artifactId> <artifactId>quarkus-security</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.quarkiverse.mapstruct</groupId>
<artifactId>quarkus-mapstruct</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency> <dependency>
<groupId>net.datafaker</groupId> <groupId>net.datafaker</groupId>
<artifactId>datafaker</artifactId> <artifactId>datafaker</artifactId>
@@ -135,6 +153,18 @@
<version>${compiler-plugin.version}</version> <version>${compiler-plugin.version}</version>
<configuration> <configuration>
<parameters>true</parameters> <parameters>true</parameters>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
</annotationProcessorPaths>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
@@ -0,0 +1,25 @@
package com.drinkool.dtos;
import com.drinkool.interfaces.MenuItemInterface;
import io.quarkus.runtime.annotations.RegisterForReflection;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.microprofile.graphql.Input;
import org.eclipse.microprofile.graphql.NonNull;
@Input
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@RegisterForReflection
public class AddMenuItem implements MenuItemInterface {
@NonNull
private String name;
@NonNull
private Double price;
}
@@ -0,0 +1,18 @@
package com.drinkool.dtos;
import com.drinkool.entities.MenuItemEntity;
import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import org.mapstruct.NullValuePropertyMappingStrategy;
@Mapper(componentModel = "cdi")
public interface DtoMapper {
@BeanMapping(
nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE
)
void updateMenuItemToEntity(
UpdateMenuItem input,
@MappingTarget MenuItemEntity entity
);
}
@@ -0,0 +1,28 @@
package com.drinkool.dtos;
import com.drinkool.interfaces.EntityInterface;
import com.drinkool.interfaces.MenuItemInterface;
import io.quarkus.runtime.annotations.RegisterForReflection;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.eclipse.microprofile.graphql.Input;
import org.eclipse.microprofile.graphql.NonNull;
@Input
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@RegisterForReflection
public class UpdateMenuItem implements EntityInterface, MenuItemInterface {
@NonNull
UUID id;
String name;
Double price;
}
@@ -25,7 +25,7 @@ public class EateryEntity extends BaseEntity {
cascade = CascadeType.ALL, cascade = CascadeType.ALL,
orphanRemoval = true orphanRemoval = true
) )
public List<MenuItemEntity> menus = new ArrayList<>(); public List<MenuItemEntity> menuItems = new ArrayList<>();
public EateryEntity() {} public EateryEntity() {}
@@ -1,36 +1,43 @@
package com.drinkool.entities; package com.drinkool.entities;
import com.drinkool.dtos.AddMenuItem;
import com.drinkool.interfaces.MenuItemInterface;
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 lombok.Getter;
import lombok.Setter;
@Entity @Entity
@Table @Table
public class MenuItemEntity extends BaseEntity { @Getter
@Setter
public class MenuItemEntity extends BaseEntity implements MenuItemInterface {
@Column(nullable = false) @Column(nullable = false)
public String name; public String name;
@Column(nullable = false) @Column(nullable = false)
public double price; public Double price;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "eatery_id") @JoinColumn(name = "eatery_id")
public EateryEntity eatery; public EateryEntity eatery;
MenuItemEntity() {}
MenuItemEntity(MenuItemInterface input) {
this.setName(input.getName());
this.setPrice(input.getPrice());
}
/** /**
* 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( public static MenuItemEntity create(EateryEntity eatery, AddMenuItem input) {
EateryEntity eatery, MenuItemEntity menuItem = new MenuItemEntity(input);
String name,
double price
) {
MenuItemEntity menuItem = new MenuItemEntity();
menuItem.name = name;
menuItem.price = price;
menuItem.eatery = eatery; menuItem.eatery = eatery;
menuItem.persist(); menuItem.persist();
@@ -2,9 +2,12 @@ package com.drinkool.services;
import com.drinkool.InternalValue; import com.drinkool.InternalValue;
import com.drinkool.Role; import com.drinkool.Role;
import com.drinkool.dtos.event.ManagerCreate; import com.drinkool.dtos.AddMenuItem;
import com.drinkool.dtos.DtoMapper;
import com.drinkool.dtos.UpdateMenuItem;
import com.drinkool.entities.EateryEntity; import com.drinkool.entities.EateryEntity;
import com.drinkool.entities.MenuItemEntity; import com.drinkool.entities.MenuItemEntity;
import com.drinkool.lib.dtos.event.ManagerCreate;
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;
@@ -22,6 +25,9 @@ import org.eclipse.microprofile.reactive.messaging.Incoming;
@GraphQLApi @GraphQLApi
public class EateryService { public class EateryService {
@Inject
DtoMapper dtoMapper;
@Inject @Inject
HttpServerRequest request; HttpServerRequest request;
@@ -46,20 +52,57 @@ public class EateryService {
@Mutation("addMenuItem") @Mutation("addMenuItem")
@RolesAllowed(Role.Manager) @RolesAllowed(Role.Manager)
@Transactional @Transactional
public MenuItemEntity addMenuItem( public MenuItemEntity addMenuItem(@Name("menuItem") AddMenuItem menuItem) {
@Name("name") String name,
@Name("price") double price
) {
String ownerId = request.getHeader(InternalValue.userId); String ownerId = request.getHeader(InternalValue.userId);
EateryEntity eatery = EateryEntity.findByOwnerId(ownerId); EateryEntity eatery = EateryEntity.findByOwnerId(ownerId);
if (eatery == null) return null; if (eatery == null) return null;
MenuItemEntity item = MenuItemEntity.create(eatery, name, price); MenuItemEntity item = MenuItemEntity.create(eatery, menuItem);
return item; return item;
} }
@Mutation("updateMenuItem")
@RolesAllowed(Role.Manager)
@Transactional
public MenuItemEntity updateMenuItem(UpdateMenuItem menuItem) {
UUID ownerId = UUID.fromString(request.getHeader(InternalValue.userId));
MenuItemEntity item = MenuItemEntity.find(
"id = ?1 and eatery.ownerId = ?2",
menuItem.getId(),
ownerId
).firstResult();
if (item == null) return null;
dtoMapper.updateMenuItemToEntity(menuItem, item);
item.persist();
return item;
}
@Mutation("deleteMenuItem")
@RolesAllowed(Role.Manager)
@Transactional
public boolean deleteMenuItem(@Name("menuItemId") UUID menuItemId) {
UUID ownerId = UUID.fromString(request.getHeader(InternalValue.userId));
MenuItemEntity item = MenuItemEntity.find(
"id = ?1 and eatery.ownerId = ?2",
menuItemId,
ownerId
).firstResult();
if (item == null) return false;
item.delete();
return true;
}
@Query("menuItemsByEatery") @Query("menuItemsByEatery")
public List<MenuItemEntity> getMenuItemsByEatery( public List<MenuItemEntity> getMenuItemsByEatery(
@Name("eateryId") UUID eateryId @Name("eateryId") UUID eateryId
@@ -1,7 +1,8 @@
package com.drinkool.services; package com.drinkool.services;
import com.drinkool.dtos.SendReview;
import com.drinkool.entities.ReviewEntity; import com.drinkool.entities.ReviewEntity;
import com.drinkool.lib.dtos.SendReview;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
@@ -27,7 +27,8 @@ quarkus.native.remote-container-build=true
quarkus.native.additional-build-args=--future-defaults=all quarkus.native.additional-build-args=--future-defaults=all
# Kafka # Kafka
mp.messaging.connector.smallrye-kafka.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST:host.docker.internal}:9092 %prod.mp.messaging.connector.smallrye-kafka.bootstrap.servers=${KAFKA_SERVICE_SERVICE_HOST:host.docker.internal}:9092
mp.messaging.incoming.manager-in.connector=smallrye-in-memory
## Create restaurant topic ## Create restaurant topic
mp.messaging.incoming.manager-in.connector=smallrye-kafka mp.messaging.incoming.manager-in.connector=smallrye-kafka
@@ -9,9 +9,10 @@ import static org.hamcrest.Matchers.hasSize;
import com.drinkool.InternalValue; import com.drinkool.InternalValue;
import com.drinkool.Role; import com.drinkool.Role;
import com.drinkool.dtos.event.ManagerCreate; import com.drinkool.dtos.AddMenuItem;
import com.drinkool.entities.EateryEntity; import com.drinkool.entities.EateryEntity;
import com.drinkool.entities.MenuItemEntity; import com.drinkool.entities.MenuItemEntity;
import com.drinkool.lib.dtos.event.ManagerCreate;
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;
@@ -19,6 +20,8 @@ import jakarta.enterprise.context.control.ActivateRequestContext;
import jakarta.enterprise.inject.Any; import jakarta.enterprise.inject.Any;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import net.datafaker.Faker; import net.datafaker.Faker;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
@@ -57,9 +60,10 @@ public class EateryServiceTest {
Assertions.assertEquals("Quan Bun Cha Test", eatery.name); Assertions.assertEquals("Quan Bun Cha Test", eatery.name);
} }
private UUID lastSavedId; private UUID savedEateryId;
private String lastSavedName; private String savedEateryName;
private UUID lastOwnerId = UUID.randomUUID(); private UUID savedOwnerId = UUID.randomUUID();
private UUID savedMenuItemId;
@BeforeEach @BeforeEach
@Transactional @Transactional
@@ -67,11 +71,11 @@ public class EateryServiceTest {
MenuItemEntity.deleteAll(); MenuItemEntity.deleteAll();
EateryEntity.deleteAll(); EateryEntity.deleteAll();
lastSavedName = faker.restaurant().name(); savedEateryName = faker.restaurant().name();
EateryEntity eatery = new EateryEntity(); EateryEntity eatery = new EateryEntity();
eatery = eatery.create(lastOwnerId, lastSavedName); eatery = eatery.create(savedOwnerId, savedEateryName);
lastSavedId = eatery.id; savedEateryId = eatery.id;
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
EateryEntity e = new EateryEntity(); EateryEntity e = new EateryEntity();
@@ -79,11 +83,13 @@ public class EateryServiceTest {
} }
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
MenuItemEntity.create( savedMenuItemId = MenuItemEntity.create(
eatery, eatery,
faker.food().dish(), new AddMenuItem(
faker.number().randomDouble(2, 10, 100) faker.food().dish(),
); faker.number().randomDouble(2, 10, 100)
)
).id;
} }
} }
@@ -101,7 +107,7 @@ public class EateryServiceTest {
.statusCode(200) .statusCode(200)
// GraphQL trả về dữ liệu bọc trong object "data" // GraphQL trả về dữ liệu bọc trong object "data"
.body("data.allEateries", notNullValue()) .body("data.allEateries", notNullValue())
.body("data.allEateries.name", hasItems(lastSavedName)); .body("data.allEateries.name", hasItems(savedEateryName));
} }
@Test @Test
@@ -110,7 +116,7 @@ public class EateryServiceTest {
// Lưu ý: Trong GraphQL, String/UUID phải nằm trong dấu ngoặc kép // Lưu ý: Trong GraphQL, String/UUID phải nằm trong dấu ngoặc kép
String query = String.format( String query = String.format(
"{ \"query\": \"{ eateryById(id: \\\"%s\\\") { ownerId name } }\" }", "{ \"query\": \"{ eateryById(id: \\\"%s\\\") { ownerId name } }\" }",
lastSavedId savedEateryId
); );
given() given()
@@ -120,32 +126,35 @@ public class EateryServiceTest {
.post("/graphql") .post("/graphql")
.then() .then()
.statusCode(200) .statusCode(200)
.body("data.eateryById.name", is(lastSavedName)); .body("data.eateryById.name", is(savedEateryName));
} }
@Test @Test
public void testAddMenuItemSuccess() { public void testAddMenuItemSuccess() {
String mutation = String mutation =
"mutation addMenuItem($name: String!, $price: Float!) {" + "mutation addMenuItem($menuItem: AddMenuItemInput!) {" +
" addMenuItem(name: $name, price: $price) {" + " addMenuItem(menuItem: $menuItem) {" +
" id" + " id" +
" name" + " name" +
" price" + " price" +
" }" + " }" +
"}"; "}";
java.util.Map<String, Object> variables = new java.util.HashMap<>(); Map<String, Object> menuItemData = new HashMap<>();
variables.put("name", "Trà Sữa"); menuItemData.put("name", "Trà Sữa");
variables.put("price", 30000.0); menuItemData.put("price", 30000.0);
java.util.Map<String, Object> requestBody = new java.util.HashMap<>(); Map<String, Object> variables = new HashMap<>();
variables.put("menuItem", menuItemData);
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", mutation); requestBody.put("query", mutation);
requestBody.put("variables", variables); requestBody.put("variables", variables);
given() given()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.header(InternalValue.role, Role.Manager) .header(InternalValue.role, Role.Manager)
.header(InternalValue.userId, lastOwnerId) // Thay "x-user-id" bằng InternalValue.userId của bạn .header(InternalValue.userId, savedOwnerId) // Thay "x-user-id" bằng InternalValue.userId của bạn
.body(requestBody) .body(requestBody)
.when() .when()
.post("/graphql") .post("/graphql")
@@ -158,26 +167,29 @@ public class EateryServiceTest {
@Test @Test
public void testAddMenuItemFailInvalidRole() { public void testAddMenuItemFailInvalidRole() {
String mutation = String mutation =
"mutation addMenuItem($name: String!, $price: Float!) {" + "mutation addMenuItem($menuItem: AddMenuItemInput!) {" +
" addMenuItem(name: $name, price: $price) {" + " addMenuItem(menuItem: $menuItem) {" +
" id" + " id" +
" name" + " name" +
" price" + " price" +
" }" + " }" +
"}"; "}";
java.util.Map<String, Object> variables = new java.util.HashMap<>(); Map<String, Object> menuItemData = new HashMap<>();
variables.put("name", "Trà Sữa"); menuItemData.put("name", "Trà Sữa");
variables.put("price", 30000.0); menuItemData.put("price", 30000.0);
java.util.Map<String, Object> requestBody = new java.util.HashMap<>(); Map<String, Object> variables = new HashMap<>();
variables.put("menuItem", menuItemData);
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", mutation); requestBody.put("query", mutation);
requestBody.put("variables", variables); requestBody.put("variables", variables);
given() given()
.contentType(ContentType.JSON) .contentType(ContentType.JSON)
.header(InternalValue.role, Role.Customer) .header(InternalValue.role, Role.Customer)
.header(InternalValue.userId, lastOwnerId) .header(InternalValue.userId, savedOwnerId)
.body(requestBody) .body(requestBody)
.when() .when()
.post("/graphql") .post("/graphql")
@@ -190,7 +202,7 @@ public class EateryServiceTest {
String mutation = String mutation =
"mutation { addMenuItem(name: \"Coffee\", price: 20000.0) { id } }"; "mutation { addMenuItem(name: \"Coffee\", price: 20000.0) { id } }";
java.util.Map<String, Object> requestBody = new java.util.HashMap<>(); Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", mutation); requestBody.put("query", mutation);
given() given()
@@ -216,10 +228,10 @@ public class EateryServiceTest {
" }" + " }" +
"}"; "}";
java.util.Map<String, Object> variables = new java.util.HashMap<>(); Map<String, Object> variables = new HashMap<>();
variables.put("id", lastSavedId.toString()); variables.put("id", savedEateryId.toString());
java.util.Map<String, Object> requestBody = new java.util.HashMap<>(); Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", query); requestBody.put("query", query);
requestBody.put("variables", variables); requestBody.put("variables", variables);
@@ -244,10 +256,10 @@ public class EateryServiceTest {
" }" + " }" +
"}"; "}";
java.util.Map<String, Object> variables = new java.util.HashMap<>(); Map<String, Object> variables = new HashMap<>();
variables.put("id", randomId); variables.put("id", randomId);
java.util.Map<String, Object> requestBody = new java.util.HashMap<>(); Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", query); requestBody.put("query", query);
requestBody.put("variables", variables); requestBody.put("variables", variables);
@@ -260,4 +272,69 @@ public class EateryServiceTest {
.statusCode(200) .statusCode(200)
.body("data.menuItemsByEatery", hasSize(0)); // Phải trả về List rỗng như code bạn viết .body("data.menuItemsByEatery", hasSize(0)); // Phải trả về List rỗng như code bạn viết
} }
@Test
public void testUpdateMenuItem_Success() {
String mutation = """
mutation updateMenuItem($menuItem: UpdateMenuItemInput!) {
updateMenuItem(menuItem: $menuItem) {
id
name
price
}
}
""";
String newValue = "Phở Bò";
Map<String, Object> menuItemData = new HashMap<>();
menuItemData.put("id", savedMenuItemId);
menuItemData.put("name", newValue);
Map<String, Object> variables = new HashMap<>();
variables.put("menuItem", menuItemData);
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", mutation);
requestBody.put("variables", variables);
given()
.contentType(ContentType.JSON)
.header(InternalValue.role, Role.Manager)
.header(InternalValue.userId, savedOwnerId)
.body(requestBody)
.when()
.post("/graphql")
.then()
.body("data.updateMenuItem.name", is(newValue))
.body("data.updateMenuItem.id", is(savedMenuItemId.toString()))
.statusCode(200);
}
@Test
public void testDeleteMenuItem_Success() {
String mutation = """
mutation deleteItem($input: String!) {
deleteMenuItem(menuItemId: $input)
}
""";
Map<String, Object> variables = new HashMap<>();
variables.put("input", savedMenuItemId.toString());
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("query", mutation);
requestBody.put("variables", variables);
given()
.contentType(ContentType.JSON)
.header(InternalValue.role, Role.Manager)
.header(InternalValue.userId, savedOwnerId)
.body(requestBody)
.when()
.post("/graphql")
.then()
.statusCode(200)
.body("data.deleteMenuItem", is(true));
}
} }
@@ -3,8 +3,8 @@ package com.drinkool.services;
import static io.restassured.RestAssured.given; import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import com.drinkool.dtos.SendReview;
import com.drinkool.entities.ReviewEntity; import com.drinkool.entities.ReviewEntity;
import com.drinkool.lib.dtos.SendReview;
import com.drinkool.lib.models.ReviewModel; import com.drinkool.lib.models.ReviewModel;
import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.junit.QuarkusTest;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
+1 -1
View File
@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>com.drinkool</groupId> <groupId>com.drinkool</groupId>
<artifactId>drinkool</artifactId> <artifactId>drinkool</artifactId>
<version>1.5.18</version> <version>1.5.19</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@@ -1,7 +1,7 @@
package com.drinkool.controller; package com.drinkool.controller;
import com.drinkool.*; import com.drinkool.*;
import com.drinkool.dtos.*; import com.drinkool.lib.dtos.*;
import com.drinkool.services.CustomerService; import com.drinkool.services.CustomerService;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject; import jakarta.inject.Inject;
@@ -1,18 +1,19 @@
package com.drinkool.controller; package com.drinkool.controller;
import com.drinkool.InternalValue; import com.drinkool.InternalValue;
import com.drinkool.dtos.GraphqlDto; import com.drinkool.lib.dtos.GraphqlDto;
import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClient;
import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder; import io.smallrye.graphql.client.dynamic.api.DynamicGraphQLClientBuilder;
import jakarta.inject.Inject;
import jakarta.json.bind.Jsonb;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.config.inject.ConfigProperty;
import jakarta.inject.Inject;
import jakarta.json.bind.Jsonb;
import jakarta.ws.rs.core.MediaType;
@Path("/api/eatery") @Path("/api/eatery")
public class EateryController { public class EateryController {
@@ -21,7 +22,7 @@ public class EateryController {
String eateryUrl; String eateryUrl;
@Inject @Inject
Jsonb jsonb; Jsonb jsonb;
@POST @POST
@Path("/graphql") @Path("/graphql")
@@ -51,12 +52,14 @@ public class EateryController {
); );
if (response.hasError()) { if (response.hasError()) {
return Response.status(400).entity(jsonb.toJson(response.getErrors())).build(); return Response.status(400)
.entity(jsonb.toJson(response.getErrors()))
.build();
} }
return Response.ok(jsonb.toJson(response.getData())) return Response.ok(jsonb.toJson(response.getData()))
.type(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON)
.build(); .build();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return Response.serverError() return Response.serverError()
@@ -1,7 +1,7 @@
package com.drinkool.controller; package com.drinkool.controller;
import com.drinkool.Url; import com.drinkool.Url;
import com.drinkool.dtos.SmsOtp; import com.drinkool.lib.dtos.SmsOtp;
import com.drinkool.services.BaseService; import com.drinkool.services.BaseService;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject; import jakarta.inject.Inject;
@@ -1,7 +1,7 @@
package com.drinkool.controller; package com.drinkool.controller;
import com.drinkool.Url; import com.drinkool.Url;
import com.drinkool.dtos.Login; import com.drinkool.lib.dtos.Login;
import com.drinkool.services.CustomerService; import com.drinkool.services.CustomerService;
import com.drinkool.services.ManagerService; import com.drinkool.services.ManagerService;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
@@ -1,7 +1,7 @@
package com.drinkool.controller; package com.drinkool.controller;
import com.drinkool.*; import com.drinkool.*;
import com.drinkool.dtos.*; import com.drinkool.lib.dtos.*;
import com.drinkool.services.ManagerService; import com.drinkool.services.ManagerService;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject; import jakarta.inject.Inject;
@@ -1,7 +1,8 @@
package com.drinkool.services; package com.drinkool.services;
import com.drinkool.Url; import com.drinkool.Url;
import com.drinkool.dtos.SmsOtp; import com.drinkool.lib.dtos.SmsOtp;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.POST; import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path; import jakarta.ws.rs.Path;
@@ -3,7 +3,8 @@ package com.drinkool.services;
import com.drinkool.InternalValue; import com.drinkool.InternalValue;
import com.drinkool.Role; import com.drinkool.Role;
import com.drinkool.Url; import com.drinkool.Url;
import com.drinkool.dtos.*; import com.drinkool.lib.dtos.*;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
@@ -3,7 +3,8 @@ package com.drinkool.services;
import com.drinkool.InternalValue; import com.drinkool.InternalValue;
import com.drinkool.Role; import com.drinkool.Role;
import com.drinkool.Url; import com.drinkool.Url;
import com.drinkool.dtos.*; import com.drinkool.lib.dtos.*;
import io.smallrye.mutiny.Uni; import io.smallrye.mutiny.Uni;
import jakarta.ws.rs.*; import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Response;
+1 -1
View File
@@ -14,7 +14,7 @@ spec:
spec: spec:
containers: containers:
- name: account-pod - name: account-pod
image: git.demonkernel.io.vn/foodsurf/account-service:1.5.18 image: git.demonkernel.io.vn/foodsurf/account-service:1.5.19
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 8080 - containerPort: 8080
+1 -1
View File
@@ -14,7 +14,7 @@ spec:
spec: spec:
containers: containers:
- name: eatery-pod - name: eatery-pod
image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.18 image: git.demonkernel.io.vn/foodsurf/eatery-service:1.5.19
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 8080 - containerPort: 8080
+1 -1
View File
@@ -14,7 +14,7 @@ spec:
spec: spec:
containers: containers:
- name: gateway-pod - name: gateway-pod
image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.18 image: git.demonkernel.io.vn/foodsurf/gateway-service:1.5.19
imagePullPolicy: IfNotPresent imagePullPolicy: IfNotPresent
ports: ports:
- containerPort: 8080 - containerPort: 8080
+6 -2
View File
@@ -9,7 +9,7 @@
<parent> <parent>
<groupId>com.drinkool</groupId> <groupId>com.drinkool</groupId>
<artifactId>drinkool</artifactId> <artifactId>drinkool</artifactId>
<version>1.5.18</version> <version>1.5.19</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@@ -41,7 +41,7 @@
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.30</version> <version>1.18.46</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -62,5 +62,9 @@
<version>5.10.0</version> <version>5.10.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-graphql</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>
@@ -0,0 +1,12 @@
package com.drinkool.interfaces;
import java.util.UUID;
public interface EateryInterface {
UUID getOwnerId();
void setOwnerId(UUID x);
String getName();
void setName(String x);
boolean getIsVerified();
void setIsVerified(boolean x);
}
@@ -0,0 +1,8 @@
package com.drinkool.interfaces;
import java.util.UUID;
public interface EntityInterface {
UUID getId();
void setId(UUID x);
}
@@ -0,0 +1,8 @@
package com.drinkool.interfaces;
public interface MenuItemInterface {
String getName();
void setName(String x);
Double getPrice();
void setPrice(Double x);
}
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
public class AddInventory { public class AddInventory {
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
public class GraphqlDto { public class GraphqlDto {
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
public class Login { public class Login {
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
public class ManagerSignup extends Signup { public class ManagerSignup extends Signup {
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
public class QuickLogin { public class QuickLogin {
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
public class QuickSignup { public class QuickSignup {
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
import com.drinkool.lib.models.ReviewModel; import com.drinkool.lib.models.ReviewModel;
import java.util.UUID; import java.util.UUID;
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
public class Signup { public class Signup {
@@ -1,4 +1,4 @@
package com.drinkool.dtos; package com.drinkool.lib.dtos;
public class SmsOtp { public class SmsOtp {
@@ -1,4 +1,4 @@
package com.drinkool.dtos.event; package com.drinkool.lib.dtos.event;
import io.quarkus.runtime.annotations.RegisterForReflection; import io.quarkus.runtime.annotations.RegisterForReflection;
import java.util.UUID; import java.util.UUID;
@@ -1,13 +1,15 @@
package com.drinkool.lib.entities; package com.drinkool.lib.entities;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase; import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import jakarta.persistence.*; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.MappedSuperclass;
import java.util.UUID; import java.util.UUID;
@MappedSuperclass @MappedSuperclass
public class BaseEntity extends PanacheEntityBase { public class BaseEntity extends PanacheEntityBase {
@Id @jakarta.persistence.Id
@GeneratedValue(strategy = GenerationType.UUID) @GeneratedValue(strategy = GenerationType.UUID)
public UUID id; public UUID id;
} }
+1 -1
View File
@@ -7,7 +7,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.drinkool</groupId> <groupId>com.drinkool</groupId>
<artifactId>drinkool</artifactId> <artifactId>drinkool</artifactId>
<version>1.5.18</version> <version>1.5.19</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<properties> <properties>
<maven.compiler.source>25</maven.compiler.source> <maven.compiler.source>25</maven.compiler.source>
+33 -1
View File
@@ -1 +1,33 @@
mvn clean package -Dquarkus.container-image.push=false -Dquarkus.container-image.build=false #!/bin/bash
# Khởi tạo giá trị mặc định
DEBUG_FLAG=""
TEST_FLAG=""
# Duyệt qua các tham số đầu vào
for arg in "$@"; do
case $arg in
--debug)
DEBUG_FLAG="-Dmaven.surefire.debug"
shift # Bỏ qua flag này
;;
--test=*)
# Lấy giá trị sau dấu =
TEST_NAME="${arg#*=}"
TEST_FLAG="-Dtest=$TEST_NAME"
shift
;;
*)
# Các tham số không xác định (nếu cần xử lý thêm)
;;
esac
done
echo "Running: mvn clean package $DEBUG_FLAG $TEST_FLAG"
# Chạy lệnh Maven
mvn clean package \
-Dquarkus.container-image.push=false \
-Dquarkus.container-image.build=false \
$DEBUG_FLAG \
$TEST_FLAG