add OrderStatus statistic, stock fullfilment dummy
This commit is contained in:
Binary file not shown.
@@ -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";
|
||||
|
||||
}
|
||||
@@ -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<Map<OrderStatus, Integer>> 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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Integer> getSalesVolume();
|
||||
|
||||
CatMonthModel<Integer> getSalesRevenue();
|
||||
|
||||
Map<OrderStatus, Integer> getOrderStatus();
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Integer> getSalesRevenue() {
|
||||
return getMonthCategoryMap(item -> item.getArticle().getPrice100(), Integer::sum, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<OrderStatus, Integer> getOrderStatus() {
|
||||
Map<OrderStatus, Integer> map = new TreeMap<>();
|
||||
orderService.findAll().forEach(order -> {
|
||||
map.putIfAbsent(order.getStatus(), 0);
|
||||
map.computeIfPresent(order.getStatus(), (k,v) -> ++v);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<BarSeriesType[]>([]);
|
||||
const [monthlyVolumeXaxis, setMonthlyVolumeXaxis] = useState([{ data: [] }]);
|
||||
const [totalVolume, setTotalVolume] = useState([{ data: [] }]);
|
||||
const [totalVolume, setTotalVolume] = useState([]);
|
||||
|
||||
const [monthlyRevenue, setMonthlyRevenue] = useState<BarSeriesType[]>([]);
|
||||
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 (
|
||||
<Box className="" sx={{ color: theme.palette.text.primary }}>
|
||||
<Typography mt={4} variant="h4" align="center" gutterBottom>
|
||||
@@ -132,27 +152,64 @@ export default function StatisticsInfo() {
|
||||
/>
|
||||
</Box>
|
||||
<Box display={"flex"} mb={9}>
|
||||
<Box sx={{ m: 2 }}>
|
||||
<Box className="vw20" sx={{ m: 2 }}>
|
||||
<Typography variant="h6" align="center" gutterBottom>
|
||||
Item Volume Distribution
|
||||
</Typography>
|
||||
<PieChart
|
||||
series={totalVolume}
|
||||
series={[{
|
||||
data: totalVolume,
|
||||
highlightScope: { fade: 'global', highlight: 'item' },
|
||||
faded: { innerRadius: 30, additionalRadius: -30, color: 'gray' },
|
||||
}]}
|
||||
width={200}
|
||||
height={200}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ m: 2 }}>
|
||||
<Box className="vw20" sx={{ m: 2 }}>
|
||||
<Typography variant="h6" align="center" gutterBottom>
|
||||
Item Revenue Distribution
|
||||
</Typography>
|
||||
<PieChart
|
||||
series={totalRevenue}
|
||||
series={[{
|
||||
data: totalRevenue,
|
||||
highlightScope: { fade: 'global', highlight: 'item' },
|
||||
}]}
|
||||
width={200}
|
||||
height={200}
|
||||
/>
|
||||
</Box>
|
||||
<Box className="vw20" sx={{ m: 2 }}>
|
||||
<Typography variant="h6" align="center" gutterBottom>
|
||||
Stock fulfillment
|
||||
</Typography>
|
||||
<PieChart
|
||||
series={[{
|
||||
data: totalRevenue,
|
||||
}]}
|
||||
width={200}
|
||||
height={200}
|
||||
/>
|
||||
</Box>
|
||||
<Box className="vw20" sx={{ m: 2 }}>
|
||||
<Typography variant="h6" align="center" gutterBottom>
|
||||
Order Status
|
||||
</Typography>
|
||||
<PieChart
|
||||
series={[{
|
||||
data: orderStatus,
|
||||
innerRadius: 20,
|
||||
outerRadius: 70,
|
||||
cornerRadius: 5,
|
||||
paddingAngle: 1,
|
||||
highlightScope: { fade: 'global', highlight: 'item' },
|
||||
faded: { innerRadius: 30, additionalRadius: -10, color: 'gray' },
|
||||
}]}
|
||||
height={200}
|
||||
width={200}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -30,3 +30,7 @@
|
||||
.rating-text-field{
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
|
||||
.vw20 {
|
||||
width: 20vw;
|
||||
}
|
||||
@@ -207,3 +207,11 @@ export const orderPatch = async (order: OrderPatch) => {
|
||||
}
|
||||
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();
|
||||
};
|
||||
Reference in New Issue
Block a user