Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature_shopping_list #9

Merged
merged 12 commits into from
Nov 18, 2024
89 changes: 89 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: "Deploy App"

on:
push:
branches:
- main

jobs:
build-frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Build Frontend
working-directory: frontend
run: |
npm install
npm run build

- uses: actions/upload-artifact@v4
with:
name: frontend-build
path: frontend/dist/

build-backend:
runs-on: ubuntu-latest
needs: build-frontend
steps:
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
name: frontend-build
path: backend/src/main/resources/static

- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '21' # must match the version in the pom.xml
distribution: 'temurin'
cache: 'maven'

- name: Build with maven
run: mvn -B package --file backend/pom.xml

- uses: actions/upload-artifact@v4
with:
name: app.jar
path: backend/target/app.jar # must match the finalName in the pom.xml

push-to-docker-hub:
runs-on: ubuntu-latest
needs: build-backend
steps:
- uses: actions/checkout@v4

- uses: actions/download-artifact@v4
with:
name: app.jar
path: backend/target

- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }} # must match the name of the Dockerhub account
password: ${{ secrets.DOCKERHUB_PASSWORD }} # must match the password of the Dockerhub account

- name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ secrets.DOCKERHUB_TAG }} # Example: username/project:latest
context: .

deploy:
name: deploy-to-render
runs-on: ubuntu-latest
needs: push-to-docker-hub
environment:
name: Capstone Project # Capstone Project name
url: https://neuefische.de/ # Link to deployment
steps:
- name: Trigger Render.com Deployment
run: |
curl -X POST ${{ secrets.RENDER_DEPLOY }} #muss mit der url des Render Deployments übereinstimmen
12 changes: 12 additions & 0 deletions backend/src/main/java/springweb/backend/Client.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package springweb.backend;

import org.springframework.data.mongodb.core.mapping.Document;

import java.util.List;

@Document("clients")
public record Client(
String id,
List<GroceryProduct> shoppingList
) {
}
54 changes: 54 additions & 0 deletions backend/src/main/java/springweb/backend/ClientController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package springweb.backend;


import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.NoSuchElementException;


@RestController
@RequestMapping("/api/store/clients")
public class ClientController {

private final ClientService clientService;

public ClientController(ClientService clientService) {
this.clientService = clientService;
}

@GetMapping
public List<Client> getAllClients() {
return clientService.getAllClients();
}

@GetMapping({"{id}"})
public Client getClientByID(@PathVariable String id) {
return clientService.getClientById(id).orElseThrow(() -> new NoSuchElementException("Task not found"));
}

@PostMapping("{id}/shoppingList")
public Client addGroceryProductToClient(@PathVariable String id, @RequestBody GroceryProduct groceryProduct) {
return clientService.addGroceryProductToClient(groceryProduct, id);
}

@PostMapping
public Client addClient(@RequestBody Client client) {
return clientService.addClient(client);
}

@PutMapping("/{id}")
public Client updateTask(@PathVariable String id, @RequestBody Client clientDto) {
return clientService.updateClient(id, clientDto);
}

@DeleteMapping({"{id}"})
public void deleteClientById(@PathVariable String id) {
clientService.deleteClientById(id);
}

@DeleteMapping("{idClient}/shoppingList/{idProduct}")
public void deleteProductByIdFromClientById(@PathVariable String idClient, @PathVariable String idProduct) {
clientService.deleteProductByIdFromClientById(idClient,idProduct);
}
}
6 changes: 6 additions & 0 deletions backend/src/main/java/springweb/backend/ClientRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package springweb.backend;

import org.springframework.data.mongodb.repository.MongoRepository;

public interface ClientRepository extends MongoRepository<Client,String> {
}
93 changes: 93 additions & 0 deletions backend/src/main/java/springweb/backend/ClientService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package springweb.backend;

