Compare commits
59 Commits
e138476d76
...
9dff6adb3d
Author | SHA1 | Date | |
---|---|---|---|
9dff6adb3d | |||
445b504188 | |||
bd8b3db7f3 | |||
8a4ff4cfa5 | |||
2245309198 | |||
d078c44027 | |||
bd8b07990b | |||
2f4c45ed71 | |||
b600040bf3 | |||
4f5e1fe185 | |||
d4ddd8a9a3 | |||
9660e52f34 | |||
72ddfa42ef | |||
5e1170839e | |||
2ef9eb29ac | |||
f4ba79a4cd | |||
b7134a60da | |||
ff4c984f54 | |||
21502a0b1c | |||
b38ffdea34 | |||
6988d3f213 | |||
f5ad05f49f | |||
e539a9433a | |||
b14c565e81 | |||
b04d627695 | |||
839bebcd89 | |||
|
922e3cadef | ||
|
0fb1d5704e | ||
dfa528484c | |||
38fcda708f | |||
9238162a4c | |||
e7e3864b4c | |||
407229f15d | |||
8a2eff1fe9 | |||
e4d6642d61 | |||
9406bbc4ac | |||
e5b28250c2 | |||
db1d3d31b2 | |||
819cca7f2a | |||
846e448f01 | |||
614a929592 | |||
60699ed847 | |||
83ad1f3999 | |||
5b4c0be1c8 | |||
0256c19e8f | |||
adcd840154 | |||
b5495bda3d | |||
106b00a907 | |||
7c73f69865 | |||
86a2e5d8c2 | |||
8d65998ac2 | |||
178f98d664 | |||
33ff754b9d | |||
8ede86fdce | |||
39eefbdd3e | |||
6e3d1cbcf5 | |||
1ce9a971ba | |||
4711527971 | |||
b7b5c7a6b3 |
@ -30,9 +30,10 @@ public class UpdateOffersAction {
|
||||
public List<ArticleOffer> finish() {
|
||||
HashMap<ArticleIdentifier, ArticleOffer> availableOffers = mapOffers();
|
||||
|
||||
// Reset all advertise-flags first. They are set again below.
|
||||
// Reset all advertise-flags and supplier relations first. They are set again below.
|
||||
for (ArticleOffer offer : availableOffers.values()) {
|
||||
offer.shouldBeAdvertised = false;
|
||||
offer.cheapestSupplier = null;
|
||||
}
|
||||
|
||||
for (Entry<ArticleIdentifier, Offer> cheapestOffer : cheapestOffer.entrySet()) {
|
||||
@ -47,7 +48,10 @@ public class UpdateOffersAction {
|
||||
}
|
||||
Article currentOfferedArticle = cheapestOffer.getValue().apiSupplier.findArticle(manufacturer,
|
||||
articleNumber);
|
||||
currentOffer.title = currentOfferedArticle.title;
|
||||
currentOffer.vatPercent = currentOfferedArticle.vatPercent;
|
||||
currentOffer.cheapestSupplier = cheapestOffer.getValue().dbSupplier;
|
||||
currentOffer.pricePerUnitNet = currentOfferedArticle.pricePerUnitNet;
|
||||
|
||||
// Set advertise-flag if any supplier wants it to be set
|
||||
if (currentOfferedArticle.shouldBeAdvertised) {
|
||||
|
@ -0,0 +1,40 @@
|
||||
package org.hso.ecommerce.action.shop;
|
||||
|
||||
import org.hso.ecommerce.entities.shop.Article;
|
||||
import org.hso.ecommerce.repos.shop.ArticleRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class SearchByTermAction {
|
||||
|
||||
public static List<Article> searchByTerm(String sourceTerm, ArticleRepository repository) {
|
||||
|
||||
List<String> terms = Arrays.asList(sourceTerm.split(" "));
|
||||
List<Article> resultArticles = new ArrayList<>();
|
||||
|
||||
terms.forEach(term -> {
|
||||
List<Article> titleArticles = repository.getArticlesByTermInTitle(term); //search in Title
|
||||
titleArticles.forEach(article -> {
|
||||
if(!resultArticles.contains(article)){
|
||||
resultArticles.add(article);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
terms.forEach(term -> {
|
||||
List<Article> descArticles = repository.getArticlesByTermInDescription(term); //search by Term
|
||||
descArticles.forEach(article -> {
|
||||
if(!resultArticles.contains(article)){
|
||||
resultArticles.add(article);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
return resultArticles;
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package org.hso.ecommerce.action.user;
|
||||
|
||||
import org.hso.ecommerce.entities.booking.PaymentMethod;
|
||||
import org.hso.ecommerce.entities.user.User;
|
||||
import org.hso.ecommerce.repos.user.UserRepository;
|
||||
|
||||
public class UpdateUserSettingsAction {
|
||||
|
||||
private User user;
|
||||
private UserRepository repository;
|
||||
|
||||
public UpdateUserSettingsAction(User user, UserRepository repository) {
|
||||
this.user = user;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public UpdateResult updateEmail(String newMail) {
|
||||
UpdateResult result = new UpdateResult(false);
|
||||
if (!newMail.contains("@")) {
|
||||
result.errorString = "Ändern der Email-Addresse nicht möglich. Bitte versuchen Sie es erneut.";
|
||||
} else {
|
||||
this.user.email = newMail;
|
||||
this.repository.save(this.user);
|
||||
result.updated = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public UpdateResult updatePassword(String oldPassword, String password1, String password2) {
|
||||
UpdateResult result = new UpdateResult(false);
|
||||
if (this.user.validatePassword(oldPassword)) {
|
||||
if (password1.equals(password2)) {
|
||||
if (!password1.equals(oldPassword)) {
|
||||
this.user.setPassword(password1);
|
||||
this.repository.save(this.user);
|
||||
result.updated = true;
|
||||
} else {
|
||||
result.errorString = "Das neue Passwort entspricht dem alten Passwort.";
|
||||
}
|
||||
} else {
|
||||
result.errorString = "Die beiden neuen Passwörter stimmen nicht überein. Bitte versuchen Sie es erneut.";
|
||||
}
|
||||
} else {
|
||||
result.errorString = "Das eingegebene alte Passwort stimmt nicht mit dem momentan gespeicherten Passwort überein. Bitte versuchen Sie es erneut.";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public UpdateResult updateShippingInfo(String salutation, String name, String address) {
|
||||
this.user.salutation = salutation;
|
||||
this.user.name = name;
|
||||
this.user.defaultDeliveryAddress.addressString = address;
|
||||
this.repository.save(this.user);
|
||||
return new UpdateResult(true);
|
||||
}
|
||||
|
||||
public UpdateResult updatePaymentInfo(String creditCardNumber) {
|
||||
UpdateResult result = new UpdateResult(false);
|
||||
if (creditCardNumber.matches("[0-9]+")) {
|
||||
this.user.defaultPayment = PaymentMethod.fromCreditCardNumber(creditCardNumber);
|
||||
this.repository.save(this.user);
|
||||
result.updated = true;
|
||||
} else {
|
||||
result.errorString = "Kreditkartennummer darf nur Zahlen enthalten. Bitte versuchen Sie es erneut.";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public class UpdateResult {
|
||||
public boolean updated; //if true worked, if false not worked
|
||||
public String errorString;
|
||||
|
||||
public UpdateResult(boolean updated, String errorString) {
|
||||
this.updated = updated;
|
||||
this.errorString = errorString;
|
||||
}
|
||||
|
||||
public UpdateResult(boolean updated) {
|
||||
this.updated = updated;
|
||||
this.errorString = "";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package org.hso.ecommerce.app;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("user")
|
||||
public class UserRequestController {
|
||||
|
||||
@GetMapping("/")
|
||||
public String user() {
|
||||
return "redirect:/user/settings";
|
||||
}
|
||||
|
||||
@GetMapping("/settings")
|
||||
public String userSettings() {
|
||||
return "user/settings";
|
||||
}
|
||||
|
||||
@GetMapping("/orders/")
|
||||
public String userOrdeers() {
|
||||
return "user/orders/index";
|
||||
}
|
||||
|
||||
@GetMapping("/bonuspoints")
|
||||
public String userBonuspoints() {
|
||||
return "user/bonuspoints";
|
||||
}
|
||||
|
||||
@GetMapping("/notifications/")
|
||||
public String userNotifications() {
|
||||
return "user/notifications/index";
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.hso.ecommerce.controller;
|
||||
|
||||
import org.hso.ecommerce.entities.booking.PaymentMethod;
|
||||
import org.hso.ecommerce.entities.shop.Address;
|
||||
import org.hso.ecommerce.entities.user.User;
|
||||
import org.hso.ecommerce.repos.user.UserRepository;
|
||||
@ -11,6 +12,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.Optional;
|
||||
|
||||
@Controller
|
||||
@ -30,7 +32,8 @@ public class RegisterController {
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam("address") String address,
|
||||
@RequestParam("type") String type,
|
||||
@RequestParam("ad") String ad
|
||||
@RequestParam("ad") String ad,
|
||||
HttpSession session
|
||||
)
|
||||
{
|
||||
Optional<User> user = userRepository.findByEmail(username);
|
||||
@ -52,7 +55,8 @@ public class RegisterController {
|
||||
newUser.setPassword(password);
|
||||
newUser.email = username;
|
||||
newUser.isEmployee = false;
|
||||
//TODO for salutation, type, ad are no attributes/fields in the class/database. Add when they are there.
|
||||
newUser.salutation = salutation;
|
||||
newUser.defaultPayment = PaymentMethod.fromCreditCardNumber("");
|
||||
|
||||
newUser.isActive = true;
|
||||
newUser.created = new java.sql.Timestamp(System.currentTimeMillis());
|
||||
@ -64,7 +68,10 @@ public class RegisterController {
|
||||
|
||||
userRepository.save(newUser); // save newUser
|
||||
|
||||
return "redirect:/login";
|
||||
user = userRepository.findByEmail(username);
|
||||
session.setAttribute("userId", user.get().getId());
|
||||
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
@GetMapping("/register")
|
||||
|
@ -1,8 +1,127 @@
|
||||
package org.hso.ecommerce.controller;
|
||||
|
||||
import org.hso.ecommerce.action.user.UpdateUserSettingsAction;
|
||||
import org.hso.ecommerce.entities.shop.CustomerOrder;
|
||||
import org.hso.ecommerce.entities.user.User;
|
||||
import org.hso.ecommerce.repos.shop.CustomerOrderRepository;
|
||||
import org.hso.ecommerce.repos.user.UserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
//@RequestMapping("...")
|
||||
@RequestMapping("/user")
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
private final UserRepository userRepository = null;
|
||||
|
||||
@Autowired
|
||||
private final CustomerOrderRepository customerOrderRepository = null;
|
||||
|
||||
@GetMapping("/")
|
||||
public String user() {
|
||||
return "redirect:/user/settings";
|
||||
}
|
||||
|
||||
@GetMapping("/settings")
|
||||
public String userSettings(Model model,
|
||||
HttpSession session
|
||||
) {
|
||||
long userId = (long) session.getAttribute("userId");
|
||||
User user = userRepository.findById(userId).get();
|
||||
model.addAttribute("user", user);
|
||||
|
||||
return "user/settings";
|
||||
}
|
||||
|
||||
@GetMapping("/orders/")
|
||||
public String userOrdeers(HttpSession session,
|
||||
Model model
|
||||
) {
|
||||
List<CustomerOrder> orders = customerOrderRepository.getOrdersByUserId((long) session.getAttribute("userId"));
|
||||
model.addAttribute("orders", orders);
|
||||
|
||||
return "user/orders/index";
|
||||
}
|
||||
|
||||
@PostMapping("/settings/changeMail")
|
||||
public String changeMail(HttpSession session,
|
||||
@RequestParam("email") String email,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
User user = userRepository.findById((long) session.getAttribute("userId")).get();
|
||||
|
||||
UpdateUserSettingsAction cusa = new UpdateUserSettingsAction(user, userRepository);
|
||||
UpdateUserSettingsAction.UpdateResult result = cusa.updateEmail(email);
|
||||
if (result.updated == false) {
|
||||
request.setAttribute("error", result.errorString);
|
||||
return "user/settings";
|
||||
}
|
||||
|
||||
return "redirect:/user/settings";
|
||||
}
|
||||
|
||||
@PostMapping("/settings/changePwd")
|
||||
public String changePwd(HttpSession session,
|
||||
@RequestParam("old-password") String oldPassword,
|
||||
@RequestParam("password1") String password1,
|
||||
@RequestParam("password2") String password2,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
User user = userRepository.findById((long) session.getAttribute("userId")).get();
|
||||
|
||||
UpdateUserSettingsAction cusa = new UpdateUserSettingsAction(user, userRepository);
|
||||
UpdateUserSettingsAction.UpdateResult result = cusa.updatePassword(oldPassword, password1, password2);
|
||||
if (result.updated == false) {
|
||||
request.setAttribute("error", result.errorString);
|
||||
return "user/settings";
|
||||
}
|
||||
|
||||
return "redirect:/user/settings";
|
||||
}
|
||||
|
||||
@PostMapping("/settings/changeAddress")
|
||||
public String changeAddress(HttpSession session,
|
||||
@RequestParam("salutation") String salutation,
|
||||
@RequestParam("name") String name,
|
||||
@RequestParam("address") String address,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
User user = userRepository.findById((long) session.getAttribute("userId")).get();
|
||||
|
||||
UpdateUserSettingsAction cusa = new UpdateUserSettingsAction(user, userRepository);
|
||||
UpdateUserSettingsAction.UpdateResult result = cusa.updateShippingInfo(salutation, name, address);
|
||||
if (result.updated == false) {
|
||||
request.setAttribute("error", result.errorString);
|
||||
return "user/settings";
|
||||
}
|
||||
|
||||
return "redirect:/user/settings";
|
||||
}
|
||||
|
||||
@PostMapping("/settings/changePaymentInfo")
|
||||
public String changePaymentInfo(HttpSession session,
|
||||
@RequestParam("creditCardNumber") String creditCardNumber,
|
||||
HttpServletRequest request
|
||||
) {
|
||||
User user = userRepository.findById((long) session.getAttribute("userId")).get();
|
||||
|
||||
UpdateUserSettingsAction cusa = new UpdateUserSettingsAction(user, userRepository);
|
||||
UpdateUserSettingsAction.UpdateResult result = cusa.updatePaymentInfo(creditCardNumber);
|
||||
if (result.updated == false) {
|
||||
request.setAttribute("error", result.errorString);
|
||||
return "user/settings";
|
||||
}
|
||||
|
||||
return "redirect:/user/settings";
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import org.hso.ecommerce.repos.booking.BookingAccountEntryRepository;
|
||||
import org.hso.ecommerce.repos.booking.BookingRepository;
|
||||
import org.hso.ecommerce.repos.cronjob.BackgroundJobRepository;
|
||||
import org.hso.ecommerce.repos.shop.ArticleRepository;
|
||||
import org.hso.ecommerce.repos.shop.CustomerOderRepository;
|
||||
import org.hso.ecommerce.repos.shop.CustomerOrderRepository;
|
||||
import org.hso.ecommerce.repos.supplier.ArticleOfferRepository;
|
||||
import org.hso.ecommerce.repos.supplier.SupplierOrderRepository;
|
||||
import org.hso.ecommerce.repos.supplier.SupplierRepository;
|
||||
@ -230,7 +230,7 @@ class CronjobController {
|
||||
final ArticleOfferRepository articleOfferRepository = null;
|
||||
|
||||
@Autowired
|
||||
final CustomerOderRepository customerOrderRepository = null;
|
||||
final CustomerOrderRepository customerOrderRepository = null;
|
||||
|
||||
@Autowired
|
||||
final BookingRepository bookingRepository = null;
|
||||
|
@ -1,15 +1,5 @@
|
||||
package org.hso.ecommerce.controller.intern;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.hso.ecommerce.entities.shop.Article;
|
||||
import org.hso.ecommerce.entities.shop.Category;
|
||||
import org.hso.ecommerce.entities.shop.Image;
|
||||
@ -27,6 +17,16 @@ import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.view.RedirectView;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("intern/articles")
|
||||
public class InternArticleController {
|
||||
@ -76,7 +76,7 @@ public class InternArticleController {
|
||||
@RequestParam(value = "title", required = true) String title,
|
||||
@RequestParam(value = "description", required = true) String description,
|
||||
@RequestParam(value = "units-per-slot", required = true) String warehouseUnitsPerSlot,
|
||||
@RequestParam(value = "price_netto", required = true) String pricenetto,
|
||||
@RequestParam(value = "priceNet", required = true) String pricenetto,
|
||||
@RequestParam(value = "reorderMaxPrice", required = true) String reorderMaxPrice,
|
||||
@RequestParam(value = "autobuy", required = true) Boolean shouldReorder,
|
||||
@RequestParam(value = "categorie", required = true) String categories,
|
||||
@ -197,7 +197,10 @@ public class InternArticleController {
|
||||
public long id;
|
||||
|
||||
void addListedArticle(Article article, int stock) {
|
||||
this.imgPath = article.image.path;
|
||||
|
||||
if (article.image != null) {
|
||||
this.imgPath = article.image.path;
|
||||
}
|
||||
this.title = article.title;
|
||||
this.priceNet = String.format("%.2f", ((float) article.shopPricePerUnitNetCent / 100));
|
||||
this.price = String.format("%.2f", ((float) article.getPriceGross() / 100));
|
||||
@ -229,6 +232,7 @@ public class InternArticleController {
|
||||
public boolean shouldReorder;
|
||||
public String warehouseUnitsPerSlot;
|
||||
public String description;
|
||||
public int vatPercent;
|
||||
|
||||
public String getCategorie() {
|
||||
return categorie;
|
||||
@ -239,7 +243,9 @@ public class InternArticleController {
|
||||
}
|
||||
|
||||
void addArticle(Article article, int stock) {
|
||||
this.imgPath = article.image.path;
|
||||
if (article.image != null) {
|
||||
this.imgPath = article.image.path;
|
||||
}
|
||||
this.title = article.title;
|
||||
this.priceNet = String.format("%.2f", ((float) article.shopPricePerUnitNetCent / 100));
|
||||
this.price = String.format("%.2f", ((float) article.getPriceGross() / 100));
|
||||
@ -259,6 +265,7 @@ public class InternArticleController {
|
||||
this.shouldReorder = article.shouldReorder;
|
||||
this.warehouseUnitsPerSlot = String.valueOf(article.warehouseUnitsPerSlot);
|
||||
this.description = article.description;
|
||||
this.vatPercent = article.related.vatPercent;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public class SupplierOfferController {
|
||||
@GetMapping("supplierOffers")
|
||||
public String internListedArticles(Model model) {
|
||||
|
||||
List<UImodelOfferedArticle> totals = new ArrayList<UImodelOfferedArticle>();
|
||||
List<UImodelOfferedArticle> totals = new ArrayList<>();
|
||||
|
||||
for (ArticleOffer article : offersRepository.findAll()) {
|
||||
UImodelOfferedArticle tmp = new UImodelOfferedArticle();
|
||||
|
@ -100,8 +100,11 @@ public class ShopArticleController {
|
||||
@PathVariable("id") Long id
|
||||
) throws IOException {
|
||||
Article article = articleRepository.findArticleById(id);
|
||||
InputStream in = new FileInputStream(article.image.path);
|
||||
response.setContentType(MediaType.IMAGE_JPEG_VALUE);
|
||||
IOUtils.copy(in, response.getOutputStream());
|
||||
|
||||
if(article.image != null) {
|
||||
InputStream in = new FileInputStream(article.image.path);
|
||||
response.setContentType(MediaType.IMAGE_JPEG_VALUE);
|
||||
IOUtils.copy(in, response.getOutputStream());
|
||||
}
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ import org.hso.ecommerce.entities.user.User;
|
||||
import org.hso.ecommerce.repos.booking.BookingAccountEntryRepository;
|
||||
import org.hso.ecommerce.repos.booking.BookingRepository;
|
||||
import org.hso.ecommerce.repos.shop.ArticleRepository;
|
||||
import org.hso.ecommerce.repos.shop.CustomerOderRepository;
|
||||
import org.hso.ecommerce.repos.shop.CustomerOrderRepository;
|
||||
import org.hso.ecommerce.repos.user.UserRepository;
|
||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository;
|
||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingRepository;
|
||||
@ -45,7 +45,7 @@ public class ShopCheckoutController {
|
||||
private final WarehouseBookingRepository warehouseBookingRepository = null;
|
||||
|
||||
@Autowired
|
||||
private final CustomerOderRepository customerOderRepository = null;
|
||||
private final CustomerOrderRepository customerOderRepository = null;
|
||||
|
||||
@Autowired
|
||||
private final WarehouseBookingPositionSlotEntryRepository wbeseRepo = null;
|
||||
@ -122,7 +122,7 @@ public class ShopCheckoutController {
|
||||
user,
|
||||
expectedPrice,
|
||||
Address.fromString(address),
|
||||
PaymentMethod.fromCreditCarNumber(cardnumber),
|
||||
PaymentMethod.fromCreditCardNumber(cardnumber),
|
||||
bookingEntryRepository.getByUser(user.id).orElse(BookingAccountEntry.newUser(user)),
|
||||
bookingEntryRepository.getByVat().orElse(BookingAccountEntry.newVat()),
|
||||
bookingEntryRepository.getByMain().orElse(BookingAccountEntry.newMain())
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.hso.ecommerce.controller.shop;
|
||||
|
||||
import org.hso.ecommerce.action.shop.SearchByTermAction;
|
||||
import org.hso.ecommerce.entities.shop.Article;
|
||||
import org.hso.ecommerce.repos.shop.ArticleRepository;
|
||||
import org.hso.ecommerce.repos.shop.CategoryRepository;
|
||||
@ -31,8 +32,10 @@ public class ShopSearchController {
|
||||
) {
|
||||
model.addAttribute("categories", categoryRepository.getCategories()); //for sidebar
|
||||
|
||||
term = term.trim();
|
||||
|
||||
if (term != null) { //if search by Term
|
||||
List<Article> articles = articleRepository.getArticlesByTerm(term); //search by Term
|
||||
List<Article> articles = SearchByTermAction.searchByTerm(term, articleRepository);
|
||||
model.addAttribute("articles", articles);
|
||||
} else if (category != null) { //if search by Category
|
||||
List<Article> articles = articleRepository.getArticlesByCategory(category); //search by Category
|
||||
|
@ -7,7 +7,7 @@ public class PaymentMethod {
|
||||
|
||||
public String creditCardNumber;
|
||||
|
||||
public static PaymentMethod fromCreditCarNumber(String cardnumber) {
|
||||
public static PaymentMethod fromCreditCardNumber(String cardnumber) {
|
||||
PaymentMethod m = new PaymentMethod();
|
||||
m.creditCardNumber = cardnumber;
|
||||
|
||||
|
@ -4,6 +4,7 @@ import org.hso.ecommerce.entities.user.User;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@ -43,4 +44,21 @@ public class CustomerOrder {
|
||||
public int totalNetCent;
|
||||
public int totalGrossCent;
|
||||
public int totalVatCent;
|
||||
|
||||
public String formatInDeliverySince(){
|
||||
return new SimpleDateFormat("dd.MM.yyyy HH:mm").format(inDeliverySince);
|
||||
}
|
||||
|
||||
public String formatCreated(){
|
||||
return new SimpleDateFormat("dd.MM.yyyy HH:mm").format(created);
|
||||
}
|
||||
|
||||
public String formatDeliveredAt(){
|
||||
return new SimpleDateFormat("dd.MM.yyyy HH:mm").format(deliveredAt);
|
||||
}
|
||||
|
||||
public String getEstimatedArrival() {
|
||||
//TODO: get estimated arrival from api
|
||||
return "TODO TODO TODO";
|
||||
}
|
||||
}
|
||||
|
@ -19,4 +19,8 @@ public class CustomerOrderPosition {
|
||||
|
||||
public int pricePerUnit;
|
||||
public int quantity;
|
||||
|
||||
public int getSumPrice(){
|
||||
return article.getPriceGross() * quantity;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,6 @@ public class ArticleOffer {
|
||||
|
||||
public boolean shouldBeAdvertised;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@ManyToOne(optional = true)
|
||||
public Supplier cheapestSupplier;
|
||||
}
|
||||
|
@ -24,6 +24,11 @@ public class User {
|
||||
@Column(unique = true)
|
||||
public String email;
|
||||
|
||||
@Column(insertable = false, updatable = false)
|
||||
public String name;
|
||||
|
||||
public String salutation;
|
||||
|
||||
public String passwordHash;
|
||||
|
||||
public boolean isActive;
|
||||
|
@ -31,7 +31,10 @@ public interface ArticleRepository extends JpaRepository<Article, Long> {
|
||||
Optional<Integer> findArticleIDByRelatedID(@Param("relatedId") long relatedId);
|
||||
|
||||
@Query(value = "Select a.* from articles as a, warehouse_booking_position_entries as wbpe where wbpe.article_id = a.id and a.title LIKE %:term% group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true)
|
||||
List<Article> getArticlesByTerm(String term);
|
||||
List<Article> getArticlesByTermInTitle(String term);
|
||||
|
||||
@Query(value = "Select a.* from articles as a, warehouse_booking_position_entries as wbpe where wbpe.article_id = a.id and a.description LIKE %:term% group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true)
|
||||
List<Article> getArticlesByTermInDescription(String term);
|
||||
|
||||
@Query(value = "Select a.* from articles as a, categories as c, article_categories_bindings as acb, warehouse_booking_position_entries as wbpe where wbpe.article_id = a.id and acb.articles_id = a.id and acb.categories_id = c.id and c.name = :category group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true)
|
||||
List<Article> getArticlesByCategory(String category);
|
||||
|
@ -5,13 +5,17 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface CustomerOderRepository extends JpaRepository<CustomerOrder, Long> {
|
||||
public interface CustomerOrderRepository extends JpaRepository<CustomerOrder, Long> {
|
||||
|
||||
@Query("SELECT SUM(cop.quantity) FROM CustomerOrderPosition cop JOIN cop.order co WHERE cop.article.id = :articleId AND co.created >= :begin AND co.created < :end")
|
||||
Integer countOrdersOfArticleInTimespan(
|
||||
long articleId, java.sql.Timestamp begin, java.sql.Timestamp end
|
||||
);
|
||||
|
||||
}
|
||||
@Query("SELECT co FROM CustomerOrder co WHERE co.customer.id = :userId ORDER BY co.id DESC")
|
||||
List<CustomerOrder> getOrdersByUserId(long userId);
|
||||
|
||||
}
|
15
prototype/src/main/resources/static/js/editViewUpdateTax.js
vendored
Normal file
15
prototype/src/main/resources/static/js/editViewUpdateTax.js
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
let priceElm = document.getElementById("price");
|
||||
let priceGrossElm = document.getElementById("priceGross");
|
||||
let vatPercent = parseInt(document.getElementById("vatPercent").value);
|
||||
|
||||
let updateFn = () => {
|
||||
let net = Math.floor(priceElm.value*100);
|
||||
let vat = Math.floor((net * vatPercent) / 100);
|
||||
let gross = net + vat;
|
||||
|
||||
priceGrossElm.innerText = (gross / 100.0).toFixed(2).replace("\\.", ",");
|
||||
};
|
||||
|
||||
priceElm.onchange = updateFn;
|
||||
});
|
@ -12,8 +12,6 @@
|
||||
<ul class="secondary">
|
||||
<li><a th:href="@{/}"> > Zur Startseite</a></li>
|
||||
<li><a th:href="@{/user/settings}">Einstellungen</a></li>
|
||||
<li><a th:href="@{/user/bonuspoints}">Bonuspunkte</a></li>
|
||||
<li><a th:href="@{/user/notifications/}">Benachrichtigungen</a></li>
|
||||
<li><a th:href="@{/user/orders/}">Bestellungen</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
@ -18,7 +18,6 @@
|
||||
<div th:if="${user}" class="dropdown">
|
||||
<a class="dropdown-button button">Mein Konto</a>
|
||||
<div class="dropdown-content">
|
||||
<a class="black button" th:href="@{/user/notifications/}">Benachrichtigungen</a>
|
||||
<a class="black button" th:href="@{/user/}">Einstellungen</a>
|
||||
<a class="black button" th:href="@{/user/orders/}">Meine Bestellungen</a>
|
||||
<form th:if="${user}" method="post" th:action="@{/logout}" class="no-margin">
|
||||
|
@ -5,6 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
||||
<title>Bearbeiten: Artikel</title>
|
||||
<script th:src="@{/js/filterTable.js}"></script>
|
||||
<script th:src="@{/js/editViewUpdateTax.js}"></script>
|
||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
||||
</head>
|
||||
<body>
|
||||
@ -47,10 +48,13 @@
|
||||
<div class="s">
|
||||
<p>
|
||||
<label for="price">Preis (Netto)</label>
|
||||
<input class="" type="number" id="price" step="0.01" name="price_netto" required th:value="${ArticleID.priceNet}"/> EUR <br/>
|
||||
(19% Mwst.)
|
||||
<input class="" type="number" id="price" step="0.01" name="priceNet" required
|
||||
th:value="${ArticleID.priceNet}"/> EUR <br/>
|
||||
(<span th:text="${ArticleID.vatPercent}"></span>% Mwst.)
|
||||
<input type="hidden" id="vatPercent" name="vatPercent" th:value="${ArticleID.vatPercent}"/>
|
||||
|
||||
<!-- Info von article ref--> <br/>
|
||||
= <span th:text="${ArticleID.price}"></span> EUR Brutto
|
||||
= <span id="priceGross" th:text="${ArticleID.price}"></span> EUR Brutto
|
||||
</p>
|
||||
<p>
|
||||
<label for="reorderMaxPrice">Maximaler Einkaufspreis (Netto)</label>
|
||||
@ -106,4 +110,4 @@
|
||||
</main>
|
||||
<footer th:replace="fragments/footer :: footer"></footer>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@ -63,25 +63,6 @@
|
||||
<textarea rows="5" class="full-width" type="text" name="address" id="address"
|
||||
placeholder="Optional: Zusatz Optional: Unternehmen Straße Hausnummer Postleitzeit Ort Land"></textarea>
|
||||
</div>
|
||||
<fieldset>
|
||||
<input type="radio" name="type" value="priv" id="type-priv" required>
|
||||
<label for="type-priv">Ich bin Privatkunde.</label> <br/>
|
||||
<input type="radio" name="type" value="bus" id="type-bus" required>
|
||||
<label for="type-bus">Ich bin Geschäftskunde.</label> <br/>
|
||||
</fieldset>
|
||||
|
||||
<div>
|
||||
<h2> Werbung </h2>
|
||||
</div>
|
||||
<div>
|
||||
<fieldset>
|
||||
<input type="radio" name="ad" value="y" id="ad-y" required>
|
||||
<label for="type-priv">Ich möchte Werbung erhalten.</label> <br/>
|
||||
<input type="radio" name="ad" value="n" id="ad-n" required>
|
||||
<label for="type-bus">Ich möchte keine Werbung erhalten.</label> <br/>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class="full-width" type="submit" name="action" value="login">Registeren</button>
|
||||
<a th:href="@{/terms}">
|
||||
|
@ -21,30 +21,22 @@
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/customer :: sidebar"></nav>
|
||||
<div class="content-width detailflex">
|
||||
<div>
|
||||
<h2 id="20202701"> Bestellung vom 27.01.2020 </h2>
|
||||
<div th:each="order: ${orders}">
|
||||
<h2 id="20202701" th:text="|Bestellung vom ${order.formatCreated()}" />
|
||||
<div>
|
||||
<table class="key-value">
|
||||
<tr>
|
||||
<th>Lieferstatus</th>
|
||||
<td><b>Unterwegs</b> <br/> Vorraussichtliche Ankunft: 29.01.2020</td>
|
||||
<td th:if="${order.deliveredAt == null}"><b>Unterwegs</b> <br/> Vorraussichtliche Ankunft: <span th:text="${order.getEstimatedArrival()}" /></td>
|
||||
<td th:if="${order.deliveredAt != null}"><b>Angekommen</b> <br/> Ankunft: <span th:text="${order.formatDeliveredAt()}" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Sendeverfolgungsnummer</th>
|
||||
<td>XE51451436DE</td>
|
||||
<td th:text="${order.trackingId}"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td>
|
||||
Hans Maier <br/>
|
||||
Hauptstraße 12<br/>
|
||||
74880 Musterstadt<br/>
|
||||
Deutschland <br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Eingelösste Bonuspunkte</th>
|
||||
<td>10</td>
|
||||
<td th:text="${order.destination.toString()}" />
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@ -55,17 +47,11 @@
|
||||
<th>Menge</th>
|
||||
<th>Preis (Brutto)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-1.jpg}" class="s"/><a></td>
|
||||
<td><a th:href="@{/shop/articles/4151}">Kamera<a/></td>
|
||||
<td> 1</td>
|
||||
<td>100,50 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-2.jpg}" class="s"/><a/></td>
|
||||
<td><a th:href="@{/shop/articles/4151}">Earbuds<a/></td>
|
||||
<td> 3</td>
|
||||
<td>63,95 EUR</td>
|
||||
<tr th:each="position: ${order.positions}">
|
||||
<td><a th:href="@{/shop/articles/{id}(id = ${position.article.id})}"><img th:src="@{/shop/articles/{id}/image.jpg(id=${position.article.id})}" class="s"/></a></td>
|
||||
<td><a th:href="@{/shop/articles/{id}(id = ${position.article.id})}" th:text="${position.article.title}" class="s"></a></td>
|
||||
<td th:text="${position.quantity}" />
|
||||
<td th:text="${#numbers.formatDecimal(position.getSumPrice() * 0.01, 1, 'POINT', 2, 'COMMA')}" />
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
@ -77,19 +63,13 @@
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Artikel (Netto)</td>
|
||||
<td> 120,00 EUR</td>
|
||||
<td th:text="${#numbers.formatDecimal(order.totalNetCent * 0.01, 1, 'POINT', 2, 'COMMA')}" />
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Bonuspunkte</td>
|
||||
<td> 5,00 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Umsatzsteuer (19%)</td>
|
||||
<td> 42,00 EUR</td>
|
||||
<td>Umsatzsteuer</td>
|
||||
<td th:text="${#numbers.formatDecimal(order.totalVatCent * 0.01, 1, 'POINT', 2, 'COMMA')}" />
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
@ -98,89 +78,7 @@
|
||||
<h3>Gesammtpreis</h3>
|
||||
</td>
|
||||
<td>
|
||||
<h3>240,79 EUR</h3>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<h2 id="20200101"> Bestellung vom 01.01.2020 </h2>
|
||||
<div>
|
||||
<table class="key-value">
|
||||
<tr>
|
||||
<th>Lieferstatus</th>
|
||||
<td><b>Angekommen</b> <br/> 03.01.2020</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Sendeverfolgungsnummer</th>
|
||||
<td>XE5140684351DE</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td>
|
||||
Hans Maier <br/>
|
||||
Hauptstraße 12<br/>
|
||||
74880 Musterstadt<br/>
|
||||
Deutschland <br/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Gutgeschriebene Bonuspunkte</th>
|
||||
<td>5</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Bild</th>
|
||||
<th>Name</th>
|
||||
<th>Menge</th>
|
||||
<th>Preis pro Artikel (Brutto)</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-1.jpg}" class="s"/><a></td>
|
||||
<td><a th:href="@{/shop/articles/4151}"> Billige Kamera<a/></td>
|
||||
<td> 1</td>
|
||||
<td>40,50 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a th:href="@{/shop/articles/4151}"><img th:src="@{/img/product-5.jpg}" class="s"/><a></td>
|
||||
<td><a th:href="@{/shop/articles/4151}">Apfel<a/></td>
|
||||
<td> 5</td>
|
||||
<td>1,00 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th>Position</th>
|
||||
<th>Preis</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Artikel (Netto)</td>
|
||||
<td> 20,00 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Umsatzsteuer (19%)</td>
|
||||
<td> 5,00 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>Umsatzsteuer (7%)</td>
|
||||
<td> 2,00 EUR</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<h3>Gesammtpreis</h3>
|
||||
</td>
|
||||
<td>
|
||||
<h3>50,79 EUR</h3>
|
||||
<h3 th:text="${#numbers.formatDecimal(order.totalGrossCent * 0.01, 1, 'POINT', 2, 'COMMA')}"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -21,19 +21,19 @@
|
||||
<main class="sidebar-layout content-width">
|
||||
<nav th:replace="fragments/customer :: sidebar"></nav>
|
||||
<div class="content-width">
|
||||
<form class="detailflex">
|
||||
<form method="POST" th:action="@{/user/settings/changeMail}">
|
||||
<div>
|
||||
<h2> Login Daten </h2>
|
||||
</div>
|
||||
<div>
|
||||
<div class="input-icon">
|
||||
<input class="full-width" type="text" name="email" value="max.mueller@example.com" required/>
|
||||
<input class="full-width" type="text" name="email" th:value="${user.email}" required/>
|
||||
<button> Email-Adresse ändern</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="detailflex">
|
||||
<form class="detailflex" method="POST" th:action="@{/user/settings/changePwd}">
|
||||
<div>
|
||||
<h2> Sicherheit </h2>
|
||||
</div>
|
||||
@ -42,8 +42,8 @@
|
||||
<input class="full-width" type="password" name="old-password" placeholder="Passwort" id="password"
|
||||
required>
|
||||
|
||||
<label for="password">Neues Passwort</label>
|
||||
<input class="full-width" type="password" name="password" placeholder="Passwort" id="password" required>
|
||||
<label for="password1">Neues Passwort</label>
|
||||
<input class="full-width" type="password" name="password1" placeholder="Passwort" id="password1" required>
|
||||
<label for="password2">Neues Passwort wiederholen</label>
|
||||
<input class="full-width" type="password" name="password2" placeholder="Passwort" id="password2"
|
||||
required>
|
||||
@ -51,7 +51,7 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="detailflex">
|
||||
<form class="detailflex" method="POST" th:action="@{/user/settings/changeAddress}">
|
||||
<div>
|
||||
<h2> Rechungs- und Lieferinformation </h2>
|
||||
</div>
|
||||
@ -59,7 +59,7 @@
|
||||
<div class="col-2">
|
||||
<div>
|
||||
<label for="salutation">Anrede</label>
|
||||
<input class="full-width" list="salutationsOpt" name="salutation" placeholder="Anrede" value="Herr"
|
||||
<input class="full-width" list="salutationsOpt" name="salutation" id="salutation" placeholder="Anrede" th:value="${user.salutation}"
|
||||
required/>
|
||||
<datalist id="salutationsOpt">
|
||||
<option value="Herr">
|
||||
@ -70,52 +70,28 @@
|
||||
</div>
|
||||
<div>
|
||||
<label for="name">Name</label>
|
||||
<input class="full-width" type="text" name="name" placeholder="Nachname Vorname" value="Max Müller"
|
||||
<input class="full-width" type="text" name="name" id="name" placeholder="Nachname Vorname" th:value="${user.name}"
|
||||
required/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="address">Anschrift</label>
|
||||
<textarea rows="5" class="full-width" type="text" name="address"
|
||||
placeholder="Optional: Zusatz Optional: Unternehmen Straße Hausnummer Postleitzeit Ort Land">
|
||||
Musterstraße 26
|
||||
7158 Mustertal
|
||||
Deutschland</textarea>
|
||||
<textarea rows="5" class="full-width" type="text" name="address" id="address"
|
||||
placeholder="Optional: Zusatz Optional: Unternehmen Straße Hausnummer Postleitzeit Ort Land" th:text="${user.defaultDeliveryAddress.addressString}"/>
|
||||
</div>
|
||||
<fieldset>
|
||||
<input type="radio" name="type" value="priv" id="type-priv" required checked>
|
||||
<label for="type-priv">Ich bin Privatkunde.</label> <br/>
|
||||
<input type="radio" name="type" value="bus" id="type-bus" required>
|
||||
<label for="type-bus">Ich bin Geschäftskunde.</label> <br/>
|
||||
</fieldset>
|
||||
<div>
|
||||
<button> Lieferinformation ändern</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="detailflex">
|
||||
<div>
|
||||
<h2> Werbung </h2>
|
||||
</div>
|
||||
<div>
|
||||
<fieldset>
|
||||
<input type="radio" name="ad" value="y" id="ad-y" required checked>
|
||||
<label for="type-priv">Ich möchte Werbung erhalten.</label> <br/>
|
||||
<input type="radio" name="ad" value="n" id="ad-n" required>
|
||||
<label for="type-bus">Ich möchte keine Werbung erhalten.</label> <br/>
|
||||
</fieldset>
|
||||
<button type="submit"> Speichern</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form class="detailflex">
|
||||
<form class="detailflex" method="POST" th:action="@{/user/settings/changePaymentInfo}">
|
||||
<div>
|
||||
<h2> Zahlungsinformation</h2>
|
||||
</div>
|
||||
<div>
|
||||
<div class="input-icon">
|
||||
<input class="full-width" type="text" name="payment-card" placeholder="XXXXXXXX840" required/>
|
||||
<input class="full-width" type="text" name="creditCardNumber" th:value="${user.defaultPayment.creditCardNumber}"/>
|
||||
<button> Kreditkartennummer ändern</button>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user