diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..868293e
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,22 @@
+name: Build Project
+on:
+ pull_request:
+ branches: [ "main", "develop", "release" ]
+
+jobs:
+ Build:
+ runs-on: self-hosted
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ cache: maven
+
+ - name: Build with Maven
+ env:
+ CONFIG_IP: ${{ secrets.DEV_INTEG_HOST }}
+ run: mvn clean install
diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml
index f700652..8a79107 100644
--- a/.github/workflows/deploy-dev.yml
+++ b/.github/workflows/deploy-dev.yml
@@ -1,41 +1,16 @@
name: Deploy Develop
on:
- push:
- branches: ["develop"]
pull_request:
- branches: ["develop"]
+ branches:
+ - develop
+ types:
+ - closed
workflow_dispatch:
jobs:
- Build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Install Maven
- run: sudo apt-get install -y maven
- - name: Set up JDK 21
- uses: actions/setup-java@v4
- with:
- java-version: "21"
- distribution: "temurin"
- cache: maven
- - name: Build with Maven
- env:
- DATASOURCE_PASSWORD: ${{ secrets.DATASOURCE_PASSWORD }}
- DATASOURCE_URL: ${{ secrets.NEON_DATASOURCE_URL }}/${{ secrets.DB_NAME }}
- DATASOURCE_USERNAME: ${{ secrets.DATASOURCE_USERNAME }}
- GOOGLE_ADMIN_CONFIG_TYPE: ${{ secrets.GOOGLE_ADMIN_CONFIG_TYPE }}
- GOOGLE_ADMIN_CONFIG_PROJECT_ID: ${{ secrets.GOOGLE_ADMIN_CONFIG_PROJECT_ID }}
- GOOGLE_ADMIN_CONFIG_PRIVATE_KEY: ${{ secrets.GOOGLE_ADMIN_CONFIG_PRIVATE_KEY }}
- GOOGLE_ADMIN_CONFIG_PRIVATE_KEY_ID: ${{ secrets.GOOGLE_ADMIN_CONFIG_PRIVATE_KEY_ID }}
- GOOGLE_ADMIN_CONFIG_CLIENT_EMAIL: ${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_EMAIL }}
- GOOGLE_ADMIN_CONFIG_CLIENT_ID: ${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_ID }}
- GOOGLE_ADMIN_CONFIG_CLIENT_X509_CERT_URL: ${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_X509_CERT_URL }}
- run: mvn clean install
-
- deploy:
+ Deploy:
name: Deploy on Develop
+ if: ${{ github.event.pull_request.merged == true }}
runs-on: self-hosted
- needs: Build
steps:
- name: executing remote ssh commands using ssh key
uses: appleboy/ssh-action@master
@@ -53,16 +28,8 @@ jobs:
echo "Building Docker image..."
docker build -t ${{ github.event.repository.name }} .
echo "Creating .env file..."
- echo "DATASOURCE_URL=${{ secrets.DEV_DATASOURCE_URL }}/${{ secrets.DB_NAME }}" >> .env
- echo "DATASOURCE_USERNAME=${{ secrets.DATASOURCE_USERNAME }}" >> .env
- echo "DATASOURCE_PASSWORD=${{ secrets.DATASOURCE_PASSWORD }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_TYPE=${{ secrets.GOOGLE_ADMIN_CONFIG_TYPE }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_PROJECT_ID=${{ secrets.GOOGLE_ADMIN_CONFIG_PROJECT_ID }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_PRIVATE_KEY=${{ secrets.GOOGLE_ADMIN_CONFIG_PRIVATE_KEY }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_PRIVATE_KEY_ID=${{ secrets.GOOGLE_ADMIN_CONFIG_PRIVATE_KEY_ID }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_CLIENT_EMAIL=${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_EMAIL }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_CLIENT_ID=${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_ID }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_X509_CERT_URL=${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_X509_CERT_URL }}" >> .env
+ echo "PROFILE=dev" >> .env
+ echo "CONFIG_IP=10.43.101.114" >> .env
docker rm -f ${{ github.event.repository.name }}
docker run --name ${{ github.event.repository.name }} --network all_connected -d -p ${{ secrets.SERVICE_PORT }}:8080 --env-file .env ${{ github.event.repository.name }}
echo "Docker container running..."
diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml
new file mode 100644
index 0000000..efa963e
--- /dev/null
+++ b/.github/workflows/deploy-prod.yml
@@ -0,0 +1,33 @@
+name: Deploy PROD
+on:
+ push:
+ tags:
+ - '*'
+ workflow_dispatch:
+jobs:
+ Deploy:
+ name: Deploy on PROD
+ runs-on: self-hosted
+ steps:
+ - name: executing remote ssh commands using ssh key
+ uses: appleboy/ssh-action@master
+ with:
+ host: ${{ secrets.PROD_G2_HOST }}
+ username: ${{ secrets.HOSTS_USERNAME }}
+ key: ${{ secrets.PROD_G2_SSH_KEY }}
+ port: ${{ secrets.SSH_PORT }}
+ script: |
+ cd AllConnected/${{ github.event.repository.name }}
+ echo "Fetching latest code..."
+ git fetch
+ git checkout main
+ git pull
+ echo "Building Docker image..."
+ docker build -t ${{ github.event.repository.name }} .
+ echo "Creating .env file..."
+ echo "PROFILE=prod2" >> .env
+ echo "CONFIG_IP=10.43.101.72" >> .env
+ docker rm -f ${{ github.event.repository.name }}
+ docker run --name ${{ github.event.repository.name }} --network all_connected -d -p ${{ secrets.SERVICE_PORT }}:8080 --env-file .env ${{ github.event.repository.name }}
+ echo "Docker container running..."
+ rm .env
diff --git a/.github/workflows/deploy-qa.yml b/.github/workflows/deploy-qa.yml
index 7612477..bf5ff75 100644
--- a/.github/workflows/deploy-qa.yml
+++ b/.github/workflows/deploy-qa.yml
@@ -1,41 +1,16 @@
name: Deploy QA
on:
- push:
- branches: ["release"]
pull_request:
- branches: ["release"]
+ branches:
+ - release
+ types:
+ - closed
workflow_dispatch:
jobs:
- Build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Install Maven
- run: sudo apt-get install -y maven
- - name: Set up JDK 21
- uses: actions/setup-java@v4
- with:
- java-version: "21"
- distribution: "temurin"
- cache: maven
- - name: Build with Maven
- env:
- DATASOURCE_PASSWORD: ${{ secrets.DATASOURCE_PASSWORD }}
- DATASOURCE_URL: ${{ secrets.NEON_DATASOURCE_URL }}/${{ secrets.DB_NAME }}
- DATASOURCE_USERNAME: ${{ secrets.DATASOURCE_USERNAME }}
- GOOGLE_ADMIN_CONFIG_TYPE: ${{ secrets.GOOGLE_ADMIN_CONFIG_TYPE }}
- GOOGLE_ADMIN_CONFIG_PROJECT_ID: ${{ secrets.GOOGLE_ADMIN_CONFIG_PROJECT_ID }}
- GOOGLE_ADMIN_CONFIG_PRIVATE_KEY: ${{ secrets.GOOGLE_ADMIN_CONFIG_PRIVATE_KEY }}
- GOOGLE_ADMIN_CONFIG_PRIVATE_KEY_ID: ${{ secrets.GOOGLE_ADMIN_CONFIG_PRIVATE_KEY_ID }}
- GOOGLE_ADMIN_CONFIG_CLIENT_EMAIL: ${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_EMAIL }}
- GOOGLE_ADMIN_CONFIG_CLIENT_ID: ${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_ID }}
- GOOGLE_ADMIN_CONFIG_CLIENT_X509_CERT_URL: ${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_X509_CERT_URL }}
- run: mvn clean install
-
Deploy:
name: Deploy on QA
+ if: ${{ github.event.pull_request.merged == true }}
runs-on: self-hosted
- needs: Build
steps:
- name: executing remote ssh commands using ssh key
uses: appleboy/ssh-action@master
@@ -53,17 +28,9 @@ jobs:
echo "Building Docker image..."
docker build -t ${{ github.event.repository.name }} .
echo "Creating .env file..."
- echo "DATASOURCE_URL=${{ secrets.QA_DATASOURCE_G2_URL }}/${{ secrets.DB_NAME }}" >> .env
- echo "DATASOURCE_USERNAME=${{ secrets.DATASOURCE_USERNAME }}" >> .env
- echo "DATASOURCE_PASSWORD=${{ secrets.DATASOURCE_PASSWORD }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_TYPE=${{ secrets.GOOGLE_ADMIN_CONFIG_TYPE }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_PROJECT_ID=${{ secrets.GOOGLE_ADMIN_CONFIG_PROJECT_ID }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_PRIVATE_KEY=${{ secrets.GOOGLE_ADMIN_CONFIG_PRIVATE_KEY }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_PRIVATE_KEY_ID=${{ secrets.GOOGLE_ADMIN_CONFIG_PRIVATE_KEY_ID }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_CLIENT_EMAIL=${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_EMAIL }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_CLIENT_ID=${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_ID }}" >> .env
- echo "GOOGLE_ADMIN_CONFIG_X509_CERT_URL=${{ secrets.GOOGLE_ADMIN_CONFIG_CLIENT_X509_CERT_URL }}" >> .env
+ echo "PROFILE=qa2" >> .env
+ echo "CONFIG_IP=10.43.100.223" >> .env
docker rm -f ${{ github.event.repository.name }}
docker run --name ${{ github.event.repository.name }} --network all_connected -d -p ${{ secrets.SERVICE_PORT }}:8080 --env-file .env ${{ github.event.repository.name }}
echo "Docker container running..."
- rm .env
\ No newline at end of file
+ rm .env
diff --git a/pom.xml b/pom.xml
index 0f4fc77..0dd9cb7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,7 +47,14 @@
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
-
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
org.springframework.boot
spring-boot-devtools
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/config/WebConfig.java b/src/main/java/co/allconnected/fussiontech/productsservice/config/WebConfig.java
deleted file mode 100644
index 8375cc0..0000000
--- a/src/main/java/co/allconnected/fussiontech/productsservice/config/WebConfig.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package co.allconnected.fussiontech.productsservice.config;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class WebConfig implements WebMvcConfigurer {
-
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**")
- .allowedOriginPatterns("*")
- .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
- .allowedHeaders("*")
- .allowCredentials(true);
- }
-}
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/controllers/LabelsController.java b/src/main/java/co/allconnected/fussiontech/productsservice/controllers/LabelsController.java
new file mode 100644
index 0000000..3ee4e60
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/controllers/LabelsController.java
@@ -0,0 +1,78 @@
+package co.allconnected.fussiontech.productsservice.controllers;
+
+import co.allconnected.fussiontech.productsservice.dtos.LabelDTO;
+import co.allconnected.fussiontech.productsservice.dtos.Response;
+import co.allconnected.fussiontech.productsservice.services.LabelService;
+import co.allconnected.fussiontech.productsservice.utils.OperationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api/v1/labels")
+public class LabelsController {
+ private final LabelService labelService;
+
+ @Autowired
+ public LabelsController(LabelService labelService) {
+ this.labelService = labelService;
+ }
+
+ @PostMapping
+ public ResponseEntity createLabel(@RequestParam String name) {
+ try {
+ if (name == null || name.trim().isEmpty()) {
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null); // Manejo del error si 'name' es nulo o vacĂo
+ }
+ LabelDTO labelDTO = labelService.createLabel(name);
+ return ResponseEntity.status(HttpStatus.CREATED).body(labelDTO);
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
+ }
+ }
+ @PutMapping("/{id}")
+ public ResponseEntity> updateLabel(@PathVariable String id, @RequestParam String name) {
+ try {
+ return ResponseEntity.status(HttpStatus.OK).body(labelService.updateLabel(id, name));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @GetMapping("/{id}")
+ public ResponseEntity> getLabel(@PathVariable String id) {
+ try {
+ return ResponseEntity.status(HttpStatus.OK).body(labelService.getLabel(id));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+
+ @GetMapping()
+ public ResponseEntity> getLabels() {
+ try {
+ LabelDTO[] listLabelsDTO = labelService.getLabels();
+ return ResponseEntity.status(HttpStatus.OK).body(listLabelsDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (RuntimeException e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()));
+ }
+ }
+
+ @DeleteMapping("/{id}")
+ public ResponseEntity> deleteLabel(@PathVariable String id) {
+ try {
+ labelService.deleteLabel(id);
+ return ResponseEntity.status(HttpStatus.OK).body(new Response(HttpStatus.OK.value(), "Label deleted"));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+}
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/controllers/ProductsController.java b/src/main/java/co/allconnected/fussiontech/productsservice/controllers/ProductsController.java
new file mode 100644
index 0000000..9c846eb
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/controllers/ProductsController.java
@@ -0,0 +1,243 @@
+package co.allconnected.fussiontech.productsservice.controllers;
+
+import co.allconnected.fussiontech.productsservice.dtos.*;
+import co.allconnected.fussiontech.productsservice.services.ProductService;
+import co.allconnected.fussiontech.productsservice.utils.OperationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+@RestController
+@RequestMapping("/api/v1/products")
+public class ProductsController {
+ private final ProductService productService;
+
+ @Autowired
+ public ProductsController(ProductService productService) {
+ this.productService = productService;
+ }
+ /*
+ CRUD PRODUCTS
+ */
+ @PostMapping
+ public ResponseEntity> createProduct(@ModelAttribute ProductCreateDTO product, @RequestParam(value = "photo", required = false) MultipartFile photo) {
+ try {
+ System.out.println(product.idBusiness());
+ ProductDTO productDTO = productService.createProduct(product, photo);
+ return ResponseEntity.status(HttpStatus.CREATED).body(productDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @PutMapping("/{id}")
+ public ResponseEntity> updateProduct(@PathVariable String id, @ModelAttribute ProductCreateDTO product, @RequestParam(value = "photo", required = false) MultipartFile photo) {
+ try {
+ return ResponseEntity.status(HttpStatus.OK).body(productService.updateProduct(id, product, photo));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @GetMapping("/{id}")
+ public ResponseEntity> getProduct(@PathVariable String id) {
+ try {
+ return ResponseEntity.status(HttpStatus.OK).body(productService.getProduct(id));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @GetMapping("/businesses/{id_business}")
+ public ResponseEntity> getProductsByBusiness(@PathVariable String id_business) {
+ try {
+ ProductDTO[] listProductsDTO = productService.getProductsByBusiness(id_business);
+ return ResponseEntity.status(HttpStatus.OK).body(listProductsDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (RuntimeException e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()));
+ }
+ }
+ @GetMapping
+ public ResponseEntity> getProducts() {
+ try {
+ ProductDTO[] listProductsDTO = productService.getProducts();
+ return ResponseEntity.status(HttpStatus.OK).body(listProductsDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (RuntimeException e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()));
+ }
+ }
+
+ @DeleteMapping("/{id}")
+ public ResponseEntity> deleteProduct(@PathVariable String id) {
+ try {
+ productService.deleteProduct(id);
+ return ResponseEntity.status(HttpStatus.OK).body(new Response(HttpStatus.OK.value(), "Product deleted"));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ /*
+ OPERATIONS PRODUCTS - LABELS
+ */
+ @PostMapping("/{id_product}/labels/{id_label}")
+ public ResponseEntity> addLabel(@PathVariable String id_product, @PathVariable String id_label) {
+ try {
+ productService.assignLabelToProduct(id_product, id_label);
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(new Response(HttpStatus.OK.value(), "Label assigned to product successfully."));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @DeleteMapping("/{id_product}/labels/{id_label}/delete")
+ public ResponseEntity> deleteLabel(@PathVariable String id_product, @PathVariable String id_label) {
+ try {
+ productService.deleteLabelFromProduct(id_product, id_label);
+ return ResponseEntity.status(HttpStatus.OK)
+ .body(new Response(HttpStatus.OK.value(), "Label deleted from product successfully."));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ /*
+ OPERATIONS PRODUCTS - REPORTS
+ */
+ @PostMapping("/{id_product}/report")
+ public ResponseEntity> addReport(@PathVariable String id_product, @RequestBody ReportedProductCreateDTO reportedProductCreateDTO){
+ try {
+ ReportedProductDTO reportedProductDTO = productService.reportProduct(id_product, reportedProductCreateDTO);
+ return ResponseEntity.status(HttpStatus.CREATED).body(reportedProductDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @PutMapping("/{id_product}/report")
+ public ResponseEntity> updateReport(@PathVariable String id_product, @RequestBody ReportedProductCreateDTO reportedProductCreateDTO){
+ try {
+ ReportedProductDTO reportedProductDTO = productService.updateProductReport(id_product, reportedProductCreateDTO);
+ return ResponseEntity.status(HttpStatus.OK).body(reportedProductDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @DeleteMapping("/{id_product}/report")
+ public ResponseEntity> deleteReport(@PathVariable String id_product){
+ try {
+ productService.deleteReport(id_product);
+ return ResponseEntity.status(HttpStatus.OK).body(new Response(HttpStatus.OK.value(), "Report deleted"));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @GetMapping("/{id_product}/report")
+ public ResponseEntity> getReport(@PathVariable String id_product){
+ try {
+ return ResponseEntity.status(HttpStatus.OK).body(productService.getReport(id_product));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+ @GetMapping("/reports")
+ public ResponseEntity> getReports(){
+ try {
+ ReportedProductDTO[] listReportsDTO = productService.getReports();
+ if (listReportsDTO.length == 0)
+ return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new Response(HttpStatus.NOT_FOUND.value(), "No reports found"));
+ return ResponseEntity.status(HttpStatus.OK).body(listReportsDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (RuntimeException e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()));
+ }
+ }
+ /*
+ RATING OPERATIONS
+ */
+ @PostMapping("/rating/{id_product}")
+ public ResponseEntity> addRating(@PathVariable String id_product, @RequestBody RatingCreateDTO ratingCreateDTO){
+ try {
+ /*
+ System.out.println(ratingCreateDTO.userId());
+ System.out.println(ratingCreateDTO.productId());
+ System.out.println(ratingCreateDTO.rating());
+
+ */
+ RatingDTO ratingDTO = productService.rateProduct(id_product, ratingCreateDTO);
+ return ResponseEntity.status(HttpStatus.CREATED).body(ratingDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+
+ @GetMapping("/rating")
+ public ResponseEntity> getRatings(){
+ try {
+ RatingDTO[] listRatingsDTO = productService.getAllRating();
+ return ResponseEntity.status(HttpStatus.OK).body(listRatingsDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (RuntimeException e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()));
+ }
+ }
+
+ @GetMapping("/rating/{id_product}/average")
+ public ResponseEntity> getRating(@PathVariable String id_product){
+ try {
+ float rating = productService.getAverageRating(id_product);
+ return ResponseEntity.status(HttpStatus.OK).body(new Response(HttpStatus.OK.value(), "Average rating: " + rating));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (RuntimeException e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()));
+ }
+ }
+
+ @GetMapping("/rating/{id_product}")
+ public ResponseEntity> getRatingsByProduct(@PathVariable String id_product){
+ try {
+ RatingDTO[] listRatingsDTO = productService.getRatingByProduct(id_product);
+ return ResponseEntity.status(HttpStatus.OK).body(listRatingsDTO);
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (RuntimeException e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()));
+ }
+ }
+ @DeleteMapping("/rating/{id_rating}")
+ public ResponseEntity> deleteRating (@PathVariable String id_rating){
+ try {
+ productService.deleteRating(id_rating);
+ return ResponseEntity.status(HttpStatus.OK).body(new Response(HttpStatus.OK.value(), "Rating deleted"));
+ } catch (OperationException e) {
+ return ResponseEntity.status(e.getCode()).body(new Response(e.getCode(), e.getMessage()));
+ } catch (Exception e) {
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Response(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Unexpected error occurred: " + e.getMessage()));
+ }
+ }
+}
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/controllers/delete.txt b/src/main/java/co/allconnected/fussiontech/productsservice/controllers/delete.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/LabelDTO.java b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/LabelDTO.java
new file mode 100644
index 0000000..9d41bf2
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/LabelDTO.java
@@ -0,0 +1,29 @@
+package co.allconnected.fussiontech.productsservice.dtos;
+
+import co.allconnected.fussiontech.productsservice.model.Label;
+import co.allconnected.fussiontech.productsservice.model.Product;
+import lombok.Getter;
+import lombok.Setter;
+import java.io.Serializable;
+
+@Getter
+@Setter
+
+public class LabelDTO implements Serializable {
+ Integer id;
+ String label;
+ String [] products;
+
+ public LabelDTO(){
+
+ }
+
+ public LabelDTO(Label label){
+ this.id = label.getId();
+ this.label = label.getLabel();
+ this.products = label.getProducts().stream().map(Product::getName).toArray(String[]::new);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ProductCreateDTO.java b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ProductCreateDTO.java
new file mode 100644
index 0000000..07dfcb9
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ProductCreateDTO.java
@@ -0,0 +1,6 @@
+package co.allconnected.fussiontech.productsservice.dtos;
+
+import java.util.UUID;
+
+public record ProductCreateDTO (UUID idBusiness, String name, String description, Integer stock, Double price, String status) {
+}
\ No newline at end of file
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ProductDTO.java b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ProductDTO.java
new file mode 100644
index 0000000..9856223
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ProductDTO.java
@@ -0,0 +1,33 @@
+package co.allconnected.fussiontech.productsservice.dtos;
+
+import co.allconnected.fussiontech.productsservice.model.Label;
+import co.allconnected.fussiontech.productsservice.model.Product;
+import lombok.Getter;
+import lombok.Setter;
+import java.io.Serializable;
+
+@Getter
+@Setter
+public class ProductDTO implements Serializable {
+ private Integer id;
+ private String idBusiness;
+ private String name;
+ private String description;
+ private String photoUrl;
+ private Integer stock;
+ private Double price;
+ private String status;
+ private String [] labels;
+
+ public ProductDTO(Product product){
+ this.id = product.getId();
+ this.idBusiness = product.getIdBusiness().toString();
+ this.name = product.getName();
+ this.description = product.getDescription();
+ this.photoUrl = product.getPhotoUrl();
+ this.stock = product.getStock();
+ this.price = product.getPrice();
+ this.status = product.getStatus();
+ this.labels = product.getLabels().stream().map(Label::getLabel).toArray(String[]::new);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/RatingCreateDTO.java b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/RatingCreateDTO.java
new file mode 100644
index 0000000..d38e72c
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/RatingCreateDTO.java
@@ -0,0 +1,4 @@
+package co.allconnected.fussiontech.productsservice.dtos;
+
+public record RatingCreateDTO(Integer productId, String userId, Integer rating, String comment) {
+}
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/RatingDTO.java b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/RatingDTO.java
new file mode 100644
index 0000000..bb44e5c
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/RatingDTO.java
@@ -0,0 +1,29 @@
+package co.allconnected.fussiontech.productsservice.dtos;
+
+import co.allconnected.fussiontech.productsservice.model.Rating;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import java.io.Serializable;
+import java.time.Instant;
+
+@Getter
+@Setter
+@NoArgsConstructor
+public class RatingDTO implements Serializable {
+ private Integer idRating;
+ private Integer productId;
+ private String userId;
+ private Integer rating;
+ private String comment;
+ private Instant date;
+
+ public RatingDTO(Rating rating){
+ this.idRating = rating.getId();
+ this.productId = rating.getIdProduct().getId();
+ this.userId = rating.getIdUser();
+ this.rating = rating.getRating();
+ this.comment = rating.getComment();
+ this.date = rating.getDate();
+ }
+}
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ReportedProductCreateDTO.java b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ReportedProductCreateDTO.java
new file mode 100644
index 0000000..0011ea8
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ReportedProductCreateDTO.java
@@ -0,0 +1,4 @@
+package co.allconnected.fussiontech.productsservice.dtos;
+
+public record ReportedProductCreateDTO (String reason, String description) {
+}
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ReportedProductDTO.java b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ReportedProductDTO.java
new file mode 100644
index 0000000..1d39780
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/ReportedProductDTO.java
@@ -0,0 +1,24 @@
+package co.allconnected.fussiontech.productsservice.dtos;
+
+import co.allconnected.fussiontech.productsservice.model.ReportedProduct;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.time.Instant;
+
+@Getter
+@Setter
+public class ReportedProductDTO implements Serializable {
+ private Integer productId;
+ private String reason;
+ private String description;
+ private Instant reportDate;
+
+ public ReportedProductDTO (ReportedProduct reportedProduct){
+ this.productId = reportedProduct.getProduct().getId();
+ this.reason = reportedProduct.getReason();
+ this.description = reportedProduct.getDescription();
+ this.reportDate = reportedProduct.getReportDate();
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/Response.java b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/Response.java
new file mode 100644
index 0000000..ac7a347
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/Response.java
@@ -0,0 +1,4 @@
+package co.allconnected.fussiontech.productsservice.dtos;
+
+public record Response(int code, String message) {
+}
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/dtos/delete.txt b/src/main/java/co/allconnected/fussiontech/productsservice/dtos/delete.txt
deleted file mode 100644
index e69de29..0000000
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/model/Label.java b/src/main/java/co/allconnected/fussiontech/productsservice/model/Label.java
new file mode 100644
index 0000000..2d3fa62
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/model/Label.java
@@ -0,0 +1,35 @@
+package co.allconnected.fussiontech.productsservice.model;
+
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+@Getter
+@Setter
+@Entity
+@NoArgsConstructor
+@Table(name = "label", schema = "all_connected_products")
+public class Label {
+ public Label(String label) {
+ this.label = label;
+ }
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id_label", nullable = false)
+ private Integer id;
+
+ @Column(name = "label", nullable = false, length = 45)
+ private String label;
+
+ @ManyToMany
+ @JoinTable(name = "product_label",
+ schema = "all_connected_products", // Agrega el esquema explĂcitamente
+ joinColumns = @JoinColumn(name = "id_label"),
+ inverseJoinColumns = @JoinColumn(name = "id_announcement"))
+ private Set products = new LinkedHashSet<>();
+}
diff --git a/src/main/java/co/allconnected/fussiontech/productsservice/model/Product.java b/src/main/java/co/allconnected/fussiontech/productsservice/model/Product.java
new file mode 100644
index 0000000..44ba4c7
--- /dev/null
+++ b/src/main/java/co/allconnected/fussiontech/productsservice/model/Product.java
@@ -0,0 +1,58 @@
+package co.allconnected.fussiontech.productsservice.model;
+
+import co.allconnected.fussiontech.productsservice.dtos.ProductCreateDTO;
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.UUID;
+
+@Getter
+@Setter
+@Entity
+@NoArgsConstructor
+@Table(name = "product", schema = "all_connected_products")
+public class Product {
+ public Product (ProductCreateDTO dto) {
+ this.idBusiness = dto.idBusiness();
+ this.name = dto.name();
+ this.description = dto.description();
+ this.stock = dto.stock();
+ this.price = dto.price();
+ this.status = dto.status();
+ }
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id_product", nullable = false)
+ private Integer id;
+
+ @Column(name = "id_business", nullable = false)
+ private UUID idBusiness;
+
+ @Column(name = "name", nullable = false, length = 45)
+ private String name;
+
+ @Column(name = "description", nullable = false, length = 280)
+ private String description;
+
+ @Column(name = "photo_url", length = 700)
+ private String photoUrl;
+
+ @Column(name = "stock", nullable = false)
+ private Integer stock;
+
+ @Column(name = "price", nullable = false)
+ private Double price;
+
+ @Column(name = "status", nullable = false, length = Integer.MAX_VALUE)
+ private String status;
+
+ @ManyToMany(mappedBy = "products")
+ private Set