Add full project files
This commit is contained in:
50
controllers/panel/advertising/academyCategoryController.js
Normal file
50
controllers/panel/advertising/academyCategoryController.js
Normal file
@@ -0,0 +1,50 @@
|
||||
const AcademyCategoryModel = require('../../models/AcademyCategoryModel');
|
||||
|
||||
// دریافت همه دستهبندیهای اکادمی
|
||||
exports.getAll = async (req, res) => {
|
||||
try {
|
||||
const categories = await AcademyCategoryModel.find({}).sort({ createdAt: -1 });
|
||||
res.json({ success: true, data: categories });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// ایجاد دستهبندی جدید
|
||||
exports.create = async (req, res) => {
|
||||
try {
|
||||
const { title } = req.body;
|
||||
if (!title) return res.status(400).json({ success: false, message: "عنوان الزامی است" });
|
||||
|
||||
const category = await AcademyCategoryModel.create({ title });
|
||||
res.status(201).json({ success: true, message: "دستهبندی ایجاد شد", data: category });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// ویرایش دستهبندی
|
||||
exports.update = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { title, status } = req.body;
|
||||
|
||||
const category = await AcademyCategoryModel.findByIdAndUpdate(id, { title, status }, { new: true });
|
||||
if (!category) return res.status(404).json({ success: false, message: "دستهبندی یافت نشد" });
|
||||
|
||||
res.json({ success: true, message: "دستهبندی ویرایش شد", data: category });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// حذف دستهبندی
|
||||
exports.remove = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
await AcademyCategoryModel.findByIdAndDelete(id);
|
||||
res.json({ success: true, message: "دستهبندی حذف شد" });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
350
controllers/panel/advertising/advertisingController.js
Normal file
350
controllers/panel/advertising/advertisingController.js
Normal file
@@ -0,0 +1,350 @@
|
||||
/* eslint-disable eqeqeq */
|
||||
/* eslint-disable camelcase */
|
||||
const { ProvinceModel, CityModel } = require('../../../models/StateCity')
|
||||
const AdvertisingModel = require('../../../models/AdvertisingModel')
|
||||
// const AdvertisingLikeModel = require('../../../models/AdvertisingLikeModel')
|
||||
// const AdvertisingComment = require('../../../models/AdvertisingCommentModel')
|
||||
const AdvertisingProfileModel = require('../../../models/AdvertisingProfile')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const AdvertisingCategoryModel = require('../../../models/AdvertisingCategoryModel')
|
||||
|
||||
|
||||
const getAdvertisings = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const {
|
||||
page = 1, limit = 10, province, city, category, search,
|
||||
startDate,
|
||||
endDate,
|
||||
status
|
||||
} = req.query
|
||||
|
||||
const filter = {
|
||||
}
|
||||
if (province) {
|
||||
const provinceFind = await ProvinceModel.findOne({ id: province }, { _id: 0 })
|
||||
filter.province = provinceFind
|
||||
}
|
||||
if (city) {
|
||||
const cityFind = await CityModel.findOne({ id: city })
|
||||
filter.city = cityFind
|
||||
}
|
||||
if (category) {
|
||||
filter.category = category
|
||||
}
|
||||
if (search) {
|
||||
filter.$or = [
|
||||
{ title: { $regex: search, $options: 'i' } },
|
||||
{ category: { $regex: search, $options: 'i' } }
|
||||
]
|
||||
}
|
||||
|
||||
// Date
|
||||
if (startDate || endDate) {
|
||||
filter.createdAt = {}
|
||||
|
||||
if (startDate) {
|
||||
filter.createdAt.$gte = new Date(startDate) // تاریخ شروع
|
||||
}
|
||||
|
||||
if (endDate) {
|
||||
filter.createdAt.$lte = new Date(endDate) // تاریخ پایان
|
||||
}
|
||||
}
|
||||
|
||||
if (status) {
|
||||
filter.status = status
|
||||
}
|
||||
const options = {
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
sort: { createdAt: -1 },
|
||||
populate: [
|
||||
{ path: 'creator_id', select: 'user_name first_name last_name' }
|
||||
]
|
||||
}
|
||||
const advertisings = await AdvertisingModel.paginate(filter, options)
|
||||
|
||||
const newAds = advertisings.docs.map(ad => {
|
||||
return {
|
||||
// فیلدهای مشخصشده از ad._doc
|
||||
_id: ad._doc._id,
|
||||
creator_id: ad._doc.creator_id,
|
||||
category: ad._doc.category,
|
||||
title: ad._doc.title,
|
||||
province: ad._doc.province,
|
||||
city: ad._doc.city,
|
||||
status: ad._doc.status,
|
||||
neighbourhood: ad._doc.neighbourhood
|
||||
}
|
||||
})
|
||||
res.status(200).json({
|
||||
advertisings: newAds,
|
||||
totalPages: advertisings.totalPages,
|
||||
totalItems: advertisings.totalDocs
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getSingleAdvertising = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const advertisingId = req.query.advertisingId
|
||||
const advertising = await AdvertisingModel.findById(advertisingId)
|
||||
.populate('creator_id', '_id user_name first_name last_name')
|
||||
|
||||
if (!advertising) {
|
||||
return res.status(404).json({ message: 'ویترین مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
const creator = await AdvertisingProfileModel.findOne({ user: advertising.creator_id._id })
|
||||
|
||||
// اضافه کردن تعداد لایکها، تعداد کامنتها و وضعیت لایک به تبلیغ
|
||||
const advertisingData = {
|
||||
...advertising._doc
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
advertising: advertisingData,
|
||||
creator
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const acceptAdvertising = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { advertisingId } = req.body
|
||||
|
||||
// پیدا کردن تبلیغ
|
||||
const advertising = await AdvertisingModel.findById(advertisingId)
|
||||
if (!advertising) {
|
||||
return res.status(404).json({ message: 'تبلیغ مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
// تغییر وضعیت به accepted و ذخیره زمان قبول شدن
|
||||
advertising.status = 'accepted'
|
||||
advertising.acceptedAt = new Date()
|
||||
await advertising.save()
|
||||
const notification = new NotificationModel({
|
||||
user_id: advertising?.creator_id,
|
||||
project_post_id: advertising?._id,
|
||||
type: 'vitrine',
|
||||
title: 'تایید ویترین',
|
||||
description: `ویترین شما با عنوان: ${advertising?.title} تایید و منتشر شد `
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
res.status(200).json({ message: 'تبلیغ اکسپت شد و پس از 15 روز منقضی خواهد شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const rejectAdvertising = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { advertisingId, rejectReason } = req.body
|
||||
|
||||
// پیدا کردن تبلیغ
|
||||
const advertising = await AdvertisingModel.findById(advertisingId)
|
||||
if (!advertising) {
|
||||
return res.status(404).json({ message: 'تبلیغ مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
// تغییر وضعیت به rejected و ذخیره دلیل رد شدن
|
||||
advertising.status = 'rejected'
|
||||
advertising.reject_reason = rejectReason
|
||||
await advertising.save()
|
||||
const notification = new NotificationModel({
|
||||
user_id: advertising?.creator_id,
|
||||
project_post_id: advertising?._id,
|
||||
type: 'vitrine',
|
||||
title: 'رد ویترین',
|
||||
description: `ویترین شما با عنوان: ${advertising?.title} رد شد، برای دیدن علت رد، لمس کنید `
|
||||
})
|
||||
await notification.save()
|
||||
res.status(200).json({ message: 'تبلیغ رد شد', advertising })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const deleteAdvertisingCategory = async (req, res, next) => {
|
||||
try {
|
||||
const { id } = req.params
|
||||
|
||||
// چک کنه که ID معتبره
|
||||
if (!id.match(/^[0-9a-fA-F]{24}$/)) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'شناسه معتبر نمیباشد'
|
||||
})
|
||||
}
|
||||
|
||||
// پیدا کنه دستهبندی رو
|
||||
const category = await AdvertisingCategoryModel.findById(id)
|
||||
if (!category) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: 'دستهبندی مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// حذف کنه
|
||||
await category.deleteOne()
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
message: 'دستهبندی تبلیغات با موفقیت حذف شد',
|
||||
data: { id }
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const createAdvertisingCategory = async (req, res, next) => {
|
||||
try {
|
||||
const { title, status } = req.body
|
||||
|
||||
// اعتبارسنجی ورودیها
|
||||
if (!title || title.trim().length < 1) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'عنوان دستهبندی الزامی است'
|
||||
})
|
||||
}
|
||||
|
||||
if (title.length > 255) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: 'عنوان دستهبندی نباید بیشتر از ۲۵۵ کاراکتر باشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بررسی اینکه دستهبندی تکراری نباشد
|
||||
const exists = await AdvertisingCategoryModel.findOne({ title: title.trim() })
|
||||
if (exists) {
|
||||
return res.status(409).json({
|
||||
success: false,
|
||||
message: 'این دستهبندی از قبل وجود دارد'
|
||||
})
|
||||
}
|
||||
|
||||
// ایجاد دستهبندی جدید
|
||||
const newCategory = await AdvertisingCategoryModel.create({
|
||||
title: title.trim(),
|
||||
status: status ?? true
|
||||
})
|
||||
|
||||
return res.status(201).json({
|
||||
success: true,
|
||||
message: 'دستهبندی تبلیغات با موفقیت ایجاد شد',
|
||||
data: newCategory
|
||||
})
|
||||
} catch (error) {
|
||||
next(error) // میره به errorHandler مرکزی
|
||||
}
|
||||
}
|
||||
|
||||
const getAdvertisingCategories = async (req, res, next) => {
|
||||
try {
|
||||
const page = Math.max(parseInt(req.query.page || '1', 10), 1);
|
||||
const limit = Math.max(Math.min(parseInt(req.query.limit || '20', 10), 100), 1);
|
||||
const { status, q, sort } = req.query;
|
||||
|
||||
const query = {};
|
||||
if (typeof status !== 'undefined') {
|
||||
// accept 'true'/'false' or boolean
|
||||
if (status === 'true' || status === 'false') query.status = status === 'true';
|
||||
else if (status === '1' || status === '0') query.status = status === '1';
|
||||
}
|
||||
if (q) {
|
||||
query.title = { $regex: q.trim(), $options: 'i' };
|
||||
}
|
||||
|
||||
const options = {
|
||||
page,
|
||||
limit,
|
||||
sort: sort || '-createdAt',
|
||||
lean: true,
|
||||
};
|
||||
|
||||
// اگر mongoose-paginate-v2 نصب و فعال است:
|
||||
if (typeof AdvertisingCategoryModel.paginate === 'function') {
|
||||
const result = await AdvertisingCategoryModel.paginate(query, options);
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
totalDocs: result.totalDocs,
|
||||
totalPages: result.totalPages,
|
||||
page: result.page,
|
||||
limit: result.limit,
|
||||
docs: result.docs,
|
||||
});
|
||||
}
|
||||
|
||||
// fallback بدون paginate
|
||||
const docs = await AdvertisingCategoryModel.find(query)
|
||||
.sort(options.sort)
|
||||
.skip((page - 1) * limit)
|
||||
.limit(limit)
|
||||
.lean();
|
||||
|
||||
const totalDocs = await AdvertisingCategoryModel.countDocuments(query);
|
||||
const totalPages = Math.ceil(totalDocs / limit);
|
||||
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
totalDocs,
|
||||
totalPages,
|
||||
page,
|
||||
limit,
|
||||
docs,
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* GET /advertising/advertising-categories/:id
|
||||
*/
|
||||
const getAdvertisingCategoryById = async (req, res, next) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
if (!id || !id.match(/^[0-9a-fA-F]{24}$/)) {
|
||||
return res.status(400).json({ success: false, message: 'شناسه معتبر نیست' });
|
||||
}
|
||||
|
||||
const category = await AdvertisingCategoryModel.findById(id).lean();
|
||||
if (!category) {
|
||||
return res.status(404).json({ success: false, message: 'دستهبندی یافت نشد' });
|
||||
}
|
||||
|
||||
return res.status(200).json({ success: true, data: category });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
getSingleAdvertising,
|
||||
getAdvertisings,
|
||||
deleteAdvertisingCategory,
|
||||
createAdvertisingCategory,
|
||||
getAdvertisingCategories,
|
||||
getAdvertisingCategoryById,
|
||||
acceptAdvertising,
|
||||
rejectAdvertising
|
||||
}
|
||||
Reference in New Issue
Block a user