avatarciao 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EJS/DynamicGreet.ejs +16 -0
- package/EJS/ErrorHandlingCustom.ejs +119 -0
- package/EJS/IncludeHeaderFooter.ejs +25 -0
- package/EJS/StudentDashboard.ejs +100 -0
- package/EJS/StudentDetailTable.ejs +62 -0
- package/EJS/paginationSystem.ejs +104 -0
- package/Express Session/index.js +155 -0
- package/ExpressModularRoutes/DynamicRouting.js +30 -0
- package/ExpressModularRoutes/MultiModuleBlogapi.js +36 -0
- package/ExpressModularRoutes/userRoutes.js +26 -0
- package/FS/basics.js +54 -0
- package/FS/copyFile.js +18 -0
- package/FS/periodicLogger.js +30 -0
- package/Http/BasicsOfHttp.js +73 -0
- package/Http/getPostHandling.js +44 -0
- package/Http/serveFiles.js +34 -0
- package/JWT/u1.js +78 -0
- package/JWT/u2.js +92 -0
- package/JWT/u3.js +97 -0
- package/JWT/u4.js +120 -0
- package/MongoDB/StudentManagementWithPagination.js +148 -0
- package/MongoDB/companyManagementSystem.js +139 -0
- package/Mongoose/Aggregate-E-commOrderAnalytics.js +287 -0
- package/Mongoose/EmployeePayrollSystem.js +104 -0
- package/Mongoose/EventManagementSystem.js +96 -0
- package/Multer/FileManagementApi.js +107 -0
- package/Multer/FileSize&TypeValidation.js +53 -0
- package/Multer/FileUploadFormData.js +77 -0
- package/Multer/MultiFileUpload.js +52 -0
- package/Multer/SingleFileUpload.js +58 -0
- package/express-routing/DynamicRoute.js +20 -0
- package/express-routing/StaticRouting.js +18 -0
- package/keys/all.txt +36 -0
- package/package.json +13 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
const express = require("express")
|
|
2
|
+
const { MongoClient, ObjectId } = require("mongodb")
|
|
3
|
+
const ejs = require("ejs")
|
|
4
|
+
|
|
5
|
+
const app = express()
|
|
6
|
+
app.use(express.urlencoded({ extended: true }))
|
|
7
|
+
app.use(express.json())
|
|
8
|
+
|
|
9
|
+
const url = "mongodb://127.0.0.1:27017"
|
|
10
|
+
const dbName = "testingproject"
|
|
11
|
+
let db
|
|
12
|
+
|
|
13
|
+
async function connectDB() {
|
|
14
|
+
if (db) return db
|
|
15
|
+
const client = new MongoClient(url)
|
|
16
|
+
await client.connect()
|
|
17
|
+
db = client.db(dbName)
|
|
18
|
+
return db
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const template = `
|
|
22
|
+
<!DOCTYPE html>
|
|
23
|
+
<html>
|
|
24
|
+
<head>
|
|
25
|
+
<title>Student Dashboard</title>
|
|
26
|
+
<style>
|
|
27
|
+
table{border-collapse:collapse;width:100%}
|
|
28
|
+
th,td{border:1px solid #000;padding:8px}
|
|
29
|
+
button{cursor:pointer}
|
|
30
|
+
</style>
|
|
31
|
+
</head>
|
|
32
|
+
<body>
|
|
33
|
+
|
|
34
|
+
<h2>Add Student</h2>
|
|
35
|
+
<form action="/add" method="POST">
|
|
36
|
+
<input name="name" placeholder="Name" required>
|
|
37
|
+
<input name="section" placeholder="Section" required>
|
|
38
|
+
<input name="marks" type="number" placeholder="Marks" required>
|
|
39
|
+
<button>Add</button>
|
|
40
|
+
</form>
|
|
41
|
+
|
|
42
|
+
<hr>
|
|
43
|
+
|
|
44
|
+
<h2>Filter By Marks</h2>
|
|
45
|
+
<form method="GET">
|
|
46
|
+
<input type="number" name="marks" value="<%= marks %>" placeholder="Minimum Marks">
|
|
47
|
+
<button>Filter</button>
|
|
48
|
+
</form>
|
|
49
|
+
|
|
50
|
+
<hr>
|
|
51
|
+
|
|
52
|
+
<table>
|
|
53
|
+
<tr>
|
|
54
|
+
<th>Name</th>
|
|
55
|
+
<th>Section</th>
|
|
56
|
+
<th>Marks</th>
|
|
57
|
+
<th>Actions</th>
|
|
58
|
+
</tr>
|
|
59
|
+
|
|
60
|
+
<% students.forEach(s => { %>
|
|
61
|
+
<tr>
|
|
62
|
+
<td><%= s.name %></td>
|
|
63
|
+
<td><%= s.section %></td>
|
|
64
|
+
<td><%= s.marks %></td>
|
|
65
|
+
<td>
|
|
66
|
+
<button onclick="delStudent('<%= s._id %>')">Delete</button>
|
|
67
|
+
<button onclick="updStudent('<%= s._id %>','<%= s.name %>','<%= s.section %>','<%= s.marks %>')">Update</button>
|
|
68
|
+
</td>
|
|
69
|
+
</tr>
|
|
70
|
+
<% }) %>
|
|
71
|
+
</table>
|
|
72
|
+
|
|
73
|
+
<br>
|
|
74
|
+
|
|
75
|
+
<% if(hasPrev){ %>
|
|
76
|
+
<a href="/?page=<%= page-1 %>&marks=<%= marks %>">Previous</a>
|
|
77
|
+
<% } %>
|
|
78
|
+
|
|
79
|
+
<% if(hasNext){ %>
|
|
80
|
+
<a href="/?page=<%= page+1 %>&marks=<%= marks %>">Next</a>
|
|
81
|
+
<% } %>
|
|
82
|
+
|
|
83
|
+
<script>
|
|
84
|
+
function delStudent(id){
|
|
85
|
+
fetch("/delete/"+id,{method:"DELETE"}).then(()=>location.reload())
|
|
86
|
+
}
|
|
87
|
+
function updStudent(id,n,s,m){
|
|
88
|
+
const name=prompt("Name",n)
|
|
89
|
+
const section=prompt("Section",s)
|
|
90
|
+
const marks=prompt("Marks",m)
|
|
91
|
+
fetch("/update/"+id,{
|
|
92
|
+
method:"PATCH",
|
|
93
|
+
headers:{"Content-Type":"application/json"},
|
|
94
|
+
body:JSON.stringify({name,section,marks})
|
|
95
|
+
}).then(()=>location.reload())
|
|
96
|
+
}
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
</body>
|
|
100
|
+
</html>
|
|
101
|
+
`
|
|
102
|
+
|
|
103
|
+
app.get("/", async (req, res) => {
|
|
104
|
+
const db = await connectDB()
|
|
105
|
+
const col = db.collection("students")
|
|
106
|
+
const page = parseInt(req.query.page) || 1
|
|
107
|
+
const limit = 5
|
|
108
|
+
const skip = (page - 1) * limit
|
|
109
|
+
const filter = {}
|
|
110
|
+
if (req.query.marks) filter.marks = { $gte: parseInt(req.query.marks) }
|
|
111
|
+
const total = await col.countDocuments(filter)
|
|
112
|
+
const students = await col.find(filter).skip(skip).limit(limit).toArray()
|
|
113
|
+
const html = ejs.render(template, {
|
|
114
|
+
students,
|
|
115
|
+
page,
|
|
116
|
+
hasPrev: page > 1,
|
|
117
|
+
hasNext: page * limit < total,
|
|
118
|
+
marks: req.query.marks || ""
|
|
119
|
+
})
|
|
120
|
+
res.send(html)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
app.post("/add", async (req, res) => {
|
|
124
|
+
const db = await connectDB()
|
|
125
|
+
await db.collection("students").insertOne({
|
|
126
|
+
name: req.body.name,
|
|
127
|
+
section: req.body.section,
|
|
128
|
+
marks: parseInt(req.body.marks)
|
|
129
|
+
})
|
|
130
|
+
res.redirect("/")
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
app.delete("/delete/:id", async (req, res) => {
|
|
134
|
+
const db = await connectDB()
|
|
135
|
+
await db.collection("students").deleteOne({ _id: new ObjectId(req.params.id) })
|
|
136
|
+
res.sendStatus(200)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
app.patch("/update/:id", async (req, res) => {
|
|
140
|
+
const db = await connectDB()
|
|
141
|
+
await db.collection("students").updateOne(
|
|
142
|
+
{ _id: new ObjectId(req.params.id) },
|
|
143
|
+
{ $set: { name: req.body.name, section: req.body.section, marks: parseInt(req.body.marks) } }
|
|
144
|
+
)
|
|
145
|
+
res.sendStatus(200)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
app.listen(3000)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
const express = require("express");
|
|
2
|
+
const { MongoClient } = require("mongodb");
|
|
3
|
+
|
|
4
|
+
const app = express();
|
|
5
|
+
const PORT = 3000;
|
|
6
|
+
const URL = "mongodb://127.0.0.1:27017";
|
|
7
|
+
const DB_NAME = "CompanyDB";
|
|
8
|
+
|
|
9
|
+
let db, employees, departments;
|
|
10
|
+
|
|
11
|
+
MongoClient.connect(URL)
|
|
12
|
+
.then(client => {
|
|
13
|
+
db = client.db(DB_NAME);
|
|
14
|
+
employees = db.collection("employees");
|
|
15
|
+
departments = db.collection("departments");
|
|
16
|
+
|
|
17
|
+
employees.createIndex({ empid: 1 }, { unique: true });
|
|
18
|
+
departments.createIndex({ deptid: 1 }, { unique: true });
|
|
19
|
+
})
|
|
20
|
+
.catch(err => console.error(err));
|
|
21
|
+
|
|
22
|
+
app.get("/seed-employees", async (req, res) => {
|
|
23
|
+
const data = [
|
|
24
|
+
{ empid: 1, name: "Amit", salary: 50000, deptid: 101 },
|
|
25
|
+
{ empid: 2, name: "Ravi", salary: 60000, deptid: 102 },
|
|
26
|
+
{ empid: 3, name: "Neha", salary: 55000, deptid: 101 },
|
|
27
|
+
{ empid: 4, name: "Kiran", salary: 70000, deptid: 103 },
|
|
28
|
+
{ empid: 5, name: "Pooja", salary: 65000, deptid: 102 },
|
|
29
|
+
{ empid: 6, name: "Anil", salary: 48000, deptid: 103 }
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
await employees.insertMany(data);
|
|
34
|
+
res.send("Employees seeded successfully");
|
|
35
|
+
} catch (err) {
|
|
36
|
+
res.send(err.message);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
app.get("/view-employees", async (req, res) => {
|
|
41
|
+
const result = await employees.find().toArray();
|
|
42
|
+
res.json(result);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
app.get("/add-employee/:id/:name/:salary/:deptid", async (req, res) => {
|
|
46
|
+
const emp = {
|
|
47
|
+
empid: parseInt(req.params.id),
|
|
48
|
+
name: req.params.name,
|
|
49
|
+
salary: parseInt(req.params.salary),
|
|
50
|
+
deptid: parseInt(req.params.deptid)
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
await employees.insertOne(emp);
|
|
55
|
+
res.send("Employee added");
|
|
56
|
+
} catch (err) {
|
|
57
|
+
res.send(err.message);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
app.get("/delete-employee/:id", async (req, res) => {
|
|
62
|
+
await employees.deleteOne({ empid: parseInt(req.params.id) });
|
|
63
|
+
res.send("Employee deleted");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
app.get("/delete-employee-lt/:id", async (req, res) => {
|
|
67
|
+
await employees.deleteMany({ empid: { $lt: parseInt(req.params.id) } });
|
|
68
|
+
res.send("Employees deleted");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
app.get("/update-salary/:id/:amount", async (req, res) => {
|
|
72
|
+
await employees.updateOne(
|
|
73
|
+
{ empid: parseInt(req.params.id) },
|
|
74
|
+
{ $set: { salary: parseInt(req.params.amount) } }
|
|
75
|
+
);
|
|
76
|
+
res.send("Salary updated");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
app.get("/update-salary-range/:id/:amount", async (req, res) => {
|
|
80
|
+
await employees.updateMany(
|
|
81
|
+
{ empid: { $gte: parseInt(req.params.id) } },
|
|
82
|
+
{ $inc: { salary: parseInt(req.params.amount) } }
|
|
83
|
+
);
|
|
84
|
+
res.send("Salary incremented");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
app.get("/search-employee/:name", async (req, res) => {
|
|
88
|
+
const result = await employees.find({ name: req.params.name }).toArray();
|
|
89
|
+
res.json(result);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
app.get("/seed-departments", async (req, res) => {
|
|
93
|
+
const data = [
|
|
94
|
+
{ deptid: 101, name: "HR" },
|
|
95
|
+
{ deptid: 102, name: "IT" },
|
|
96
|
+
{ deptid: 103, name: "Finance" }
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
await departments.insertMany(data);
|
|
101
|
+
res.send("Departments seeded successfully");
|
|
102
|
+
} catch (err) {
|
|
103
|
+
res.send(err.message);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
app.get("/view-departments", async (req, res) => {
|
|
108
|
+
const result = await departments.find().toArray();
|
|
109
|
+
res.json(result);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
app.get("/add-department/:id/:name", async (req, res) => {
|
|
113
|
+
try {
|
|
114
|
+
await departments.insertOne({
|
|
115
|
+
deptid: parseInt(req.params.id),
|
|
116
|
+
name: req.params.name
|
|
117
|
+
});
|
|
118
|
+
res.send("Department added");
|
|
119
|
+
} catch (err) {
|
|
120
|
+
res.send(err.message);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
app.get("/delete-department/:id", async (req, res) => {
|
|
125
|
+
await departments.deleteOne({ deptid: parseInt(req.params.id) });
|
|
126
|
+
res.send("Department deleted");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
app.get("/update-department/:id/:newname", async (req, res) => {
|
|
130
|
+
await departments.updateOne(
|
|
131
|
+
{ deptid: parseInt(req.params.id) },
|
|
132
|
+
{ $set: { name: req.params.newname } }
|
|
133
|
+
);
|
|
134
|
+
res.send("Department updated");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
app.listen(PORT, () => {
|
|
138
|
+
console.log(`Server running on http://localhost:${PORT}`);
|
|
139
|
+
});
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
const mongoose = require("mongoose")
|
|
2
|
+
|
|
3
|
+
mongoose.connect("mongodb://127.0.0.1:27017/ecommerce")
|
|
4
|
+
|
|
5
|
+
const orderSchema = new mongoose.Schema({
|
|
6
|
+
orderId: String,
|
|
7
|
+
userId: String,
|
|
8
|
+
city: String,
|
|
9
|
+
category: String,
|
|
10
|
+
product: String,
|
|
11
|
+
quantity: Number,
|
|
12
|
+
price: Number,
|
|
13
|
+
discount: Number,
|
|
14
|
+
status: String,
|
|
15
|
+
orderDate: Date
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const Order = mongoose.model("Order", orderSchema)
|
|
19
|
+
|
|
20
|
+
async function runAnalytics() {
|
|
21
|
+
|
|
22
|
+
const topCities = await Order.aggregate([
|
|
23
|
+
{ $match: { status: { $ne: "cancelled" } } },
|
|
24
|
+
{
|
|
25
|
+
$addFields: {
|
|
26
|
+
revenue: {
|
|
27
|
+
$subtract: [
|
|
28
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
29
|
+
{
|
|
30
|
+
$multiply: [
|
|
31
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
32
|
+
{ $divide: ["$discount", 100] }
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
$group: {
|
|
41
|
+
_id: "$city",
|
|
42
|
+
totalRevenue: { $sum: "$revenue" },
|
|
43
|
+
avgOrderValue: { $avg: "$revenue" }
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{ $sort: { totalRevenue: -1 } },
|
|
47
|
+
{ $limit: 3 },
|
|
48
|
+
{
|
|
49
|
+
$project: {
|
|
50
|
+
_id: 0,
|
|
51
|
+
city: "$_id",
|
|
52
|
+
totalRevenue: 1,
|
|
53
|
+
avgOrderValue: 1
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
])
|
|
57
|
+
|
|
58
|
+
const categorySummary = await Order.aggregate([
|
|
59
|
+
{ $match: { status: "delivered" } },
|
|
60
|
+
{
|
|
61
|
+
$addFields: {
|
|
62
|
+
orderValue: {
|
|
63
|
+
$subtract: [
|
|
64
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
65
|
+
{
|
|
66
|
+
$multiply: [
|
|
67
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
68
|
+
{ $divide: ["$discount", 100] }
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
$group: {
|
|
77
|
+
_id: "$category",
|
|
78
|
+
totalOrders: { $sum: 1 },
|
|
79
|
+
totalQuantity: { $sum: "$quantity" },
|
|
80
|
+
avgOrderValue: { $avg: "$orderValue" },
|
|
81
|
+
highestOrderValue: { $max: "$orderValue" }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
])
|
|
85
|
+
|
|
86
|
+
const bigSpenders = await Order.aggregate([
|
|
87
|
+
{
|
|
88
|
+
$addFields: {
|
|
89
|
+
orderValue: {
|
|
90
|
+
$subtract: [
|
|
91
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
92
|
+
{
|
|
93
|
+
$multiply: [
|
|
94
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
95
|
+
{ $divide: ["$discount", 100] }
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
$group: {
|
|
104
|
+
_id: "$userId",
|
|
105
|
+
totalSpent: { $sum: "$orderValue" },
|
|
106
|
+
avgOrderValue: { $avg: "$orderValue" }
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{ $match: { totalSpent: { $gt: 20000 } } },
|
|
110
|
+
{ $sort: { totalSpent: -1 } },
|
|
111
|
+
{
|
|
112
|
+
$project: {
|
|
113
|
+
_id: 0,
|
|
114
|
+
userId: "$_id",
|
|
115
|
+
totalSpent: 1,
|
|
116
|
+
avgOrderValue: 1
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
])
|
|
120
|
+
|
|
121
|
+
const monthlyRevenue = await Order.aggregate([
|
|
122
|
+
{
|
|
123
|
+
$match: {
|
|
124
|
+
orderDate: {
|
|
125
|
+
$gte: new Date(new Date().getFullYear(), 0, 1),
|
|
126
|
+
$lte: new Date(new Date().getFullYear(), 11, 31)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
$addFields: {
|
|
132
|
+
revenue: {
|
|
133
|
+
$subtract: [
|
|
134
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
135
|
+
{
|
|
136
|
+
$multiply: [
|
|
137
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
138
|
+
{ $divide: ["$discount", 100] }
|
|
139
|
+
]
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
month: { $month: "$orderDate" }
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
$group: {
|
|
148
|
+
_id: "$month",
|
|
149
|
+
totalRevenue: { $sum: "$revenue" },
|
|
150
|
+
avgOrderValue: { $avg: "$revenue" },
|
|
151
|
+
totalOrders: { $sum: 1 }
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
$project: {
|
|
156
|
+
_id: 0,
|
|
157
|
+
month: {
|
|
158
|
+
$arrayElemAt: [
|
|
159
|
+
["","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],
|
|
160
|
+
"$_id"
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
totalRevenue: 1,
|
|
164
|
+
avgOrderValue: 1,
|
|
165
|
+
totalOrders: 1
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
])
|
|
169
|
+
|
|
170
|
+
const outliers = await Order.aggregate([
|
|
171
|
+
{
|
|
172
|
+
$addFields: {
|
|
173
|
+
orderValue: {
|
|
174
|
+
$subtract: [
|
|
175
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
176
|
+
{
|
|
177
|
+
$multiply: [
|
|
178
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
179
|
+
{ $divide: ["$discount", 100] }
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
$group: {
|
|
188
|
+
_id: null,
|
|
189
|
+
avgValue: { $avg: "$orderValue" },
|
|
190
|
+
orders: { $push: "$$ROOT" }
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
{ $unwind: "$orders" },
|
|
194
|
+
{ $match: { $expr: { $gt: ["$orders.orderValue", "$avgValue"] } } },
|
|
195
|
+
{ $sort: { "orders.orderValue": -1 } },
|
|
196
|
+
{ $limit: 5 },
|
|
197
|
+
{ $replaceRoot: { newRoot: "$orders" } }
|
|
198
|
+
])
|
|
199
|
+
|
|
200
|
+
const dailySummary = await Order.aggregate([
|
|
201
|
+
{
|
|
202
|
+
$addFields: {
|
|
203
|
+
orderValue: {
|
|
204
|
+
$subtract: [
|
|
205
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
206
|
+
{
|
|
207
|
+
$multiply: [
|
|
208
|
+
{ $multiply: ["$price", "$quantity"] },
|
|
209
|
+
{ $divide: ["$discount", 100] }
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
day: {
|
|
215
|
+
$dateToString: { format: "%Y-%m-%d", date: "$orderDate" }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
$group: {
|
|
221
|
+
_id: "$day",
|
|
222
|
+
totalOrders: { $sum: 1 },
|
|
223
|
+
totalQuantity: { $sum: "$quantity" },
|
|
224
|
+
totalRevenue: { $sum: "$orderValue" },
|
|
225
|
+
minOrderValue: { $min: "$orderValue" },
|
|
226
|
+
maxOrderValue: { $max: "$orderValue" }
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
$project: {
|
|
231
|
+
_id: 0,
|
|
232
|
+
date: "$_id",
|
|
233
|
+
totalOrders: 1,
|
|
234
|
+
totalQuantity: 1,
|
|
235
|
+
totalRevenue: 1,
|
|
236
|
+
minOrderValue: 1,
|
|
237
|
+
maxOrderValue: 1
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
])
|
|
241
|
+
|
|
242
|
+
const cityDistribution = await Order.aggregate([
|
|
243
|
+
{
|
|
244
|
+
$group: {
|
|
245
|
+
_id: "$city",
|
|
246
|
+
totalOrders: { $sum: 1 }
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
{ $match: { totalOrders: { $gt: 10 } } },
|
|
250
|
+
{
|
|
251
|
+
$project: {
|
|
252
|
+
_id: 0,
|
|
253
|
+
city: "$_id",
|
|
254
|
+
totalOrders: 1
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
])
|
|
258
|
+
|
|
259
|
+
const categoryPopularity = await Order.aggregate([
|
|
260
|
+
{
|
|
261
|
+
$group: {
|
|
262
|
+
_id: "$category",
|
|
263
|
+
totalQuantity: { $sum: "$quantity" },
|
|
264
|
+
avgPrice: { $avg: "$price" }
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
$addFields: {
|
|
269
|
+
popularityScore: { $multiply: ["$totalQuantity", "$avgPrice"] }
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
{ $sort: { popularityScore: -1 } },
|
|
273
|
+
{ $limit: 5 },
|
|
274
|
+
{
|
|
275
|
+
$project: {
|
|
276
|
+
_id: 0,
|
|
277
|
+
category: "$_id",
|
|
278
|
+
popularityScore: 1
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
])
|
|
282
|
+
|
|
283
|
+
console.log({ topCities, categorySummary, bigSpenders, monthlyRevenue, outliers, dailySummary, cityDistribution, categoryPopularity })
|
|
284
|
+
mongoose.disconnect()
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
runAnalytics()
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const express = require("express")
|
|
2
|
+
const mongoose = require("mongoose")
|
|
3
|
+
|
|
4
|
+
const app = express()
|
|
5
|
+
app.use(express.json())
|
|
6
|
+
|
|
7
|
+
mongoose.connect("mongodb://127.0.0.1:27017/payrollDB")
|
|
8
|
+
|
|
9
|
+
const employeeSchema = new mongoose.Schema(
|
|
10
|
+
{
|
|
11
|
+
name: {
|
|
12
|
+
type: String,
|
|
13
|
+
required: true,
|
|
14
|
+
minlength: 3,
|
|
15
|
+
maxlength: 50,
|
|
16
|
+
trim: true
|
|
17
|
+
},
|
|
18
|
+
employeeId: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: true,
|
|
21
|
+
unique: true
|
|
22
|
+
},
|
|
23
|
+
departments: {
|
|
24
|
+
type: [String],
|
|
25
|
+
required: true
|
|
26
|
+
},
|
|
27
|
+
salary: {
|
|
28
|
+
type: Number,
|
|
29
|
+
required: true,
|
|
30
|
+
min: 10000,
|
|
31
|
+
validate: v => v % 1000 === 0
|
|
32
|
+
},
|
|
33
|
+
joiningDate: {
|
|
34
|
+
type: Date,
|
|
35
|
+
default: Date.now
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{ timestamps: true }
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
employeeSchema.pre("save", function (next) {
|
|
42
|
+
this.name =
|
|
43
|
+
this.name.charAt(0).toUpperCase() + this.name.slice(1).toLowerCase()
|
|
44
|
+
next()
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const Employee = mongoose.model("Employee", employeeSchema)
|
|
48
|
+
|
|
49
|
+
app.post("/employees", async (req, res) => {
|
|
50
|
+
try {
|
|
51
|
+
const employee = new Employee(req.body)
|
|
52
|
+
await employee.save()
|
|
53
|
+
res.status(201).json(employee)
|
|
54
|
+
} catch (err) {
|
|
55
|
+
res.status(400).json({ error: err.message })
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
app.get("/employees", async (req, res) => {
|
|
60
|
+
const employees = await Employee.find()
|
|
61
|
+
res.json(employees)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
app.get("/employees/:id", async (req, res) => {
|
|
65
|
+
const employee = await Employee.findOne({ employeeId: req.params.id })
|
|
66
|
+
if (!employee) return res.status(404).json({ message: "Not found" })
|
|
67
|
+
res.json(employee)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
app.put("/employees/:id", async (req, res) => {
|
|
71
|
+
const employee = await Employee.findOneAndUpdate(
|
|
72
|
+
{ employeeId: req.params.id },
|
|
73
|
+
req.body,
|
|
74
|
+
{ new: true, runValidators: true }
|
|
75
|
+
)
|
|
76
|
+
if (!employee) return res.status(404).json({ message: "Not found" })
|
|
77
|
+
res.json(employee)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
app.delete("/employees/:id", async (req, res) => {
|
|
81
|
+
const employee = await Employee.findOneAndDelete({
|
|
82
|
+
employeeId: req.params.id
|
|
83
|
+
})
|
|
84
|
+
if (!employee) return res.status(404).json({ message: "Not found" })
|
|
85
|
+
res.json({ message: "Deleted" })
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
app.get("/employees/average/:department", async (req, res) => {
|
|
89
|
+
const result = await Employee.aggregate([
|
|
90
|
+
{ $unwind: "$departments" },
|
|
91
|
+
{ $match: { departments: req.params.department } },
|
|
92
|
+
{
|
|
93
|
+
$group: {
|
|
94
|
+
_id: "$departments",
|
|
95
|
+
avgSalary: { $avg: "$salary" }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
])
|
|
99
|
+
if (result.length === 0)
|
|
100
|
+
return res.json({ message: "No employees in this department" })
|
|
101
|
+
res.json(result[0])
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
app.listen(3000)
|