system now uses seperate pricing.
All checks were successful
Build Frontend / Build Frontend (push) Successful in 22s
All checks were successful
Build Frontend / Build Frontend (push) Successful in 22s
This commit is contained in:
241
routes/admin.js
241
routes/admin.js
@@ -1,6 +1,7 @@
|
||||
import { authenticate } from "../middleware/auth.js";
|
||||
import { authenticate, isAdmin } from "../middleware/auth.js";
|
||||
import pricingService from "../services/pricing.js";
|
||||
import Item from "../models/Item.js";
|
||||
import MarketPrice from "../models/MarketPrice.js";
|
||||
import Transaction from "../models/Transaction.js";
|
||||
import User from "../models/User.js";
|
||||
|
||||
@@ -1115,4 +1116,242 @@ export default async function adminRoutes(fastify, options) {
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// ============================================
|
||||
// MARKETPRICE MANAGEMENT
|
||||
// ============================================
|
||||
|
||||
// GET /admin/marketprices - Get paginated list of MarketPrice items
|
||||
fastify.get(
|
||||
"/marketprices",
|
||||
{
|
||||
preHandler: [authenticate, isAdmin],
|
||||
schema: {
|
||||
querystring: {
|
||||
type: "object",
|
||||
properties: {
|
||||
page: { type: "integer", minimum: 1, default: 1 },
|
||||
limit: { type: "integer", minimum: 1, maximum: 100, default: 50 },
|
||||
game: { type: "string", enum: ["cs2", "rust", ""] },
|
||||
search: { type: "string" },
|
||||
sort: { type: "string", default: "name-asc" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
async (request, reply) => {
|
||||
try {
|
||||
const {
|
||||
page = 1,
|
||||
limit = 50,
|
||||
game = "",
|
||||
search = "",
|
||||
sort = "name-asc",
|
||||
} = request.query;
|
||||
|
||||
// Build query
|
||||
const query = {};
|
||||
if (game) {
|
||||
query.game = game;
|
||||
}
|
||||
if (search) {
|
||||
query.$or = [
|
||||
{ name: { $regex: search, $options: "i" } },
|
||||
{ marketHashName: { $regex: search, $options: "i" } },
|
||||
];
|
||||
}
|
||||
|
||||
// Build sort
|
||||
let sortObj = {};
|
||||
switch (sort) {
|
||||
case "name-asc":
|
||||
sortObj = { name: 1 };
|
||||
break;
|
||||
case "name-desc":
|
||||
sortObj = { name: -1 };
|
||||
break;
|
||||
case "price-asc":
|
||||
sortObj = { price: 1 };
|
||||
break;
|
||||
case "price-desc":
|
||||
sortObj = { price: -1 };
|
||||
break;
|
||||
case "updated-desc":
|
||||
sortObj = { lastUpdated: -1 };
|
||||
break;
|
||||
default:
|
||||
sortObj = { name: 1 };
|
||||
}
|
||||
|
||||
// Get total count
|
||||
const total = await MarketPrice.countDocuments(query);
|
||||
|
||||
// Get items
|
||||
const items = await MarketPrice.find(query)
|
||||
.sort(sortObj)
|
||||
.limit(limit)
|
||||
.skip((page - 1) * limit)
|
||||
.lean();
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
items,
|
||||
page,
|
||||
limit,
|
||||
total,
|
||||
pages: Math.ceil(total / limit),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("❌ Failed to get market prices:", error);
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: "Failed to get market prices",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// GET /admin/marketprices/stats - Get MarketPrice statistics
|
||||
fastify.get(
|
||||
"/marketprices/stats",
|
||||
{
|
||||
preHandler: [authenticate, isAdmin],
|
||||
},
|
||||
async (request, reply) => {
|
||||
try {
|
||||
const total = await MarketPrice.countDocuments();
|
||||
const cs2 = await MarketPrice.countDocuments({ game: "cs2" });
|
||||
const rust = await MarketPrice.countDocuments({ game: "rust" });
|
||||
|
||||
// Get most recent update
|
||||
const lastItem = await MarketPrice.findOne()
|
||||
.sort({ lastUpdated: -1 })
|
||||
.select("lastUpdated")
|
||||
.lean();
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
stats: {
|
||||
total,
|
||||
cs2,
|
||||
rust,
|
||||
lastUpdated: lastItem?.lastUpdated || null,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("❌ Failed to get market price stats:", error);
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: "Failed to get stats",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// PATCH /admin/marketprices/:id - Update a MarketPrice item
|
||||
fastify.patch(
|
||||
"/marketprices/:id",
|
||||
{
|
||||
preHandler: [authenticate, isAdmin],
|
||||
schema: {
|
||||
params: {
|
||||
type: "object",
|
||||
required: ["id"],
|
||||
properties: {
|
||||
id: { type: "string" },
|
||||
},
|
||||
},
|
||||
body: {
|
||||
type: "object",
|
||||
properties: {
|
||||
price: { type: "number", minimum: 0 },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
async (request, reply) => {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
const { price } = request.body;
|
||||
|
||||
const item = await MarketPrice.findById(id);
|
||||
if (!item) {
|
||||
return reply.status(404).send({
|
||||
success: false,
|
||||
message: "Item not found",
|
||||
});
|
||||
}
|
||||
|
||||
item.price = price;
|
||||
item.priceType = "manual"; // Mark as manually updated
|
||||
item.lastUpdated = new Date();
|
||||
await item.save();
|
||||
|
||||
console.log(
|
||||
`⚙️ Admin ${request.user.username} updated price for ${item.name}: $${price}`
|
||||
);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
message: "Price updated successfully",
|
||||
item,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("❌ Failed to update market price:", error);
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: "Failed to update price",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// DELETE /admin/marketprices/:id - Delete a MarketPrice item
|
||||
fastify.delete(
|
||||
"/marketprices/:id",
|
||||
{
|
||||
preHandler: [authenticate, isAdmin],
|
||||
schema: {
|
||||
params: {
|
||||
type: "object",
|
||||
required: ["id"],
|
||||
properties: {
|
||||
id: { type: "string" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
async (request, reply) => {
|
||||
try {
|
||||
const { id } = request.params;
|
||||
|
||||
const item = await MarketPrice.findByIdAndDelete(id);
|
||||
if (!item) {
|
||||
return reply.status(404).send({
|
||||
success: false,
|
||||
message: "Item not found",
|
||||
});
|
||||
}
|
||||
|
||||
console.log(
|
||||
`⚙️ Admin ${request.user.username} deleted market price for ${item.name}`
|
||||
);
|
||||
|
||||
return reply.send({
|
||||
success: true,
|
||||
message: "Item deleted successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("❌ Failed to delete market price:", error);
|
||||
return reply.status(500).send({
|
||||
success: false,
|
||||
message: "Failed to delete item",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user