import org.springframework.stereotype.Service;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class ClientService {
private final ClientRepository clientRepository;

public ClientService(ClientRepository clientRepository) {
this.clientRepository = clientRepository;
}

public List<Client> getAllClients() {
return clientRepository.findAll();
}

public Optional<Client> getClientById(String id) {
return clientRepository.findById(id);
}

public Client addGroceryProductToClient(GroceryProduct groceryProduct, String id) {

if (clientRepository.existsById(id)) {
Client client = clientRepository.findById(id).get();
client.shoppingList().add(groceryProduct);
return clientRepository.save(client);
} else {
throw new NoSuchElementException("No Client found with Id:" + id);
}
}

public Client addClient(Client clientDto) {
Client client = new Client(clientDto.id(), clientDto.shoppingList());
return clientRepository.save(client);
}

public Client updateClient(String id, Client clientDto) {
if (clientRepository.existsById(id)) {
Client updatedClient = new Client(id, clientDto.shoppingList());
return clientRepository.save(updatedClient);
} else {
throw new NoSuchElementException("No Client found with Id:" + id);
}
}

public boolean deleteClientById(String id) {
if (clientRepository.existsById(id)) {
clientRepository.deleteById(id);
return true;
} else {
throw new NoSuchElementException("No Client found with Id:" + id);
}
}

/* WIP
public List<GroceryProduct> getAllGroceryProductsFromClient(String id) {
if (clientRepository.existsById(id)) {
return clientRepository.findById(id).get().shoppingList();
}
throw new NoSuchElementException("No Client found with Id:" + id);
}
*/

public void deleteProductByIdFromClientById(String idClient, String idProduct) {
if (clientRepository.existsById(idClient)) {
Client client = clientRepository.findById(idClient).get();
boolean productExists = client.shoppingList()
.stream()
.anyMatch(product -> product.id().equals(idProduct));
if (!client.shoppingList().isEmpty() && productExists) {

List<GroceryProduct> filteredList = client.shoppingList()
.stream()
.filter(product -> !product.id().equals(idProduct))
.collect(Collectors.toList());

client.shoppingList().clear();
client.shoppingList().addAll(filteredList);

clientRepository.save(client);
} else {
throw new NoSuchElementException("No Product found with Id:" + idProduct);
}
} else {
throw new NoSuchElementException("No Client found with Id:" + idClient);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package springweb.backend;


import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -10,7 +9,7 @@


@RestController
@RequestMapping("/api/store")
@RequestMapping("/api/store/products")
public class GroceryController {

GroceryService groceryService;
Expand Down
4 changes: 2 additions & 2 deletions backend/src/main/java/springweb/backend/GroceryService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package springweb.backend;

import lombok.NoArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import java.util.List;
Expand All @@ -18,4 +16,6 @@ public GroceryService(GroceryRepository groceryRepository) {
public List<GroceryProduct> getAllGroceryProducts() {
return groceryRepository.findAll();
}


}
58 changes: 58 additions & 0 deletions backend/src/test/java/springweb/backend/ClientServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package springweb.backend;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Optional;

import static com.mongodb.internal.connection.tlschannel.util.Util.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;

public class ClientServiceTest {

private final ClientRepository mockUserRepo = mock(ClientRepository.class);

@Test
public void GetAllClients_Test() {
// GIVEN
GroceryProduct product = new GroceryProduct("1", "Fruit", "Apple", 0.99, "apple.jpg");
List<GroceryProduct> shoppingList1 = List.of(product);
Client expectedClient1 = new Client("123", shoppingList1);

GroceryProduct product2 = new GroceryProduct("2", "Fruit", "Banana", 500, "banane.jpg");
GroceryProduct product3 = new GroceryProduct("3", "Fruit", "Kiwi", 1.80, "ps5.jpg");
List<GroceryProduct> shoppingList2 = List.of(product2, product3);
Client expectedClient2 = new Client("456", shoppingList2);

List<Client> clientList = List.of(expectedClient1, expectedClient2);

when(mockUserRepo.findAll()).thenReturn(clientList);
ClientService clientService = new ClientService(mockUserRepo);

// WHEN
List<Client> actual = clientService.getAllClients();

// THEN
verify(mockUserRepo).findAll();
assertEquals(clientList, actual);
}

@Test
public void GetClientById_Test() {
// GIVEN
GroceryProduct product = new GroceryProduct("1", "Fruit", "Apple", 0.99, "apple.jpg");
List<GroceryProduct> shoppingList = List.of(product);
Client expectedClient = new Client("123", shoppingList);

when(mockUserRepo.findById("123")).thenReturn(Optional.of(expectedClient));
ClientService clientService = new ClientService(mockUserRepo);

// WHEN
Optional<Client> result = clientService.getClientById("123");

// THEN
verify(mockUserRepo).findById("123");
assertTrue(result.isPresent());
assertEquals(expectedClient, result.get());
}
}
40 changes: 40 additions & 0 deletions frontend/public/_GroceryDB.clients.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[
{
"_id": "1",
"shoppingList": [
{
"_id": "1",
"category": "fruit",
"name": "apple",
"price": 1.5,
"image": "apple.jpg"
},
{
"_id": "2",
"category": "fruit",
"name": "banana",
"price": 1,
"image": "banane.jpg"
}
]
},
{
"_id": "2",
"shoppingList": [
{
"_id": "1",
"category": "fruit",
"name": "apple",
"price": 1.5,
"image": "apple.jpg"
},
{
"_id": "2",
"category": "fruit",
"name": "banana",
"price": 1,
"image": "banane.jpg"
}
]
}
]
Loading