Skip to content
This repository has been archived by the owner on Feb 13, 2023. It is now read-only.

Remove and edit producs groups #40

Merged
merged 5 commits into from
Mar 21, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ch.wisv.payments.admin.products.request.ProductGroupRequest;
import ch.wisv.payments.admin.products.request.ProductRequest;
import ch.wisv.payments.model.Product;
import ch.wisv.payments.model.ProductGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
Expand Down Expand Up @@ -43,7 +44,7 @@ public String productEdit(@PathVariable Integer productId, Model model) {
Product product = productService.getProductById(productId);
ProductRequest productRequest = new ProductRequest();

productRequest.setProductId(product.getId());
productRequest.setId(product.getId());
productRequest.setName(product.getName());
productRequest.setDescription(product.getDescription());
productRequest.setPrice(product.getPrice());
Expand All @@ -58,7 +59,7 @@ public String productEdit(@PathVariable Integer productId, Model model) {

model.addAttribute("product", productRequest);

return "edit";
return "editProduct";
}

@PostMapping(value = "/add")
Expand Down Expand Up @@ -88,9 +89,48 @@ public String deleteProduct(@PathVariable int productId, RedirectAttributes redi
return "redirect:/products";
}

@PostMapping(value = "/addGroup")
@PostMapping(value = "/group")
public String addProductGroup(@ModelAttribute @Validated ProductGroupRequest productGroupRequest) {
productService.addProductGroup(productGroupRequest);
System.out.println("here");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, this is old.


return "redirect:/products";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add RedirectAttributes to show a message on the success of the adding

}

@GetMapping(value = "/group/edit/{productGroupId}")
public String productGroupEdit(@PathVariable Integer productGroupId, Model model) {
model.addAttribute("committees", committeeService.getAllCommittees());

ProductGroup productGroup = productService.getProductGroupById(productGroupId);
ProductGroupRequest productGroupRequest = new ProductGroupRequest();

productGroupRequest.setId(productGroup.getId());
productGroupRequest.setName(productGroup.getName());
productGroupRequest.setCommitteeId(productGroup.getCommittee().getId());
productGroupRequest.setDescription(productGroup.getDescription());
productGroupRequest.setGroupLimit(productGroup.getGroupLimit());

model.addAttribute("productGroup", productGroupRequest);

return "editProductGroup";
}

@PostMapping(value = "/group/edit")
public String editProductGroup(@ModelAttribute @Validated ProductGroupRequest productGroupRequest, RedirectAttributes redirectAttributes) {
productService.editProductGroup(productGroupRequest);

redirectAttributes.addFlashAttribute("message", productGroupRequest.getName() + " successfully updated!");

return "redirect:/products";
}

@PostMapping(value = "/group/delete/{productGroupId}")
public String deleteProductGroup(@PathVariable int productGroupId, RedirectAttributes redirectAttributes) {
try {
productService.deleteProductGroup(productGroupId);
} catch (RuntimeException e) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add a ExceptionHandler method for this controller, as the logic is the same for all RuntimeExceptions

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to have that "redirect" to the current page, so you don't lose a filled in form.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you imagine that? This is a delete endpoint, what should happen?

redirectAttributes.addFlashAttribute("error", e.getMessage());
}

return "redirect:/products";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@ public interface ProductService {
void addProductGroup(ProductGroupRequest productGroupRequest);

void addProductToGroup(Product product, ProductGroup productGroup);

void deleteProductGroup(int productGroupId);

ProductGroup getProductGroupById(Integer productGroupId);

void editProductGroup(ProductGroupRequest productGroupRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import ch.wisv.payments.admin.products.request.ProductGroupRequest;
import ch.wisv.payments.admin.products.request.ProductRequest;
import ch.wisv.payments.exception.CommmitteeNotFoundException;
import ch.wisv.payments.exception.ProductGroupInUseException;
import ch.wisv.payments.exception.ProductInUseException;
import ch.wisv.payments.model.*;
import ch.wisv.payments.rest.OrderService;
Expand Down Expand Up @@ -79,9 +80,9 @@ public void addProductToGroup(Product product, ProductGroup productGroup) {

@Override
public void editProduct(ProductRequest productRequest) {
if (productRequest.getProductId() != 0) {
if (productRequest.getId() != 0) {
Committee committee = committeeRepository.findOne(productRequest.getCommitteeId());
Product product = productRepository.findOne(productRequest.getProductId());
Product product = productRepository.findOne(productRequest.getId());

product.setName(productRequest.getName());
product.setDescription(productRequest.getDescription());
Expand All @@ -102,6 +103,17 @@ public void editProduct(ProductRequest productRequest) {
}
}

@Override
public void deleteProduct(int productId) {
List<Order> orders = orderService.getOrdersByProductId(productId);

if (orders.size() > 0) {
throw new ProductInUseException("Products are already ordered");
} else {
productRepository.delete(productId);
}
}

@Override
public Product getProductById(Integer productId) {
return productRepository.findOne(productId);
Expand Down Expand Up @@ -130,13 +142,32 @@ public boolean isProductAvailable(Integer productId) {
}

@Override
public void deleteProduct(int productId) {
List<Order> orders = orderService.getOrdersByProductId(productId);
public ProductGroup getProductGroupById(Integer productGroupId) {
return productGroupRepository.findOne(productGroupId);
}

if (orders.size() > 0) {
throw new ProductInUseException("Products are already ordered");
@Override
public void editProductGroup(ProductGroupRequest productGroupRequest) {
if (productGroupRequest.getId() != 0) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this if?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was also in the editProduct() method, could you shed some light on this?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, probably because the id's are int, which defaults to 0 instead of null

Committee committee = committeeRepository.findOne(productGroupRequest.getCommitteeId());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's take the committeeRepository out of this Service. Use the CommitteeService instead

ProductGroup productGroup = productGroupRepository.findOne(productGroupRequest.getId());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for this. Create/use a servicecall getProductGroupById() for this, with proper error handling


productGroup.setCommittee(committee);
productGroup.setName(productGroupRequest.getName());
productGroup.setDescription(productGroupRequest.getDescription());
productGroup.setGroupLimit(productGroupRequest.getGroupLimit());

productGroupRepository.saveAndFlush(productGroup);
}
}

@Override
public void deleteProductGroup(int productGroupId) {
ProductGroup productGroup = productGroupRepository.findOne(productGroupId);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Servicecall here too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So do we want to make a new ProductGroupService and ProductGroupServiceImpl? Either that or leave it here.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can put that in one service. Once we need more functionality that requires a lot more methods, we'll separate them.

if (!productGroup.getProducts().isEmpty()) {
throw new ProductGroupInUseException("Product group must be empty");
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really the case? What would break if you remove a group with products in it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had previously implemented it in a way where products were removed from the group when the group was removed, but this may be an action where we don't want it to be very easy to perform. I'm also not quite sure which way to go, it made sense to me that since there is a limit involved, you don't want it to be this easy, just like removing a product that is already ordered.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, then perhaps add a section to the editGroup page where you can remove products currently in the group?

Copy link
Contributor Author

@martijnjanssen martijnjanssen Mar 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also add the removal of tickets from a group as a hoothub issue, since this is not very high prioroty. It is also not relevant to editing the product group, it would make more sense to have it in a different page. /products/group/editproductsor something similar.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave it like this for now, and create a HootHub issue to implement this nicely.

} else {
productRepository.delete(productId);
productGroupRepository.delete(productGroupId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class ProductRequest {

@Getter
@Setter
int productId;
int id;
@Setter
@Getter
int committeeId;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ch.wisv.payments.exception;

public class ProductGroupInUseException extends RuntimeException {
public ProductGroupInUseException(String s) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constructor is already in RuntimeException

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You unfortunately have to do this to make use of the super(...) constructor though.

super(s);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ <h3 class="panel-title">Edit</h3>
<!--/*@thymesVar id="product" type="ch.wisv.payments.admin.products.request.ProductRequest"*/-->
<form class="form-horizontal" th:action="@{/products/edit}" th:object="${product}"
method="post">
<input type="hidden" th:field="*{productId}">
<input type="hidden" th:field="*{id}">
<div class="form-group">
<label for="committeeName">Committee</label>
<select class="form-control" th:field="*{committeeId}" id="committeeName">
Expand Down Expand Up @@ -110,7 +110,7 @@ <h3 class="panel-title">Edit</h3>
<input type="text" class="form-control" th:field="*{returnURL}" id="ReturnURL"
placeholder="Return URL">
</div>
<button type="submit" class="btn btn-default">Edit product</button>
<button type="submit" class="btn btn-success">Save product</button>
</form>
</div>
</div>
Expand Down
93 changes: 93 additions & 0 deletions src/main/resources/templates/editProductGroup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="../../favicon.ico">

<title>CH Payments</title>

<!-- Bootstrap core CSS -->
<link th:href="@{/webjars/bootstrap/3.3.7-1/css/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{/webjars/wisvch-bootstrap-theme/0.0.3/dist/css/bootstrap.min.css}"
rel="stylesheet" media="screen"/>

<!-- Custom styles for this template -->
<link th:href="@{/css/dashboard.css}" rel="stylesheet">

<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs/dt-1.10.12/datatables.min.css"/>

<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>

<body>
<div th:replace="fragments/header :: header">
<nav class="navbar navbar-inverse navbar-fixed-top"></nav>
</div>

<div class="container-fluid">
<div class="row">
<div th:replace="fragments/sidebar :: sidebar"></div>
</div>
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="page-header">Products</h1>

<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Edit</h3>
</div>
<div class="panel-body col-lg-12">
<!--/*@thymesVar id="productGroup" type="ch.wisv.payments.admin.products.request.ProductGroupRequest"*/-->
<form class="form-horizontal" th:action="@{/products/group/edit}" th:object="${productGroup}"
method="post">
<input type="hidden" th:field="*{id}">
<div class="form-group">
<label for="committeeName">Committee</label>
<select class="form-control" th:field="*{committeeId}" id="committeeName">
<option th:each="committee : ${committees}"
th:value="${committee.id}"
th:text="${committee.getName().getName()} + ' ' + ${committee.year}">
</option>
</select>
</div>
<div class="form-group">
<label for="productName">Group Name</label>
<input type="text" class="form-control" th:field="*{name}" id="productName"
placeholder="Name"
required>
</div>
<div class="form-group">
<label for="productDescription">Description</label>
<input type="text" class="form-control" th:field="*{description}" id="productDescription"
placeholder="Description" required>
</div>
<div class="form-group">
<label for="groupLimit">Group Limit</label>
<div class="input-group">
<input type="number" step="1" th:field="*{groupLimit}" class="form-control"
id="groupLimit"
placeholder="Max tickets sold in group">
</div>
</div>
<button type="submit" class="btn btn-success">Save product group</button>
</form>
</div>
</div>
</div>
</div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script th:src="@{/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js}"></script>
</body>
</html>
20 changes: 11 additions & 9 deletions src/main/resources/templates/products.html
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ <h3 class="panel-title">Add Product Group</h3>
</div>
<div class="panel-body">
<!--/*@thymesVar id="productGroup" type="ch.wisv.payments.admin.products.request.ProductGroupRequest"*/-->
<form class="form-inline" th:action="@{/products/addGroup}" th:object="${productGroup}"
<form class="form-inline" th:action="@{/products/group}" th:object="${productGroup}"
method="post">
<div class="form-group">
<label class="sr-only" for="committeeNameGroup">Committee</label>
Expand Down Expand Up @@ -218,14 +218,16 @@ <h3 class="panel-title">Add Product Group</h3>
</ul>
</td>
<td>
<!--<div class="btn-group" role="group" aria-label="...">-->
<!--<button type="button" class="btn btn-info" aria-label="Edit">-->
<!--<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>-->
<!--</button>-->
<!--<button type="button" class="btn btn-danger" aria-label="Remove">-->
<!--<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>-->
<!--</button>-->
<!--</div>-->
<form th:action="@{/products/group/delete/} + ${group.id}" method="post">
<div class="btn-group" role="group" aria-label="...">
<a class="btn btn-info" th:href="@{/products/group/edit/} + ${group.id}" href="#">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
</a>
<button type="submit" class="btn btn-danger" aria-label="Remove">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
</div>
</form>
</td>
</tr>
</tbody>
Expand Down