Compare commits
232 Commits
72ddfa42ef
...
master
Author | SHA1 | Date | |
---|---|---|---|
ea940672d7 | |||
d03d94049d | |||
6a23759bbc | |||
b039e2d568 | |||
e320f5b02b | |||
5aca84c43b | |||
5b483d5c5d | |||
037f1ff671 | |||
0edb9572b6
|
|||
a2e05edb7a | |||
99896a4f77 | |||
624ade2032 | |||
99b123565c | |||
be6de240bb | |||
7cf1819460 | |||
17f0c645f1 | |||
bdd1017232 | |||
f4299c33c1 | |||
f86a14b2f8 | |||
2fb5826a3b | |||
b993700ae4 | |||
5d506a1526 | |||
e87d0d8cdd | |||
fb222c9213 | |||
cf9ab66e68 | |||
cdc372d574 | |||
2290f01a8f | |||
3bc0996c73 | |||
758c6810ab | |||
577a4f72f0 | |||
a2aca7a8ca | |||
3b7317a831 | |||
32921a3f87 | |||
63e9bc2336 | |||
31bff55a20 | |||
5861b61565 | |||
f0c9823e45 | |||
6fbb16fea2 | |||
0d547c8903 | |||
5162e3fc19 | |||
8bfe8b37f5 | |||
2e07d03908 | |||
b9e87f5bd4 | |||
cd641d6cc4 | |||
4e9f7800be | |||
8d27c486d5 | |||
714ac4f1de | |||
186db31b17 | |||
fb53c68be3 | |||
19cf6ccfc5 | |||
7fafd14715 | |||
d5181f149a | |||
a950ecb2b9 | |||
f42a50d24d | |||
33118ddb2f | |||
a6a2adc7db | |||
62df2346c3 | |||
c1a0ecdcf3 | |||
a1abbf5329 | |||
deaf283a98 | |||
ffe9af0633 | |||
2989b54593 | |||
b846b919b7 | |||
1f83a82f17 | |||
cd1a8568e6 | |||
53cdb20091 | |||
9389675b5c | |||
97a7f3a8ad | |||
aa2f42a10a | |||
f128a8b9ed | |||
ffea25c082 | |||
d77b8c046a | |||
8fdfe9cc69 | |||
e5332a3348 | |||
c3eaf5ac11 | |||
fa75beb9c4 | |||
4bef17dc0a | |||
79e4986880 | |||
181a09e16b | |||
f4aae9c581
|
|||
ea0c8c45d6
|
|||
8416783e0a | |||
bcbebe8e8d | |||
a570696795 | |||
187656814e | |||
8c0652b26b
|
|||
ef07447abc | |||
bb7b35dc28 | |||
93cfbb4a27 | |||
68cc35cec3 | |||
b2ee048f25 | |||
020a30474e | |||
4bfc8a2cc6 | |||
0ff873baaa | |||
1812c89994 | |||
2442a477c8
|
|||
ebb3c8c235 | |||
e6c068e71a | |||
86e3ced19b | |||
44df9e4b4f | |||
18cbfbf148 | |||
e037b75f7c | |||
486f237135 | |||
396d3fda14 | |||
3b1d378968 | |||
5a0b303601
|
|||
d5825ba7a0
|
|||
8199bd8a23 | |||
774e62f892
|
|||
e1c00eca8f
|
|||
e904eba7a4 | |||
6284a4d7bf | |||
3b364ae815
|
|||
2ba4968556 | |||
18f35c43e7 | |||
709c80fa37 | |||
87bade71b4 | |||
b6eb66e348 | |||
0a7722d612 | |||
d121532fba
|
|||
985169117d | |||
fa610cae3b | |||
3bb3c5b513 | |||
15616e05f3 | |||
0ab185f143 | |||
1dd4b5cfa5 | |||
266bba095a | |||
fa7bdf2f7e | |||
76550be9e7 | |||
ef8aa826a3 | |||
114453b5b9 | |||
7397698929 | |||
9fa2c1f3a7
|
|||
327ba182f5
|
|||
30226c5c19 | |||
e0e853a575 | |||
d2b98f083b | |||
a41889b2cb | |||
0f7d248d40 | |||
11ade7b8f9 | |||
a664b42853 | |||
56f4ec0dda | |||
1590821f64 | |||
16803d2b12 | |||
938d16301d | |||
5a59ac11b0 | |||
c194f44308 | |||
fc68e231d3 | |||
6d8a36b7ac | |||
49e26039a3 | |||
28834431ce | |||
5691f0eeec | |||
7f643987f3
|
|||
6b8bf25e0e | |||
ebeba72278 | |||
f671baf7f0 | |||
691916894f
|
|||
e7e2017825 | |||
03d557d67b
|
|||
8fff0e2dca
|
|||
6317780dfa | |||
78a7ad053a | |||
f6554629d7 | |||
eb82d05f4f | |||
41320473d9 | |||
bd6be54149 | |||
99612165f5 | |||
9dff6adb3d | |||
445b504188 | |||
bd8b3db7f3 | |||
8a4ff4cfa5 | |||
2245309198 | |||
d078c44027 | |||
bd8b07990b | |||
2f4c45ed71 | |||
b600040bf3 | |||
4f5e1fe185 | |||
f348d33c94
|
|||
6f90b9c941
|
|||
e53c1e0872
|
|||
e138476d76 | |||
c1b9588189 | |||
5e05100d21 | |||
93a5863fbe | |||
7f652e38f0 | |||
0061d25082
|
|||
d4ddd8a9a3 | |||
a192f0ac51 | |||
9660e52f34 | |||
fc239983a7 | |||
5e1170839e | |||
f4ba79a4cd | |||
976e2d1949 | |||
b7134a60da | |||
ff4c984f54 | |||
21502a0b1c
|
|||
3775f96f3f | |||
2394157be8 | |||
dfa528484c | |||
1cb52a20d4 | |||
67c101ebea | |||
657d315850 | |||
5d7ecbdfb7 | |||
c8d3ab3ff0 | |||
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 | |||
bba4173269 | |||
e1d7becc2e |
@ -15,3 +15,5 @@ Philipp Schweizer
|
|||||||
Hendrik Schutter
|
Hendrik Schutter
|
||||||
|
|
||||||
Angewandte Informatik WS 2019 + SS 2020
|
Angewandte Informatik WS 2019 + SS 2020
|
||||||
|
|
||||||
|
Resultat: 1.0 für alle! ;-)
|
0
delivery/gradlew
vendored
Normal file → Executable file
@ -4,9 +4,9 @@ package org.hso.ecommerce.supplier;
|
|||||||
import org.hso.ecommerce.supplier.data.Delivery;
|
import org.hso.ecommerce.supplier.data.Delivery;
|
||||||
import org.hso.ecommerce.supplier.data.DeliveryManager;
|
import org.hso.ecommerce.supplier.data.DeliveryManager;
|
||||||
import org.hso.ecommerce.supplier.data.ReturnStatus;
|
import org.hso.ecommerce.supplier.data.ReturnStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
@ -19,14 +19,19 @@ public class RequestController {
|
|||||||
public String supplier(HttpServletResponse response, HttpServletRequest request, @RequestBody Delivery delivery) {
|
public String supplier(HttpServletResponse response, HttpServletRequest request, @RequestBody Delivery delivery) {
|
||||||
DeliveryManager.getInstance().add(delivery);
|
DeliveryManager.getInstance().add(delivery);
|
||||||
|
|
||||||
return delivery.getUuid().toString();
|
return delivery.getUuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/status")
|
@GetMapping(value = "/status", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
public ReturnStatus searchArticles(@RequestParam(value = "trackingID") String trackingID, HttpServletRequest request, HttpServletResponse response) {
|
public ReturnStatus searchArticles(@RequestParam(value = "trackingID") String trackingID, HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
|
||||||
Delivery delivery = DeliveryManager.getInstance().getDeliveryByeID(trackingID);
|
Delivery delivery = DeliveryManager.getInstance().getDeliveryByID(trackingID);
|
||||||
|
if (delivery == null) {
|
||||||
|
Delivery lostDelivery = Delivery.lostDelivery(trackingID);
|
||||||
|
DeliveryManager.getInstance().add(lostDelivery);
|
||||||
|
delivery = lostDelivery;
|
||||||
|
}
|
||||||
|
|
||||||
return new ReturnStatus(delivery.getStatus(),delivery.getEstimatedArrival());
|
return new ReturnStatus(delivery.getStatus(), delivery.getEstimatedArrival());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,38 +8,48 @@ import java.util.UUID;
|
|||||||
|
|
||||||
public class Delivery {
|
public class Delivery {
|
||||||
|
|
||||||
private String[] states = {"Bestellung eingegangen","Bestellung auf dem Weg","Lieferung erfolgreich"};
|
private String[] states = {"Bestellung eingegangen", "Bestellung auf dem Weg", "Lieferung erfolgreich"};
|
||||||
private int[] timeBorder = {4,24};
|
private int[] timeBorder = {4, 24};
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private String address;
|
private String address;
|
||||||
private String estimatedArrival;
|
|
||||||
private Date creationTime;
|
|
||||||
private UUID uuid;
|
|
||||||
|
|
||||||
public Delivery(String name, String address)
|
// Why is this a string and creationTime a Date?!
|
||||||
{
|
private String estimatedArrival;
|
||||||
|
|
||||||
|
private Date creationTime;
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
public Delivery(String name, String address) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID().toString();
|
||||||
this.creationTime = new Date();
|
this.creationTime = new Date();
|
||||||
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
|
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
|
||||||
this.estimatedArrival = formatter.format(addDays((Date)this.creationTime.clone(),1));
|
this.estimatedArrival = formatter.format(addDays((Date) this.creationTime.clone(), 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Delivery lostDelivery(String uuid) {
|
||||||
|
Delivery delivery = new Delivery("", "");
|
||||||
|
delivery.uuid = uuid;
|
||||||
|
delivery.creationTime = addDays(new Date(), -1);
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
|
||||||
|
delivery.estimatedArrival = formatter.format(addDays((Date) delivery.creationTime.clone(), 1));
|
||||||
|
return delivery;
|
||||||
|
}
|
||||||
|
|
||||||
public String getStatus()
|
public String getStatus() {
|
||||||
{
|
|
||||||
Date now = new Date();
|
Date now = new Date();
|
||||||
Long timeNow = now.getTime();
|
long timeNow = now.getTime();
|
||||||
Long creationTime = this.creationTime.getTime();
|
long creationTime = this.creationTime.getTime();
|
||||||
|
|
||||||
Long diff = timeNow - creationTime;
|
// Wow, that's how calculate date diffs.
|
||||||
|
long diff = timeNow - creationTime;
|
||||||
double hour = (((diff / 1000.0) / 3600.0));
|
double hour = (((diff / 1000.0) / 3600.0));
|
||||||
|
|
||||||
for (int i = 0; i < timeBorder.length; i++) {
|
for (int i = 0; i < timeBorder.length; i++) {
|
||||||
|
|
||||||
if(hour < timeBorder[i])
|
if (hour < timeBorder[i])
|
||||||
return states[i];
|
return states[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,15 +61,14 @@ public class Delivery {
|
|||||||
return estimatedArrival;
|
return estimatedArrival;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Date addDays(Date date, int days)
|
private static Date addDays(Date date, int days) {
|
||||||
{
|
|
||||||
Calendar cal = Calendar.getInstance();
|
Calendar cal = Calendar.getInstance();
|
||||||
cal.setTime(date);
|
cal.setTime(date);
|
||||||
cal.add(Calendar.DATE, days);
|
cal.add(Calendar.DATE, days);
|
||||||
return cal.getTime();
|
return cal.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getUuid() {
|
public String getUuid() {
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
package org.hso.ecommerce.supplier.data;
|
package org.hso.ecommerce.supplier.data;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class DeliveryManager {
|
public class DeliveryManager {
|
||||||
|
|
||||||
private List<Delivery> deliveryList;
|
private HashMap<String, Delivery> deliveryList;
|
||||||
private static DeliveryManager deliveryManager;
|
private static DeliveryManager deliveryManager;
|
||||||
|
|
||||||
private DeliveryManager()
|
private DeliveryManager()
|
||||||
{
|
{
|
||||||
deliveryList = new ArrayList<>();
|
deliveryList = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DeliveryManager getInstance () {
|
public static DeliveryManager getInstance() {
|
||||||
|
|
||||||
if (DeliveryManager.deliveryManager == null) {
|
if (DeliveryManager.deliveryManager == null) {
|
||||||
DeliveryManager.deliveryManager = new DeliveryManager();
|
DeliveryManager.deliveryManager = new DeliveryManager();
|
||||||
@ -22,13 +20,11 @@ public class DeliveryManager {
|
|||||||
return DeliveryManager.deliveryManager;
|
return DeliveryManager.deliveryManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean add(Delivery delivery)
|
public void add(Delivery delivery) {
|
||||||
{
|
deliveryList.put(delivery.getUuid(), delivery);
|
||||||
return deliveryList.add(delivery);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Delivery getDeliveryByeID(String uuid)
|
public Delivery getDeliveryByID(String uuid) {
|
||||||
{
|
return deliveryList.getOrDefault(uuid, null);
|
||||||
return deliveryList.parallelStream().filter(d -> d.getUuid().equals(UUID.fromString(uuid))).findAny().get();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
123485
doc/charter/charter.fodt
@ -1,479 +0,0 @@
|
|||||||
:root {
|
|
||||||
font-family: "Fira Sans";
|
|
||||||
line-height: 1.15;
|
|
||||||
|
|
||||||
--u5: calc(1em * 1.5 * 1.5 * 1.5 * 1.5 * 1.5 );
|
|
||||||
--u4: calc(1em * 1.5 * 1.5 * 1.5 * 1.5);
|
|
||||||
--u3: calc(1em * 1.5 * 1.5 * 1.5);
|
|
||||||
--u2: calc(1em * 1.5 * 1.5);
|
|
||||||
--u1: calc(1em * 1.5);
|
|
||||||
--u0: calc(1em);
|
|
||||||
--u-1: calc(1em * 0.666);
|
|
||||||
--u-2: calc(1em * 0.666 * 0.666);
|
|
||||||
--u-3: calc(1em * 0.666 * 0.666 * 0.666);
|
|
||||||
--u-4: calc(1em * 0.666 * 0.666 * 0.666 * 0.666);
|
|
||||||
|
|
||||||
|
|
||||||
--root-c-base: #ecf0f1;
|
|
||||||
--root-c-base-highlight: #bdc3c7;
|
|
||||||
|
|
||||||
--root-c-primary: #1abc9c;
|
|
||||||
--root-c-primary-highlight: #16a085;
|
|
||||||
|
|
||||||
--root-c-secondary: #9b59b6;
|
|
||||||
--root-c-secondary-highlight: #8e44ad;
|
|
||||||
|
|
||||||
--root-c-black: #2c3e50;
|
|
||||||
--root-c-black-highlight: #34495e;
|
|
||||||
|
|
||||||
|
|
||||||
--c-base: var(--root-c-base);
|
|
||||||
--c-base-highlight: var(--root-c-base-highlight);
|
|
||||||
|
|
||||||
--c-primary:var(--root-c-primary);
|
|
||||||
--c-primary-highlight: var(--root-c-primary-highlight);
|
|
||||||
|
|
||||||
--c-secondary: var(--c-secondary);
|
|
||||||
--c-secondary-highlight: var(--root-c-secondary-highlight);
|
|
||||||
|
|
||||||
--c-black: var(--root-c-black);
|
|
||||||
--c-black-highlight: var(--root-c-black-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
.primary {
|
|
||||||
--c-base: var(--root-c-base);
|
|
||||||
--c-base-highlight: var(--root-c-base-highlight);
|
|
||||||
|
|
||||||
--c-primary:var(--root-c-primary);
|
|
||||||
--c-primary-highlight: var(--root-c-primary-highlight);
|
|
||||||
|
|
||||||
--c-secondary: var(--c-secondary);
|
|
||||||
--c-secondary-highlight: var(--root-c-secondary-highlight);
|
|
||||||
|
|
||||||
--c-black: var(--root-c-black);
|
|
||||||
--c-black: var(--root-c-black-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondary {
|
|
||||||
--c-base: var(--root-c-base);
|
|
||||||
--c-base-highlight: var(--root-c-base-highlight);
|
|
||||||
|
|
||||||
--c-primary:var(--root-c-secondary);
|
|
||||||
--c-primary-highlight: var(--root-c-secondary-highlight);
|
|
||||||
|
|
||||||
--c-secondary: var(--root-c-primary);
|
|
||||||
--c-secondary-highlight: var(--root-c-primary-highlight);
|
|
||||||
|
|
||||||
--c-black: var(--root-c-black);
|
|
||||||
--c-black-highlight: var(--root-c-black-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
.inverted {
|
|
||||||
--c-base: var(--root-c-black);
|
|
||||||
--c-base-highlight: var(--root-c-black-highlight);
|
|
||||||
|
|
||||||
--c-primary:var(--root-c-primary);
|
|
||||||
--c-primary-highlight: var(--root-c-primary-highlight);
|
|
||||||
|
|
||||||
--c-secondary: var(--c-secondary);
|
|
||||||
--c-secondary-highlight: var(--root-c-secondary-highlight);
|
|
||||||
|
|
||||||
--c-black: var(--root-c-base);
|
|
||||||
--c-black-highlight: var(--root-c-base-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
* {
|
|
||||||
margin: 0em;
|
|
||||||
padding: 0em;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
html, body {
|
|
||||||
font-size: var(--u0);
|
|
||||||
height: 100%;
|
|
||||||
background-color: var(--c-base);
|
|
||||||
color: var(--c-black)
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
h1, h2, h3, h4, h5 {
|
|
||||||
font-family: "Fira Mono";
|
|
||||||
padding-top: 1em;
|
|
||||||
padding-bottom: 0.618em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
padding-top: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: var(--u2);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: var(--u1);
|
|
||||||
}
|
|
||||||
|
|
||||||
h3, h4, h5 {
|
|
||||||
font-size: var(--u0);
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
list-style-type: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
table td,
|
|
||||||
table th {
|
|
||||||
padding: var(--u0);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
table th {
|
|
||||||
background-color: var(--c-primary);
|
|
||||||
color: var(--c-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
table tr:nth-child(2n+1) {
|
|
||||||
background-color: var(--c-base-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NAV
|
|
||||||
*/
|
|
||||||
|
|
||||||
nav {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
nav h1 {
|
|
||||||
font-size: var(--u0);
|
|
||||||
margin: 0rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav li {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav li li {
|
|
||||||
margin-left: var(--u0);
|
|
||||||
}
|
|
||||||
|
|
||||||
nav li a {
|
|
||||||
padding: var(--u0);
|
|
||||||
transition: all 0.1s ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
nav li a:hover,
|
|
||||||
nav li a.selected {
|
|
||||||
padding: var(--u0);
|
|
||||||
background-color: var(--c-primary);
|
|
||||||
color: var(--c-base);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* FOOTER
|
|
||||||
*/
|
|
||||||
|
|
||||||
footer {
|
|
||||||
padding-top: var(--u3);
|
|
||||||
padding-bottom: var(--u1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* INPUTS
|
|
||||||
*/
|
|
||||||
|
|
||||||
form * {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="text"],
|
|
||||||
input[type="password"] {
|
|
||||||
|
|
||||||
background-color: var(--c-base);
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
border-radius: var(--u-2);
|
|
||||||
margin-top: var(--u0);
|
|
||||||
margin-bottom: var(--u0);
|
|
||||||
|
|
||||||
padding: var(--u0);
|
|
||||||
font-size: var(--u0);
|
|
||||||
color: var(--c-black);
|
|
||||||
|
|
||||||
/* box-shadow: var(--s-0-secondary); */
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="text"]::placeholder,
|
|
||||||
input[type="password"]::placeholder {
|
|
||||||
color: var(--c-primary-highlight);
|
|
||||||
opacity: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
button, .button {
|
|
||||||
font-family: "Fira Mono";
|
|
||||||
font-weight: bold;
|
|
||||||
|
|
||||||
background-color: var(--c-primary);
|
|
||||||
color: var(--c-base);
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
border-radius: var(--u-2);
|
|
||||||
|
|
||||||
margin-bottom: var(--u0);
|
|
||||||
margin-top: var(--u0);
|
|
||||||
|
|
||||||
padding: var(--u0);
|
|
||||||
|
|
||||||
min-width: 10em;
|
|
||||||
|
|
||||||
font-family: "Fira Mono";
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: var(--u0);
|
|
||||||
|
|
||||||
/* box-shadow: var(--s-0-secondary); */
|
|
||||||
}
|
|
||||||
|
|
||||||
button:active, .button:active {
|
|
||||||
background-color: var(--c-primary-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="text"],
|
|
||||||
input[type="password"],
|
|
||||||
button,
|
|
||||||
.button {
|
|
||||||
transition: all 0.1s ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: block;
|
|
||||||
min-width: 10em;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HERO
|
|
||||||
*/
|
|
||||||
|
|
||||||
.hero {
|
|
||||||
background-color: var(--c-primary);
|
|
||||||
color: var(--c-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-black {
|
|
||||||
background-color: var(--c-black);
|
|
||||||
color: var(--c-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* LAYOUT
|
|
||||||
*/
|
|
||||||
|
|
||||||
.content-width {
|
|
||||||
max-width: 80rem;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
|
|
||||||
padding-left: var(--u0);
|
|
||||||
padding-right: var(--u0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-flex {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-flex > * {
|
|
||||||
margin: var(--u0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-flex > .spacer {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-layout {
|
|
||||||
display: flex;
|
|
||||||
align-items: stretch;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-layout > *:nth-child(2) {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.vertical-center {
|
|
||||||
align-items: center;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.center {
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid > * {
|
|
||||||
flex: 1;
|
|
||||||
margin: var(--u0);
|
|
||||||
padding: var(--u0);
|
|
||||||
border-radius: var(--u0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.base > * {
|
|
||||||
background-color: var(--c-base);
|
|
||||||
color: var(--c-black);
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.black > * {
|
|
||||||
background-color: var(--c-black);
|
|
||||||
color: var(--c-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.primary > * {
|
|
||||||
background-color: var(--c-primary);
|
|
||||||
color: var(--c-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.secondary > * {
|
|
||||||
background-color: var(--c-primary-highlight);
|
|
||||||
color: var(--c-base);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-primary .grid.shadow > * {
|
|
||||||
/* box-shadow: var(--s-0-secondary); */
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-black .grid.shadow > * {
|
|
||||||
/* box-shadow: var(--s-0-secondary); */
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.s > .spacer {
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
margin: calc(var(--u0) * 2);
|
|
||||||
padding: 0px;
|
|
||||||
|
|
||||||
width: 10rem;
|
|
||||||
max-width: 10rem;
|
|
||||||
min-width: 7.5rem;
|
|
||||||
height: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.s > * {
|
|
||||||
max-width: 10rem;
|
|
||||||
min-width: 7.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.grid.m > .spacer {
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
margin: calc(var(--u0) * 2);
|
|
||||||
padding: 0px;
|
|
||||||
|
|
||||||
width: 20rem;
|
|
||||||
max-width: 20rem;
|
|
||||||
min-width: 15rem;
|
|
||||||
height: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.m > * {
|
|
||||||
width: 20rem;
|
|
||||||
max-width: 20rem;
|
|
||||||
min-width: 15rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.l > .spacer {
|
|
||||||
box-shadow: none;
|
|
||||||
|
|
||||||
margin: calc(var(--u0) * 2);
|
|
||||||
padding: 0px;
|
|
||||||
|
|
||||||
width: 40rem;
|
|
||||||
max-width: 40rem;
|
|
||||||
min-width: 15rem;
|
|
||||||
height: 0px;
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid.l > * {
|
|
||||||
width: 40rem;
|
|
||||||
max-width: 40rem;
|
|
||||||
min-width: 15rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-spacer.s {
|
|
||||||
min-height: 10rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-spacer.m {
|
|
||||||
min-height: 20rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-spacer.l {
|
|
||||||
min-height: 40rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Impov
|
|
||||||
*/
|
|
||||||
|
|
||||||
.input-icon {
|
|
||||||
/* box-shadow: var(--s-0-secondary); */
|
|
||||||
display: flex;
|
|
||||||
padding: 0px;
|
|
||||||
|
|
||||||
border-radius: var(--u0);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-icon > input {
|
|
||||||
flex: 1;
|
|
||||||
margin: 0px;
|
|
||||||
border-top-right-radius: 0px;
|
|
||||||
border-bottom-right-radius: 0px;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-icon > button {
|
|
||||||
margin: 0px;
|
|
||||||
|
|
||||||
border-top-left-radius: 0px;
|
|
||||||
border-bottom-left-radius: 0px;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CONTENT
|
|
||||||
*/
|
|
||||||
|
|
||||||
.price {
|
|
||||||
opacity: 75%;
|
|
||||||
font-size: var(--u1);
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
@ -1,124 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Frontpage</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="css/ecom.css">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav class='hero'>
|
|
||||||
<div class='content-width bar-flex'>
|
|
||||||
<h1>Project eCommerce</h1>
|
|
||||||
<button>Angebote</button>
|
|
||||||
<div class='spacer input-icon secondary'>
|
|
||||||
<input type="text" placeholder="Nach Produkten suchen..."/>
|
|
||||||
<button>Finden</button>
|
|
||||||
</div>
|
|
||||||
<button>Login</button>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
<main>
|
|
||||||
<div class='hero'>
|
|
||||||
<div class='content-width'>
|
|
||||||
<h1>Angebote</h1>
|
|
||||||
<div class='grid m base shadow'>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<img src="pics/product-1.jpg">
|
|
||||||
<h2>Lorem Ipsum</h2>
|
|
||||||
<p class='price'> 25.14 €</p>
|
|
||||||
<p>
|
|
||||||
Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<img src="pics/product-2.jpg">
|
|
||||||
<h2>Lorem Ipsum</h2>
|
|
||||||
<p class='price'> 10.14 €</p>
|
|
||||||
<p>
|
|
||||||
Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<img src="pics/product-1.jpg">
|
|
||||||
<h2>Lorem Ipsum</h2>
|
|
||||||
<p class='price'> 25.14 €</p>
|
|
||||||
<p>
|
|
||||||
Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<img src="pics/product-2.jpg">
|
|
||||||
<h2>Lorem Ipsum</h2>
|
|
||||||
<p class='price'> 10.14 €</p>
|
|
||||||
<p>
|
|
||||||
Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<img src="pics/product-3.jpg">
|
|
||||||
<h2>Lorem Ipsum</h2>
|
|
||||||
<p class='price'> 44.14 €</p>
|
|
||||||
<p>
|
|
||||||
|
|
||||||
Als Gregor Samsa eines Morgens aus unruhigen Träumen erwachte.
|
|
||||||
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="spacer"></section>
|
|
||||||
<section class="spacer"></section>
|
|
||||||
<section class="spacer"></section>
|
|
||||||
<section class="spacer"></section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="vertical-spacer s"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class=''>
|
|
||||||
<div class='content-width'>
|
|
||||||
<h1>Personalisierte Empfehlungen</h1>
|
|
||||||
<div class="grid l">
|
|
||||||
<img src="undraw/undraw_successful_purchase_secondary.svg"/>
|
|
||||||
<div>
|
|
||||||
<h2>Werde jetzt Kunde</h2>
|
|
||||||
<p> Jetzt Kunde werden und viele Vorteile sichern,
|
|
||||||
wie z.B. personalisierte Empfehlungen. </p>
|
|
||||||
<button>Registieren</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="vertical-spacer s"></div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<footer class="hero-black">
|
|
||||||
<div class='content-width bar-flex'>
|
|
||||||
<h3>Project eCommerce</h3>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div>
|
|
||||||
<h4>Seite</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a>Login</a></li>
|
|
||||||
<li><a>Angebote</a></li>
|
|
||||||
<li><a>Suche</a></li>
|
|
||||||
<li><a>Mitarbeiter Login</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4>Mehr</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a>Nutzungsbedingungen</a></li>
|
|
||||||
<li><a>Datenschutz</a></li>
|
|
||||||
<li><a>Über</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,158 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Frontpage</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="css/ecom.css">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav class='hero'>
|
|
||||||
<div class='content-width bar-flex'>
|
|
||||||
<h1>Project eCommerce</h1>
|
|
||||||
<button>Angebote</button>
|
|
||||||
<div class='spacer input-icon secondary'>
|
|
||||||
<input type="text" placeholder="Nach Produkten suchen..."/>
|
|
||||||
<button>Finden</button>
|
|
||||||
</div>
|
|
||||||
<button>Login</button>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav>
|
|
||||||
<ul>
|
|
||||||
<li><a>Dashboard</a>
|
|
||||||
<ul>
|
|
||||||
<li><a>Artikel</a></li>
|
|
||||||
<li><a>Umsatzsteuer</a></li>
|
|
||||||
<li><a class='selected'>Geldbuchungen</a></li>
|
|
||||||
<li><a>Einstellungen</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a>Lieferanten</a>
|
|
||||||
<ul>
|
|
||||||
<li><a>Warenbuchungen</a></li>
|
|
||||||
<li><a>Geldbuchungen</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a>Lager</a>
|
|
||||||
<ul>
|
|
||||||
<li><a>Bestandsbuchungen</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
<li><a>Kunden</a>
|
|
||||||
<ul>
|
|
||||||
<li><a>Bestellungen</a></li>
|
|
||||||
<li><a>Geldbuchungen</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="content-width">
|
|
||||||
<h1>Geldbuchungen</h1>
|
|
||||||
<p>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Id</th>
|
|
||||||
<th>Datum</th>
|
|
||||||
<th>Betrag</th>
|
|
||||||
<th>Gegenkonto</th>
|
|
||||||
<th>Betreff</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>#100</td>
|
|
||||||
<td>2019-10-08</td>
|
|
||||||
<td>100,50 €</td>
|
|
||||||
<td>Lieferant: Hans</td>
|
|
||||||
<td>Bestellungen: #41</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a class="button">Manuelle Buchung</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer class="hero-black">
|
|
||||||
<div class='content-width bar-flex'>
|
|
||||||
<h3>Project eCommerce</h3>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div>
|
|
||||||
<h4>Seite</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a>Login</a></li>
|
|
||||||
<li><a>Angebote</a></li>
|
|
||||||
<li><a>Suche</a></li>
|
|
||||||
<li><a>Mitarbeiter Login</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4>Mehr</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a>Nutzungsbedingungen</a></li>
|
|
||||||
<li><a>Datenschutz</a></li>
|
|
||||||
<li><a>Über</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,48 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Frontpage</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="css/ecom.css">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class='grid m center vertical-center'>
|
|
||||||
<form class='hero primary'>
|
|
||||||
<p>
|
|
||||||
<label>Nutzername</label>
|
|
||||||
<input type="text" placeholder=""/>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<label>Passwort</label>
|
|
||||||
<input type="password" placeholder=""/>
|
|
||||||
</p>
|
|
||||||
<button class='secondary'>Login</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer class="hero-black">
|
|
||||||
<div class='content-width bar-flex'>
|
|
||||||
<h3>Project eCommerce</h3>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div>
|
|
||||||
<h4>Seite</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a>Login</a></li>
|
|
||||||
<li><a>Angebote</a></li>
|
|
||||||
<li><a>Suche</a></li>
|
|
||||||
<li><a>Mitarbeiter Login</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h4>Mehr</h4>
|
|
||||||
<ul>
|
|
||||||
<li><a>Nutzungsbedingungen</a></li>
|
|
||||||
<li><a>Datenschutz</a></li>
|
|
||||||
<li><a>Über</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 20 KiB |
@ -1,11 +0,0 @@
|
|||||||
package org.hso.ecommerce.action.shop;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.shop.CustomerOrder;
|
|
||||||
|
|
||||||
public class EnableTrackingAction {
|
|
||||||
|
|
||||||
public static void addTrackingInfo(CustomerOrder customerOrder) {
|
|
||||||
// TODO:
|
|
||||||
customerOrder.trackingId = "555-NASE";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,186 +0,0 @@
|
|||||||
package org.hso.ecommerce.app;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.user.User;
|
|
||||||
import org.hso.ecommerce.repos.user.UserRepository;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO clean up this class
|
|
||||||
*/
|
|
||||||
@Controller
|
|
||||||
public class RequestController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private final UserRepository userRepository = null;
|
|
||||||
|
|
||||||
static int notSoRandom = 0;
|
|
||||||
|
|
||||||
@GetMapping("/login")
|
|
||||||
public String login() {
|
|
||||||
return "login";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/login")
|
|
||||||
public String loginPost(
|
|
||||||
HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
@RequestParam("username") String username,
|
|
||||||
@RequestParam("password") String password,
|
|
||||||
HttpSession session
|
|
||||||
) {
|
|
||||||
String gto = (String) session.getAttribute("afterLogin");
|
|
||||||
|
|
||||||
Optional<User> user = userRepository.findByEmail(username);
|
|
||||||
if (!user.isPresent()) {
|
|
||||||
request.setAttribute("error", "Email Adresse falsch.");
|
|
||||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
|
||||||
return "login";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.get().validatePassword(password)) {
|
|
||||||
request.setAttribute("error", "Passwort falsch.");
|
|
||||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
|
||||||
return "login";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.get().isActive) {
|
|
||||||
request.setAttribute("error", "User ist deaktiviert.");
|
|
||||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
|
||||||
return "login";
|
|
||||||
}
|
|
||||||
|
|
||||||
session.setAttribute("userId", user.get().getId());
|
|
||||||
|
|
||||||
if (gto != null && gto.startsWith("/")) {
|
|
||||||
return "redirect:" + gto;
|
|
||||||
} else {
|
|
||||||
return "redirect:/";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/logout")
|
|
||||||
public String logoutPost(HttpServletResponse response,
|
|
||||||
HttpSession session
|
|
||||||
) {
|
|
||||||
session.removeAttribute("userId");
|
|
||||||
return "redirect:/";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/")
|
|
||||||
public String intern() {
|
|
||||||
return "intern/index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/customers/")
|
|
||||||
public String internCustomers() {
|
|
||||||
return "intern/customers/index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/customers/{id}")
|
|
||||||
public String internCustomersId() {
|
|
||||||
return "intern/customers/id";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/customerOrders/")
|
|
||||||
public String internCustomerOrder() {
|
|
||||||
return "intern/customerOrders/index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/customerOrders/{id}")
|
|
||||||
public String internCustomerOrdersId() {
|
|
||||||
return "intern/customerOrders/id";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/suppliers/")
|
|
||||||
public String internSuppliers() {
|
|
||||||
return "intern/suppliers/index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/suppliers/{id}")
|
|
||||||
public String internSuppliersId() {
|
|
||||||
return "intern/suppliers/id";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/supplierOrders/")
|
|
||||||
public String internSupplierOrders() {
|
|
||||||
return "intern/supplierOrders/index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/supplierOrders/{id}")
|
|
||||||
public String internSupplierOrdersId() {
|
|
||||||
return "intern/supplierOrders/id";
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
@GetMapping("/intern/suppliersOffers")
|
|
||||||
public String internSuppliersOffers() {
|
|
||||||
return "intern/offeredArticles/index";
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("/intern/accounting/")
|
|
||||||
public String accounting() {
|
|
||||||
return "intern/accounting/index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/accounting/vat")
|
|
||||||
public String accountingVat() {
|
|
||||||
return "intern/accounting/vat";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/accounting/main")
|
|
||||||
public String accountingIntern() {
|
|
||||||
return "intern/accounting/main";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/accounting/addManual")
|
|
||||||
public String accountingAddManual() {
|
|
||||||
return "intern/accounting/addManual";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/warehouse/")
|
|
||||||
public String accountingWarehouse() {
|
|
||||||
return "intern/warehouse/index";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/warehouse/todo")
|
|
||||||
public String accountingWarehouseTodo() {
|
|
||||||
return "intern/warehouse/todo";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/warehouse/addManual")
|
|
||||||
public String accountingWarehouseAddManual() {
|
|
||||||
return "intern/warehouse/addManual";
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostMapping("/intern/warehouse/progress/{id}")
|
|
||||||
public String accountingWarehouseProgressIdPost(HttpServletResponse response) {
|
|
||||||
if ((notSoRandom++) % 2 == 1) {
|
|
||||||
return "redirect:/intern/warehouse/progress/450";
|
|
||||||
} else {
|
|
||||||
response.setStatus(409);
|
|
||||||
return "intern/warehouse/error_progress_failed";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/warehouse/progress/{id}")
|
|
||||||
public String accountingWarehouseProgressId() {
|
|
||||||
return "intern/warehouse/id_progress";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/intern/warehouse/slots/")
|
|
||||||
public String accountingWarehouseSlots() {
|
|
||||||
return "intern/warehouse/slots/index";
|
|
||||||
}
|
|
||||||
}
|
|
@ -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,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class BookingController {
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class LoginController {
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.shop.Address;
|
|
||||||
import org.hso.ecommerce.entities.user.User;
|
|
||||||
import org.hso.ecommerce.repos.user.UserRepository;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
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
|
|
||||||
public class RegisterController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private final UserRepository userRepository = null;
|
|
||||||
|
|
||||||
@PostMapping("/register")
|
|
||||||
public String registerPost(
|
|
||||||
HttpServletRequest request,
|
|
||||||
HttpServletResponse response,
|
|
||||||
@RequestParam("username") String username,
|
|
||||||
@RequestParam("password") String password,
|
|
||||||
@RequestParam("password2") String password2,
|
|
||||||
@RequestParam("salutation") String salutation,
|
|
||||||
@RequestParam("name") String name,
|
|
||||||
@RequestParam("address") String address,
|
|
||||||
@RequestParam("type") String type,
|
|
||||||
@RequestParam("ad") String ad,
|
|
||||||
HttpSession session
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Optional<User> user = userRepository.findByEmail(username);
|
|
||||||
if (user.isPresent()) {
|
|
||||||
request.setAttribute("error", "Email Adresse existiert bereits!");
|
|
||||||
response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
|
||||||
return "register";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!password.equals(password2)){
|
|
||||||
request.setAttribute("error", "Passwörter sind nicht gleich");
|
|
||||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
|
||||||
return "register";
|
|
||||||
}
|
|
||||||
|
|
||||||
//set values for new user
|
|
||||||
User newUser = new User();
|
|
||||||
newUser.email = username;
|
|
||||||
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.isActive = true;
|
|
||||||
newUser.created = new java.sql.Timestamp(System.currentTimeMillis());
|
|
||||||
|
|
||||||
Address newAddress = new Address();
|
|
||||||
newAddress.name = name;
|
|
||||||
newAddress.addressString = address;
|
|
||||||
newUser.defaultDeliveryAddress = newAddress;
|
|
||||||
|
|
||||||
userRepository.save(newUser); // save newUser
|
|
||||||
|
|
||||||
user = userRepository.findByEmail(username);
|
|
||||||
session.setAttribute("userId", user.get().getId());
|
|
||||||
|
|
||||||
return "redirect:/";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/register")
|
|
||||||
public String register() {
|
|
||||||
return "register";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class UserController {
|
|
||||||
}
|
|
@ -1,331 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller.cronjob;
|
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.action.booking.CreateBookingAction;
|
|
||||||
import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction;
|
|
||||||
import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.ArticleIdentifier;
|
|
||||||
import org.hso.ecommerce.action.cronjob.ReorderAction;
|
|
||||||
import org.hso.ecommerce.action.cronjob.UpdateOffersAction;
|
|
||||||
import org.hso.ecommerce.entities.booking.Booking;
|
|
||||||
import org.hso.ecommerce.entities.booking.BookingAccountEntry;
|
|
||||||
import org.hso.ecommerce.entities.booking.BookingReason;
|
|
||||||
import org.hso.ecommerce.entities.cron.BackgroundJob;
|
|
||||||
import org.hso.ecommerce.entities.shop.Article;
|
|
||||||
import org.hso.ecommerce.entities.supplier.ArticleOffer;
|
|
||||||
import org.hso.ecommerce.entities.supplier.Supplier;
|
|
||||||
import org.hso.ecommerce.entities.supplier.SupplierOrder;
|
|
||||||
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.supplier.ArticleOfferRepository;
|
|
||||||
import org.hso.ecommerce.repos.supplier.SupplierOrderRepository;
|
|
||||||
import org.hso.ecommerce.repos.supplier.SupplierRepository;
|
|
||||||
import org.hso.ecommerce.repos.warehouse.WarehouseBookingPositionSlotEntryRepository;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
interface ICronjob {
|
|
||||||
/**
|
|
||||||
* Calculate the earliest cronjob execution time that happens after the given reference time.
|
|
||||||
*
|
|
||||||
* @param reference Position in time to start searching. The implementor is allowed to modify the reference time.
|
|
||||||
* @return A new Calendar instance (or the same) containing the time for next execution.
|
|
||||||
*/
|
|
||||||
Calendar nextExecution(Calendar reference);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate the latest cronjob execution time that happens before or exactly at the given refernce time.
|
|
||||||
*
|
|
||||||
* @param reference Position in time to start searching. The implementor is allowed to modify the reference time.
|
|
||||||
* @return A new Calendar instance (or the same) containing the time of the last execution.
|
|
||||||
*/
|
|
||||||
Calendar previousExecution(Calendar reference);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute this cronjob.
|
|
||||||
*
|
|
||||||
* @param time The point in time this execution was scheduled. In case of a missed cronjob, the actual time of
|
|
||||||
* this call might be much later.
|
|
||||||
* @param controller Back-reference that allows to use repositories.
|
|
||||||
*/
|
|
||||||
void executeAt(Calendar time, CronjobController controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component
|
|
||||||
class Reorder implements ICronjob {
|
|
||||||
@Override
|
|
||||||
public Calendar nextExecution(Calendar reference) {
|
|
||||||
if (reference.get(Calendar.HOUR_OF_DAY) >= 8) {
|
|
||||||
reference.add(Calendar.DAY_OF_MONTH, 1);
|
|
||||||
}
|
|
||||||
reference.set(Calendar.HOUR_OF_DAY, 8);
|
|
||||||
reference.set(Calendar.MINUTE, 0);
|
|
||||||
reference.set(Calendar.SECOND, 0);
|
|
||||||
reference.set(Calendar.MILLISECOND, 0);
|
|
||||||
return reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Calendar previousExecution(Calendar reference) {
|
|
||||||
if (reference.get(Calendar.HOUR_OF_DAY) < 8) {
|
|
||||||
reference.add(Calendar.DAY_OF_MONTH, -1);
|
|
||||||
}
|
|
||||||
reference.set(Calendar.HOUR_OF_DAY, 8);
|
|
||||||
reference.set(Calendar.MINUTE, 0);
|
|
||||||
reference.set(Calendar.SECOND, 0);
|
|
||||||
reference.set(Calendar.MILLISECOND, 0);
|
|
||||||
return reference;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the amount of ordered articles by customers for the given article type in the time between begin and
|
|
||||||
* end.
|
|
||||||
*
|
|
||||||
* @param article The article to search orders for.
|
|
||||||
* @param begin The start time for the search (included)
|
|
||||||
* @param end The end time for the search (excluded)
|
|
||||||
* @return The number of articles that were ordered by customers in the given range.
|
|
||||||
*/
|
|
||||||
private Integer getOrderedAmounts(Article article, Calendar begin, Calendar end, CronjobController controller) {
|
|
||||||
return controller.customerOrderRepository.countOrdersOfArticleInTimespan(
|
|
||||||
article.id,
|
|
||||||
new Timestamp(begin.getTimeInMillis()), new Timestamp(end.getTimeInMillis()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the amount of ordered articles by customers for the given article type in the three days before the
|
|
||||||
* given reference time. The return-array contains 3 fields: Index 0: Orders 72 to 48 hours ago; Index 1: Orders 48
|
|
||||||
* to 24 hours ago; Index 2: Orders 24 to 0 hours ago.
|
|
||||||
*
|
|
||||||
* @param article The article for which the customer orders are checked.
|
|
||||||
* @param time The reference time to use for calculation of the last orders.
|
|
||||||
* @return A 3-element array containing the orders of the last three days.
|
|
||||||
*/
|
|
||||||
private Integer[] getOrderedAmounts(Article article, Calendar time, CronjobController controller) {
|
|
||||||
Calendar oneDayBefore = (Calendar) time.clone();
|
|
||||||
oneDayBefore.add(Calendar.DAY_OF_MONTH, -1);
|
|
||||||
Calendar twoDaysBefore = (Calendar) time.clone();
|
|
||||||
twoDaysBefore.add(Calendar.DAY_OF_MONTH, -2);
|
|
||||||
Calendar threeDaysBefore = (Calendar) time.clone();
|
|
||||||
threeDaysBefore.add(Calendar.DAY_OF_MONTH, -3);
|
|
||||||
|
|
||||||
return new Integer[] { //
|
|
||||||
getOrderedAmounts(article, threeDaysBefore, twoDaysBefore, controller), //
|
|
||||||
getOrderedAmounts(article, twoDaysBefore, oneDayBefore, controller), //
|
|
||||||
getOrderedAmounts(article, oneDayBefore, time, controller), //
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private HashMap<ArticleIdentifier, ArticleOffer> mapArticleOffers(List<ArticleOffer> articleOffers) {
|
|
||||||
HashMap<ArticleIdentifier, ArticleOffer> map = new HashMap<>();
|
|
||||||
for (ArticleOffer articleOffer : articleOffers) {
|
|
||||||
ArticleIdentifier identifier = new ArticleIdentifier(articleOffer.manufacturer, articleOffer.articleNumber);
|
|
||||||
map.put(identifier, articleOffer);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void executeAt(Calendar time, CronjobController controller) {
|
|
||||||
List<Supplier> suppliers = controller.supplierRepository.findAll();
|
|
||||||
ReadSupplierDataAction.Result supplierData = new ReadSupplierDataAction(suppliers).finish();
|
|
||||||
|
|
||||||
// Save the new offers in the database
|
|
||||||
List<ArticleOffer> allOffers = controller.articleOfferRepository.findAll();
|
|
||||||
allOffers = new UpdateOffersAction(allOffers, supplierData.cheapestOffer).finish();
|
|
||||||
controller.articleOfferRepository.saveAll(allOffers);
|
|
||||||
|
|
||||||
HashMap<ArticleIdentifier, ArticleOffer> mappedOffers = mapArticleOffers(allOffers);
|
|
||||||
|
|
||||||
// Reorder
|
|
||||||
List<Article> allArticles = controller.articleRepository.findAll();
|
|
||||||
for (Article article : allArticles) {
|
|
||||||
Integer[] orderedAmounts = getOrderedAmounts(article, time, controller);
|
|
||||||
|
|
||||||
Integer undeliveredReorders = controller.supplierOrderRepository
|
|
||||||
.countUndeliveredReorders(article.related.articleNumber);
|
|
||||||
|
|
||||||
int amountInStock = controller.warehouseBookingPositionSlotEntryRepository.getArticleStock(article.id)
|
|
||||||
.orElse(0);
|
|
||||||
|
|
||||||
ReorderAction action = new ReorderAction(article, orderedAmounts,
|
|
||||||
undeliveredReorders,
|
|
||||||
amountInStock,
|
|
||||||
supplierData.cheapestOffer, mappedOffers);
|
|
||||||
SupplierOrder order = action.finish();
|
|
||||||
if (order != null) {
|
|
||||||
controller.supplierOrderRepository.save(order);
|
|
||||||
|
|
||||||
// Create bookings for this order
|
|
||||||
int netPrice = order.totalPriceNet;
|
|
||||||
int vatPercent = order.ordered.vatPercent;
|
|
||||||
int vatAmount = netPrice * vatPercent / 100;
|
|
||||||
int grossPrice = netPrice + vatAmount;
|
|
||||||
|
|
||||||
// Obligation towards the supplier
|
|
||||||
BookingAccountEntry mainAccount = controller.bookingAccountEntryRepository.getByMain()
|
|
||||||
.orElseGet(BookingAccountEntry::newMain);
|
|
||||||
BookingAccountEntry supplierAccount = controller.bookingAccountEntryRepository
|
|
||||||
.getBySupplier(order.supplier.id)
|
|
||||||
.orElseGet(() -> BookingAccountEntry.newSupplier(order.supplier));
|
|
||||||
BookingReason obligationReason = new BookingReason(order);
|
|
||||||
Booking obligationBooking = new CreateBookingAction(mainAccount,
|
|
||||||
supplierAccount,
|
|
||||||
obligationReason,
|
|
||||||
grossPrice).finish();
|
|
||||||
controller.bookingRepository.save(obligationBooking);
|
|
||||||
|
|
||||||
// Input Tax
|
|
||||||
BookingAccountEntry vatAccount = controller.bookingAccountEntryRepository.getByVat()
|
|
||||||
.orElseGet(BookingAccountEntry::newVat);
|
|
||||||
mainAccount = controller.bookingAccountEntryRepository.getByMain().get();
|
|
||||||
BookingReason inputTaxReason = new BookingReason(order);
|
|
||||||
Booking inputTaxBooking = new CreateBookingAction(vatAccount, mainAccount, inputTaxReason, vatAmount)
|
|
||||||
.finish();
|
|
||||||
controller.bookingRepository.save(inputTaxBooking);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ScheduledCronjob {
|
|
||||||
public final Calendar executionTime;
|
|
||||||
public final ICronjob cronjob;
|
|
||||||
public final BackgroundJob model;
|
|
||||||
|
|
||||||
public ScheduledCronjob(Calendar executionTime, ICronjob cronjob, BackgroundJob model) {
|
|
||||||
this.executionTime = executionTime;
|
|
||||||
this.cronjob = cronjob;
|
|
||||||
this.model = model;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component
|
|
||||||
class CronjobController {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(CronjobController.class);
|
|
||||||
|
|
||||||
private static final Map<String, ICronjob> cronjobs = getCronjobs();
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private final BackgroundJobRepository cronjobRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
final ArticleRepository articleRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
final ArticleOfferRepository articleOfferRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
final CustomerOderRepository customerOrderRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
final BookingRepository bookingRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
final BookingAccountEntryRepository bookingAccountEntryRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
final WarehouseBookingPositionSlotEntryRepository warehouseBookingPositionSlotEntryRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
final SupplierRepository supplierRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
final SupplierOrderRepository supplierOrderRepository = null;
|
|
||||||
|
|
||||||
private static Map<String, ICronjob> getCronjobs() {
|
|
||||||
HashMap<String, ICronjob> map = new HashMap<>();
|
|
||||||
|
|
||||||
// Register all existing cronjobs
|
|
||||||
map.put(BackgroundJob.JOB_REORDER, new Reorder());
|
|
||||||
|
|
||||||
return Collections.unmodifiableMap(map);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ScheduledCronjob getNextCronjob() {
|
|
||||||
Calendar currentTime = new GregorianCalendar();
|
|
||||||
Iterable<BackgroundJob> jobs = cronjobRepository.findAll();
|
|
||||||
HashMap<String, BackgroundJob> alreadyExecuted = new HashMap<>();
|
|
||||||
for (BackgroundJob job : jobs) {
|
|
||||||
alreadyExecuted.put(job.jobName, job);
|
|
||||||
}
|
|
||||||
ScheduledCronjob earliestJob = null;
|
|
||||||
for (Entry<String, ICronjob> entry : cronjobs.entrySet()) {
|
|
||||||
ScheduledCronjob resultingJob;
|
|
||||||
BackgroundJob dbEntry = alreadyExecuted.get(entry.getKey());
|
|
||||||
if (dbEntry != null) {
|
|
||||||
Calendar previousExecution = new GregorianCalendar();
|
|
||||||
previousExecution.setTimeInMillis(dbEntry.lastExecution.getTime());
|
|
||||||
Calendar followingSchedule = entry.getValue().nextExecution((Calendar) previousExecution.clone());
|
|
||||||
Calendar lastSchedule = entry.getValue().previousExecution((Calendar) currentTime.clone());
|
|
||||||
if (lastSchedule.getTimeInMillis() > followingSchedule.getTimeInMillis()) {
|
|
||||||
// This happens, if more than one execution was missed.
|
|
||||||
// In this case, run the job only once.
|
|
||||||
followingSchedule = lastSchedule;
|
|
||||||
}
|
|
||||||
resultingJob = new ScheduledCronjob(followingSchedule, entry.getValue(), dbEntry);
|
|
||||||
} else {
|
|
||||||
// This cronjob has never been executed before.
|
|
||||||
Calendar lastScheduleTime = entry.getValue().previousExecution((Calendar) currentTime.clone());
|
|
||||||
BackgroundJob model = new BackgroundJob();
|
|
||||||
model.jobName = entry.getKey();
|
|
||||||
resultingJob = new ScheduledCronjob(lastScheduleTime, entry.getValue(), model);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for the job with earliest executionTime - it will run next
|
|
||||||
if (earliestJob == null
|
|
||||||
|| resultingJob.executionTime.getTimeInMillis() < earliestJob.executionTime.getTimeInMillis()) {
|
|
||||||
earliestJob = resultingJob;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return earliestJob;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runCronjobExecutionLoop() {
|
|
||||||
Thread.currentThread().setName("Cronjob");
|
|
||||||
try {
|
|
||||||
while (true) {
|
|
||||||
ScheduledCronjob nextJob = getNextCronjob();
|
|
||||||
if (nextJob == null) {
|
|
||||||
// In case there are no cronjobs
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
long waitingTime = nextJob.executionTime.getTimeInMillis() - System.currentTimeMillis();
|
|
||||||
if (waitingTime > 0) {
|
|
||||||
Thread.sleep(waitingTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
nextJob.cronjob.executeAt(nextJob.executionTime, this);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
log.error("Failed to execute cronjob " + nextJob.cronjob.getClass() + ":");
|
|
||||||
t.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
nextJob.model.lastExecution = new Timestamp(nextJob.executionTime.getTimeInMillis());
|
|
||||||
cronjobRepository.save(nextJob.model);
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.error("The cronjob execution thread has been interrupted");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void onPostConstruct() {
|
|
||||||
new Thread(this::runCronjobExecutionLoop).start();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller.intern;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class InternIndexController {
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller.intern;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class WarehouseController {
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller.intern.customers;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class CustomerOrderController {
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller.intern.customers;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class CustomersIndexController {
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller.intern.suppliers;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class SupplierIndexController {
|
|
||||||
}
|
|
@ -1,145 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller.intern.suppliers;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.supplier.ArticleOffer;
|
|
||||||
import org.hso.ecommerce.repos.shop.ArticleRepository;
|
|
||||||
import org.hso.ecommerce.repos.shop.OffersRepository;
|
|
||||||
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.RequestMapping;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
@RequestMapping("/intern/")
|
|
||||||
public class SupplierOfferController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private final OffersRepository offersRepository = null;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private final ArticleRepository articleRepository = null;
|
|
||||||
|
|
||||||
@GetMapping("supplierOffers")
|
|
||||||
public String internListedArticles(Model model) {
|
|
||||||
|
|
||||||
List<UImodelOfferedArticle> totals = new ArrayList<>();
|
|
||||||
|
|
||||||
for (ArticleOffer article : offersRepository.findAll()) {
|
|
||||||
UImodelOfferedArticle tmp = new UImodelOfferedArticle();
|
|
||||||
tmp.addData(article, articleRepository.findArticleIDByRelatedID(article.id));
|
|
||||||
totals.add(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
model.addAttribute("OfferedArticles", totals);
|
|
||||||
return "intern/offeredArticles/index";
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UImodelOfferedArticle {
|
|
||||||
|
|
||||||
long offer_id;
|
|
||||||
String title;
|
|
||||||
String manufacturer;
|
|
||||||
String articlenumber;
|
|
||||||
String supplierName;
|
|
||||||
String price;
|
|
||||||
String ads;
|
|
||||||
int listedArticleId;
|
|
||||||
boolean offerIsListed; // true --> offered article is listed
|
|
||||||
|
|
||||||
public long getOffer_id() {
|
|
||||||
return offer_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOffer_id(long offer_id) {
|
|
||||||
this.offer_id = offer_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOfferIsListed() {
|
|
||||||
return offerIsListed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOfferIsListed(boolean offerIsListed) {
|
|
||||||
this.offerIsListed = offerIsListed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getManufacturer() {
|
|
||||||
return manufacturer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setManufacturer(String manufacturer) {
|
|
||||||
this.manufacturer = manufacturer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getArticlenumber() {
|
|
||||||
return articlenumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setArticlenumber(String articlenumber) {
|
|
||||||
this.articlenumber = articlenumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSupplierName() {
|
|
||||||
return supplierName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSupplierName(String supplierName) {
|
|
||||||
this.supplierName = supplierName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPrice() {
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPrice(String price) {
|
|
||||||
this.price = price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAds() {
|
|
||||||
return ads;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAds(String ads) {
|
|
||||||
this.ads = ads;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getListedArticleId() {
|
|
||||||
return listedArticleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setListedArticleId(int listedArticleId) {
|
|
||||||
this.listedArticleId = listedArticleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addData(ArticleOffer article, Optional<Integer> listedArticleId) {
|
|
||||||
|
|
||||||
this.offer_id = article.id;
|
|
||||||
this.title = article.title;
|
|
||||||
this.manufacturer = article.manufacturer;
|
|
||||||
this.articlenumber = article.articleNumber;
|
|
||||||
this.supplierName = article.cheapestSupplier.name;
|
|
||||||
this.price = String.format("%.2f", ((float) article.pricePerUnitNet / 100));
|
|
||||||
this.ads = (article.shouldBeAdvertised) ? "Ja" : "Nein";
|
|
||||||
|
|
||||||
if (listedArticleId.isPresent()) {
|
|
||||||
// this offer is listed --> show link
|
|
||||||
this.listedArticleId = listedArticleId.get();
|
|
||||||
offerIsListed = true;
|
|
||||||
} else {
|
|
||||||
// this offer is not listed
|
|
||||||
offerIsListed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package org.hso.ecommerce.controller.intern.suppliers;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
//@RequestMapping("...")
|
|
||||||
public class SupplierOrderController {
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package org.hso.ecommerce.entities.warehouse;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.shop.CustomerOrder;
|
|
||||||
import org.hso.ecommerce.entities.supplier.SupplierOrder;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "warehouse_booking_reasons")
|
|
||||||
public class WarehouseBookingReason {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
@Basic
|
|
||||||
public long id;
|
|
||||||
|
|
||||||
public String comment;
|
|
||||||
|
|
||||||
@ManyToOne(optional = true)
|
|
||||||
public SupplierOrder causeSupplierOrder;
|
|
||||||
|
|
||||||
@ManyToOne(optional = true)
|
|
||||||
public CustomerOrder customerOrder;
|
|
||||||
|
|
||||||
public boolean isManuel;
|
|
||||||
|
|
||||||
// Default Constructor is needed for construction by ORM
|
|
||||||
public WarehouseBookingReason() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public WarehouseBookingReason(CustomerOrder order) {
|
|
||||||
this.customerOrder = order;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package org.hso.ecommerce.repos.booking;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.booking.Booking;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface BookingRepository extends JpaRepository<Booking, Long> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
package org.hso.ecommerce.repos.shop;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.shop.Article;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.data.repository.query.Param;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface ArticleRepository extends JpaRepository<Article, Long> {
|
|
||||||
|
|
||||||
@Query("SELECT a FROM Article a WHERE a.id = :articleId")
|
|
||||||
Article findArticleById(@Param("articleId") long articleId);
|
|
||||||
|
|
||||||
@Query("SELECT a FROM Article a")
|
|
||||||
List<Article> findAll();
|
|
||||||
|
|
||||||
@Query(value = "Select a.* from articles as a, article_offers as ao, warehouse_booking_position_entries as wbpe where a.related_id = ao.id and wbpe.article_id = a.id and ao.should_be_advertised = true group by wbpe.slot_id having max(wbpe.id) and wbpe.new_sum_slot != 0", nativeQuery = true)
|
|
||||||
List<Article> getAdvertisedArticles();
|
|
||||||
|
|
||||||
@Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a ORDER BY co.id DESC")
|
|
||||||
List<Article> getOrderedArticles();
|
|
||||||
|
|
||||||
@Query("SELECT a FROM CustomerOrderPosition cop JOIN cop.order co JOIN co.customer c JOIN cop.article a WHERE c.id = :customerId ORDER BY co.id DESC")
|
|
||||||
List<Article> getOrderedArticles(long customerId);
|
|
||||||
|
|
||||||
@Query(value = "SELECT a.id FROM articles a WHERE a.related_id = :relatedId", nativeQuery = true)
|
|
||||||
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> 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);
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package org.hso.ecommerce.repos.shop;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.shop.CustomerOrder;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface CustomerOderRepository 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
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
package org.hso.ecommerce.repos.supplier;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.supplier.SupplierOrder;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface SupplierOrderRepository extends JpaRepository<SupplierOrder, Long> {
|
|
||||||
|
|
||||||
@Query("SELECT SUM(so.numberOfUnits) FROM SupplierOrder so JOIN so.ordered ao WHERE ao.articleNumber = :articleNumber AND so.delivered IS NULL")
|
|
||||||
Integer countUndeliveredReorders(String articleNumber);
|
|
||||||
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package org.hso.ecommerce.repos.supplier;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.supplier.Supplier;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface SupplierRepository extends JpaRepository<Supplier, Long> {
|
|
||||||
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
package org.hso.ecommerce.repos.user;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.entities.user.User;
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
import org.springframework.data.jpa.repository.Query;
|
|
||||||
import org.springframework.stereotype.Repository;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
public interface UserRepository extends JpaRepository<User, Long> {
|
|
||||||
|
|
||||||
@Query("SELECT c FROM User c WHERE c.email = :email")
|
|
||||||
Optional<User> findByEmail(String email);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Artikelübersicht</title>
|
|
||||||
<script th:src="@{/js/filterTable.js}"></script>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Bestellung 1010</h1>
|
|
||||||
|
|
||||||
<script th:src="@{/js/back.js}"></script>
|
|
||||||
<div class="back" data-group="intern" data-insert="true"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
|
||||||
<div class="content-width">
|
|
||||||
<div>
|
|
||||||
<h2 id="20202701"> Bestellung vom 27.01.2020 </h2>
|
|
||||||
<div>
|
|
||||||
<table class="key-value">
|
|
||||||
<tr>
|
|
||||||
<th>Nutzer</th>
|
|
||||||
<td><a th:href="@{/intern/customers/498}">K-4850</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Lieferstatus</th>
|
|
||||||
<td><b>Unterwegs</b> <br/> Vorraussichtliche Ankunft: 29.01.2020</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Sendeverfolgungsnummer</th>
|
|
||||||
<td>XE51451436DE</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>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Bild</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<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>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th></th>
|
|
||||||
<th>Position</th>
|
|
||||||
<th>Preis</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td>Artikel (Netto)</td>
|
|
||||||
<td> 120,00 EUR</td>
|
|
||||||
</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>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td>
|
|
||||||
<h3>Gesammtpreis</h3>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<h3>240,79 EUR</h3>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,129 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Kunden</title>
|
|
||||||
<script th:src="@{/js/filterTable.js}"></script>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Kunden</h1>
|
|
||||||
<script th:src="@{/js/back.js}"></script>
|
|
||||||
<div class="back" data-group="intern" data-name="Zurück zur Kundenübersicht." data-insert="false"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
|
||||||
<div class="content-width">
|
|
||||||
<p>
|
|
||||||
<table id="main-table">
|
|
||||||
<tr>
|
|
||||||
<th colspan="7">
|
|
||||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
|
||||||
data-target-id="main-table"></input>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Kundennummer</th>
|
|
||||||
<th>Beitrittsdatum</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>E-Mail</th>
|
|
||||||
<th>Status</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1209</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td>Geschäftskunde</td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1208</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td>Inaktiv, Geschäftskunde</td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1207</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1206</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1205</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1204</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1203</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1202</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1201</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>hans.maier@example.com</td>
|
|
||||||
<td>Inaktiv, Mitarbeiter</td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1214</td>
|
|
||||||
<td>2019-11-10</td>
|
|
||||||
<td>Hans Maier</td>
|
|
||||||
<td>admin@example.com</td>
|
|
||||||
<td>Mitarbeiter</td>
|
|
||||||
<td><a th:href="@{/intern/customers/4884}" class="button smaller">Details</a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,103 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Lieferanten Bestellungen</title>
|
|
||||||
<script th:src="@{/js/filterTable.js}"></script>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Lieferanten Bestellungen</h1>
|
|
||||||
|
|
||||||
<script th:src="@{/js/back.js}"></script>
|
|
||||||
<div class="back" data-group="intern" data-name="Zurück zu den Bestellungen bei Lieferanten."
|
|
||||||
data-insert="false"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
|
||||||
<div class="content-width">
|
|
||||||
<p>
|
|
||||||
<table id="main-table">
|
|
||||||
<tr>
|
|
||||||
<th colspan="9">
|
|
||||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
|
||||||
data-target-id="main-table"></input>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Bestellnummer</th>
|
|
||||||
<th>Datum</th>
|
|
||||||
<th>Leiferant</th>
|
|
||||||
<th>Artikel</th>
|
|
||||||
<th>Preis/Stk (Netto)</th>
|
|
||||||
<th>Menge</th>
|
|
||||||
<th>Gesamtpreis (Netto)</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>4545</td>
|
|
||||||
<td>2019-18-10</td>
|
|
||||||
<td><a th:href="@{/intern/suppliers/45015}">Cheap AG</a></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>20,00 EUR</td>
|
|
||||||
<td>10</td>
|
|
||||||
<td>200,00 EUR</td>
|
|
||||||
<td>Unterwegs <br/><a th:href="@{/intern/warehouse/todo}" class="button smaller">Angekommen</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>2455</td>
|
|
||||||
<td>2019-18-10</td>
|
|
||||||
<td><a th:href="@{/intern/suppliers/45015}">Cheap AG</a></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>20,00 EUR</td>
|
|
||||||
<td>11</td>
|
|
||||||
<td>220,00 EUR</td>
|
|
||||||
<td>Unterwegs <br/><a th:href="@{/intern/warehouse/todo}" class="button smaller">Angekommen</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>1224</td>
|
|
||||||
<td>2019-18-10</td>
|
|
||||||
<td><a th:href="@{/intern/suppliers/45015}">Cheap AG</a></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>20,00 EUR</td>
|
|
||||||
<td>11</td>
|
|
||||||
<td>220,00 EUR</td>
|
|
||||||
<td>Angekommen</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>4520</td>
|
|
||||||
<td>2019-18-10</td>
|
|
||||||
<td><a th:href="@{/intern/suppliers/45015}">Cheap AG</a></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>20,00 EUR</td>
|
|
||||||
<td>11</td>
|
|
||||||
<td>220,00 EUR</td>
|
|
||||||
<td>Angekommen</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>4521</td>
|
|
||||||
<td>2019-18-10</td>
|
|
||||||
<td><a th:href="@{/intern/suppliers/45015}">Cheap AG</a></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>20,00 EUR</td>
|
|
||||||
<td>11</td>
|
|
||||||
<td>220,00 EUR</td>
|
|
||||||
<td>Angekommen</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,86 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Lieferanten Details</title>
|
|
||||||
<script th:src="@{/js/filterTable.js}"></script>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Lierfant Cheap AG</h1>
|
|
||||||
|
|
||||||
<script th:src="@{/js/back.js}"></script>
|
|
||||||
<div class="back" data-group="intern" data-insert="true"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
|
||||||
<div class="content-width">
|
|
||||||
<h2>Bestellungen</h2>
|
|
||||||
<p>
|
|
||||||
<table id="main-table">
|
|
||||||
<tr>
|
|
||||||
<th colspan="9">
|
|
||||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
|
||||||
data-target-id="main-table"></input>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Bestellnummer</th>
|
|
||||||
<th>Datum</th>
|
|
||||||
<th>Artikel</th>
|
|
||||||
<th>Preis/Stk (Netto)</th>
|
|
||||||
<th>Menge</th>
|
|
||||||
<th>Gesamtpreis (Netto)</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>4545</td>
|
|
||||||
<td>2019-18-10</td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>20,00 EUR</td>
|
|
||||||
<td>10</td>
|
|
||||||
<td>200,00 EUR</td>
|
|
||||||
<td>Unterwegs <br/><a th:href="@{/intern/warehouse/todo}" class="button smaller">Angekommen</a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
<h2>Buchungen</h2>
|
|
||||||
<div>
|
|
||||||
<h4> Kontostand </h4>
|
|
||||||
<h3> -100,00 EUR </h3>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
<table id="main-table">
|
|
||||||
<tr>
|
|
||||||
<th>Zeitpunkt</th>
|
|
||||||
<th>Betrag</th>
|
|
||||||
<th>Von</th>
|
|
||||||
<th>Kontostand</th>
|
|
||||||
<th>Grund</th>
|
|
||||||
<th>Referenz</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>10.09.2019 13:45</td>
|
|
||||||
<td>100,00 EUR</td>
|
|
||||||
<td><a th:href="@{/intern/accounting/main}">Hauptkonto</a></td>
|
|
||||||
<td>-100,00 EUR</td>
|
|
||||||
<td>Lieferanten-Bestellung</td>
|
|
||||||
<td><a th:href="@{/intern/supplierOrders/#q=4520}">2504</a></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,58 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>e-commerce</title>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<body>
|
|
||||||
<main class="modal l">
|
|
||||||
<div class="detailflex l">
|
|
||||||
<h1>Erfolgreich zugewiesen.</h1>
|
|
||||||
<p>
|
|
||||||
<table id="main-table">
|
|
||||||
<tr>
|
|
||||||
<th>Zeitpunkt</th>
|
|
||||||
<th>Artikel</th>
|
|
||||||
<th>Anzahl</th>
|
|
||||||
<th>Von</th>
|
|
||||||
<th>Nach</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-------------------------------------------------------------->
|
|
||||||
<tr data-group="3">
|
|
||||||
<td>2020-01-12 12:18</td>
|
|
||||||
<td colspan="4" class="l">
|
|
||||||
<a th:href="@{/intern/customerOrders/4808}">Bestellung 8408</a>
|
|
||||||
<div>
|
|
||||||
Hans Maier <br/>
|
|
||||||
Hauptstraße 12<br/>
|
|
||||||
74880 Musterstadt<br/>
|
|
||||||
Deutschland <br/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="3">
|
|
||||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>1</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
|
||||||
<td> -</td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="3">
|
|
||||||
<td><img th:src="@{/img/product-2.jpg}" class="s"/></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/4205}">Spielzeugauto</a></td>
|
|
||||||
<td>2</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%232}">Lagerplatz 02</a></td>
|
|
||||||
<td> -</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
<a class="secondary button" th:href="@{/intern/warehouse/todo}"> Abschließen </a>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,127 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Lager</title>
|
|
||||||
<script th:src="@{/js/filterTable.js}"></script>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Lagerbuchungen</h1>
|
|
||||||
|
|
||||||
<script th:src="@{/js/back.js}"></script>
|
|
||||||
<div class="back" data-group="intern" data-name="Zurück zu den Lagerbuchungen." data-insert="false"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
|
||||||
<div class="content-width">
|
|
||||||
<p>
|
|
||||||
Die Lagerbestände nach Artikel können Sie unter den <a th:href="@{/intern/listedArticles/}">gelisteten
|
|
||||||
Artikeln</a> einsehen.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<table id="main-table">
|
|
||||||
<tr>
|
|
||||||
<th colspan="7">
|
|
||||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
|
||||||
data-target-id="main-table"></input>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Zeitpunkt</th>
|
|
||||||
<th>Artikel</th>
|
|
||||||
<th>Anzahl</th>
|
|
||||||
<th>Von</th>
|
|
||||||
<th>Nach</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
<!-------------------------------------------------------------->
|
|
||||||
<tr data-group="3">
|
|
||||||
<td>2020-01-12 12:18</td>
|
|
||||||
<td colspan="4" class="l">
|
|
||||||
<a th:href="@{/intern/customerOrders/4808}">Bestellung 8408</a>
|
|
||||||
</td>
|
|
||||||
<td>Auf Warteliste <br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="3">
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>1</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
|
||||||
<td> -</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="3">
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/4205}">Spielzeugauto</a></td>
|
|
||||||
<td>2</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%232}">Lagerplatz 02</a></td>
|
|
||||||
<td> -</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-------------------------------------------------------------->
|
|
||||||
<tr data-group="2">
|
|
||||||
<td>2020-01-12 12:15</td>
|
|
||||||
<td colspan="4" class="l">
|
|
||||||
Manuell: Ware war defekt.
|
|
||||||
</td>
|
|
||||||
<td>In Arbeit <br/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="2">
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>1</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
|
||||||
<td> -</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
<!-------------------------------------------------------------->
|
|
||||||
<tr data-group="1">
|
|
||||||
<td>2020-01-12 12:11</td>
|
|
||||||
<td colspan="4" class="l">
|
|
||||||
<a th:href="@{/intern/supplierOrders/#q=4545}">Lieferung 4545</a>
|
|
||||||
</td>
|
|
||||||
<td>Fertig <br/></td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="1">
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>10</td>
|
|
||||||
<td> -</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a>
|
|
||||||
</th>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="1">
|
|
||||||
<td></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>1</td>
|
|
||||||
<td> -</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%234}">Lagerplatz 04</a></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,105 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Packliste</title>
|
|
||||||
<script th:src="@{/js/filterTable.js}"></script>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Packliste</h1>
|
|
||||||
|
|
||||||
<script th:src="@{/js/back.js}"></script>
|
|
||||||
<div class="back" data-group="intern" data-name="Zurück zur Packliste." data-insert="false"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav th:replace="fragments/intern :: sidebar"></nav>
|
|
||||||
<div class="content-width">
|
|
||||||
<p>
|
|
||||||
<table id="main-table">
|
|
||||||
<tr>
|
|
||||||
<th colspan="7">
|
|
||||||
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
|
|
||||||
data-target-id="main-table"></input>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Zeitpunkt</th>
|
|
||||||
<th>Artikel</th>
|
|
||||||
<th>Anzahl</th>
|
|
||||||
<th>Von</th>
|
|
||||||
<th>Nach</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
<!-------------------------------------------------------------->
|
|
||||||
<tr data-group="3">
|
|
||||||
<td>2020-01-12 12:18</td>
|
|
||||||
<td colspan="4" class="l">
|
|
||||||
<a th:href="@{/intern/customerOrders/4808}">Bestellung 8408</a>
|
|
||||||
<div>
|
|
||||||
Hans Maier <br/>
|
|
||||||
Hauptstraße 12<br/>
|
|
||||||
74880 Musterstadt<br/>
|
|
||||||
Deutschland <br/>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<form th:action="@{/intern/warehouse/progress/5410}" method="post">
|
|
||||||
<button type="submit">Beginnen</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="3">
|
|
||||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>1</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
|
||||||
<td> -</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="3">
|
|
||||||
<td><img th:src="@{/img/product-2.jpg}" class="s"/></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/4205}">Spielzeugauto</a></td>
|
|
||||||
<td>2</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%232}">Lagerplatz 02</a></td>
|
|
||||||
<td> -</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<!-------------------------------------------------------------->
|
|
||||||
<tr data-group="2">
|
|
||||||
<td>2020-01-12 12:15</td>
|
|
||||||
<td colspan="4" class="l">
|
|
||||||
Manuell: Ware war defekt.
|
|
||||||
</td>
|
|
||||||
<td><a class="secondary button">Abschließen</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr data-group="2">
|
|
||||||
<td><img th:src="@{/img/product-1.jpg}" class="s"/></td>
|
|
||||||
<td><a th:href="@{/intern/listedArticles/45015}">Kamera</a></td>
|
|
||||||
<td>1</td>
|
|
||||||
<td><a th:href="@{/intern/warehouse/slots/#q=%231}">Lagerplatz 01</a></td>
|
|
||||||
<td> -</td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,97 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Neuen Account erstellen</title>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
|
|
||||||
<script th:src="@{/js/scrollToContent.js}"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
<main class="modal">
|
|
||||||
<form class="detailflex m" th:action="@{/register}" method="POST">
|
|
||||||
<div>
|
|
||||||
<h1>Neuen Account erstellen</h1>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h2> Login Daten </h2>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="username">Email Adresse</label>
|
|
||||||
<input class="full-width" type="text" name="username" placeholder="Email Adresse" id="username" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="password">Passwort</label>
|
|
||||||
<input class="full-width" type="password" name="password" placeholder="Passwort" id="password" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="password2">Passwort wiederholen</label>
|
|
||||||
<input class="full-width" type="password" name="password2" placeholder="Passwort" id="password2" required>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h2> Rechungs- und Lieferinformation </h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-2">
|
|
||||||
<div>
|
|
||||||
<label for="salutation">Anrede</label>
|
|
||||||
<input class="full-width" list="salutationsOpt" name="salutation" id="salutation" placeholder="Anrede"
|
|
||||||
required/>
|
|
||||||
<datalist id="salutationsOpt">
|
|
||||||
<option value="Herr">
|
|
||||||
<option value="Frau">
|
|
||||||
<option value="Herr Dr.">
|
|
||||||
<option value="Frau Dr.">
|
|
||||||
</datalist>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="name">Name</label>
|
|
||||||
<input class="full-width" type="text" name="name" id="name" placeholder="Nachname Vorname" required/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label for="address">Anschrift</label>
|
|
||||||
<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}">
|
|
||||||
Unsere AGBs finden sie hier.
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,57 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Bonusprogramm</title>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Bonusprogramm</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav th:replace="fragments/customer :: sidebar"></nav>
|
|
||||||
<div class="content-width">
|
|
||||||
<div class="grid xl">
|
|
||||||
<div class="card">
|
|
||||||
<h2> Ihr Bonuspunktestand beträgt: </h2>
|
|
||||||
<h1 class="huge"> 15 </h1>
|
|
||||||
</div>
|
|
||||||
<div class="s">
|
|
||||||
<h2> Bonuspunkte sichern </h2>
|
|
||||||
<p>
|
|
||||||
Sie sichern sich automatisch bei jedem Einkaufen pro Angefangenen
|
|
||||||
10 EUR einen Bonuspunkt.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Eine Übersicht ihrer Bonuspunkt finden sie hier auf dieser
|
|
||||||
Bonus.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Um die Bonuspunkte einzulösen hacken sie einfach
|
|
||||||
"Bonuspunkte" verwenden beim Abschließen der Bestellung
|
|
||||||
an. Für jeden Bonuspunkt wird ihnen 0,50 EUR gutgeschrieben.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="s">
|
|
||||||
<img th:src="@{/img/undraw_gift.svg}"/>
|
|
||||||
</div>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
<div class="spacer"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,92 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Meine Benachrichtigungen</title>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Meine Benachrichtigungen</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<main class="sidebar-layout content-width">
|
|
||||||
<nav th:replace="fragments/customer :: sidebar"></nav>
|
|
||||||
<div>
|
|
||||||
<div class="grid xl">
|
|
||||||
<section class="notification unread">
|
|
||||||
<h2>Nachricht vom 17.08.2020, 14:38 Uhr</h2>
|
|
||||||
<h3>Ihre Bestellung kommt voraussichtlich am Donnerstag, den 20.08.2020</h3>
|
|
||||||
<p>
|
|
||||||
Vielen Dank für Ihre Bestellung der folgenden Artikel:<br>
|
|
||||||
<br>
|
|
||||||
2x tolle Kamera<br>
|
|
||||||
1x Bluetooth Kopfhörer<br>
|
|
||||||
3x USB-Magic Light<br>
|
|
||||||
<br>
|
|
||||||
Die Sendung wird Ihnen voraussichtlich am Donnerstag, den 20.08.2020 zugestellt.
|
|
||||||
Den aktuellen Status des Pakets können Sie jederzeit in der <a th:href="@{/shop/orders/}">Bestellübersicht</a>
|
|
||||||
nachvollziehen.
|
|
||||||
</p>
|
|
||||||
<button type="button" name="button">Als gelesen makieren</button>
|
|
||||||
</section>
|
|
||||||
<section class="notification">
|
|
||||||
<h2>Nachricht vom 15.08.2020, 16:38 Uhr</h2>
|
|
||||||
<h3>Jetzt unsere Tagesangebote entdecken.</h3>
|
|
||||||
<p>
|
|
||||||
Entdecken sie jetzt unseren neusten Angebote:
|
|
||||||
</p>
|
|
||||||
<div class="flowflex">
|
|
||||||
<div>
|
|
||||||
<a th:href="@{/shop/articles/1234}" class="section">
|
|
||||||
<h3>Lorem Ipsum</h3>
|
|
||||||
<img th:src="@{/img/product-2.jpg}" class="s"/>
|
|
||||||
<p>Nur 15,00 EUR</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<a th:href="@{/shop/articles/1234}" class="section">
|
|
||||||
<h3>Stativ</h3>
|
|
||||||
<img th:src="@{/img/product-4.jpg}" class="s"/>
|
|
||||||
<p>Nur 7,00 EUR</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<a th:href="@{/shop/articles/1234}" class="section">
|
|
||||||
<h3>Ersatzfernbedinung</h3>
|
|
||||||
<img th:src="@{/img/product-6.jpg}" class="s"/>
|
|
||||||
<p>Nur 17,00 EUR</p>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<section class="notification">
|
|
||||||
<h2>Nachricht vom 13.08.2020, 14:38 Uhr</h2>
|
|
||||||
<h3>Ihre Bestellung ist angekommen.</h3>
|
|
||||||
<p>
|
|
||||||
Vielen Dank für Ihre Bestellung der folgenden Artikel:<br>
|
|
||||||
<br>
|
|
||||||
3x USB-Magic Light<br>
|
|
||||||
<br>
|
|
||||||
Ihre Bestellungen ist angekommen.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
<section class="spacer"></section>
|
|
||||||
<section class="spacer"></section>
|
|
||||||
<section class="spacer"></section>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,193 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
|
|
||||||
|
|
||||||
<title>Meine Bestellungen</title>
|
|
||||||
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<nav th:replace="fragments/header :: header">Header</nav>
|
|
||||||
|
|
||||||
<div class="sidebar-layout content-width">
|
|
||||||
<nav></nav>
|
|
||||||
<div>
|
|
||||||
<h1>Meine Bestellungen</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<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>
|
|
||||||
<table class="key-value">
|
|
||||||
<tr>
|
|
||||||
<th>Lieferstatus</th>
|
|
||||||
<td><b>Unterwegs</b> <br/> Vorraussichtliche Ankunft: 29.01.2020</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Sendeverfolgungsnummer</th>
|
|
||||||
<td>XE51451436DE</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>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Bild</th>
|
|
||||||
<th>Name</th>
|
|
||||||
<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>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th></th>
|
|
||||||
<th>Position</th>
|
|
||||||
<th>Preis</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td>Artikel (Netto)</td>
|
|
||||||
<td> 120,00 EUR</td>
|
|
||||||
</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>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td>
|
|
||||||
<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>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<footer th:replace="fragments/footer :: footer"></footer>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
50
supplier/config/mda.json
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"id" : "mda",
|
||||||
|
"name" : "MDA",
|
||||||
|
"discount" : {
|
||||||
|
"minimumDailySalesVolumeNetCent": 20,
|
||||||
|
"percentDiscount": 3
|
||||||
|
},
|
||||||
|
"articles": [
|
||||||
|
{
|
||||||
|
"title": "MDA Nezyr 7",
|
||||||
|
"manufacturer": "MDA",
|
||||||
|
"articleNumber": "n7",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 29990,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "MDA Nezyr 5",
|
||||||
|
"manufacturer": "MDA",
|
||||||
|
"articleNumber": "n5",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 19700,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "MDA Nezyr 3",
|
||||||
|
"manufacturer": "MDA",
|
||||||
|
"articleNumber": "n3",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 8990,
|
||||||
|
"shouldBeAdvertised": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "MDA Nezyr Threadcracker 3990",
|
||||||
|
"manufacturer": "MDA",
|
||||||
|
"articleNumber": "ntc3990",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 404900,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "MDA Radon RX 5700",
|
||||||
|
"manufacturer": "MDA",
|
||||||
|
"articleNumber": "rrx5700",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 43624,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
34
supplier/config/nanosoft.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"id" : "nanosoft",
|
||||||
|
"name" : "Nanosoft",
|
||||||
|
"discount" : {
|
||||||
|
"minimumDailySalesVolumeNetCent": 50,
|
||||||
|
"percentDiscount": 0.5
|
||||||
|
},
|
||||||
|
"articles": [
|
||||||
|
{
|
||||||
|
"title": "Nanosoft Doors 10",
|
||||||
|
"manufacturer": "Nanosoft",
|
||||||
|
"articleNumber": "d10",
|
||||||
|
"vatPercent": 7,
|
||||||
|
"pricePerUnitNet": 2099,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Nanosoft Interior Pro 7",
|
||||||
|
"manufacturer": "Nanosoft",
|
||||||
|
"articleNumber": "ip7",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 90780,
|
||||||
|
"shouldBeAdvertised": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Nanosoft Ybox Two",
|
||||||
|
"manufacturer": "Nanosoft",
|
||||||
|
"articleNumber": "ybox2",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 23500,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
42
supplier/config/outtel.json
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"id" : "outtel",
|
||||||
|
"name" : "Outtel",
|
||||||
|
"discount" : {
|
||||||
|
"minimumDailySalesVolumeNetCent": 20,
|
||||||
|
"percentDiscount": 1
|
||||||
|
},
|
||||||
|
"articles": [
|
||||||
|
{
|
||||||
|
"title": "Outtel Core o7",
|
||||||
|
"manufacturer": "Outtel",
|
||||||
|
"articleNumber": "o7",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 40000,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Outtel Core o5",
|
||||||
|
"manufacturer": "Outtel",
|
||||||
|
"articleNumber": "o5",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 25000,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Outtel Core o3",
|
||||||
|
"manufacturer": "Outtel",
|
||||||
|
"articleNumber": "o3",
|
||||||
|
"vatPercent": 7,
|
||||||
|
"pricePerUnitNet": 8000,
|
||||||
|
"shouldBeAdvertised": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Outtel Core o9",
|
||||||
|
"manufacturer": "Outtel",
|
||||||
|
"articleNumber": "o9",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 55000,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
50
supplier/config/pear.json
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"id" : "pear",
|
||||||
|
"name" : "Pear",
|
||||||
|
"discount" : {
|
||||||
|
"minimumDailySalesVolumeNetCent": 100,
|
||||||
|
"percentDiscount": 2
|
||||||
|
},
|
||||||
|
"articles": [
|
||||||
|
{
|
||||||
|
"title": "Pear iMobile 10",
|
||||||
|
"manufacturer": "Pear",
|
||||||
|
"articleNumber": "iM10",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 31500,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Pear iPlate Plus",
|
||||||
|
"manufacturer": "Pear",
|
||||||
|
"articleNumber": "ipp",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 44900,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Pear iDonalds 9",
|
||||||
|
"manufacturer": "Pear",
|
||||||
|
"articleNumber": "id9",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 234800,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Pear GroundPods",
|
||||||
|
"manufacturer": "Pear",
|
||||||
|
"articleNumber": "gp",
|
||||||
|
"vatPercent": 7,
|
||||||
|
"pricePerUnitNet": 13599,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Pear Donalsbook Pro",
|
||||||
|
"manufacturer": "Pear",
|
||||||
|
"articleNumber": "dbp",
|
||||||
|
"vatPercent": 7,
|
||||||
|
"pricePerUnitNet": 145900,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
42
supplier/config/sumsang.json
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"id" : "sumsang",
|
||||||
|
"name" : "Sumsang",
|
||||||
|
"discount" : {
|
||||||
|
"minimumDailySalesVolumeNetCent": 300,
|
||||||
|
"percentDiscount": 2
|
||||||
|
},
|
||||||
|
"articles": [
|
||||||
|
{
|
||||||
|
"title": "Sumsang Universe S10",
|
||||||
|
"manufacturer": "Sumsang",
|
||||||
|
"articleNumber": "us10",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 59000,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Sumsang Universe S10e",
|
||||||
|
"manufacturer": "Sumsang",
|
||||||
|
"articleNumber": "us10e",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 70231,
|
||||||
|
"shouldBeAdvertised": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Sumsang DumbTV",
|
||||||
|
"manufacturer": "Sumsang",
|
||||||
|
"articleNumber": "dtv",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 38395,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Sumsang UniverseWatch",
|
||||||
|
"manufacturer": "Sumsang",
|
||||||
|
"articleNumber": "uw",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 20494,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
58
supplier/config/techdealer.json
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"id" : "techdealer",
|
||||||
|
"name" : "Tech Dealer",
|
||||||
|
"discount" : {
|
||||||
|
"minimumDailySalesVolumeNetCent": 100,
|
||||||
|
"percentDiscount": 2
|
||||||
|
},
|
||||||
|
"articles": [
|
||||||
|
{
|
||||||
|
"title": "TROPIC Gehäuselüfter",
|
||||||
|
"manufacturer": "TROPIC",
|
||||||
|
"articleNumber": "tgl",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 459,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Pirate PC-Netzteil",
|
||||||
|
"manufacturer": "Pirate",
|
||||||
|
"articleNumber": "ppcn",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 9355,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Pirate Void Elite RGB Wireless Gaming Headset",
|
||||||
|
"manufacturer": "Pirate",
|
||||||
|
"articleNumber": "pvergbwgh",
|
||||||
|
"vatPercent": 7,
|
||||||
|
"pricePerUnitNet": 10999,
|
||||||
|
"shouldBeAdvertised": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Aeroheat CYLON PC-Gehäuse",
|
||||||
|
"manufacturer": "Aeroheat",
|
||||||
|
"articleNumber": "acpcg",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 3999,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Illogitech C270 Webcam",
|
||||||
|
"manufacturer": "Illogitech",
|
||||||
|
"articleNumber": "ic270w",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 3499,
|
||||||
|
"shouldBeAdvertised": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Illogitech Z607 Surround Sound Lautsprecher",
|
||||||
|
"manufacturer": "Illogitech",
|
||||||
|
"articleNumber": "iz607ssl",
|
||||||
|
"vatPercent": 19,
|
||||||
|
"pricePerUnitNet": 9495,
|
||||||
|
"shouldBeAdvertised": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
package org.hso.ecommerce.supplier;
|
package org.hso.ecommerce.supplier;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.supplier.carrier.Avian;
|
||||||
|
import org.hso.ecommerce.supplier.carrier.Carrier;
|
||||||
|
import org.hso.ecommerce.supplier.carrier.Posaidon;
|
||||||
|
import org.hso.ecommerce.supplier.carrier.Shredder;
|
||||||
import org.hso.ecommerce.supplier.data.Article;
|
import org.hso.ecommerce.supplier.data.Article;
|
||||||
import org.hso.ecommerce.supplier.data.Order;
|
import org.hso.ecommerce.supplier.data.Order;
|
||||||
import org.hso.ecommerce.supplier.data.OrderConfirmation;
|
import org.hso.ecommerce.supplier.data.OrderConfirmation;
|
||||||
@ -22,6 +26,10 @@ public class RequestController {
|
|||||||
private final HashMap<String, Supplier> knownSuppliers = new HashMap<>();
|
private final HashMap<String, Supplier> knownSuppliers = new HashMap<>();
|
||||||
private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
private final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|
||||||
|
private final Carrier[] carriers = new Carrier[]{
|
||||||
|
new Avian(), new Posaidon(), new Shredder()
|
||||||
|
};
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() throws IOException {
|
public void init() throws IOException {
|
||||||
for (Supplier s : ConfigurationReader.read()) {
|
for (Supplier s : ConfigurationReader.read()) {
|
||||||
@ -38,7 +46,7 @@ public class RequestController {
|
|||||||
@GetMapping("/{supplier}/")
|
@GetMapping("/{supplier}/")
|
||||||
public Supplier supplier(HttpServletResponse res, @PathVariable("supplier") String supplierName) {
|
public Supplier supplier(HttpServletResponse res, @PathVariable("supplier") String supplierName) {
|
||||||
Supplier s = knownSuppliers.get(supplierName);
|
Supplier s = knownSuppliers.get(supplierName);
|
||||||
if(s == null) {
|
if (s == null) {
|
||||||
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@ -47,25 +55,32 @@ public class RequestController {
|
|||||||
@PostMapping("/{supplier}/order")
|
@PostMapping("/{supplier}/order")
|
||||||
public OrderConfirmation order(HttpServletResponse res, @PathVariable("supplier") String supplierName, @RequestBody Order order) {
|
public OrderConfirmation order(HttpServletResponse res, @PathVariable("supplier") String supplierName, @RequestBody Order order) {
|
||||||
Supplier s = knownSuppliers.get(supplierName);
|
Supplier s = knownSuppliers.get(supplierName);
|
||||||
if(s == null) {
|
if (s == null) {
|
||||||
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String dateKey = simpleDateFormat.format(new Date());
|
String dateKey = simpleDateFormat.format(new Date());
|
||||||
int dailyVolume = dailySalesVolumeCent.getOrDefault(dateKey,0);
|
int dailyVolume = dailySalesVolumeCent.getOrDefault(dateKey, 0);
|
||||||
|
|
||||||
Article a = s.findArticle(order.manufacturer, order.articleNumber);
|
Article a = s.findArticle(order.manufacturer, order.articleNumber);
|
||||||
if(a == null) {
|
if (a == null) {
|
||||||
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int priceNet = a.pricePerUnitNet * order.quantity;
|
int priceNet = a.pricePerUnitNet * order.quantity;
|
||||||
int discount = 0;
|
int discountableNetAmount = 0;
|
||||||
if(dailyVolume >= s.discount.minimumDailySalesVolumeNetCent) {
|
if (dailyVolume >= s.discount.minimumDailySalesVolumeNetCent) {
|
||||||
discount = (priceNet * s.discount.percentDiscount) / 100;
|
// grant discount on the full price
|
||||||
|
discountableNetAmount = priceNet;
|
||||||
|
} else if (dailyVolume + priceNet > s.discount.minimumDailySalesVolumeNetCent) {
|
||||||
|
// grant partial discount
|
||||||
|
discountableNetAmount = dailyVolume + priceNet - s.discount.minimumDailySalesVolumeNetCent;
|
||||||
}
|
}
|
||||||
|
int discount = (discountableNetAmount * s.discount.percentDiscount) / 100;
|
||||||
|
|
||||||
|
Carrier selectedCarrier = carriers[Math.abs((supplierName + java.time.LocalDate.now()).hashCode()) % carriers.length];
|
||||||
|
|
||||||
OrderConfirmation confirmation = new OrderConfirmation();
|
OrderConfirmation confirmation = new OrderConfirmation();
|
||||||
confirmation.articleNumber = order.articleNumber;
|
confirmation.articleNumber = order.articleNumber;
|
||||||
@ -74,6 +89,9 @@ public class RequestController {
|
|||||||
confirmation.manufacturer = a.manufacturer;
|
confirmation.manufacturer = a.manufacturer;
|
||||||
confirmation.quantity = order.quantity;
|
confirmation.quantity = order.quantity;
|
||||||
confirmation.totalPriceNetCharged = priceNet - discount;
|
confirmation.totalPriceNetCharged = priceNet - discount;
|
||||||
|
confirmation.carrier = selectedCarrier.getName();
|
||||||
|
confirmation.trackingId = selectedCarrier.generateTrackingId();
|
||||||
|
confirmation.estimatedArrival = selectedCarrier.arrivalEstimate();
|
||||||
|
|
||||||
if (confirmation.totalPriceNetCharged > order.maxTotalPriceCentNet) {
|
if (confirmation.totalPriceNetCharged > order.maxTotalPriceCentNet) {
|
||||||
res.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
res.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package org.hso.ecommerce.supplier.carrier;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Avian implements Carrier {
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Avian Carriers";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateTrackingId() {
|
||||||
|
Random rnd = new Random();
|
||||||
|
|
||||||
|
return "2001-"
|
||||||
|
+ Integer.toHexString(rnd.nextInt(0xFFFF))
|
||||||
|
+ "--"
|
||||||
|
+ Integer.toHexString(rnd.nextInt(0xFFFF))
|
||||||
|
+ "-"
|
||||||
|
+ Integer.toHexString(rnd.nextInt(0xFFFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime arrivalEstimate() {
|
||||||
|
return LocalDateTime.now().plusHours(8);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package org.hso.ecommerce.supplier.carrier;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public interface Carrier {
|
||||||
|
public String getName();
|
||||||
|
|
||||||
|
public String generateTrackingId();
|
||||||
|
|
||||||
|
public LocalDateTime arrivalEstimate();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
package org.hso.ecommerce.supplier.carrier;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Posaidon implements Carrier {
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Poseidon Inc.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateTrackingId() {
|
||||||
|
Random rnd = new Random();
|
||||||
|
return "WAT"
|
||||||
|
+ Integer.toString(rnd.nextInt(Short.MAX_VALUE))
|
||||||
|
+ "3"
|
||||||
|
+ Integer.toString(rnd.nextInt(Short.MAX_VALUE))
|
||||||
|
+ "R";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime arrivalEstimate() {
|
||||||
|
return LocalDateTime.now().plusHours(50);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.hso.ecommerce.supplier.carrier;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Shredder implements Carrier {
|
||||||
|
|
||||||
|
private Random rnd = new Random();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Schree & Derr";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generateTrackingId() {
|
||||||
|
return "O" + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + d() + "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime arrivalEstimate() {
|
||||||
|
return LocalDateTime.now().plusHours(22);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a random digit followed by a dash.
|
||||||
|
*/
|
||||||
|
private String d() {
|
||||||
|
return Integer.toString(rnd.nextInt(9)) + "-";
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package org.hso.ecommerce.supplier.data;
|
package org.hso.ecommerce.supplier.data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public class OrderConfirmation {
|
public class OrderConfirmation {
|
||||||
public String manufacturer;
|
public String manufacturer;
|
||||||
public String articleNumber;
|
public String articleNumber;
|
||||||
@ -9,4 +11,8 @@ public class OrderConfirmation {
|
|||||||
public int pricePerUnitNetCent;
|
public int pricePerUnitNetCent;
|
||||||
public int discountNetCent;
|
public int discountNetCent;
|
||||||
public int totalPriceNetCharged;
|
public int totalPriceNetCharged;
|
||||||
|
|
||||||
|
public String carrier;
|
||||||
|
public String trackingId;
|
||||||
|
public LocalDateTime estimatedArrival;
|
||||||
}
|
}
|
||||||
|
@ -5,3 +5,5 @@ e-commerce.db
|
|||||||
./e-commerce.iml
|
./e-commerce.iml
|
||||||
./e-commerce.ipr
|
./e-commerce.ipr
|
||||||
./e-commerce.iws
|
./e-commerce.iws
|
||||||
|
|
||||||
|
config.yml
|
@ -1,6 +1,7 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.2.7.RELEASE")
|
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.2.7.RELEASE")
|
||||||
@ -28,7 +29,8 @@ dependencies {
|
|||||||
implementation 'com.github.gwenn:sqlite-dialect:0.1.0'
|
implementation 'com.github.gwenn:sqlite-dialect:0.1.0'
|
||||||
implementation 'org.springframework.boot:spring-boot-devtools'
|
implementation 'org.springframework.boot:spring-boot-devtools'
|
||||||
implementation 'org.xerial:sqlite-jdbc:3.31.1'
|
implementation 'org.xerial:sqlite-jdbc:3.31.1'
|
||||||
testCompile("org.springframework.boot:spring-boot-starter-test")
|
implementation 'org.yaml:snakeyaml:1.26'
|
||||||
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.6.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
group 'org.hso'
|
group 'org.hso'
|
||||||
@ -37,3 +39,11 @@ version '0.1.0'
|
|||||||
bootRun {
|
bootRun {
|
||||||
args = ["--spring.profiles.active=dev --spring.config.location=classpath:/application.properties"]
|
args = ["--spring.profiles.active=dev --spring.config.location=classpath:/application.properties"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
|
||||||
|
testLogging {
|
||||||
|
events 'PASSED', 'FAILED', 'SKIPPED'
|
||||||
|
}
|
||||||
|
}
|
0
prototype/gradlew → web_backend/gradlew
vendored
Normal file → Executable file
3
web_backend/scripts/addsupplierorders.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
INSERT INTO supplier_orders ("created", "delivered", "number_of_units", "price_per_unit_net_cent", "total_price_net", "ordered_id", "supplier_id")
|
||||||
|
VALUES ('0', '0', '42', '42', '42', '1', '1');
|
@ -10,6 +10,7 @@ public class CreateBookingAction {
|
|||||||
|
|
||||||
public CreateBookingAction(BookingAccountEntry source, BookingAccountEntry destination, BookingReason reason, int amountCent) {
|
public CreateBookingAction(BookingAccountEntry source, BookingAccountEntry destination, BookingReason reason, int amountCent) {
|
||||||
booking = new Booking();
|
booking = new Booking();
|
||||||
|
booking.created = new java.sql.Timestamp(System.currentTimeMillis());
|
||||||
booking.reason = reason;
|
booking.reason = reason;
|
||||||
booking.amountCent = amountCent;
|
booking.amountCent = amountCent;
|
||||||
|
|
@ -1,8 +1,5 @@
|
|||||||
package org.hso.ecommerce.action.cronjob;
|
package org.hso.ecommerce.action.cronjob;
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.ArticleIdentifier;
|
import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.ArticleIdentifier;
|
||||||
import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.Offer;
|
import org.hso.ecommerce.action.cronjob.ReadSupplierDataAction.Offer;
|
||||||
import org.hso.ecommerce.api.SupplierService;
|
import org.hso.ecommerce.api.SupplierService;
|
||||||
@ -14,6 +11,9 @@ import org.hso.ecommerce.entities.supplier.SupplierOrder;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class ReorderAction {
|
public class ReorderAction {
|
||||||
private static final Logger log = LoggerFactory.getLogger(ReorderAction.class);
|
private static final Logger log = LoggerFactory.getLogger(ReorderAction.class);
|
||||||
|
|
||||||
@ -102,6 +102,10 @@ public class ReorderAction {
|
|||||||
createdOrder.numberOfUnits = confirm.quantity;
|
createdOrder.numberOfUnits = confirm.quantity;
|
||||||
createdOrder.pricePerUnitNetCent = confirm.pricePerUnitNetCent;
|
createdOrder.pricePerUnitNetCent = confirm.pricePerUnitNetCent;
|
||||||
createdOrder.totalPriceNet = confirm.totalPriceNetCharged;
|
createdOrder.totalPriceNet = confirm.totalPriceNetCharged;
|
||||||
|
createdOrder.carrier = confirm.carrier;
|
||||||
|
createdOrder.trackingId = confirm.trackingId;
|
||||||
|
createdOrder.estimatedArrival = Timestamp.valueOf(confirm.estimatedArrival);
|
||||||
|
|
||||||
return createdOrder;
|
return createdOrder;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
|
|||||||
|
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -74,9 +75,15 @@ public class CreateOrderAction {
|
|||||||
CustomerPayment payment = createPayment();
|
CustomerPayment payment = createPayment();
|
||||||
|
|
||||||
List<Booking> bookingList = new ArrayList<>();
|
List<Booking> bookingList = new ArrayList<>();
|
||||||
bookingList.add(new CreateBookingAction(latestUserBooking, latestMainBooking, new BookingReason(order), order.totalGrossCent).finish());
|
Booking purchaseBooking = new CreateBookingAction(
|
||||||
bookingList.add(new CreateBookingAction(null, latestUserBooking, new BookingReason(payment), order.totalGrossCent).finish());
|
latestUserBooking, latestMainBooking, new BookingReason(order), order.totalGrossCent).finish();
|
||||||
bookingList.add(new CreateBookingAction(latestMainBooking, latestVatBooking, new BookingReason(order), order.totalVatCent).finish());
|
Booking paymentBooking = new CreateBookingAction(
|
||||||
|
null, purchaseBooking.source /* userAccount */, new BookingReason(payment), order.totalGrossCent).finish();
|
||||||
|
Booking vatBooking = new CreateBookingAction(
|
||||||
|
purchaseBooking.destination /* mainAccount */, latestVatBooking, new BookingReason(order), order.totalVatCent).finish();
|
||||||
|
bookingList.add(purchaseBooking);
|
||||||
|
bookingList.add(paymentBooking);
|
||||||
|
bookingList.add(vatBooking);
|
||||||
|
|
||||||
WarehouseBooking warehouseBooking = createWarehouseBooking(order);
|
WarehouseBooking warehouseBooking = createWarehouseBooking(order);
|
||||||
|
|
||||||
@ -95,7 +102,14 @@ public class CreateOrderAction {
|
|||||||
for (OrderItem item : orderItems) {
|
for (OrderItem item : orderItems) {
|
||||||
int needed = item.quantity;
|
int needed = item.quantity;
|
||||||
|
|
||||||
|
// Sort for most empty slot first;
|
||||||
|
item.availableSlots.sort(Comparator.comparingInt(a -> a.newSumSlot));
|
||||||
|
|
||||||
for (WarehouseBookingPositionSlotEntry slot : item.availableSlots) {
|
for (WarehouseBookingPositionSlotEntry slot : item.availableSlots) {
|
||||||
|
if (slot.newSumSlot == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int remove = Math.min(slot.newSumSlot, needed);
|
int remove = Math.min(slot.newSumSlot, needed);
|
||||||
needed -= remove;
|
needed -= remove;
|
||||||
|
|
||||||
@ -103,7 +117,7 @@ public class CreateOrderAction {
|
|||||||
|
|
||||||
bookingPosition.article = item.article;
|
bookingPosition.article = item.article;
|
||||||
bookingPosition.amount = -remove;
|
bookingPosition.amount = -remove;
|
||||||
bookingPosition.slotEntry = slot.copyAddAmount(-remove);
|
bookingPosition.slotEntry = slot.copyAddAmount(-remove, item.article);
|
||||||
bookingPosition.booking = booking;
|
bookingPosition.booking = booking;
|
||||||
|
|
||||||
booking.positions.add(bookingPosition);
|
booking.positions.add(bookingPosition);
|
@ -0,0 +1,16 @@
|
|||||||
|
package org.hso.ecommerce.action.shop;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.api.RestServiceForDelivery;
|
||||||
|
import org.hso.ecommerce.entities.shop.CustomerOrder;
|
||||||
|
import org.springframework.web.client.ResourceAccessException;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class EnableTrackingAction {
|
||||||
|
|
||||||
|
public static void addTrackingInfo(RestServiceForDelivery deliveryService, CustomerOrder customerOrder) throws ResourceAccessException {
|
||||||
|
customerOrder.inDeliverySince = new Timestamp(new Date().getTime());
|
||||||
|
customerOrder.trackingId = deliveryService.getDeliveryID(customerOrder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package org.hso.ecommerce.action.user;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.api.RestServiceForDelivery;
|
||||||
|
import org.hso.ecommerce.entities.shop.CustomerOrder;
|
||||||
|
import org.hso.ecommerce.repos.shop.CustomerOrderRepository;
|
||||||
|
import org.hso.ecommerce.uimodel.DeliveryData;
|
||||||
|
import org.hso.ecommerce.uimodel.DeliveryDataEnum;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
public class CreateDeliveryData {
|
||||||
|
|
||||||
|
public static DeliveryData getDeliveryDataFromCustomerOrder(CustomerOrder customerOrder, CustomerOrderRepository customerOrderRepository, RestServiceForDelivery restServiceForDelivery)
|
||||||
|
{
|
||||||
|
if(customerOrder.trackingId == null)
|
||||||
|
return new DeliveryData("", "", DeliveryDataEnum.NO_TRACKING_ID);
|
||||||
|
|
||||||
|
if(customerOrder.deliveredAt == null)
|
||||||
|
{
|
||||||
|
DeliveryData deliveryData = restServiceForDelivery.getDeliveryData(customerOrder.trackingId);
|
||||||
|
|
||||||
|
|
||||||
|
if(deliveryData.isDelivered())
|
||||||
|
{
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
|
||||||
|
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");
|
||||||
|
|
||||||
|
try {
|
||||||
|
calendar.setTime(simpleDateFormat.parse(deliveryData.getEstimatedArrival()));
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
customerOrder.deliveredAt = new Timestamp(calendar.getTimeInMillis());
|
||||||
|
customerOrderRepository.save(customerOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deliveryData;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
|
||||||
|
return new DeliveryData("Lieferung erfolgreich", formatter.format(customerOrder.deliveredAt), DeliveryDataEnum.OK);
|
||||||
|
}
|
||||||
|
}
|
@ -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.defaultDeliveryAddress.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 = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.hso.ecommerce.action.warehouse;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CalculateWarehouseStatsAction {
|
||||||
|
|
||||||
|
private List<WarehouseBookingPositionSlotEntry> entryList;
|
||||||
|
|
||||||
|
public CalculateWarehouseStatsAction(List<WarehouseBookingPositionSlotEntry> everyCurrentEntry) {
|
||||||
|
this.entryList = everyCurrentEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WarehouseStats finish() {
|
||||||
|
int numArticles = calculateNumArticles();
|
||||||
|
double efficiency = calculateEfficiency();
|
||||||
|
double ratioUsedSlots = calculateRatioSlotsUsed();
|
||||||
|
|
||||||
|
return new WarehouseStats(numArticles, efficiency, ratioUsedSlots);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double calculateRatioSlotsUsed() {
|
||||||
|
int used = 0;
|
||||||
|
|
||||||
|
for (WarehouseBookingPositionSlotEntry entry : entryList) {
|
||||||
|
if (entry.newSumSlot > 0) {
|
||||||
|
used++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((double) used) / entryList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private double calculateEfficiency() {
|
||||||
|
double e = 0;
|
||||||
|
|
||||||
|
for (WarehouseBookingPositionSlotEntry entry : entryList) {
|
||||||
|
if (entry.newSumSlot > 0) {
|
||||||
|
e += entry.newSumSlot / (double) entry.article.warehouseUnitsPerSlot;
|
||||||
|
} else {
|
||||||
|
e += 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e / entryList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calculateNumArticles() {
|
||||||
|
HashSet<Long> articleIds = new HashSet<>();
|
||||||
|
|
||||||
|
for (WarehouseBookingPositionSlotEntry entry : entryList) {
|
||||||
|
if (entry.newSumSlot > 0) {
|
||||||
|
articleIds.add(entry.article.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return articleIds.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WarehouseStats {
|
||||||
|
public int numArticles;
|
||||||
|
public double efficiency;
|
||||||
|
public double ratioUsedSlots;
|
||||||
|
|
||||||
|
WarehouseStats(int numArticles, double efficiency, double ratioUsedSlots) {
|
||||||
|
this.numArticles = numArticles;
|
||||||
|
this.efficiency = efficiency;
|
||||||
|
this.ratioUsedSlots = ratioUsedSlots;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,92 @@
|
|||||||
|
package org.hso.ecommerce.action.warehouse;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.entities.booking.BookingReason;
|
||||||
|
import org.hso.ecommerce.entities.shop.Article;
|
||||||
|
import org.hso.ecommerce.entities.warehouse.WarehouseBooking;
|
||||||
|
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPosition;
|
||||||
|
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class CreateManuelBookingAction {
|
||||||
|
|
||||||
|
private Article article;
|
||||||
|
private int amount;
|
||||||
|
private Optional<WarehouseBookingPositionSlotEntry> source;
|
||||||
|
private Optional<WarehouseBookingPositionSlotEntry> destination;
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
public CreateManuelBookingAction(Article article, int amount, Optional<WarehouseBookingPositionSlotEntry> source, Optional<WarehouseBookingPositionSlotEntry> destination, String reason) {
|
||||||
|
this.article = article;
|
||||||
|
this.amount = amount;
|
||||||
|
this.source = source;
|
||||||
|
this.destination = destination;
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WarehouseBooking finish() throws ArticleSlotConstraintFailedException {
|
||||||
|
WarehouseBooking booking = new WarehouseBooking();
|
||||||
|
booking.created = new Timestamp(new Date().getTime());
|
||||||
|
booking.reason = new BookingReason(reason);
|
||||||
|
|
||||||
|
if (source.isPresent()) {
|
||||||
|
|
||||||
|
if (source.get().article.id != article.id) {
|
||||||
|
throw new ArticleSlotConstraintArticleTypeFailedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition();
|
||||||
|
bookingPosition.booking = booking;
|
||||||
|
|
||||||
|
bookingPosition.article = article;
|
||||||
|
bookingPosition.amount = -amount;
|
||||||
|
bookingPosition.slotEntry = source.get().copyAddAmount(-amount, article);
|
||||||
|
|
||||||
|
if (bookingPosition.slotEntry.newSumSlot < 0 || bookingPosition.slotEntry.newSumSlot > article.warehouseUnitsPerSlot) {
|
||||||
|
throw new ArticleSlotConstraintFailedException("The quantity of article can only be set in bounds.");
|
||||||
|
}
|
||||||
|
|
||||||
|
booking.positions.add(bookingPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination.isPresent()) {
|
||||||
|
|
||||||
|
if (destination.get().article.id != article.id && destination.get().newSumSlot > 0) {
|
||||||
|
throw new ArticleSlotConstraintArticleTypeFailedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition();
|
||||||
|
bookingPosition.booking = booking;
|
||||||
|
|
||||||
|
bookingPosition.article = article;
|
||||||
|
bookingPosition.amount = amount;
|
||||||
|
bookingPosition.slotEntry = destination.get().copyAddAmount(amount, article);
|
||||||
|
|
||||||
|
if (bookingPosition.slotEntry.newSumSlot < 0 || bookingPosition.slotEntry.newSumSlot > article.warehouseUnitsPerSlot) {
|
||||||
|
throw new ArticleSlotConstraintFailedException("The quantity of article can only be set in bounds.");
|
||||||
|
}
|
||||||
|
|
||||||
|
booking.positions.add(bookingPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
return booking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ArticleSlotConstraintFailedException extends Exception {
|
||||||
|
public ArticleSlotConstraintFailedException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArticleSlotConstraintFailedException() {
|
||||||
|
super("The quantity of article can only be set in bounds.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ArticleSlotConstraintArticleTypeFailedException extends ArticleSlotConstraintFailedException {
|
||||||
|
public ArticleSlotConstraintArticleTypeFailedException() {
|
||||||
|
super("The Article in the slot entry does not match.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
package org.hso.ecommerce.action.warehouse;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.entities.booking.BookingReason;
|
||||||
|
import org.hso.ecommerce.entities.shop.Article;
|
||||||
|
import org.hso.ecommerce.entities.supplier.SupplierOrder;
|
||||||
|
import org.hso.ecommerce.entities.warehouse.WarehouseBooking;
|
||||||
|
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPosition;
|
||||||
|
import org.hso.ecommerce.entities.warehouse.WarehouseBookingPositionSlotEntry;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SupplierOrderArrivedAction {
|
||||||
|
|
||||||
|
private final Article article;
|
||||||
|
private final ArrayList<WarehouseBookingPositionSlotEntry> warehouseCandidates;
|
||||||
|
private final SupplierOrder order;
|
||||||
|
|
||||||
|
public SupplierOrderArrivedAction(List<WarehouseBookingPositionSlotEntry> warehouseCandidates, SupplierOrder order, Article article) {
|
||||||
|
this.warehouseCandidates = new ArrayList<>(warehouseCandidates);
|
||||||
|
this.order = order;
|
||||||
|
this.article = article;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result finish() throws NoSpaceInWarehouseException {
|
||||||
|
// Sort for most filled slot first;
|
||||||
|
warehouseCandidates.sort((b, a) -> Integer.compare(a.newSumSlot, b.newSumSlot));
|
||||||
|
|
||||||
|
int needed = order.numberOfUnits;
|
||||||
|
|
||||||
|
WarehouseBooking booking = new WarehouseBooking();
|
||||||
|
booking.created = new Timestamp(new Date().getTime());
|
||||||
|
booking.reason = new BookingReason(order);
|
||||||
|
|
||||||
|
for (WarehouseBookingPositionSlotEntry entry : warehouseCandidates) {
|
||||||
|
int canBeAdded = article.warehouseUnitsPerSlot - entry.newSumSlot;
|
||||||
|
|
||||||
|
if (canBeAdded == 0) {
|
||||||
|
// this slot is full, skip
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int willBeAdded = Math.min(canBeAdded, needed);
|
||||||
|
needed -= willBeAdded;
|
||||||
|
|
||||||
|
WarehouseBookingPosition bookingPosition = new WarehouseBookingPosition();
|
||||||
|
|
||||||
|
bookingPosition.article = article;
|
||||||
|
bookingPosition.amount = willBeAdded;
|
||||||
|
bookingPosition.slotEntry = entry.copyAddAmount(willBeAdded, article);
|
||||||
|
bookingPosition.booking = booking;
|
||||||
|
|
||||||
|
booking.positions.add(bookingPosition);
|
||||||
|
|
||||||
|
if (needed == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needed > 0) {
|
||||||
|
throw new NoSpaceInWarehouseException(article);
|
||||||
|
}
|
||||||
|
|
||||||
|
order.delivered = new Timestamp(new Date().getTime());
|
||||||
|
return new Result(order, booking);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Result extends Exception {
|
||||||
|
|
||||||
|
private final SupplierOrder order;
|
||||||
|
private final WarehouseBooking booking;
|
||||||
|
|
||||||
|
public Result(SupplierOrder order, WarehouseBooking booking) {
|
||||||
|
this.order = order;
|
||||||
|
this.booking = booking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SupplierOrder getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WarehouseBooking getBooking() {
|
||||||
|
return booking;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class NoSpaceInWarehouseException extends Exception {
|
||||||
|
private Article article;
|
||||||
|
|
||||||
|
public NoSpaceInWarehouseException(Article article) {
|
||||||
|
super("The quantity of article '" + article.title + "' does not fit in warehouse.");
|
||||||
|
this.article = article;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Article getArticle() {
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package org.hso.ecommerce.api;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.app.config.AppSettings;
|
||||||
|
import org.hso.ecommerce.entities.shop.CustomerOrder;
|
||||||
|
import org.hso.ecommerce.uimodel.DeliveryData;
|
||||||
|
import org.hso.ecommerce.uimodel.DeliveryDataEnum;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.client.ResourceAccessException;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class RestServiceForDelivery {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final RestTemplateBuilder restTemplateBuilder = null;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final AppSettings settings = null;
|
||||||
|
|
||||||
|
private String getDeliveryEndpoint() {
|
||||||
|
return settings.getParcelServiceApiURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getDeliveryID(CustomerOrder customerOrder) throws ResourceAccessException {
|
||||||
|
String url = getDeliveryEndpoint() + "/newDelivery";
|
||||||
|
|
||||||
|
RestTemplate restTemplate = restTemplateBuilder.build();
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
Map<String, String> requestBody = new HashMap<>();
|
||||||
|
|
||||||
|
requestBody.put("name", customerOrder.destination.name);
|
||||||
|
requestBody.put("address", customerOrder.destination.addressString);
|
||||||
|
|
||||||
|
HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestBody, headers);
|
||||||
|
|
||||||
|
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
|
||||||
|
|
||||||
|
if (response.getStatusCode() == HttpStatus.OK) {
|
||||||
|
return response.getBody();
|
||||||
|
} else {
|
||||||
|
throw new ResourceAccessException("Http Status wrong");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeliveryData getDeliveryData(String trackingID) {
|
||||||
|
|
||||||
|
String url = getDeliveryEndpoint() + "/status";
|
||||||
|
|
||||||
|
RestTemplate restTemplate = restTemplateBuilder.build();
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url).queryParam("trackingID", trackingID);
|
||||||
|
|
||||||
|
HttpEntity<?> entity = new HttpEntity<>(headers);
|
||||||
|
|
||||||
|
ResponseEntity<DeliveryData> response;
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, entity, DeliveryData.class);
|
||||||
|
if (response.getStatusCode() == HttpStatus.OK) {
|
||||||
|
return response.getBody();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return new DeliveryData("", "", DeliveryDataEnum.NO_DATA);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return new DeliveryData("", "", DeliveryDataEnum.NO_DATA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package org.hso.ecommerce.api.data;
|
package org.hso.ecommerce.api.data;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
public class OrderConfirmation {
|
public class OrderConfirmation {
|
||||||
public String manufacturer;
|
public String manufacturer;
|
||||||
public String articleNumber;
|
public String articleNumber;
|
||||||
@ -9,4 +11,8 @@ public class OrderConfirmation {
|
|||||||
public int pricePerUnitNetCent;
|
public int pricePerUnitNetCent;
|
||||||
public int discountNetCent;
|
public int discountNetCent;
|
||||||
public int totalPriceNetCharged;
|
public int totalPriceNetCharged;
|
||||||
|
|
||||||
|
public String carrier;
|
||||||
|
public String trackingId;
|
||||||
|
public LocalDateTime estimatedArrival;
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
|||||||
public class Application {
|
public class Application {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
SpringApplication.run(Application.class, args);
|
SpringApplication.run(Application.class, args);
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,161 @@
|
|||||||
|
package org.hso.ecommerce.app.config;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.app.config.YAMLData.Address;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
import org.yaml.snakeyaml.constructor.Constructor;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
@Component("appSettings")
|
||||||
|
public class AppSettings {
|
||||||
|
|
||||||
|
private YAMLData data;
|
||||||
|
private final String configFile = "config.yml";
|
||||||
|
|
||||||
|
private String installationName;
|
||||||
|
private String companyName;
|
||||||
|
private Address companyAddress;
|
||||||
|
private int numberOfStorageSpaces;
|
||||||
|
private List<YAMLData.Supplier> suppliers;
|
||||||
|
private String parcelServiceName;
|
||||||
|
private String parcelServiceApiURL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* on initialization read the config and store the data in static objects
|
||||||
|
*/
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
data = readConfig();
|
||||||
|
|
||||||
|
installationName = data.getInstallationName();
|
||||||
|
companyName = data.getCompanyName();
|
||||||
|
companyAddress = data.getCompanyAddress();
|
||||||
|
numberOfStorageSpaces = data.getNumberOfStorageSpaces();
|
||||||
|
suppliers = data.getSuppliers();
|
||||||
|
parcelServiceName = data.getParcelServiceName();
|
||||||
|
parcelServiceApiURL = data.getParcelServiceApiURL();
|
||||||
|
|
||||||
|
System.out.println("Initialised Settings!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write the default config file
|
||||||
|
*/
|
||||||
|
public void writeDefaultConfig() {
|
||||||
|
YAMLData data = new YAMLData();
|
||||||
|
data.setInstallationName("eCommerce");
|
||||||
|
data.setCompanyName("eCommerce Shop UG");
|
||||||
|
data.setCompanyAddress(new Address(
|
||||||
|
"Musterstraße",
|
||||||
|
"1",
|
||||||
|
"12345",
|
||||||
|
"Musterstadt",
|
||||||
|
"Germany"
|
||||||
|
));
|
||||||
|
data.setNumberOfStorageSpaces(128);
|
||||||
|
|
||||||
|
List<YAMLData.Supplier> suppliers = new ArrayList<>();
|
||||||
|
suppliers.add(new YAMLData.Supplier(
|
||||||
|
"Bank of Chees",
|
||||||
|
"d41d8cd98f00b204e9800998ecf8427e",
|
||||||
|
"http://[::1]:8081/bank/",
|
||||||
|
4,
|
||||||
|
new Address(
|
||||||
|
"Musterstraße",
|
||||||
|
"2",
|
||||||
|
"12345",
|
||||||
|
"Musterstadt",
|
||||||
|
"Germany"
|
||||||
|
)
|
||||||
|
));
|
||||||
|
suppliers.add(new YAMLData.Supplier(
|
||||||
|
"MDA",
|
||||||
|
"18a17da5bac1cf00551b08c3e98720f5",
|
||||||
|
"http://[::1]:8081/mda/",
|
||||||
|
5,
|
||||||
|
new Address(
|
||||||
|
"Musterstraße",
|
||||||
|
"3",
|
||||||
|
"12345",
|
||||||
|
"Musterstadt",
|
||||||
|
"Germany"
|
||||||
|
)
|
||||||
|
));
|
||||||
|
data.setSuppliers(suppliers);
|
||||||
|
|
||||||
|
data.setParcelServiceName("Parcel Service");
|
||||||
|
data.setParcelServiceApiURL("http://[::1]:8082/");
|
||||||
|
|
||||||
|
try (FileWriter writer = new FileWriter("./" + configFile)) {
|
||||||
|
Yaml yaml = new Yaml();
|
||||||
|
yaml.dump(data, writer);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read a config file named "eCommerce_config.yml" from the applications root directory
|
||||||
|
* @return the settings as YAMLData object
|
||||||
|
*/
|
||||||
|
public YAMLData readConfig() {
|
||||||
|
YAMLData data = new YAMLData();
|
||||||
|
|
||||||
|
File file = new File("./" + configFile);
|
||||||
|
if (!file.exists()) {
|
||||||
|
writeDefaultConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStream inputStream = new FileInputStream("./" + configFile)) {
|
||||||
|
Yaml yaml = new Yaml(new Constructor(YAMLData.class));
|
||||||
|
data = yaml.load(inputStream);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
System.err.println("The file \"" + configFile + "\" has not been found, please create a valid Configuration file.");
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YAMLData getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstallationName() {
|
||||||
|
return installationName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCompanyName() {
|
||||||
|
return companyName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address getCompanyAddress() {
|
||||||
|
return companyAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberOfStorageSpaces() {
|
||||||
|
return numberOfStorageSpaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<YAMLData.Supplier> getSuppliers() {
|
||||||
|
return suppliers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParcelServiceName() {
|
||||||
|
return parcelServiceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParcelServiceApiURL() {
|
||||||
|
return parcelServiceApiURL;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,183 @@
|
|||||||
|
package org.hso.ecommerce.app.config;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class YAMLData {
|
||||||
|
|
||||||
|
private String installationName;
|
||||||
|
private String companyName;
|
||||||
|
private Address companyAddress;
|
||||||
|
private int numberOfStorageSpaces;
|
||||||
|
private List<Supplier> suppliers;
|
||||||
|
private String parcelServiceName;
|
||||||
|
private String parcelServiceApiURL;
|
||||||
|
|
||||||
|
|
||||||
|
public String getInstallationName() {
|
||||||
|
return installationName;
|
||||||
|
}
|
||||||
|
public void setInstallationName(String installationName) {
|
||||||
|
this.installationName = installationName;
|
||||||
|
}
|
||||||
|
public String getCompanyName() {
|
||||||
|
return companyName;
|
||||||
|
}
|
||||||
|
public void setCompanyName(String companyName) {
|
||||||
|
this.companyName = companyName;
|
||||||
|
}
|
||||||
|
public Address getCompanyAddress() {
|
||||||
|
return companyAddress;
|
||||||
|
}
|
||||||
|
public void setCompanyAddress(Address companyAddress) {
|
||||||
|
this.companyAddress = companyAddress;
|
||||||
|
}
|
||||||
|
public int getNumberOfStorageSpaces() {
|
||||||
|
return numberOfStorageSpaces;
|
||||||
|
}
|
||||||
|
public void setNumberOfStorageSpaces(int numberOfStorageSpaces) {
|
||||||
|
this.numberOfStorageSpaces = numberOfStorageSpaces;
|
||||||
|
}
|
||||||
|
public List<Supplier> getSuppliers() {
|
||||||
|
return suppliers;
|
||||||
|
}
|
||||||
|
public void setSuppliers(List<Supplier> suppliers) {
|
||||||
|
this.suppliers = suppliers;
|
||||||
|
}
|
||||||
|
public String getParcelServiceName() {
|
||||||
|
return parcelServiceName;
|
||||||
|
}
|
||||||
|
public void setParcelServiceName(String parcelServiceName) {
|
||||||
|
this.parcelServiceName = parcelServiceName;
|
||||||
|
}
|
||||||
|
public String getParcelServiceApiURL() {
|
||||||
|
return parcelServiceApiURL;
|
||||||
|
}
|
||||||
|
public void setParcelServiceApiURL(String parcelServiceApiURL) {
|
||||||
|
this.parcelServiceApiURL = parcelServiceApiURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Address {
|
||||||
|
|
||||||
|
public String streetName;
|
||||||
|
public String houseNumber;
|
||||||
|
public String zipCode;
|
||||||
|
public String cityName;
|
||||||
|
public String countryName;
|
||||||
|
|
||||||
|
public Address() {
|
||||||
|
// needed by snakeyaml
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address(String streetName, String houseNumber, String zipCode, String cityName, String countryName) {
|
||||||
|
this.streetName = streetName;
|
||||||
|
this.houseNumber = houseNumber;
|
||||||
|
this.zipCode = zipCode;
|
||||||
|
this.cityName = cityName;
|
||||||
|
this.countryName = countryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStreetName() {
|
||||||
|
return streetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStreetName(String streetName) {
|
||||||
|
this.streetName = streetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHouseNumber() {
|
||||||
|
return houseNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHouseNumber(String houseNumber) {
|
||||||
|
this.houseNumber = houseNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getZipCode() {
|
||||||
|
return zipCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZipCode(String zipCode) {
|
||||||
|
this.zipCode = zipCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCityName() {
|
||||||
|
return cityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCityName(String cityName) {
|
||||||
|
this.cityName = cityName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountryName() {
|
||||||
|
return countryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountryName(String countryName) {
|
||||||
|
this.countryName = countryName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Supplier {
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
public String id;
|
||||||
|
public String apiURL;
|
||||||
|
public int deliveryTime;
|
||||||
|
public Address companyAddress;
|
||||||
|
|
||||||
|
|
||||||
|
public Supplier() {
|
||||||
|
// needed by snakeyaml
|
||||||
|
}
|
||||||
|
|
||||||
|
public Supplier(String name, String id, String apiURL, int deliveryTime, Address companyAddress) {
|
||||||
|
this.name = name;
|
||||||
|
this.id = id;
|
||||||
|
this.apiURL = apiURL;
|
||||||
|
this.deliveryTime = deliveryTime;
|
||||||
|
this.companyAddress = companyAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApiURL() {
|
||||||
|
return apiURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApiURL(String apiURL) {
|
||||||
|
this.apiURL = apiURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDeliveryTime() {
|
||||||
|
return deliveryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeliveryTime(int deliveryTime) {
|
||||||
|
this.deliveryTime = deliveryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address getCompanyAddress() {
|
||||||
|
return companyAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompanyAddress(Address companyAddress) {
|
||||||
|
this.companyAddress = companyAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package org.hso.ecommerce.components;
|
||||||
|
|
||||||
|
import org.hso.ecommerce.entities.shop.Address;
|
||||||
|
import org.hso.ecommerce.entities.user.User;
|
||||||
|
import org.hso.ecommerce.repos.user.UserRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AdminInitializer {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private final UserRepository userRepository = null;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
Optional<Integer> numberOfEmployees = userRepository.numberOfEmployees();
|
||||||
|
if (numberOfEmployees.orElse(0) == 0) {
|
||||||
|
// create first admin user
|
||||||
|
User firstAdmin = new User();
|
||||||
|
firstAdmin.created = new Timestamp(System.currentTimeMillis());
|
||||||
|
firstAdmin.defaultDeliveryAddress = new Address();
|
||||||
|
firstAdmin.defaultDeliveryAddress.name = "admin";
|
||||||
|
firstAdmin.defaultPayment = null;
|
||||||
|
firstAdmin.email = "admin";
|
||||||
|
firstAdmin.isActive = true;
|
||||||
|
firstAdmin.isEmployee = true;
|
||||||
|
firstAdmin.setPassword("admin");
|
||||||
|
userRepository.save(firstAdmin); //save to DB
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|