diff --git a/src/routes.js b/src/routes.js
index 0abaa22..6a2ef09 100644
--- a/src/routes.js
+++ b/src/routes.js
@@ -167,6 +167,7 @@ import SingleSales from "./views/Sales/SingleSale";
import MobileApp from "./views/configuration/MobileApp";
import PDOpeningInventory from "./views/OpeningInventory/PDOpeningInventory";
import DistributorOpeningInventory from "./views/PrincipalDistributors/OpeningInventory";
+import UploadOpeningInventory from "./views/PrincipalDistributors/UploadOpeningInventory";
const routes = [
//dashboard
@@ -425,6 +426,12 @@ const routes = [
element: DistributorOpeningInventory,
navName: "Distributor",
},
+ {
+ path: "/:distributortype/opening-inventory/upload/:id",
+ name: " Distributor Opening Inventory Upload",
+ element: UploadOpeningInventory,
+ navName: "Distributor",
+ },
//----------------------- End Product Management Routes------------------------------------------------
//Departure
diff --git a/src/views/PrincipalDistributors/OpeningInventory.js b/src/views/PrincipalDistributors/OpeningInventory.js
index f85f2f2..755f070 100644
--- a/src/views/PrincipalDistributors/OpeningInventory.js
+++ b/src/views/PrincipalDistributors/OpeningInventory.js
@@ -15,6 +15,7 @@ const DistributorOpeningInventory = () => {
const [loading, setLoading] = useState(false);
const [productsData, setProductsData] = useState([]);
+ const [allProductsData, setAllProductsData] = useState([]);
const [categories, setCategories] = useState([]);
const [brands, setBrands] = useState([]);
const [user, setUser] = useState(null);
@@ -77,8 +78,22 @@ const DistributorOpeningInventory = () => {
},
}
);
+ // console.log(response.data.products);
setProductsData(response.data?.products || []);
setTotalData(response.data?.totalProducts || 0);
+ // Merge new products with existing ones in allProductsData
+ setAllProductsData((prev) => {
+ const updatedList = [...prev];
+ response.data?.products?.forEach((product) => {
+ const index = updatedList.findIndex((p) => p._id === product._id);
+ if (index > -1) {
+ updatedList[index] = product; // Update existing product
+ } else {
+ updatedList.push(product); // Add new product
+ }
+ });
+ return updatedList;
+ });
} catch (err) {
swal({
title: "Error",
@@ -157,19 +172,30 @@ const DistributorOpeningInventory = () => {
...prevStocks,
[sku]: newStock, // Update stock for specific product (identified by SKU)
}));
+
+ // Update the stock directly in allProductsData
+ setAllProductsData((prev) =>
+ prev.map((product) =>
+ product.SKU === sku ? { ...product, stock: newStock } : product
+ )
+ );
};
const handleSubmitStocks = async () => {
try {
- const updatedProducts = productsData.map((product) => ({
- ...product,
- stock: updatedStocks[product.SKU] || product.stock,
+ const updatedProducts = allProductsData.map((product) => ({
+ _id: product._id,
+ SKU: product.SKU,
+ name: product.name,
+ openingInventory: updatedStocks[product.SKU] || product.stock,
}));
- await axios.post(
+ // console.log(updatedProducts);
+ // console.log(id);
+ await axios.put(
distributortype === "principaldistributor"
- ? `/api/pd/updateStocks/${id}`
- : `/api/rd/updateStocks/${id}`,
- { updatedProducts },
+ ? `/api/pd/stock-update`
+ : `/api/rd/stock-update`,
+ { products: updatedProducts, userId: id },
{ headers: { Authorization: `Bearer ${token}` } }
);
swal("Success", "Stocks updated successfully!", "success");
@@ -215,7 +241,23 @@ const DistributorOpeningInventory = () => {
Email: {user?.email}
-
+
+
+
{/* Back Button on the right */}
+
+
+
-
+
{
+ const [file, setFile] = useState(null);
+ const [loading, setLoading] = useState(false);
+ const [errors, setErrors] = useState([]);
+ const [newlyCreated, setNewlyCreated] = useState([]);
+ const [updatedInventories, setupdatedInventories] = useState([]);
+ const navigate = useNavigate();
+ const token = isAutheticated();
+ const { id, distributortype } = useParams();
+ const handleFileChange = (e) => {
+ const selectedFile = e.target.files[0];
+ if (
+ selectedFile &&
+ selectedFile.type ===
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
+ ) {
+ setFile(selectedFile);
+ } else {
+ swal("Error", "Please upload a valid Excel file", "error");
+ setFile(null);
+ }
+ };
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ if (!file) {
+ toast.error("Please select a file to upload");
+ return;
+ }
+ // console.log(file);
+ // console.log(token);
+ setLoading(true);
+ setErrors([]);
+ setNewlyCreated([]);
+ setupdatedInventories([]);
+ try {
+ const formData = new FormData();
+ formData.append("file", file);
+
+ const { data } = await axios.post(
+ `/api/openinginventories/upload/${id}`,
+ formData,
+ {
+ headers: {
+ "Content-Type": "multipart/form-data",
+ Authorization: `Bearer ${token}`,
+ },
+ }
+ );
+ // console.log(data);
+ if (data?.errors && data?.errors?.length > 0) {
+ setErrors(data.errors);
+ }
+ if (data?.newlyCreated && data?.newlyCreated?.length > 0) {
+ setNewlyCreated(data?.newlyCreated);
+ }
+ if (data?.updatedOpeningInventories && data?.updatedOpeningInventories?.length > 0) {
+ setupdatedInventories(data?.updatedOpeningInventories);
+ // console.log(data.updatedOpeningInventories);
+ }
+
+ // Redirect or display success message
+ if (data?.errors && data?.errors.length > 0) {
+ setErrors(data?.errors);
+ swal({
+ title: "SpreadSheet Upload Successful",
+ text: "A few Products have errors. Please fix them and upload again.",
+ icon: "warning",
+ button: "OK",
+ });
+ } else if (
+ data?.newlyCreated.length > 0 ||
+ data?.updatedInventories.length > 0
+ ) {
+ swal({
+ title: "SpreadSheet Upload Successful",
+ text: "Product Opening Inventory uploaded successfully.",
+ icon: "success",
+ buttons: "OK",
+ });
+ } else {
+ toast.success("File processed successfully with no new entries.");
+ handleCancel();
+ }
+ setFile(null); // Clear the file input
+ document.querySelector('input[type="file"]').value = "";
+ } catch (error) {
+ console.error("Upload error:", error);
+ swal(
+ "Error",
+ `Failed to upload Opening Inventory Spreedsheet: ${
+ error.response?.data?.message || "An unexpected error occurred"
+ }`,
+ "error"
+ );
+ } finally {
+ setLoading(false);
+ }
+ };
+ const handleCancel = () => {
+ navigate(
+ distributortype === "principaldistributor"
+ ? `/principaldistributor/opening-inventory/${id}`
+ : `/retaildistributor/opening-inventory/${id}`
+ );
+ };
+ return (
+
+
+
+
+
Add Multiple Products Opening inventory
+
+
+
+
+
+
+
+
+
+
Upload only .xlsx files*
+
+
+ {errors.length > 0 && (
+
+
Finding errors while adding the Opening Inventory.
+
+
+
+ SKU |
+ Product Name |
+ Opening Inventory |
+ Message |
+
+
+
+ {errors.map((error, index) => (
+
+ {error.SKU || "N/A"} |
+ {error.productName || "N/A"} |
+ {error.openingInventory || "N/A"} |
+ {error.message} |
+
+ ))}
+
+
+
+ )}
+ {updatedInventories.length > 0 && (
+
+
Updated Products in the Opening Inventory List
+
+
+
+ SKU |
+ Product Name |
+ Opening Inventory |
+ Message |
+
+
+
+ {updatedInventories.map((distributor, index) => (
+
+ {distributor.SKU || "N/A"} |
+ {distributor.productName || "N/A"} |
+ {distributor.openingInventory || "N/A"} |
+ {distributor.updatedFields} |
+
+ ))}
+
+
+
+ )}
+ {newlyCreated.length > 0 && (
+
+
Newly Added Products in Opening Inventory:
+
+
+
+ SKU |
+ Product Name |
+ Opening Inventory |
+
+
+
+ {newlyCreated.map((distributor, index) => (
+
+ {distributor.SKU || "N/A"} |
+ {distributor.productName || "N/A"} |
+ {distributor.openingInventory } |
+
+ ))}
+
+
+
+ )}
+
+ );
+};
+
+export default UploadOpeningInventory;
diff --git a/src/views/PrincipalDistributors/principalDistributor.js b/src/views/PrincipalDistributors/principalDistributor.js
index 0795109..3286c3b 100644
--- a/src/views/PrincipalDistributors/principalDistributor.js
+++ b/src/views/PrincipalDistributors/principalDistributor.js
@@ -205,13 +205,17 @@ const principalDistributor = () => {
-