Compare commits
11 Commits
1.0.0
...
037f1ff671
Author | SHA1 | Date | |
---|---|---|---|
037f1ff671 | |||
99896a4f77 | |||
624ade2032 | |||
99b123565c | |||
be6de240bb | |||
7cf1819460 | |||
17f0c645f1 | |||
bdd1017232 | |||
f4299c33c1 | |||
f86a14b2f8 | |||
2fb5826a3b |
@ -1,6 +1,5 @@
|
|||||||
package org.hso.ecommerce.components;
|
package org.hso.ecommerce.components;
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.booking.PaymentMethod;
|
|
||||||
import org.hso.ecommerce.entities.shop.Address;
|
import org.hso.ecommerce.entities.shop.Address;
|
||||||
import org.hso.ecommerce.entities.user.User;
|
import org.hso.ecommerce.entities.user.User;
|
||||||
import org.hso.ecommerce.repos.user.UserRepository;
|
import org.hso.ecommerce.repos.user.UserRepository;
|
||||||
@ -26,8 +25,7 @@ public class AdminInitializer {
|
|||||||
firstAdmin.created = new Timestamp(System.currentTimeMillis());
|
firstAdmin.created = new Timestamp(System.currentTimeMillis());
|
||||||
firstAdmin.defaultDeliveryAddress = new Address();
|
firstAdmin.defaultDeliveryAddress = new Address();
|
||||||
firstAdmin.defaultDeliveryAddress.name = "admin";
|
firstAdmin.defaultDeliveryAddress.name = "admin";
|
||||||
firstAdmin.defaultPayment = new PaymentMethod();
|
firstAdmin.defaultPayment = null;
|
||||||
firstAdmin.defaultPayment.creditCardNumber = ""; //set empty number
|
|
||||||
firstAdmin.email = "admin";
|
firstAdmin.email = "admin";
|
||||||
firstAdmin.isActive = true;
|
firstAdmin.isActive = true;
|
||||||
firstAdmin.isEmployee = true;
|
firstAdmin.isEmployee = true;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.hso.ecommerce.controller;
|
package org.hso.ecommerce.controller;
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.booking.PaymentMethod;
|
|
||||||
import org.hso.ecommerce.entities.shop.Address;
|
import org.hso.ecommerce.entities.shop.Address;
|
||||||
import org.hso.ecommerce.entities.user.User;
|
import org.hso.ecommerce.entities.user.User;
|
||||||
import org.hso.ecommerce.repos.user.UserRepository;
|
import org.hso.ecommerce.repos.user.UserRepository;
|
||||||
@ -47,7 +46,7 @@ public class RegisterController {
|
|||||||
newUser.email = username;
|
newUser.email = username;
|
||||||
newUser.isEmployee = false;
|
newUser.isEmployee = false;
|
||||||
newUser.salutation = salutation;
|
newUser.salutation = salutation;
|
||||||
newUser.defaultPayment = PaymentMethod.fromCreditCardNumber("");
|
newUser.defaultPayment = null;
|
||||||
|
|
||||||
newUser.isActive = true;
|
newUser.isActive = true;
|
||||||
newUser.created = new java.sql.Timestamp(System.currentTimeMillis());
|
newUser.created = new java.sql.Timestamp(System.currentTimeMillis());
|
||||||
|
@ -37,6 +37,7 @@ public class ShopArticleController {
|
|||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public String shopArticlesById(Model model,
|
public String shopArticlesById(Model model,
|
||||||
|
@RequestAttribute(value = "shoppingCart") ShoppingCart shoppingCart,
|
||||||
@PathVariable("id") Long id,
|
@PathVariable("id") Long id,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response
|
HttpServletResponse response
|
||||||
@ -52,15 +53,14 @@ public class ShopArticleController {
|
|||||||
}
|
}
|
||||||
model.addAttribute("article", article);
|
model.addAttribute("article", article);
|
||||||
|
|
||||||
if (warehouseBookingPositionSlotEntryRepository
|
int inStock = warehouseBookingPositionSlotEntryRepository
|
||||||
.getByArticle(id)
|
.getByArticle(id)
|
||||||
.stream()
|
.stream()
|
||||||
.mapToInt(e -> e.newSumSlot)
|
.mapToInt(e -> e.newSumSlot)
|
||||||
.sum() > 0) { //check if in Stock
|
.sum();
|
||||||
model.addAttribute("inStock", true);
|
|
||||||
} else {
|
model.addAttribute("inStock", Math.min(inStock, 10));
|
||||||
model.addAttribute("inStock", false);
|
model.addAttribute("inCart", shoppingCart.getArticleCount(article));
|
||||||
}
|
|
||||||
|
|
||||||
List<Article> commercialArticles = GetRandomArticlesAction.getRandomArticles(3, articleRepository.getAdvertisedArticles()); //get 3 advertised Articles
|
List<Article> commercialArticles = GetRandomArticlesAction.getRandomArticles(3, articleRepository.getAdvertisedArticles()); //get 3 advertised Articles
|
||||||
model.addAttribute("commercialArticles", commercialArticles);
|
model.addAttribute("commercialArticles", commercialArticles);
|
||||||
@ -78,7 +78,7 @@ public class ShopArticleController {
|
|||||||
@RequestParam(value = "set_amount", required = false) Boolean setAmount,
|
@RequestParam(value = "set_amount", required = false) Boolean setAmount,
|
||||||
@RequestParam("fastcheckout") Boolean fastcheckout
|
@RequestParam("fastcheckout") Boolean fastcheckout
|
||||||
) {
|
) {
|
||||||
Article article = articleRepository.findArticleById(id);
|
Article article = articleRepository.findById(id).orElse(null);
|
||||||
|
|
||||||
if (article == null) {
|
if (article == null) {
|
||||||
request.setAttribute("error", "Der Artikel wurde nicht gefunden.");
|
request.setAttribute("error", "Der Artikel wurde nicht gefunden.");
|
||||||
|
@ -57,13 +57,27 @@ public class ShopCheckoutController {
|
|||||||
|
|
||||||
CheckoutListTotals totals = new CheckoutListTotals();
|
CheckoutListTotals totals = new CheckoutListTotals();
|
||||||
ArrayList<CheckoutListItem> items = new ArrayList<>();
|
ArrayList<CheckoutListItem> items = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean inValid = false;
|
||||||
|
|
||||||
for (ShoppingCart.ShoppingCartItem item : shoppingCart.getItems()) {
|
for (ShoppingCart.ShoppingCartItem item : shoppingCart.getItems()) {
|
||||||
Article article = articleRepository.findById(item.getArticleId()).get();
|
Article article = articleRepository.findById(item.getArticleId()).get();
|
||||||
|
|
||||||
|
int inStock = wbeseRepo
|
||||||
|
.getByArticle(item.getArticleId())
|
||||||
|
.stream()
|
||||||
|
.mapToInt(e -> e.newSumSlot)
|
||||||
|
.sum();
|
||||||
|
|
||||||
totals.addItem(article, item.getAmount());
|
totals.addItem(article, item.getAmount());
|
||||||
items.add(new CheckoutListItem(item.getAmount(), article));
|
items.add(new CheckoutListItem(item.getAmount(), Math.min(inStock, 10), article));
|
||||||
|
if (item.getAmount() > inStock) {
|
||||||
|
inValid = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request.setAttribute("inValid", inValid);
|
||||||
|
|
||||||
request.setAttribute("checkoutItems", items);
|
request.setAttribute("checkoutItems", items);
|
||||||
request.setAttribute("checkoutTotals", totals);
|
request.setAttribute("checkoutTotals", totals);
|
||||||
|
|
||||||
@ -87,11 +101,13 @@ public class ShopCheckoutController {
|
|||||||
public int amount;
|
public int amount;
|
||||||
public Article article;
|
public Article article;
|
||||||
public int total;
|
public int total;
|
||||||
|
public int inStock;
|
||||||
|
|
||||||
public CheckoutListItem(int amount, Article article) {
|
public CheckoutListItem(int amount, int inStock, Article article) {
|
||||||
this.amount = amount;
|
this.amount = amount;
|
||||||
this.article = article;
|
this.article = article;
|
||||||
this.total = amount * article.getPriceGross();
|
this.total = amount * article.getPriceGross();
|
||||||
|
this.inStock = inStock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +156,11 @@ public class ShopCheckoutController {
|
|||||||
bookingRepository.saveAll(result.bookings);
|
bookingRepository.saveAll(result.bookings);
|
||||||
warehouseBookingRepository.save(result.warehouseBooking);
|
warehouseBookingRepository.save(result.warehouseBooking);
|
||||||
|
|
||||||
|
if (user.defaultPayment == null) {
|
||||||
|
user.defaultPayment = PaymentMethod.fromCreditCardNumber(cardnumber);
|
||||||
|
userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
shoppingCart.clear();
|
shoppingCart.clear();
|
||||||
|
|
||||||
} catch (CreateOrderAction.ArticleNotInStockException e) {
|
} catch (CreateOrderAction.ArticleNotInStockException e) {
|
||||||
|
@ -42,9 +42,8 @@ public class ShopSearchController {
|
|||||||
List<Article> articles = articleRepository.getArticlesByCategory(category); //search by Category
|
List<Article> articles = articleRepository.getArticlesByCategory(category); //search by Category
|
||||||
model.addAttribute("articles", articles);
|
model.addAttribute("articles", articles);
|
||||||
} else {
|
} else {
|
||||||
request.setAttribute("error", "Es wurden keine Suchparameter angegeben.");
|
List<Article> articles = SearchByTermAction.searchByTerm("", articleRepository);
|
||||||
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
model.addAttribute("articles", articles);
|
||||||
return "error/404";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show term in search box
|
// Show term in search box
|
||||||
|
@ -69,6 +69,16 @@ public class ShoppingCart {
|
|||||||
items.removeIf(i -> i.getAmount() <= 0);
|
items.removeIf(i -> i.getAmount() <= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getArticleCount(Article article) {
|
||||||
|
for (ShoppingCartItem i : items) {
|
||||||
|
if (i.getArticleId() == article.id) {
|
||||||
|
return i.amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static class ShoppingCartItem {
|
public static class ShoppingCartItem {
|
||||||
private int amount;
|
private int amount;
|
||||||
private final long articleId;
|
private final long articleId;
|
||||||
|
@ -14,6 +14,7 @@ spring.jpa.show-sql=true
|
|||||||
#spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql
|
#spring.session.jdbc.schema=classpath:org/springframework/session/jdbc/schema-@@platform@@.sql
|
||||||
#spring.session.jdbc.table-name=SPRING_SESSION
|
#spring.session.jdbc.table-name=SPRING_SESSION
|
||||||
#server.servlet.session.persistent=true
|
#server.servlet.session.persistent=true
|
||||||
|
server.servlet.session.timeout=48h
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
# WEB PROPERTIES
|
# WEB PROPERTIES
|
||||||
spring.servlet.multipart.max-file-size=10MB
|
spring.servlet.multipart.max-file-size=10MB
|
||||||
|
@ -380,7 +380,7 @@ button, .button {
|
|||||||
/* box-shadow: var(--s-0-secondary); */
|
/* box-shadow: var(--s-0-secondary); */
|
||||||
}
|
}
|
||||||
|
|
||||||
button:active, .button:active {
|
button:enabled:active, .button:active {
|
||||||
background-color: var(--c-primary-highlight);
|
background-color: var(--c-primary-highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,6 +392,10 @@ button,
|
|||||||
transition: background-color 0.1s ease-out;
|
transition: background-color 0.1s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button:disabled {
|
||||||
|
filter: grayscale(100%);
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
display: block;
|
display: block;
|
||||||
min-width: 10em;
|
min-width: 10em;
|
||||||
@ -761,6 +765,7 @@ input[type="number"]:focus {
|
|||||||
|
|
||||||
.error {
|
.error {
|
||||||
background-color: var(--c-error);
|
background-color: var(--c-error);
|
||||||
|
color: var(--c-base);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: var(--u0);
|
font-size: var(--u0);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="username">Email Adresse</label>
|
<label for="username">Email Adresse</label>
|
||||||
<input class="full-width" type="text" name="username" placeholder="Email Adresse" id="username" required>
|
<input class="full-width" type="text" name="username" placeholder="Email Adresse" id="username"
|
||||||
|
pattern="[^@\s]+@[^\.\s]+\.[^\s]+" required>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="password">Passwort</label>
|
<label for="password">Passwort</label>
|
||||||
|
@ -38,17 +38,28 @@
|
|||||||
th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span>
|
th:text="${#numbers.formatDecimal(article.getPriceGross() * 0.01, 1, 'POINT', 2, 'COMMA')}"></span><span> EUR</span>
|
||||||
</h2>
|
</h2>
|
||||||
<div>
|
<div>
|
||||||
|
<input type="hidden" name="set_amount" value="true"/>
|
||||||
<label class="nolinebreak">Menge:</label>
|
<label class="nolinebreak">Menge:</label>
|
||||||
<select name="quantity" size="1">
|
<select name="quantity" size="1">
|
||||||
<option th:each="quantity : ${#numbers.sequence(1,10)}"
|
<option th:if="${inCart > 0}" th:value="${inCart}" th:text="${inCart}"
|
||||||
|
selected></option>
|
||||||
|
<option th:if="${inCart > 0}" value="0">Entfernen</option>
|
||||||
|
<option th:if="${inStock > 0}" th:each="quantity : ${#numbers.sequence(1,inStock)}"
|
||||||
th:value="${quantity}"
|
th:value="${quantity}"
|
||||||
th:text="${quantity}"></option>
|
th:text="${quantity}"></option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="no-margin secondarytext" th:text="${inStock} ? 'AUF LAGER' : 'NICHT AUF LAGER'"></h3>
|
<h3 class="no-margin secondarytext"
|
||||||
<button class="no-margin secondary" name="fastcheckout" value="false">In den Einkaufswagen
|
th:text="${inStock > 0} ? 'AUF LAGER' : 'NICHT AUF LAGER'"></h3>
|
||||||
|
<button th:if="${inCart == 0}" class="no-margin secondary" name="fastcheckout" value="false"
|
||||||
|
th:disabled="${inStock==0}">In den Einkaufswagen
|
||||||
|
</button>
|
||||||
|
<button th:if="${inCart > 0}" class="no-margin secondary" name="fastcheckout" value="false"
|
||||||
|
th:disabled="${inStock==0}">Anzahl im Einkaufswagen ändern
|
||||||
|
</button>
|
||||||
|
<button class="no-margin" name="fastcheckout" value="true" th:disabled="${inStock==0}">Schneller
|
||||||
|
Checkout
|
||||||
</button>
|
</button>
|
||||||
<button class="no-margin" name="fastcheckout" value="true">Schneller Checkout</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -58,12 +58,19 @@
|
|||||||
<select name="quantity" size="1">
|
<select name="quantity" size="1">
|
||||||
<option th:value="${item.amount}" th:text="${item.amount}" selected></option>
|
<option th:value="${item.amount}" th:text="${item.amount}" selected></option>
|
||||||
<option value="0">Entfernen</option>
|
<option value="0">Entfernen</option>
|
||||||
<option th:each="quantity : ${#numbers.sequence(1,10)}"
|
<option th:if="${item.inStock > 0}"
|
||||||
|
th:each="quantity : ${#numbers.sequence(1,item.inStock)}"
|
||||||
th:value="${quantity}"
|
th:value="${quantity}"
|
||||||
th:text="${quantity}"></option>
|
th:text="${quantity}"></option>
|
||||||
</select>
|
</select>
|
||||||
<button class="small">Ändern</button>
|
<button class="small">Ändern</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr th:if="${item.amount > item.inStock}">
|
||||||
|
<td class="error" colspan="4">
|
||||||
|
Die gewählte Anzahl des Artikels ist leider derzeit nicht lieferbar.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<th:block>
|
<th:block>
|
||||||
@ -97,6 +104,12 @@ Musterstraße 4
|
|||||||
th:value="${user.defaultPayment != null ? user.defaultPayment.creditCardNumber : ''}"
|
th:value="${user.defaultPayment != null ? user.defaultPayment.creditCardNumber : ''}"
|
||||||
pattern="[0-9]{6,16}"
|
pattern="[0-9]{6,16}"
|
||||||
required/>
|
required/>
|
||||||
|
<p th:if="${user.defaultPayment == null}" class="secondary card">
|
||||||
|
Da dies Ihre erste Bestellung ist, wird die Kreditkarte als Standartzahlungsmittel hinterlegt.
|
||||||
|
Sie kann unter den Nutzereinstellungen gelöscht oder geändert werden.
|
||||||
|
</p>
|
||||||
|
<small th:if="${user.defaultPayment != null}" class="no-padding">Die Standardkreditkarte kann unter
|
||||||
|
den <a href="/user/settings">Nutzereinstellungen</a> gelöscht oder geändert werden.</small>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@ -132,7 +145,9 @@ Musterstraße 4
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${user}">
|
<div th:if="${user}">
|
||||||
<button class=" no-margin secondary full-width">jetzt kostenpflichtig bestellen</button>
|
<button class=" no-margin secondary full-width" th:disabled="${inValid}">jetzt kostenpflichtig
|
||||||
|
bestellen
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div th:unless="${user}">
|
<div th:unless="${user}">
|
||||||
<a th:href="@{/login}" class="button secondary no-margin full-width">Einloggen und fortfahren.</a>
|
<a th:href="@{/login}" class="button secondary no-margin full-width">Einloggen und fortfahren.</a>
|
||||||
|
@ -21,13 +21,14 @@
|
|||||||
<main class="sidebar-layout content-width">
|
<main class="sidebar-layout content-width">
|
||||||
<nav th:replace="fragments/customer :: sidebar"></nav>
|
<nav th:replace="fragments/customer :: sidebar"></nav>
|
||||||
<div class="content-width">
|
<div class="content-width">
|
||||||
<form method="POST" th:action="@{/user/settings/changeMail}">
|
<form class="detailflex" method="POST" th:action="@{/user/settings/changeMail}">
|
||||||
<div>
|
<div>
|
||||||
<h2> Login Daten </h2>
|
<h2> Login Daten </h2>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="input-icon">
|
<div class="input-icon">
|
||||||
<input class="full-width" type="text" name="email" th:value="${user.email}" required/>
|
<input class="full-width" type="text" name="email" th:value="${user.email}"
|
||||||
|
pattern="[^@\s]+@[^\.\s]+\.[^\s]+" required/>
|
||||||
<button> Email-Adresse ändern</button>
|
<button> Email-Adresse ändern</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"shouldBeAdvertised": false
|
"shouldBeAdvertised": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Aeroheat CYLON PC-Geh<EFBFBD>use",
|
"title": "Aeroheat CYLON PC-Gehäuse",
|
||||||
"manufacturer": "Aeroheat",
|
"manufacturer": "Aeroheat",
|
||||||
"articleNumber": "acpcg",
|
"articleNumber": "acpcg",
|
||||||
"vatPercent": 19,
|
"vatPercent": 19,
|
||||||
@ -55,4 +55,4 @@
|
|||||||
"shouldBeAdvertised": false
|
"shouldBeAdvertised": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user