invoice and pendind
This commit is contained in:
parent
0fb2629812
commit
b8ff92deb9
@ -165,6 +165,13 @@ const _nav = [
|
|||||||
to: "/orders/delivered",
|
to: "/orders/delivered",
|
||||||
group: "Orders",
|
group: "Orders",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: CNavItem,
|
||||||
|
name: "Pending",
|
||||||
|
icon: <CIcon icon={cilNotes} customClassName="nav-icon" />,
|
||||||
|
to: "/orders/Pending",
|
||||||
|
group: "Orders",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: CNavItem,
|
component: CNavItem,
|
||||||
name: "Cancelled",
|
name: "Cancelled",
|
||||||
@ -172,6 +179,7 @@ const _nav = [
|
|||||||
to: "/orders/cancelled",
|
to: "/orders/cancelled",
|
||||||
group: "Orders",
|
group: "Orders",
|
||||||
},
|
},
|
||||||
|
|
||||||
// {
|
// {
|
||||||
// component: CNavItem,
|
// component: CNavItem,
|
||||||
// name: "In Store Cash Orders",
|
// name: "In Store Cash Orders",
|
||||||
|
97
src/assets/incoicedata.json
Normal file
97
src/assets/incoicedata.json
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"invoiceId": "INV-001234",
|
||||||
|
"orderId": "ORDER-987654",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"productId": "5f8d0d55b54764421b7156b1",
|
||||||
|
"SKU": "PRD-0001",
|
||||||
|
"name": "Wireless Mouse",
|
||||||
|
"categoryName": "Electronics",
|
||||||
|
"brandName": "Logitech",
|
||||||
|
"price": 1499,
|
||||||
|
"GST": 18,
|
||||||
|
"HSN_Code": 847160,
|
||||||
|
"processquantity": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"productId": "5f8d0d55b54764421b7156b2",
|
||||||
|
"SKU": "PRD-0002",
|
||||||
|
"name": "Keyboard",
|
||||||
|
"categoryName": "Electronics",
|
||||||
|
"brandName": "Dell",
|
||||||
|
"price": 2499,
|
||||||
|
"GST": 18,
|
||||||
|
"HSN_Code": 847160,
|
||||||
|
"processquantity": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"subtotal": 5497,
|
||||||
|
"gstTotal": 989.46,
|
||||||
|
"invoiceAmount": 6486.46,
|
||||||
|
"courier_name": "FedEx",
|
||||||
|
"courier_tracking_id": "TRK-123456789",
|
||||||
|
"courierStatus": "processing",
|
||||||
|
"courierstatus_timeline": {
|
||||||
|
"processing": "2023-09-18T09:00:00",
|
||||||
|
"dispatched": null,
|
||||||
|
"delivered": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invoiceId": "INV-001235",
|
||||||
|
"orderId": "ORDER-987655",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"productId": "5f8d0d55b54764421b7156b3",
|
||||||
|
"SKU": "PRD-0003",
|
||||||
|
"name": "Smartphone",
|
||||||
|
"categoryName": "Mobile Phones",
|
||||||
|
"brandName": "Samsung",
|
||||||
|
"price": 19999,
|
||||||
|
"GST": 12,
|
||||||
|
"HSN_Code": 851712,
|
||||||
|
"processquantity": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"subtotal": 19999,
|
||||||
|
"gstTotal": 2399.88,
|
||||||
|
"invoiceAmount": 22398.88,
|
||||||
|
"courier_name": "DHL",
|
||||||
|
"courier_tracking_id": "TRK-987654321",
|
||||||
|
"courierStatus": "dispatched",
|
||||||
|
"courierstatus_timeline": {
|
||||||
|
"processing": "2023-09-15T10:00:00",
|
||||||
|
"dispatched": "2023-09-16T12:30:00",
|
||||||
|
"delivered": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"invoiceId": "INV-001236",
|
||||||
|
"orderId": "ORDER-987656",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"productId": "5f8d0d55b54764421b7156b4",
|
||||||
|
"SKU": "PRD-0004",
|
||||||
|
"name": "Laptop",
|
||||||
|
"categoryName": "Computers",
|
||||||
|
"brandName": "HP",
|
||||||
|
"price": 59999,
|
||||||
|
"GST": 18,
|
||||||
|
"HSN_Code": 847130,
|
||||||
|
"processquantity": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"subtotal": 59999,
|
||||||
|
"gstTotal": 10799.82,
|
||||||
|
"invoiceAmount": 70798.82,
|
||||||
|
"courier_name": "Blue Dart",
|
||||||
|
"courier_tracking_id": "TRK-1122334455",
|
||||||
|
"courierStatus": "delivered",
|
||||||
|
"courierstatus_timeline": {
|
||||||
|
"processing": "2023-09-10T08:00:00",
|
||||||
|
"dispatched": "2023-09-11T11:00:00",
|
||||||
|
"delivered": "2023-09-13T14:45:00"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
@ -152,6 +152,7 @@ import ViewPrincipalDistributorSC from "./views/SalesCoOrdinators/ViewPrincipalD
|
|||||||
import ViewRetailDistributorSC from "./views/SalesCoOrdinators/ViewRetailDistributorSC";
|
import ViewRetailDistributorSC from "./views/SalesCoOrdinators/ViewRetailDistributorSC";
|
||||||
import ViewRetailDistributorPD from "./views/PrincipalDistributors/ViewRetailDistributorPD";
|
import ViewRetailDistributorPD from "./views/PrincipalDistributors/ViewRetailDistributorPD";
|
||||||
import MapRD from "./views/RetailDistributors/MapRD";
|
import MapRD from "./views/RetailDistributors/MapRD";
|
||||||
|
import PendingOrders from "./views/orders/pendingOrders";
|
||||||
const routes = [
|
const routes = [
|
||||||
//dashboard
|
//dashboard
|
||||||
|
|
||||||
@ -224,7 +225,7 @@ const routes = [
|
|||||||
element: ViewProductManual,
|
element: ViewProductManual,
|
||||||
navName: "Product Management",
|
navName: "Product Management",
|
||||||
},
|
},
|
||||||
//SalesCoOrdinator
|
//SalesCoOrdinator
|
||||||
{
|
{
|
||||||
path: "/salescoordinator/edit/:id",
|
path: "/salescoordinator/edit/:id",
|
||||||
name: "Edit SalesCoOrdinator",
|
name: "Edit SalesCoOrdinator",
|
||||||
@ -644,6 +645,12 @@ const routes = [
|
|||||||
element: DeliveredOrders,
|
element: DeliveredOrders,
|
||||||
navName: "Orders",
|
navName: "Orders",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/orders/pending",
|
||||||
|
name: "Pending Orders",
|
||||||
|
element: PendingOrders,
|
||||||
|
navName: "Orders",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/orders/cancelled",
|
path: "/orders/cancelled",
|
||||||
name: "Cancelled Orders",
|
name: "Cancelled Orders",
|
||||||
|
@ -19,12 +19,14 @@ import {
|
|||||||
TextField,
|
TextField,
|
||||||
Divider,
|
Divider,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
import onvoicesData from "../../assets/incoicedata.json";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { TableContainer } from "@material-ui/core";
|
import { TableContainer } from "@material-ui/core";
|
||||||
import axios from "axios"; // Import axios for HTTP requests
|
import axios from "axios"; // Import axios for HTTP requests
|
||||||
import { isAutheticated } from "src/auth";
|
import { isAutheticated } from "src/auth";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import OrderDetailsDialog from "./partialOrderModal";
|
import OrderDetailsDialog from "./partialOrderModal";
|
||||||
|
import InvoiceTable from "./invoiceTable";
|
||||||
|
|
||||||
const ViewOrders = () => {
|
const ViewOrders = () => {
|
||||||
const [order, setOrder] = useState(null); // State to store order details
|
const [order, setOrder] = useState(null); // State to store order details
|
||||||
@ -295,7 +297,15 @@ const ViewOrders = () => {
|
|||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item md={8} xl={8} lg={8}>
|
<Grid item md={8} xl={8} lg={8}>
|
||||||
<Box sx={{ padding: 2, background: "#fff" }}>
|
<Box sx={{ padding: 2, background: "#fff" }}>
|
||||||
<Typography variant="h4" gutterBottom>
|
{onvoicesData.length > 0 && (
|
||||||
|
<>
|
||||||
|
<Typography variant="h4" gutterBottom>
|
||||||
|
Invoices
|
||||||
|
</Typography>
|
||||||
|
<InvoiceTable invoices={onvoicesData} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Typography variant="h4" my={3} gutterBottom>
|
||||||
Order Summary
|
Order Summary
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
@ -506,6 +516,15 @@ const ViewOrders = () => {
|
|||||||
<option value="cancelled">Cancelled</option>
|
<option value="cancelled">Cancelled</option>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{status === "pending" && (
|
||||||
|
<>
|
||||||
|
<option value="processing">Processing</option>
|
||||||
|
<option value="partial-processing">
|
||||||
|
Partial Processing
|
||||||
|
</option>
|
||||||
|
<option value="cancelled">Cancelled</option>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{status === "processing" && (
|
{status === "processing" && (
|
||||||
<>
|
<>
|
||||||
<option value="">Processing</option>
|
<option value="">Processing</option>
|
||||||
|
74
src/views/orders/invoiceTable.js
Normal file
74
src/views/orders/invoiceTable.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Paper,
|
||||||
|
Button,
|
||||||
|
Chip,
|
||||||
|
} from "@mui/material";
|
||||||
|
import axios from "axios";
|
||||||
|
import { Typography } from "@material-ui/core";
|
||||||
|
|
||||||
|
const InvoiceTable = ({ invoices }) => {
|
||||||
|
return (
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Invoice ID</TableCell>
|
||||||
|
|
||||||
|
<TableCell>Items</TableCell>
|
||||||
|
<TableCell>Subtotal</TableCell>
|
||||||
|
<TableCell>GST Total</TableCell>
|
||||||
|
<TableCell>Invoice Amount</TableCell>
|
||||||
|
<TableCell>Courier Status</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{false ? (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={8} align="center">
|
||||||
|
Loading...
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
) : (
|
||||||
|
invoices.map((invoice) => (
|
||||||
|
<TableRow key={invoice.invoiceId}>
|
||||||
|
<TableCell>{invoice.invoiceId}</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
{invoice.items.map((item) => (
|
||||||
|
<div key={item.productId}>
|
||||||
|
{item.name} ({item.SKU}) x {item.processquantity}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{invoice.subtotal}</TableCell>
|
||||||
|
<TableCell>{invoice.gstTotal}</TableCell>
|
||||||
|
<TableCell>{invoice.invoiceAmount}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Chip
|
||||||
|
label={invoice.courierStatus}
|
||||||
|
color={
|
||||||
|
invoice.courierStatus === "delivered"
|
||||||
|
? "success"
|
||||||
|
: invoice.courierStatus === "dispatched"
|
||||||
|
? "primary"
|
||||||
|
: "warning"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InvoiceTable;
|
199
src/views/orders/pendingOrders.js
Normal file
199
src/views/orders/pendingOrders.js
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Paper,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableContainer,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
Typography,
|
||||||
|
TablePagination,
|
||||||
|
TextField,
|
||||||
|
MenuItem,
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
Select,
|
||||||
|
Skeleton,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import axios from "axios";
|
||||||
|
import { isAutheticated } from "src/auth";
|
||||||
|
|
||||||
|
const PendingOrders = () => {
|
||||||
|
const [orders, setOrders] = useState([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [page, setPage] = useState(0);
|
||||||
|
const [rowsPerPage, setRowsPerPage] = useState(5);
|
||||||
|
const [totalOrders, setTotalOrders] = useState(0);
|
||||||
|
const [searchField, setSearchField] = useState("Order ID");
|
||||||
|
const [searchText, setSearchText] = useState("");
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const token = isAutheticated();
|
||||||
|
|
||||||
|
// Fetch orders with pagination
|
||||||
|
const fetchOrders = async (page, limit) => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const response = await axios.get("/api/get-pending-order-admin", {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
params: {
|
||||||
|
page: page + 1, // Adjusting for zero-based index in the UI
|
||||||
|
limit,
|
||||||
|
searchField,
|
||||||
|
searchText,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// console.log(response);
|
||||||
|
setOrders(response?.data?.placedOrders);
|
||||||
|
setTotalOrders(response?.data?.totalOrders);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching orders:", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchOrders(page, rowsPerPage);
|
||||||
|
}, [page, rowsPerPage, searchField, searchText]);
|
||||||
|
|
||||||
|
const handleSearchChange = (event) => {
|
||||||
|
setSearchText(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSearchFieldChange = (event) => {
|
||||||
|
setSearchField(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangePage = (event, newPage) => {
|
||||||
|
setPage(newPage);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangeRowsPerPage = (event) => {
|
||||||
|
setRowsPerPage(parseInt(event.target.value, 10));
|
||||||
|
setPage(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filteredOrders = orders?.filter((order) => {
|
||||||
|
if (searchField === "Order ID") {
|
||||||
|
return order.uniqueId.toLowerCase().includes(searchText.toLowerCase());
|
||||||
|
}
|
||||||
|
if (searchField === "Status") {
|
||||||
|
return order.status.toLowerCase().includes(searchText.toLowerCase());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="h4" mb={2} textAlign="center">
|
||||||
|
Pending Order List
|
||||||
|
</Typography>
|
||||||
|
<Box display="flex" mb={2} alignItems="center">
|
||||||
|
<FormControl variant="outlined" sx={{ minWidth: 150, mr: 2 }}>
|
||||||
|
<InputLabel id="search-field-label">Search By</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="search-field-label"
|
||||||
|
id="search-field"
|
||||||
|
value={searchField}
|
||||||
|
onChange={handleSearchFieldChange}
|
||||||
|
label="Search By"
|
||||||
|
>
|
||||||
|
<MenuItem value="Order ID">Order ID</MenuItem>
|
||||||
|
<MenuItem value="Status">Status</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
<TextField
|
||||||
|
label={`Search by ${searchField}`}
|
||||||
|
variant="outlined"
|
||||||
|
value={searchText}
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<TableContainer component={Paper}>
|
||||||
|
<Table>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell>Order ID</TableCell>
|
||||||
|
<TableCell>Order Date</TableCell>
|
||||||
|
<TableCell>Items</TableCell>
|
||||||
|
<TableCell>Order Value</TableCell>
|
||||||
|
<TableCell>Status</TableCell>
|
||||||
|
<TableCell>Action</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{loading ? (
|
||||||
|
Array.from(new Array(rowsPerPage)).map((_, index) => (
|
||||||
|
<TableRow key={index}>
|
||||||
|
<TableCell colSpan={6}>
|
||||||
|
<Skeleton height={40} />
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : filteredOrders.length > 0 ? (
|
||||||
|
filteredOrders.map((order) => (
|
||||||
|
<TableRow key={order._id}>
|
||||||
|
<TableCell>{order.uniqueId}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
{new Date(order.createdAt).toDateString()}
|
||||||
|
<span>, {formatAMPM(order.createdAt)}</span>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{order.orderItem.length}</TableCell>
|
||||||
|
<TableCell>{order.grandTotal.toFixed(2)}</TableCell>
|
||||||
|
<TableCell>{order.status}</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={() =>
|
||||||
|
navigate(`/orders/${order.status}/${order._id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
View
|
||||||
|
</Button>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell colSpan={6} align="center">
|
||||||
|
<Typography variant="body1">Data not found</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
<TablePagination
|
||||||
|
rowsPerPageOptions={[5, 10, 25]}
|
||||||
|
component="div"
|
||||||
|
count={totalOrders}
|
||||||
|
rowsPerPage={rowsPerPage}
|
||||||
|
page={page}
|
||||||
|
onPageChange={handleChangePage}
|
||||||
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||||
|
/>
|
||||||
|
</TableContainer>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to format time as AM/PM
|
||||||
|
const formatAMPM = (date) => {
|
||||||
|
var hours = new Date(date).getHours();
|
||||||
|
var minutes = new Date(date).getMinutes();
|
||||||
|
var ampm = hours >= 12 ? "PM" : "AM";
|
||||||
|
hours = hours % 12;
|
||||||
|
hours = hours ? hours : 12;
|
||||||
|
minutes = minutes < 10 ? "0" + minutes : minutes;
|
||||||
|
var strTime = hours + ":" + minutes + " " + ampm;
|
||||||
|
return strTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PendingOrders;
|
Loading…
Reference in New Issue
Block a user