import mongoose from "mongoose"; import { Product } from "../Products/ProductModel.js"; import { PDStock } from "../Stock/PdStockModel.js"; import { RDStock } from "../Stock/RdStockModel.js"; export const getProductsWithOpenInventoryInfo = async (req, res) => { try { const { page = 1, show = 10, name, category, brand } = req.query; // Pagination setup const limit = parseInt(show, 10); const skip = (parseInt(page, 10) - 1) * limit; // Search filters const searchCriteria = {}; if (name) searchCriteria.name = { $regex: name, $options: "i" }; if (category) searchCriteria.category = mongoose.Types.ObjectId(category); if (brand) searchCriteria.brand = mongoose.Types.ObjectId(brand); // Step 1: Fetch filtered products with population const products = await Product.find(searchCriteria) .skip(skip) .limit(limit) .populate("brand", "brandName") // Populate brandName .populate("category", "categoryName") // Populate categoryName .exec(); // Step 2: Collect all product SKUs to find corresponding PDs and RDs with stock const productSKUs = products.map((product) => product.SKU); // Step 3: Fetch all PDs with non-zero opening inventory for these products using SKU const pdOIs = await PDStock.aggregate([ { $unwind: "$products" }, { $match: { "products.openingInventory": { $gt: 0 }, "products.SKU": { $in: productSKUs }, }, }, { $group: { _id: "$products.SKU", totalPdOpeningInventory: { $sum: "$products.openingInventory" }, }, }, ]); // Step 4: Fetch all RDs with non-zero opening inventory for these products using SKU const rdOIs = await RDStock.aggregate([ { $unwind: "$products" }, { $match: { "products.openingInventory": { $gt: 0 }, "products.SKU": { $in: productSKUs }, }, }, { $group: { _id: "$products.SKU", totalRdOpeningInventory: { $sum: "$products.openingInventory" }, }, }, ]); // Step 5: Prepare a mapping of PD and RD copening inventories by SKU const pdMap = {}; pdOIs.forEach((pd) => { pdMap[pd._id] = pd.totalPdOpeningInventory; }); const rdMap = {}; rdOIs.forEach((rd) => { rdMap[rd._id] = rd.totalRdOpeningInventory; }); // Step 6: Combine product info with PD/RD counts using SKU const productData = products.map((product) => ({ SKU: product.SKU, name: product.name, brand: product.brand?.brandName || "N/A", // Access brandName here category: product.category?.categoryName || "N/A", // Access categoryName here allPDs: pdMap[product.SKU] || 0, allRDs: rdMap[product.SKU] || 0, allPdAndRd: (pdMap[product.SKU] || 0) + (rdMap[product.SKU] || 0), })); // Step 7: Get total count for pagination const totalCount = await Product.countDocuments(searchCriteria); // Step 8: Respond with paginated results and total count res.status(200).json({ success: true, data: productData, pagination: { total: totalCount, page: parseInt(page, 10), pages: Math.ceil(totalCount / limit), }, }); } catch (error) { res.status(500).json({ success: false, message: error.message }); } }; export const getProductsWithStockInfo = async (req, res) => { try { const { page = 1, show = 10, name, category, brand } = req.query; // Pagination setup const limit = parseInt(show, 10); const skip = (parseInt(page, 10) - 1) * limit; // Search filters const searchCriteria = {}; if (name) searchCriteria.name = { $regex: name, $options: "i" }; if (category) searchCriteria.category = mongoose.Types.ObjectId(category); if (brand) searchCriteria.brand = mongoose.Types.ObjectId(brand); // Step 1: Fetch filtered products with population const products = await Product.find(searchCriteria) .skip(skip) .limit(limit) .populate("brand", "brandName") // Populate brandName .populate("category", "categoryName") // Populate categoryName .exec(); // Step 2: Collect all product SKUs to find corresponding PDs and RDs with stock const productSKUs = products.map((product) => product.SKU); // Step 3: Fetch all PDs with non-zero Stock for these products using SKU const pdStocks = await PDStock.aggregate([ { $unwind: "$products" }, { $match: { "products.Stock": { $gt: 0 }, "products.SKU": { $in: productSKUs }, }, }, { $group: { _id: "$products.SKU", totalpdStock: { $sum: "$products.Stock" }, }, }, ]); // Step 4: Fetch all RDs with non-zero Stock for these products using SKU const rdStocks = await RDStock.aggregate([ { $unwind: "$products" }, { $match: { "products.Stock": { $gt: 0 }, "products.SKU": { $in: productSKUs }, }, }, { $group: { _id: "$products.SKU", totalrdStock: { $sum: "$products.Stock" }, }, }, ]); // Step 5: Prepare a mapping of PD and RD Stocks by SKU const pdMap = {}; pdStocks.forEach((pd) => { pdMap[pd._id] = pd.totalpdStock; }); const rdMap = {}; rdStocks.forEach((rd) => { rdMap[rd._id] = rd.totalrdStock; }); // Step 6: Combine product info with PD/RD counts using SKU const productData = products.map((product) => ({ SKU: product.SKU, name: product.name, brand: product.brand?.brandName || "N/A", // Access brandName here category: product.category?.categoryName || "N/A", // Access categoryName here allPDs: pdMap[product.SKU] || 0, allRDs: rdMap[product.SKU] || 0, allPdAndRd: (pdMap[product.SKU] || 0) + (rdMap[product.SKU] || 0), })); // Step 7: Get total count for pagination const totalCount = await Product.countDocuments(searchCriteria); // Step 8: Respond with paginated results and total count res.status(200).json({ success: true, data: productData, pagination: { total: totalCount, page: parseInt(page, 10), pages: Math.ceil(totalCount / limit), }, }); } catch (error) { res.status(500).json({ success: false, message: error.message }); } };