diff --git a/controllers/fund.js b/controllers/fund.js index 490029d..157ce39 100644 --- a/controllers/fund.js +++ b/controllers/fund.js @@ -2,23 +2,78 @@ const Student = require("../models/students"); const catchAsync = require("../utils/catchAsync"); const MonthlyReport = require("../models/monthlyReport"); const archivedStudent = require("../models/archivedStudent"); -let thisMonthYear = new Date().toLocaleString("en-US", { - month: "short", - year: "numeric", -}); module.exports.fund = catchAsync(async (req, res) => { const now = new Date(); const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1); const view = req.query.view; - let dateFilter; - if (view === "month") { - dateFilter = { $gte: startOfMonth, $lt: endOfMonth }; - } else { - const threeDaysAgo = new Date(); - threeDaysAgo.setDate(threeDaysAgo.getDate() - 3); - dateFilter = { $gte: threeDaysAgo }; - } + const dateFilter = + view === "month" + ? { "feesHistory.paidDate": { $gte: startOfMonth, $lt: endOfMonth } } + : { "feesHistory.paidDate": { $exists: true, $ne: null } }; + const feesPipeline = + view === "month" + ? [ + { $unwind: "$feesHistory" }, + { + $match: { + "feesHistory.paidDate": { + $gte: startOfMonth, + $lt: endOfMonth, + }, + }, + }, + { $sort: { "feesHistory.paidDate": -1 } }, + { + $project: { + name: 1, + grade: 1, + "feesHistory.amount": 1, + "feesHistory.paidDate": 1, + "feesHistory.note": 1, + }, + }, + ] + : [ + { $unwind: "$feesHistory" }, + { + $match: { + "feesHistory.paidDate": { $exists: true, $ne: null }, + }, + }, + { $sort: { "feesHistory.paidDate": -1 } }, + { + $group: { + _id: { + $dateToString: { + format: "%Y-%m-%d", + date: "$feesHistory.paidDate", + }, + }, + records: { + $push: { + name: "$name", + grade: "$grade", + amount: "$feesHistory.amount", + paidDate: "$feesHistory.paidDate", + note: "$feesHistory.note", + }, + }, + }, + }, + { $sort: { _id: -1 } }, + { $limit: 3 }, + { $unwind: "$records" }, + { + $project: { + name: "$records.name", + grade: "$records.grade", + "feesHistory.amount": "$records.amount", + "feesHistory.paidDate": "$records.paidDate", + "feesHistory.note": "$records.note", + }, + }, + ]; const [studentResult, archiveFeesThisMonth] = await Promise.all([ Student.aggregate([ { $match: { owner: req.user._id } }, @@ -32,24 +87,20 @@ module.exports.fund = catchAsync(async (req, res) => { }, }, ], - feesThisMonth: [ - { $unwind: "$feesHistory" }, + totalStudents: [{ $count: "count" }], + paidStudents: [ { $match: { - "feesHistory.paidDate": dateFilter, - }, - }, - { $sort: { "feesHistory.paidDate": -1 } }, - { - $project: { - name: 1, - grade: 1, - "feesHistory.amount": 1, - "feesHistory.paidDate": 1, - "feesHistory.note": 1, + feesHistory: { + $elemMatch: { + paidDate: { $gte: startOfMonth, $lt: endOfMonth }, + }, + }, }, }, + { $count: "count" }, ], + feesThisMonth: feesPipeline, studentsThisMonth: [ { $match: { @@ -75,7 +126,7 @@ module.exports.fund = catchAsync(async (req, res) => { { $unwind: "$feesHistory" }, { $match: { - "feesHistory.paidDate": dateFilter, + "feesHistory.paidDate": { $gte: startOfMonth, $lt: endOfMonth }, }, }, { $sort: { "feesHistory.paidDate": -1 } }, @@ -93,18 +144,17 @@ module.exports.fund = catchAsync(async (req, res) => { // ✅ Extract data from facet const data = studentResult[0]; const totalDue = data.totalDue[0]?.totalDue || 0; + const totalStudents = data.totalStudents[0]?.count || 0; + const paidStudents = data.paidStudents[0]?.count || 0; const feesThisMonth = data.feesThisMonth; const stuThisMonth = data.studentsThisMonth; const todayDate = new Date().toISOString().split("T")[0]; const month = now.getMonth() + 1; const year = now.getFullYear(); - let thisMonthData = await MonthlyReport.findOne({ - owner: req.user._id, - month, - year, - }).lean(); - if (!thisMonthData) { - thisMonthData = await MonthlyReport.create({ + let thisMonthData = await MonthlyReport.findOneAndUpdate( + { owner: req.user._id, month, year }, + { + $setOnInsert: { owner: req.user._id, month, year, @@ -114,11 +164,16 @@ module.exports.fund = catchAsync(async (req, res) => { newStudents: 0, studentsLeft: 0, createdAt: new Date(), - }); + }, + }, + { + upsert: true, + new: true, + lean: true, } +); // ✅ Calculate expenses - let total = 0; - thisMonthData.expenses.forEach((e) => (total += e.amount)); + const total = thisMonthData.expenses.reduce((sum, e) => sum + e.amount, 0); const balance = Number(thisMonthData.totalEarning) - total; res.render("listings/fund", { totalDue, @@ -127,10 +182,11 @@ module.exports.fund = catchAsync(async (req, res) => { total, view, balance, - thisMonthYear, thisMonthData, stuThisMonth, archiveFeesThisMonth, + totalStudents, + paidStudents, }); }); module.exports.addExpense = catchAsync(async (req, res) => { diff --git a/controllers/students.js b/controllers/students.js index 2d9e05d..869a8df 100644 --- a/controllers/students.js +++ b/controllers/students.js @@ -42,7 +42,7 @@ module.exports.students = catchAsync(async (req, res) => { }); module.exports.showStudent = catchAsync(async (req, res, next) => { const { id } = req.params; - const student = await Student.findOne({ _id: id, owner: req.user._id }); + let student = await Student.findOne({ _id: id, owner: req.user._id }); if (!student) throw new ExpressError(404, "Student not found"); const formattedDate = formatDate(student.joiningDate); res.render("listings/show", { student, formattedDate }); @@ -66,6 +66,13 @@ module.exports.deactivateStudent = catchAsync(async (req, res) => { req.flash("success", "Student deactivated successfully"); res.redirect("/students"); }); +module.exports.editArchiveStu = catchAsync(async (req, res, next) => { + const { id } = req.params; + const student = await ArchivedStudent.findOne({ _id: id, owner: req.user._id }); + if (!student) throw new ExpressError(404, "Archived student not found"); + const formattedDate = formatDate(student.joiningDate, "input"); + res.render("listings/editArchiveStu", { student, formattedDate }); +}); module.exports.editStudent = catchAsync(async (req, res, next) => { const { id } = req.params; const student = await Student.findOne({ _id: id, owner: req.user._id }); @@ -73,6 +80,45 @@ module.exports.editStudent = catchAsync(async (req, res, next) => { const formattedDate = formatDate(student.joiningDate, "input"); res.render("listings/edit", { student, formattedDate }); // create this view }); +module.exports.saveEditArchiveStu = catchAsync(async (req, res, next) => { + const { id } = req.params; + const { + name, + grade, + parent, + contact, + phone, + note, + joiningDate, + fees, + dueFees, + } = req.body; + let student = await ArchivedStudent.findOneAndUpdate( + { _id: id, owner: req.user._id }, + { + name, + grade, + parent, + contact, + phone, + note, + joiningDate, + dueFees, + fees, + }, + { new: true, runValidators: true }, + ); + if (!student) { + req.flash("error", "Student not found"); + return res.redirect("/students"); + } + const formattedDate = formatDate(student.joiningDate); + res.render("listings/show", { + student, + formattedDate, + success: "Details updated.", + }); +}); module.exports.saveEditStudent = catchAsync(async (req, res, next) => { const { id } = req.params; const { @@ -258,6 +304,58 @@ module.exports.archived = catchAsync(async (req, res) => { .lean(); res.render("listings/archive", { studentsData: archived }); }); +module.exports.showArchiveStu = catchAsync(async (req, res, next) => { + const { id } = req.params; + let student = await ArchivedStudent.findOne({ _id: id, owner: req.user._id }); + if (!student) throw new ExpressError(404, "Student not found"); + const formattedDate = formatDate(student.joiningDate); + res.render("listings/showArchiveStu", { student, formattedDate }); +}); +module.exports.addArchiveStuFee = catchAsync(async (req, res) => { + let { id } = req.params; + let { note, amount, paidOn } = req.body; + if (!amount || Number(amount) <= 0) { + req.flash("error", "Amount must be greater than 0"); + return res.redirect(`/students/${id}`); + } + amount = Number(amount); + let paidDate = paidOn ? new Date(paidOn) : new Date(); + const student = await ArchivedStudent.findOne({ _id: id, owner: req.user._id }); + if (!student) { + return res.status(404).send("Student not found"); + } + student.feesHistory.push({ + note, + amount, + paidDate, + }); + const month = new Date().getMonth() + 1; + const year = new Date().getFullYear(); + let thisMonthData = await MonthlyReport.findOne({ + owner: req.user._id, + month, + year, + }); + if (!thisMonthData) { + thisMonthData = await MonthlyReport.create({ + owner: req.user._id, + month, + year, + totalEarning: 0, + expenses: [], + totalExpenses: 0, + newStudents: 0, + studentsLeft: 0, + createdAt: new Date(), + }); + } + thisMonthData.totalEarning += amount; + student.dueFees -= amount; + await student.save(); + await thisMonthData.save(); + req.flash("success", `Fees added for ${student.name}. `); + res.redirect(`/students`); +}); module.exports.restoreStudent = catchAsync(async (req, res) => { const { id } = req.params; const archivedStudent = await ArchivedStudent.findOne({ diff --git a/package-lock.json b/package-lock.json index 8bf35d4..9f8b0b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "connect-flash": "^0.1.1", "connect-mongo": "^5.1.0", "cookie-parser": "^1.4.7", - "dotenv": "^17.2.3", + "dotenv": "^17.4.2", "ejs": "^3.1.10", "ejs-mate": "^4.0.0", "express": "^5.1.0", @@ -164,9 +164,10 @@ } }, "node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==" + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" }, "node_modules/body-parser": { "version": "2.2.1", @@ -193,9 +194,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -364,9 +365,10 @@ } }, "node_modules/dotenv": { - "version": "17.2.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", - "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.4.2.tgz", + "integrity": "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, @@ -662,117 +664,6 @@ "node": ">=18" } }, - "node_modules/gcp-metadata": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.3.0.tgz", - "integrity": "sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "gaxios": "^5.0.0", - "json-bigint": "^1.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/gcp-metadata/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/gcp-metadata/node_modules/gaxios": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.3.tgz", - "integrity": "sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "dependencies": { - "extend": "^3.0.2", - "https-proxy-agent": "^5.0.0", - "is-stream": "^2.0.0", - "node-fetch": "^2.6.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/gcp-metadata/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/gcp-metadata/node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/gcp-metadata/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT", - "optional": true, - "peer": true - }, - "node_modules/gcp-metadata/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause", - "optional": true, - "peer": true - }, - "node_modules/gcp-metadata/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", @@ -985,20 +876,6 @@ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==" }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/jake": { "version": "10.9.4", "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", @@ -1221,9 +1098,9 @@ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -1287,9 +1164,10 @@ } }, "node_modules/mongoose": { - "version": "8.19.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.19.1.tgz", - "integrity": "sha512-oB7hGQJn4f8aebqE7mhE54EReb5cxVgpCxQCQj0K/cK3q4J3Tg08nFP6sM52nJ4Hlm8jsDnhVYpqIITZUAhckQ==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-8.24.0.tgz", + "integrity": "sha512-EEZwOibDPZ5uZN3bFapfnRskEbdljAf6sP9ln6u+P4e5IfkOAh6Tqw2g8/Tag++KHOAJ095WXT/c0uqRq4Vckg==", + "license": "MIT", "dependencies": { "bson": "^6.10.4", "kareem": "2.6.3", @@ -1558,11 +1436,13 @@ } }, "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "engines": { - "node": ">=16" + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/pause": { @@ -1597,9 +1477,9 @@ } }, "node_modules/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" diff --git a/package.json b/package.json index 83c3d37..22b06f7 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "connect-flash": "^0.1.1", "connect-mongo": "^5.1.0", "cookie-parser": "^1.4.7", - "dotenv": "^17.2.3", + "dotenv": "^17.4.2", "ejs": "^3.1.10", "ejs-mate": "^4.0.0", "express": "^5.1.0", diff --git a/public/css/fund.css b/public/css/fund.css index 69fc1d2..7f090ea 100644 --- a/public/css/fund.css +++ b/public/css/fund.css @@ -46,11 +46,12 @@ body { .stat { width: 100%; - padding: 0.6rem; color: white; - border-bottom: 1px dashed #ddd; display: flex; - justify-content: space-around; + justify-content: start; +} +.stats{ + justify-content: center; } .stat .total { border-radius: 30px; @@ -69,7 +70,8 @@ body { .stat div { margin: 0; - font-size: 14px; + font-size: 12px; + margin-left: 10px; } .new-stu { @@ -102,7 +104,7 @@ body { display: flex; justify-content: space-between; padding: 8px 0; - border-bottom: 1px dashed #ddd; + border-bottom: 1px dashed #515151; color: white; } .history { @@ -116,8 +118,9 @@ body { margin-bottom: 10px; } .feeHistory { + margin-top: .8rem; width: 23vw; - height: 55vh; + max-height: 55vh; overflow-y: scroll; } .feeHistory p{ @@ -126,8 +129,9 @@ body { .fee-entry { color: white; text-decoration: none; + text-transform: capitalize; font-size: 1.4rem; - border-bottom: 1px dashed #ddd; + /* border-bottom: 1px dashed #515151; */ padding: 5px 0; cursor: pointer; } @@ -258,6 +262,7 @@ input::-webkit-inner-spin-button { } .history { padding: 3.5vw; + margin: 3vw 0 0 0 ; } .fee-entry { font-size: 1rem; diff --git a/public/css/students.css b/public/css/students.css index 0e41793..52dc173 100644 --- a/public/css/students.css +++ b/public/css/students.css @@ -91,6 +91,13 @@ div.links-group:has(a.active)::after { display: flex; flex-wrap: wrap; } +.students a{ + text-decoration: none; +} +.students a .list { + padding: 0; + margin: 0; +} ul { list-style-type: none; } diff --git a/public/js/previousReports.js b/public/js/previousReports.js index 1224db4..d7a901a 100644 --- a/public/js/previousReports.js +++ b/public/js/previousReports.js @@ -36,7 +36,7 @@ function renderReportCard(data) {

${monthTitle}

-
+
${data.totalEarning.toLocaleString("en-IN")}₹ Archive Students - - + \ No newline at end of file diff --git a/views/listings/editArchiveStu.ejs b/views/listings/editArchiveStu.ejs new file mode 100644 index 0000000..1ae6831 --- /dev/null +++ b/views/listings/editArchiveStu.ejs @@ -0,0 +1,115 @@ +<% layout('layouts/boilerPlate') -%> + + +
+ Student reading a book +
+

Edit Details

+ +
+ + + +
+ + + + + + +
+
+ + diff --git a/views/listings/fund.ejs b/views/listings/fund.ejs index 703d3d8..f9549b3 100644 --- a/views/listings/fund.ejs +++ b/views/listings/fund.ejs @@ -5,18 +5,32 @@

Monthly Reports

-

<%= thisMonthYear %>

+

<%= new Date(thisMonthData.year, thisMonthData.month -1).toLocaleString( + "en-US",{ month: "short", year: "numeric" })%> +

<%=balance.toLocaleString('en-IN')%> ₹
Fund Balance
+
+ <%= total.toLocaleString('en-IN') %> ₹
Total Expenses +
+
+
<%=thisMonthData.totalEarning.toLocaleString('en-IN')%> ₹
Total Revenue
+
+ <%= totalDue.toLocaleString('en-IN') %> + ₹
Total Due +
@@ -33,6 +47,7 @@
+ <% if (thisMonthData && thisMonthData.expenses.length) { %>

Expense Details

    <%for(let exp of thisMonthData.expenses){%> @@ -47,8 +62,45 @@ <%}%>
-

Total Expenses : <%= total.toLocaleString('en-IN') %> ₹

-

Total Due : <%= totalDue.toLocaleString('en-IN') %> ₹

+ <% } %> +
+
+
+

+  Fees History +

+ <% if (view === "month") { %> + Show Last 3 Days + <% } else { %> + Show Full Month + <% } %> + Paid Students: <%=paidStudents%> / <%=totalStudents%> +
+ <% if (feesThisMonth && feesThisMonth.length) { %> <% + feesThisMonth.forEach(fee => { %> +
  • + <%= fee.feesHistory.amount %>₹ — <%= fee.name %> / <%= fee.grade %> + On : <%= new + Date(fee.feesHistory.paidDate) .toLocaleDateString('en-GB', { + weekday: 'short', day: 'numeric', month: 'short' }) + .replace(/,/g, '') %> <%if(fee.feesHistory.note){%>
    Note + : <%= fee.feesHistory.note %> <%}%>

    +
  • + <% }) %> <% } else { %> +

    No fees recorded this month.

    + <% } %> + <% if (archiveFeesThisMonth && archiveFeesThisMonth.length) { %> +

    Archive fees record

    + <% archiveFeesThisMonth.forEach(fee => { %> +
  • + <%= fee.feesHistory.amount %>₹ — <%= fee.name %> / <%= fee.grade %> + On : <%= new + Date(fee.feesHistory.paidDate) .toLocaleDateString('en-GB', { + weekday: 'short', day: 'numeric', month: 'short' }) + .replace(/,/g, '') %> <%if(fee.feesHistory.note){%>
    Note + : <%= fee.feesHistory.note %> <%}%>

    +
  • + <% })} %>
    @@ -91,43 +143,6 @@
    -
    -

    -  Fees This Month -

    - <% if (view === "month") { %> - Show Last 3 Days - <% } else { %> - Show Full Month - <% } %> -
    - <% if (feesThisMonth && feesThisMonth.length) { %> <% - feesThisMonth.forEach(fee => { %> -
  • - <%= fee.feesHistory.amount %>₹ — <%= fee.name %> / <%= fee.grade %> - On : <%= new - Date(fee.feesHistory.paidDate) .toLocaleDateString('en-GB', { - weekday: 'short', day: 'numeric', month: 'short' }) - .replace(/,/g, '') %> <%if(fee.feesHistory.note){%>
    Note - : <%= fee.feesHistory.note %> <%}%>

    -
  • - <% }) %> <% } else { %> -

    No fees recorded this month.

    - <% } %> - <% if (archiveFeesThisMonth && archiveFeesThisMonth.length) { %> -

    Archive fees record

    - <% archiveFeesThisMonth.forEach(fee => { %> -
  • - <%= fee.feesHistory.amount %>₹ — <%= fee.name %> / <%= fee.grade %> - On : <%= new - Date(fee.feesHistory.paidDate) .toLocaleDateString('en-GB', { - weekday: 'short', day: 'numeric', month: 'short' }) - .replace(/,/g, '') %> <%if(fee.feesHistory.note){%>
    Note - : <%= fee.feesHistory.note %> <%}%>

    -
  • - <% })} %> -
    -