diff --git a/00-backend/datasource/database.sqlite b/00-backend/datasource/database.sqlite index c048ddf..9aadb75 100644 Binary files a/00-backend/datasource/database.sqlite and b/00-backend/datasource/database.sqlite differ diff --git a/00-backend/src/main/java/de/htwsaar/webshop/config/ControllerPathConfig.java b/00-backend/src/main/java/de/htwsaar/webshop/config/ControllerPathConfig.java index 084eed2..cdc1f56 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/config/ControllerPathConfig.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/config/ControllerPathConfig.java @@ -49,5 +49,6 @@ public class ControllerPathConfig { private static final String STATISTICS_BASE = "/statistics"; public static final String STATISTICS_VOLUME = STATISTICS_BASE + "/volume"; public static final String STATISTICS_REVENUE = STATISTICS_BASE + "/revenue"; + public static final String STATISTICS_ORDERSTATUS = STATISTICS_BASE + "/orderstatus"; } \ No newline at end of file diff --git a/00-backend/src/main/java/de/htwsaar/webshop/controller/StatisticsController.java b/00-backend/src/main/java/de/htwsaar/webshop/controller/StatisticsController.java index bc68251..3c1e3e6 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/controller/StatisticsController.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/controller/StatisticsController.java @@ -1,6 +1,7 @@ package de.htwsaar.webshop.controller; import de.htwsaar.webshop.model.CatMonthModel; +import de.htwsaar.webshop.model.OrderStatus; import de.htwsaar.webshop.service.SessionService; import de.htwsaar.webshop.service.StatisticsService; import jakarta.servlet.http.HttpServletRequest; @@ -11,10 +12,10 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.util.Map; import java.util.UUID; -import static de.htwsaar.webshop.config.ControllerPathConfig.STATISTICS_REVENUE; -import static de.htwsaar.webshop.config.ControllerPathConfig.STATISTICS_VOLUME; +import static de.htwsaar.webshop.config.ControllerPathConfig.*; import static de.htwsaar.webshop.config.ParameterConfig.PARAM_EMAIL; import static de.htwsaar.webshop.config.ParameterConfig.PARAM_SESSION; import static de.htwsaar.webshop.util.LoggerUtil.logRequest; @@ -55,4 +56,16 @@ public class StatisticsController { return ResponseEntity.ok(statisticsService.getSalesRevenue()); } + @RequestMapping(value = STATISTICS_ORDERSTATUS, method = RequestMethod.GET, produces = "application/json") + public ResponseEntity> getOrderStatus(HttpServletRequest request, + @RequestParam(value = PARAM_SESSION) UUID token, + @RequestParam(value = PARAM_EMAIL) String email) { + logRequest(request); + if (!sessionService.isAdmin(token, email)) { + log.warn("Invalid session requesting Admin {}", token); + return ResponseEntity.status(403).build(); + } + return ResponseEntity.ok(statisticsService.getOrderStatus()); + } + } diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/StatisticsService.java b/00-backend/src/main/java/de/htwsaar/webshop/service/StatisticsService.java index 1801fbb..8c1480b 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/service/StatisticsService.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/StatisticsService.java @@ -1,10 +1,15 @@ package de.htwsaar.webshop.service; import de.htwsaar.webshop.model.CatMonthModel; +import de.htwsaar.webshop.model.OrderStatus; + +import java.util.Map; public interface StatisticsService { CatMonthModel getSalesVolume(); CatMonthModel getSalesRevenue(); + Map getOrderStatus(); + } diff --git a/00-backend/src/main/java/de/htwsaar/webshop/service/impl/StatisticsServiceImpl.java b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/StatisticsServiceImpl.java index d853be5..9cb7bc4 100644 --- a/00-backend/src/main/java/de/htwsaar/webshop/service/impl/StatisticsServiceImpl.java +++ b/00-backend/src/main/java/de/htwsaar/webshop/service/impl/StatisticsServiceImpl.java @@ -2,6 +2,7 @@ package de.htwsaar.webshop.service.impl; import de.htwsaar.webshop.model.ArticleCategory; import de.htwsaar.webshop.model.CatMonthModel; +import de.htwsaar.webshop.model.OrderStatus; import de.htwsaar.webshop.repository.entities.OrderItem; import de.htwsaar.webshop.service.OrderService; import de.htwsaar.webshop.service.StatisticsService; @@ -57,4 +58,14 @@ public class StatisticsServiceImpl implements StatisticsService { public CatMonthModel getSalesRevenue() { return getMonthCategoryMap(item -> item.getArticle().getPrice100(), Integer::sum, 0); } + + @Override + public Map getOrderStatus() { + Map map = new TreeMap<>(); + orderService.findAll().forEach(order -> { + map.putIfAbsent(order.getStatus(), 0); + map.computeIfPresent(order.getStatus(), (k,v) -> ++v); + }); + return map; + } } diff --git a/01-frontend/src/helper/adminpanel/StatisticsInfo.tsx b/01-frontend/src/helper/adminpanel/StatisticsInfo.tsx index ae8d647..36516dc 100644 --- a/01-frontend/src/helper/adminpanel/StatisticsInfo.tsx +++ b/01-frontend/src/helper/adminpanel/StatisticsInfo.tsx @@ -5,8 +5,9 @@ import { BarSeriesType } from '@mui/x-charts' import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useQuery } from "@tanstack/react-query"; -import { fetchStatisticsVolume, fetchStatisticsRevenue } from "../query/Queries.tsx"; +import { fetchStatisticsVolume, fetchStatisticsRevenue, fetchOrderStatus } from "../query/Queries.tsx"; import { useAccount } from "../AccountProvider.tsx"; +import { data } from "react-router-dom"; export default function StatisticsInfo() { const theme = useTheme(); @@ -14,16 +15,17 @@ export default function StatisticsInfo() { const [monthlyVolume, setMonthlyVolume] = useState([]); const [monthlyVolumeXaxis, setMonthlyVolumeXaxis] = useState([{ data: [] }]); - const [totalVolume, setTotalVolume] = useState([{ data: [] }]); + const [totalVolume, setTotalVolume] = useState([]); const [monthlyRevenue, setMonthlyRevenue] = useState([]); const [monthlyRevenueXaxis, setMonthlyRevenueXaxis] = useState([{ data: [] }]); - const [totalRevenue, setTotalRevenue] = useState([{ data: [] }]); - + const [totalRevenue, setTotalRevenue] = useState([]); + const [orderStatus, setOrderStatus] = useState([]); const { user: loginData } = useAccount(); + const { data: dataVolume } = useQuery({ queryKey: ["fetchStatisticsVolume", loginData], queryFn: () => fetchStatisticsVolume(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }), @@ -38,15 +40,23 @@ export default function StatisticsInfo() { retryDelay: 0, }); + const { data: dataOrderStatus } = useQuery({ + queryKey: ["fetchOrderStatus", loginData], + queryFn: () => fetchOrderStatus(loginData ? loginData : { email: "", password: "", session: "", customerId: -1, isAdmin: false }), + retry: 0, + retryDelay: 0, + }); + + + useEffect(() => { if (dataVolume) { const cmm = [] const cmmx = monthlyVolumeXaxis - const tv = [{data:[]}] + const tv = [] let i = 0 for (const cat in dataVolume.catMonthMap) { for (const timestamp in dataVolume.catMonthMap[cat]) { - console.log(i + "." + timestamp); const date = new Date(parseInt(timestamp)) const formattedDate = date.getFullYear() + "-" + String(date.getMonth() + 1).padStart(2, '0') if (!cmmx[0].data.includes(formattedDate)) { @@ -58,10 +68,10 @@ export default function StatisticsInfo() { } cmm[i].data.push(datapoint) - if(tv[0].data.length == i) { - tv[0].data.push({ id: i, value: 0, label: t(cat)}) + if(tv.length == i) { + tv.push({ id: i, value: 0, label: t(cat)}) } - tv[0].data[i].value += datapoint + tv[i].value += datapoint } i++; } @@ -76,7 +86,7 @@ export default function StatisticsInfo() { if (dataRevenue) { const cmm = [] const cmmx = monthlyRevenueXaxis - const tv = [{data:[]}] + const tv = [] let i = 0 for (const cat in dataRevenue.catMonthMap) { for (const timestamp in dataRevenue.catMonthMap[cat]) { @@ -85,16 +95,16 @@ export default function StatisticsInfo() { if (!cmmx[0].data.includes(formattedDate)) { cmmx[0].data.push(formattedDate); } - const datapoint = dataRevenue.catMonthMap[cat][timestamp] + const datapoint = dataRevenue.catMonthMap[cat][timestamp] / 100 if(cmm.length == i) { cmm.push({ id: i, data: [], label: t(cat), type: "bar" }) } cmm[i].data.push(datapoint) - if(tv[0].data.length == i) { - tv[0].data.push({ id: i, value: 0, label: t(cat)}) + if(tv.length == i) { + tv.push({ id: i, value: 0, label: t(cat)}) } - tv[0].data[i].value += datapoint + tv[i].value += datapoint } i++; } @@ -105,6 +115,16 @@ export default function StatisticsInfo() { } }, [dataRevenue]); + useEffect(() => { + if(dataOrderStatus) { + const orderStatus = [] + for(var status in dataOrderStatus) { + orderStatus.push({value: dataOrderStatus[status], label: t(status)}) + } + setOrderStatus(orderStatus) + } + }, [dataOrderStatus]) + return ( @@ -132,27 +152,64 @@ export default function StatisticsInfo() { /> - + Item Volume Distribution - + Item Revenue Distribution + + + Stock fulfillment + + + + + + Order Status + + + ); diff --git a/01-frontend/src/helper/helper.css b/01-frontend/src/helper/helper.css index 2d35240..0e44c1e 100644 --- a/01-frontend/src/helper/helper.css +++ b/01-frontend/src/helper/helper.css @@ -29,4 +29,8 @@ .rating-text-field{ background-color: whitesmoke; +} + +.vw20 { + width: 20vw; } \ No newline at end of file diff --git a/01-frontend/src/helper/query/Queries.tsx b/01-frontend/src/helper/query/Queries.tsx index e76d186..f38d2c4 100644 --- a/01-frontend/src/helper/query/Queries.tsx +++ b/01-frontend/src/helper/query/Queries.tsx @@ -206,4 +206,12 @@ export const orderPatch = async (order: OrderPatch) => { throw new Error("Order patch failed"); } return response.json(); +}; + +export const fetchOrderStatus = async (loginData: User) => { + const response = await fetch("http://localhost:8085/statistics/orderstatus?email=" + loginData.email + "&session=" + loginData.session); + if (!response.ok) { + throw new Error("fetching satistics Revenue failed"); + } + return response.json(); }; \ No newline at end of file