Skip to content

Commit

Permalink
Merge branch 'main' into new_page_11
Browse files Browse the repository at this point in the history
  • Loading branch information
manikumarreddyu authored Nov 10, 2024
2 parents e084c43 + b455203 commit f75f455
Show file tree
Hide file tree
Showing 32 changed files with 1,936 additions and 3 deletions.
44 changes: 44 additions & 0 deletions backend/controllers/shop/sub-controllers/adminController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const Payment = require("../models/payment");
const Invoice = require("../models/invoice");

// Admin view all payments
const adminViewPayments = async (req, res) => {
try {
const payments = await Payment.find()
.populate("orderId")
.populate("userId");
res.status(200).json(payments);
} catch (error) {
res.status(500).json({ message: error.message });
}
};

// Admin view all invoices
const adminViewInvoices = async (req, res) => {
try {
const invoices = await Invoice.find()
.populate("orderId")
.populate("userId");
res.status(200).json(invoices);
} catch (error) {
res.status(500).json({ message: error.message });
}
};

// Admin filter/sort payments
const adminFilterPayments = async (req, res) => {
const { status, startDate, endDate } = req.query;
const filters = {};
if (status) filters.paymentStatus = status;
if (startDate && endDate)
filters.paymentDate = { $gte: startDate, $lte: endDate };

try {
const payments = await Payment.find(filters);
res.status(200).json(payments);
} catch (error) {
res.status(500).json({ message: error.message });
}
};

module.exports = { adminViewPayments, adminViewInvoices, adminFilterPayments };
217 changes: 217 additions & 0 deletions backend/controllers/shop/sub-controllers/invoiceController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
const Invoice = require("../models/invoice");
const Joi = require("joi");

// Validation Schemas
const invoiceSchema = Joi.object({
orderId: Joi.string().required(),
userId: Joi.string().required(),
amount: Joi.number().min(0).required(),
dueDate: Joi.date().required(),
paymentId: Joi.string().optional(),
});

const statusUpdateSchema = Joi.object({
status: Joi.string()
.valid("Paid", "Unpaid", "Overdue", "Cancelled")
.required(),
});

// Generate invoice after payment confirmation
const generateInvoice = async (req, res) => {
const { error, value } = invoiceSchema.validate(req.body);
if (error) return res.status(400).json({ message: error.message });

const { orderId, userId, amount, dueDate, paymentId } = value;

const newInvoice = new Invoice({
invoiceId: `INV${Date.now()}`,
orderId,
userId,
amount,
dueDate,
paymentId,
});

try {
const invoice = await newInvoice.save();
res.status(201).json(invoice);
} catch (error) {
console.error(`Error generating invoice: ${error.message}`);
res.status(500).json({ message: "Internal server error" });
}
};

// Retrieve invoices by user, order, status, or date range with pagination
const getInvoices = async (req, res) => {
const {
userId,
orderId,
status,
startDate,
endDate,
page = 1,
limit = 10,
sortBy = "invoiceDate",
order = "desc",
} = req.query;

try {
const filters = {};
if (userId) filters.userId = userId;
if (orderId) filters.orderId = orderId;
if (status) filters.status = status;

if (startDate || endDate) {
filters.invoiceDate = {};
if (startDate) filters.invoiceDate.$gte = new Date(startDate);
if (endDate) filters.invoiceDate.$lte = new Date(endDate);
}

const invoices = await Invoice.find(filters)
.sort({ [sortBy]: order === "asc" ? 1 : -1 })
.skip((page - 1) * limit)
.limit(Number(limit));

res.status(200).json(invoices);
} catch (error) {
console.error(`Error fetching invoices: ${error.message}`);
res.status(500).json({ message: "Internal server error" });
}
};

// Retrieve a single invoice by ID
const getInvoiceById = async (req, res) => {
try {
const invoice = await Invoice.findById(req.params.id);
if (!invoice) return res.status(404).json({ message: "Invoice not found" });
res.status(200).json(invoice);
} catch (error) {
console.error(`Error fetching invoice by ID: ${error.message}`);
res.status(500).json({ message: "Internal server error" });
}
};

// Update invoice status with validation
const updateInvoiceStatus = async (req, res) => {
const { error, value } = statusUpdateSchema.validate(req.body);
if (error) return res.status(400).json({ message: error.message });

try {
const invoice = await Invoice.findByIdAndUpdate(
req.params.id,
{ status: value.status },
{ new: true }
);
if (!invoice) return res.status(404).json({ message: "Invoice not found" });
res.status(200).json(invoice);
} catch (error) {
console.error(`Error updating invoice status: ${error.message}`);
res.status(500).json({ message: "Internal server error" });
}
};

// Delete an invoice by ID
const deleteInvoice = async (req, res) => {
try {
const invoice = await Invoice.findByIdAndDelete(req.params.id);
if (!invoice) return res.status(404).json({ message: "Invoice not found" });
res.status(200).json({ message: "Invoice deleted successfully" });
} catch (error) {
console.error(`Error deleting invoice: ${error.message}`);
res.status(500).json({ message: "Internal server error" });
}
};

// Mark overdue invoices
const markOverdueInvoices = async (req, res) => {
try {
const overdueInvoices = await Invoice.updateMany(
{ dueDate: { $lt: new Date() }, status: "Unpaid" },
{ status: "Overdue" }
);
res
.status(200)
.json({
message: `${overdueInvoices.nModified} invoices marked as overdue`,
});
} catch (error) {
console.error(`Error marking overdue invoices: ${error.message}`);
res.status(500).json({ message: "Internal server error" });
}
};

// Summary of invoices by status
const invoiceSummary = async (req, res) => {
const { userId } = req.query;

try {
const match = userId ? { userId } : {};

const summary = await Invoice.aggregate([
{ $match: match },
{
$group: {
_id: "$status",
totalAmount: { $sum: "$amount" },
count: { $sum: 1 },
},
},
]);

const summaryData = summary.reduce((acc, item) => {
acc[item._id] = { totalAmount: item.totalAmount, count: item.count };
return acc;
}, {});

res.status(200).json(summaryData);
} catch (error) {
console.error(`Error generating invoice summary: ${error.message}`);
res.status(500).json({ message: "Internal server error" });
}
};

// Bulk invoice generation
const generateBulkInvoices = async (req, res) => {
const { invoices } = req.body;

if (!Array.isArray(invoices) || invoices.length === 0) {
return res.status(400).json({ message: "Invalid invoices data" });
}

const validationErrors = invoices
.map((invoiceData, index) => {
const { error } = invoiceSchema.validate(invoiceData);
return error ? { index, message: error.message } : null;
})
.filter(Boolean);

if (validationErrors.length > 0) {
return res
.status(400)
.json({ message: "Validation errors", errors: validationErrors });
}

try {
const invoiceDocuments = invoices.map((invoiceData) => ({
...invoiceData,
invoiceId: `INV${Date.now() + Math.floor(Math.random() * 1000)}`,
}));

const createdInvoices = await Invoice.insertMany(invoiceDocuments);
res.status(201).json(createdInvoices);
} catch (error) {
console.error(`Error generating bulk invoices: ${error.message}`);
res.status(500).json({ message: "Internal server error" });
}
};

module.exports = {
generateInvoice,
getInvoices,
getInvoiceById,
updateInvoiceStatus,
deleteInvoice,
markOverdueInvoices,
invoiceSummary,
generateBulkInvoices,
};
Loading

0 comments on commit f75f455

Please sign in to comment.