modified: controllers/application/academy/academyCategoryController.js
modified: controllers/application/academy/academyControllers.js modified: controllers/application/academy/helpers/chatHelpers.js modified: controllers/application/academy/middlewares/404.js modified: controllers/application/academy/middlewares/adminAuth.js modified: controllers/application/academy/middlewares/auth.js modified: controllers/application/academy/middlewares/blockCheck.js modified: controllers/application/academy/middlewares/exception.js modified: controllers/application/academy/middlewares/index.js modified: controllers/application/academy/middlewares/isHalfRegister.js modified: controllers/application/academy/middlewares/isRegister.js modified: controllers/application/academy/middlewares/lastOnline.js modified: controllers/application/academy/middlewares/upload.js modified: controllers/application/academy/models/AcademyCategoryModel.js modified: controllers/application/academy/models/AcademyContentModel.js modified: controllers/application/academy/models/AcademyLikeModel.js modified: controllers/application/academy/models/AcademyModel.js modified: controllers/application/academy/models/AcademyPaymentModel.js modified: controllers/application/academy/models/AdminModel.js modified: controllers/application/academy/models/AdvertisingCategoryModel.js modified: controllers/application/academy/models/AdvertisingCommentModel.js modified: controllers/application/academy/models/AdvertisingFeaturesModel.js modified: controllers/application/academy/models/AdvertisingLikeModel.js modified: controllers/application/academy/models/AdvertisingModel.js modified: controllers/application/academy/models/AdvertisingProfile.js modified: controllers/application/academy/models/AdvertisingRatingModel.js modified: controllers/application/academy/models/AdvertisingTypeModel.js modified: controllers/application/academy/models/CommentModel.js modified: controllers/application/academy/models/CourseComentModel.js modified: controllers/application/academy/models/CourseModel.js modified: controllers/application/academy/models/CoursePaymentModel.js modified: controllers/application/academy/models/ExpertiseModel.js modified: controllers/application/academy/models/IsPaymentCourseModel.js modified: controllers/application/academy/models/LikeModel.js modified: controllers/application/academy/models/MessageModel.js modified: controllers/application/academy/models/NotificationModel.js modified: controllers/application/academy/models/OfferModel.js modified: controllers/application/academy/models/OfferTypeModel.js modified: controllers/application/academy/models/PaymentModel.js modified: controllers/application/academy/models/PostModel.js modified: controllers/application/academy/models/ProjectModel.js modified: controllers/application/academy/models/RequestModel.js modified: controllers/application/academy/models/SettingsModel.js modified: controllers/application/academy/models/StateCity.js modified: controllers/application/academy/models/TaxModel.js modified: controllers/application/academy/models/TicketMessageModel.js modified: controllers/application/academy/models/TicketModel.js modified: controllers/application/academy/models/TypeAndPriceModel.js modified: controllers/application/academy/models/UserModel.js modified: controllers/application/academy/models/VersionModel.js modified: controllers/application/academy/models/license.js modified: controllers/application/advertising/advertisingController.js modified: controllers/application/citysController.js modified: controllers/application/expertise/expertiseController.js modified: controllers/application/financial/financialController.js modified: controllers/application/login/changePasswordController.js modified: controllers/application/login/loginController.js modified: controllers/application/login/loginWithUserName.js modified: controllers/application/login/verifyController.js modified: controllers/application/messages/messageController.js modified: controllers/application/notification/notificationController.js modified: controllers/application/offer/offerController.js modified: controllers/application/payment/paymentController.js modified: controllers/application/payment/paymentControllerWeb.js modified: controllers/application/posts/likeController.js modified: controllers/application/posts/postController.js modified: controllers/application/profile/profileController.js modified: controllers/application/projects/createProjectController.js modified: controllers/application/projects/getProjectController.js modified: controllers/application/projects/projectTypesController.js modified: controllers/application/projects/requestProjectController.js modified: controllers/application/projects/updateProjectController.js modified: controllers/application/provincesController.js modified: controllers/application/register/registerController.js modified: controllers/application/register/userFullNameController.js modified: controllers/application/register/userTypeController.js modified: controllers/application/register/usernameController.js modified: controllers/application/register/verifyController.js modified: controllers/application/search-web/searchController.js modified: controllers/application/search/searchController.js modified: controllers/application/settings/settingsController.js modified: controllers/application/tickets/ticketsController.js modified: controllers/application/users/getUserController.js modified: controllers/application/verify/addressController.js modified: controllers/application/verify/authController.js modified: controllers/application/verify/colorsController.js modified: controllers/application/verify/conversationController.js modified: controllers/application/verify/cooperationTypeController.js modified: controllers/application/verify/expertiseController.js modified: controllers/application/verify/genderController.js modified: controllers/application/verify/servicesController.js modified: controllers/application/verify/setNationalCardImageController.js modified: controllers/application/verify/setProfileImageController.js modified: controllers/application/verify/sizesController.js modified: controllers/application/version/versionController.js modified: controllers/application/workroom/workroomController.js modified: controllers/panel/advertising/academyCategoryController.js modified: controllers/panel/advertising/advertisingController.js modified: controllers/panel/comments/advertisingCommentController.js modified: controllers/panel/comments/commentController.js modified: controllers/panel/expertise/expertiseController.js modified: controllers/panel/financial/financialController.js modified: controllers/panel/login/loginController.js modified: controllers/panel/posts/postController.js modified: controllers/panel/projects/projectController.js modified: controllers/panel/projects/projectTypesController.js modified: controllers/panel/settings/settingsController.js modified: controllers/panel/shops/shopsController.js modified: controllers/panel/tickets/ticketsController.js modified: controllers/panel/users/usersController.js modified: controllers/panel/version/versionController.js modified: helpers/chatHelpers.js modified: index.js deleted: logs/sms-irs/13-03-2024.log modified: middlewares/404.js modified: middlewares/adminAuth.js modified: middlewares/auth.js modified: middlewares/blockCheck.js modified: middlewares/exception.js modified: middlewares/index.js modified: middlewares/isHalfRegister.js modified: middlewares/isRegister.js modified: middlewares/lastOnline.js modified: middlewares/upload.js modified: models/AcademyCategoryModel.js modified: models/AcademyContentModel.js modified: models/AcademyLikeModel.js modified: models/AcademyModel.js modified: models/AcademyPaymentModel.js modified: models/AdminModel.js modified: models/AdvertisingCategoryModel.js modified: models/AdvertisingCommentModel.js modified: models/AdvertisingFeaturesModel.js modified: models/AdvertisingLikeModel.js modified: models/AdvertisingModel.js modified: models/AdvertisingProfile.js modified: models/AdvertisingRatingModel.js modified: models/AdvertisingTypeModel.js modified: models/CommentModel.js modified: models/CourseComentModel.js modified: models/CourseModel.js modified: models/CoursePaymentModel.js modified: models/ExpertiseModel.js modified: models/IsPaymentCourseModel.js modified: models/LikeModel.js modified: models/MessageModel.js modified: models/NotificationModel.js modified: models/OfferModel.js modified: models/OfferTypeModel.js modified: models/PaymentModel.js modified: models/PostModel.js modified: models/ProjectModel.js modified: models/RequestModel.js modified: models/SettingsModel.js modified: models/StateCity.js modified: models/TaxModel.js modified: models/TicketMessageModel.js modified: models/TicketModel.js modified: models/TypeAndPriceModel.js modified: models/UserModel.js modified: models/VersionModel.js modified: models/license.js modified: routes/application/academy/index.js modified: routes/application/advertising/index.js modified: routes/application/city/index.js modified: routes/application/expertise/index.js modified: routes/application/financial/index.js modified: routes/application/login/index.js modified: routes/application/messages/index.js modified: routes/application/notification/index.js modified: routes/application/offers/index.js modified: routes/application/posts/index.js modified: routes/application/profile/index.js modified: routes/application/projects/index.js modified: routes/application/provinces/index.js modified: routes/application/register/index.js modified: routes/application/search-web/index.js modified: routes/application/search/index.js modified: routes/application/settings/index.js modified: routes/application/tickets/index.js modified: routes/application/users/index.js modified: routes/application/verify/index.js modified: routes/application/version/index.js modified: routes/application/workroom/index.js modified: routes/index.js modified: routes/panel/advertising/index.js modified: routes/panel/comments/index.js modified: routes/panel/expertise/index.js modified: routes/panel/financial/index.js modified: routes/panel/login/index.js modified: routes/panel/posts/index.js modified: routes/panel/projects/index.js modified: routes/panel/settings/index.js modified: routes/panel/shops/index.js modified: routes/panel/tickets/index.js modified: routes/panel/users/index.js modified: routes/panel/version/index.js modified: scripts/dns/db.modstagram.com modified: scripts/dns/db.modstagram.ir modified: scripts/dns/named.conf.local.snippet modified: scripts/nginx/api.modstagram.com.conf modified: scripts/nginx/app.modstagram.com.conf modified: scripts/nginx/blog.modstagram.com.conf modified: scripts/nginx/cdn.modstagram.com.conf modified: scripts/nginx/cdn.modstagram.com.http.conf modified: scripts/nginx/modstagram-redirects.conf modified: scripts/nginx/modstagram.com.conf modified: scripts/nginx/panel.modstagram.com.conf modified: scripts/nginx/pay.modstagram.com.conf modified: scripts/server-setup.sh modified: services/AdvertisingCron.js modified: services/ProjectCron.js modified: services/TokenService.js deleted: storage/courses/videos/course-69f8b2da55f31efffa601c57-1778257437373.mp4 deleted: storage/courses/videos/course-69f8b2da55f31efffa601c57-1778257586892.mp4 deleted: storage/courses/videos/course-69f8b2da55f31efffa601c57-1778257829783.mp4 deleted: storage/courses/videos/course-69f8b2da55f31efffa601c57-1778257903018.mp4 deleted: storage/posts/videos/1766758940571-0-video_2025-05-21_16-30-58.mp4 deleted: storage/posts/videos/1766781626514-0-video_2025-05-21_16-30-58.mp4 deleted: storage/posts/videos/1766824222908-0-Find 'modeling videos' on TikTok - TikTok Search_7.mp4 deleted: storage/posts/videos/1766824281937-0-Find 'modeling videos' on TikTok - TikTok Search_6.mp4 deleted: storage/posts/videos/1766824360366-0-Find 'bridal makeup' on TikTok - TikTok Search_4.mp4 deleted: storage/posts/videos/1766824425868-0-Find 'Makeup' on TikTok - TikTok Search_25.mp4 deleted: storage/posts/videos/1766824503238-0-Find 'Makeup' on TikTok - TikTok Search.mp4 deleted: storage/posts/videos/1766824554864-0-Jalal.hafed (@jalal.hafed) Official.mp4 deleted: storage/posts/videos/1766824618322-0-Find 'Hairdressing' on TikTok - TikTok Search_3.mp4 deleted: storage/posts/videos/1766824689078-0-Find 'Beauty clinic' on TikTok - TikTok Search_22.mp4 deleted: storage/posts/videos/1766824721659-0-Find 'Beauty clinic' on TikTok - TikTok Search_13.mp4 deleted: storage/posts/videos/1766824796958-0-Find 'photography' on TikTok - TikTok Search_6.mp4 deleted: storage/posts/videos/1766825351987-0-aaaa.mp4 deleted: storage/posts/videos/1766825448136-0-sasasa.mp4 deleted: storage/posts/videos/1766825535111-0-qqq.mp4 deleted: "storage/posts/videos/1766825855902-0-Nail desin by Labella beauty salon\360\237\214\270\360\237\222\205\360\237\217\273 #nail #nailart #manicure #manicure\360\237\222\205 #salon #pedicure #labella.mp4" deleted: storage/posts/videos/1766825905907-0-dsdsdsdsdsds.mp4 deleted: "storage/posts/videos/1766826114243-0-Every piece of jewelry tells a story\360\237\217\271 @mirjaliligold @mohseneh_b.mp4" deleted: "storage/posts/videos/1766826180365-0-Romeo, save me\360\237\246\242.mp4" deleted: storage/posts/videos/1766826458195-0-aaaaa.mp4 deleted: storage/posts/videos/1766826609640-0-asasa.mp4 deleted: storage/posts/videos/1766826685281-0-s.mp4 deleted: storage/posts/videos/1766826815345-0-asasa.mp4 deleted: storage/posts/videos/1766826842822-0-aaa.mp4 deleted: "storage/posts/videos/1766827337926-0-Snow, mountains, and me\342\200\246 a story that never gets old! #backstage #stylish #snow #style#streetstyle.mp4" deleted: "storage/posts/videos/1766828100639-0-\330\263\330\263\330\263\330\263.mp4" deleted: storage/posts/videos/1766828130001-0-aaa.mp4 deleted: storage/posts/videos/1766828157845-0-ssss.mp4 deleted: storage/posts/videos/1766828203643-0-aaaa.mp4 deleted: "storage/posts/videos/1766828345460-0-You deserve to be happy, and you can\342\200\231t stay where your heart doesn\342\200\231t belong #\330\252\331\210\331\204\330\257\331\205_\331\205\330\250\330\247\330\261\332\251 #\330\242\330\250\333\214 #\330\247\331\207\331\210\330\247\330\262 #\330\252\331\210\331\204\330\257 #\330\250\331\204\330\247\332\257\330\261 @gallery.nilai.mp4" deleted: storage/posts/videos/1766828424672-0-1111.mp4 deleted: storage/posts/videos/1766828464781-0-sss.mp4 deleted: storage/posts/videos/1766828486889-0-aaaa.mp4 deleted: storage/posts/videos/1766828514279-0-sss.mp4 deleted: storage/posts/videos/1766828727356-0-ddd.mp4 deleted: "storage/posts/videos/1766828816020-0-Jewlery project Brand- @houseofme_official Dop- @_alishariatt Videographer- @peyman_bozorgomid Assistant- @amir.kh.k Model- @ana.elitee #jewleryphotography #fashionreels #\330\261\333\214\331\204.mp4" deleted: "storage/posts/videos/1766828848513-0-Some of my favorite shots Models- @saharjalilii @setayesh.ghalenoeii @parmisaadat @paaarand @asalllbayat @bitakhaajoii #photographer #\330\271\332\251\330\247\330\263\333\214_\331\201\330\264\331\206 #photosoftheday.mp4" deleted: "storage/posts/videos/1766831745457-0-\330\263\330\263\330\263.mp4" deleted: "storage/posts/videos/1766831795030-0-\330\264\330\264\330\264\330\264.mp4" deleted: "storage/posts/videos/1766833279276-0-\330\247\330\262 \332\206\330\264\330\247\331\205 \331\207\331\204\330\252 \330\257\330\247\330\257\331\205\342\200\214 \331\210\331\204\333\214 .....mp4" deleted: "storage/posts/videos/1766835292259-0-\330\263\333\214\330\263.mp4" deleted: storage/posts/videos/1766835327424-0-a.mp4 deleted: storage/posts/videos/1766835787091-0-s.mp4 deleted: storage/posts/videos/1767012113143-0-aaa.mp4 deleted: "storage/posts/videos/1767012137018-0-Makeup by-\360\237\221\207\360\237\217\275\360\237\215\267 @pegah.mua @kiavash_royalvideo.mp4" deleted: storage/posts/videos/1767012672738-0-dddd.mp4 deleted: storage/posts/videos/1767012722043-0-Instagram.mp4 deleted: "storage/posts/videos/1768740975998-0-Faouzia\343\200\212Desert Rose\343\200\213.mp4" deleted: storage/posts/videos/1768741493380-0-a.mp4 deleted: "storage/posts/videos/1771318409261-0-\330\266\330\265\330\266\330\265\330\266\330\265\330\266.mp4" deleted: "storage/posts/videos/1771319189820-0-\330\263\330\263\330\263\330\263.mp4" deleted: storage/posts/videos/1771937200099-0-WhatsApp Video 2025-05-17 at 11.50.09.mp4 deleted: storage/posts/videos/1772005435124-0-qqqq.mp4 deleted: storage/posts/videos/1772005611958-0-aaaaa.mp4 deleted: storage/posts/videos/1772006456443-0-qqqqww.mp4 deleted: storage/posts/videos/1772006543741-0-1111.mp4 deleted: storage/posts/videos/1772006606627-0-wewewe.mp4 deleted: storage/posts/videos/1772006663579-0-wwww.mp4 deleted: storage/posts/videos/1772006685382-0-333.mp4 deleted: storage/posts/videos/1772006740696-0-www.mp4 deleted: storage/posts/videos/1772006786181-0-4444.mp4 deleted: storage/posts/videos/1772009213487-0-aaaa.mp4 deleted: storage/posts/videos/1772009260843-0-sss.mp4 deleted: "storage/posts/videos/1772013946491-0-\330\250\330\250\330\250\330\250\330\250.mp4" deleted: "storage/posts/videos/1772089789739-0-\330\266\330\266\330\266\330\266.mp4" deleted: storage/posts/videos/1772090631353-0-qqqq.mp4 deleted: "storage/posts/videos/1772092053138-0-\330\265\330\265\330\265.mp4" deleted: storage/posts/videos/1772101142214-0-2222.mp4 deleted: "storage/posts/videos/1772101261385-0-\330\266\330\266\330\266\330\266.mp4" deleted: storage/posts/videos/1772101312006-0-Instagram.mp4 deleted: "storage/posts/videos/1772101434744-0-\330\263\333\214\330\263\333\214\330\263\333\214.mp4" deleted: "storage/posts/videos/1772203614700-0-\330\263\330\247\331\205\330\250\330\261\331\207 \330\250\331\204\331\210\331\206\330\257 \330\250\330\261\330\247\333\214 \331\201\330\247\330\267\331\205\331\207 \330\271\330\262\333\214\330\262\331\205\360\237\222\225.mp4" deleted: "storage/posts/videos/1772203641829-0-\330\257\332\251\331\204\330\261\331\207 \331\210 \330\261\331\206\332\257 \331\210 \332\251\331\210\330\252\330\247\331\207\333\214 \330\250\330\261\330\247\333\214 \330\263\331\210\330\257\330\247 \331\202\330\264\331\206\332\257\331\205\360\237\222\225.mp4" deleted: "storage/posts/videos/1772203698315-0-\330\247\333\214\331\206 \332\251\330\247\330\261 \330\262\333\214\330\250\330\247\331\205\331\210\331\206 \330\250\330\261\330\247\333\214 \330\255\330\250\333\214\330\250\331\207 \330\256\330\247\331\206\331\205 \330\271\330\262\333\214\330\262\360\237\222\225.mp4" deleted: "storage/posts/videos/1772205300232-0-\330\264\330\264\330\264\330\264.mp4" deleted: "storage/posts/videos/1772205333900-0-\330\265\330\265\330\265\330\265\330\265.mp4" deleted: "storage/posts/videos/1772207461030-0-\330\265\330\265\330\265.mp4" deleted: "storage/posts/videos/1772207616124-0-\330\264\330\264\330\264.mp4" deleted: "storage/posts/videos/1772207684446-0-\330\253\330\253\330\253\330\253.mp4" deleted: "storage/posts/videos/1772208440984-0-\331\201\331\201\331\201.mp4" deleted: "storage/posts/videos/1772208506469-0-\330\253\330\253\330\253\330\253.mp4" deleted: "storage/posts/videos/1772208627195-0-\330\264\330\264\330\264\330\264.mp4" deleted: "storage/posts/videos/1772208646258-0-\330\250\330\263\333\214\330\263.mp4" deleted: storage/posts/videos/1772208704438-0-111.mp4 deleted: "storage/posts/videos/1772211057722-0-\330\266\330\266\330\266.mp4" deleted: "storage/posts/videos/1772211118907-0-\330\265\330\265\330\265\330\265.mp4" deleted: "storage/posts/videos/1772211184550-0-\330\253\330\253\330\253.mp4" deleted: "storage/posts/videos/1772211618341-0-\330\265\330\265\330\265\330\265.mp4" deleted: storage/posts/videos/1772211740270-0-4444.mp4
This commit is contained in:
@@ -1,74 +1,74 @@
|
||||
const AcademyCategoryModel = require('../../../models/AcademyCategoryModel');
|
||||
// GET all categories
|
||||
exports.getAll = async (req, res) => {
|
||||
try {
|
||||
const categories = await AcademyCategoryModel.find({}).sort({ createdAt: -1 });
|
||||
res.status(200).json({ success: true, categories });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// CREATE category
|
||||
exports.create = async (req, res) => {
|
||||
try {
|
||||
const { title, status } = req.body;
|
||||
|
||||
if (!title) {
|
||||
return res.status(400).json({ success: false, message: "title is required" });
|
||||
}
|
||||
|
||||
const newCategory = new AcademyCategoryModel({
|
||||
title,
|
||||
status: status ?? true,
|
||||
});
|
||||
|
||||
await newCategory.save();
|
||||
|
||||
res.status(201).json({ success: true, category: newCategory });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// UPDATE category
|
||||
exports.update = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { title, status } = req.body;
|
||||
|
||||
const updated = await AcademyCategoryModel.findByIdAndUpdate(
|
||||
id,
|
||||
{ title, status },
|
||||
{ new: true, runValidators: true }
|
||||
);
|
||||
|
||||
if (!updated) {
|
||||
return res.status(404).json({ success: false, message: "category not found" });
|
||||
}
|
||||
|
||||
res.status(200).json({ success: true, category: updated });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// DELETE
|
||||
exports.remove = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const deleted = await AcademyCategoryModel.findByIdAndDelete(id);
|
||||
|
||||
if (!deleted) {
|
||||
return res.status(404).json({ success: false, message: "category not found" });
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'category deleted successfully'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
const AcademyCategoryModel = require('../../../models/AcademyCategoryModel');
|
||||
// GET all categories
|
||||
exports.getAll = async (req, res) => {
|
||||
try {
|
||||
const categories = await AcademyCategoryModel.find({}).sort({ createdAt: -1 });
|
||||
res.status(200).json({ success: true, categories });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// CREATE category
|
||||
exports.create = async (req, res) => {
|
||||
try {
|
||||
const { title, status } = req.body;
|
||||
|
||||
if (!title) {
|
||||
return res.status(400).json({ success: false, message: "title is required" });
|
||||
}
|
||||
|
||||
const newCategory = new AcademyCategoryModel({
|
||||
title,
|
||||
status: status ?? true,
|
||||
});
|
||||
|
||||
await newCategory.save();
|
||||
|
||||
res.status(201).json({ success: true, category: newCategory });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// UPDATE category
|
||||
exports.update = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { title, status } = req.body;
|
||||
|
||||
const updated = await AcademyCategoryModel.findByIdAndUpdate(
|
||||
id,
|
||||
{ title, status },
|
||||
{ new: true, runValidators: true }
|
||||
);
|
||||
|
||||
if (!updated) {
|
||||
return res.status(404).json({ success: false, message: "category not found" });
|
||||
}
|
||||
|
||||
res.status(200).json({ success: true, category: updated });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// DELETE
|
||||
exports.remove = async (req, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
const deleted = await AcademyCategoryModel.findByIdAndDelete(id);
|
||||
|
||||
if (!deleted) {
|
||||
return res.status(404).json({ success: false, message: "category not found" });
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'category deleted successfully'
|
||||
});
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,72 +1,72 @@
|
||||
const moment = require('moment-jalaali')
|
||||
const MessageModel = require('../models/MessageModel')
|
||||
const UserModel = require('../models/UserModel')
|
||||
|
||||
function formatTimeOnly(date) {
|
||||
return moment(date).locale('fa').format('HH:mm:ss')
|
||||
}
|
||||
|
||||
async function enrichMessage(message) {
|
||||
const doc = message._doc ? { ...message._doc } : { ...message }
|
||||
let replyTo = null
|
||||
|
||||
if (doc.replyToId) {
|
||||
const parent = await MessageModel.findById(doc.replyToId).lean()
|
||||
if (parent) {
|
||||
const parentUser =
|
||||
String(parent.senderId) === String(doc.senderId)
|
||||
? await UserModel.findById(doc.senderId).select('first_name last_name user_name').lean()
|
||||
: await UserModel.findById(parent.senderId).select('first_name last_name user_name').lean()
|
||||
replyTo = {
|
||||
_id: parent._id,
|
||||
content: (parent.content || 'پیام').slice(0, 200),
|
||||
senderName: parentUser
|
||||
? `${parentUser.first_name || ''} ${parentUser.last_name || ''}`.trim() || parentUser.user_name
|
||||
: 'کاربر'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...doc,
|
||||
createdAt: formatTimeOnly(doc.createdAt),
|
||||
replyTo,
|
||||
forwardedFrom: doc.forwardedFrom || undefined
|
||||
}
|
||||
}
|
||||
|
||||
function emitChatEvents(io, message, senderId, receiverId) {
|
||||
const payload = message
|
||||
const roomA = `chat:${senderId}:${receiverId}`
|
||||
const roomB = `chat:${receiverId}:${senderId}`
|
||||
io.to(roomA).to(roomB).emit('newMessage', payload)
|
||||
io.to(`user:${senderId}`).to(`user:${receiverId}`).emit('chatListUpdate', {
|
||||
senderId,
|
||||
receiverId,
|
||||
message: payload
|
||||
})
|
||||
}
|
||||
|
||||
function parseForwardedContent(content) {
|
||||
if (!content) return { body: '', forwardedFrom: null }
|
||||
try {
|
||||
const line = content.split('\n')[0]
|
||||
const j = JSON.parse(line)
|
||||
if (j.forwardedFrom) {
|
||||
return {
|
||||
forwardedFrom: j.forwardedFrom,
|
||||
body: content.replace(/^\{.*\}\n?/, '').trim()
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
/* not json */
|
||||
}
|
||||
return { body: content, forwardedFrom: null }
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
formatTimeOnly,
|
||||
enrichMessage,
|
||||
emitChatEvents,
|
||||
parseForwardedContent
|
||||
}
|
||||
const moment = require('moment-jalaali')
|
||||
const MessageModel = require('../models/MessageModel')
|
||||
const UserModel = require('../models/UserModel')
|
||||
|
||||
function formatTimeOnly(date) {
|
||||
return moment(date).locale('fa').format('HH:mm:ss')
|
||||
}
|
||||
|
||||
async function enrichMessage(message) {
|
||||
const doc = message._doc ? { ...message._doc } : { ...message }
|
||||
let replyTo = null
|
||||
|
||||
if (doc.replyToId) {
|
||||
const parent = await MessageModel.findById(doc.replyToId).lean()
|
||||
if (parent) {
|
||||
const parentUser =
|
||||
String(parent.senderId) === String(doc.senderId)
|
||||
? await UserModel.findById(doc.senderId).select('first_name last_name user_name').lean()
|
||||
: await UserModel.findById(parent.senderId).select('first_name last_name user_name').lean()
|
||||
replyTo = {
|
||||
_id: parent._id,
|
||||
content: (parent.content || 'پیام').slice(0, 200),
|
||||
senderName: parentUser
|
||||
? `${parentUser.first_name || ''} ${parentUser.last_name || ''}`.trim() || parentUser.user_name
|
||||
: 'کاربر'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...doc,
|
||||
createdAt: formatTimeOnly(doc.createdAt),
|
||||
replyTo,
|
||||
forwardedFrom: doc.forwardedFrom || undefined
|
||||
}
|
||||
}
|
||||
|
||||
function emitChatEvents(io, message, senderId, receiverId) {
|
||||
const payload = message
|
||||
const roomA = `chat:${senderId}:${receiverId}`
|
||||
const roomB = `chat:${receiverId}:${senderId}`
|
||||
io.to(roomA).to(roomB).emit('newMessage', payload)
|
||||
io.to(`user:${senderId}`).to(`user:${receiverId}`).emit('chatListUpdate', {
|
||||
senderId,
|
||||
receiverId,
|
||||
message: payload
|
||||
})
|
||||
}
|
||||
|
||||
function parseForwardedContent(content) {
|
||||
if (!content) return { body: '', forwardedFrom: null }
|
||||
try {
|
||||
const line = content.split('\n')[0]
|
||||
const j = JSON.parse(line)
|
||||
if (j.forwardedFrom) {
|
||||
return {
|
||||
forwardedFrom: j.forwardedFrom,
|
||||
body: content.replace(/^\{.*\}\n?/, '').trim()
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
/* not json */
|
||||
}
|
||||
return { body: content, forwardedFrom: null }
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
formatTimeOnly,
|
||||
enrichMessage,
|
||||
emitChatEvents,
|
||||
parseForwardedContent
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
module.exports = (app) => {
|
||||
app.use((req, res, next) => {
|
||||
res.status(404).send({
|
||||
code: 'Not Found',
|
||||
status: 404,
|
||||
message: 'requested resource could not be found!'
|
||||
})
|
||||
})
|
||||
}
|
||||
module.exports = (app) => {
|
||||
app.use((req, res, next) => {
|
||||
res.status(404).send({
|
||||
code: 'Not Found',
|
||||
status: 404,
|
||||
message: 'requested resource could not be found!'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
const AdminModel = require('../models/AdminModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'you are not authorized!'
|
||||
})
|
||||
}
|
||||
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
let decodedToken
|
||||
try {
|
||||
decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
} catch (err) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!',
|
||||
error: err.message
|
||||
})
|
||||
}
|
||||
if (!decodedToken) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!'
|
||||
})
|
||||
}
|
||||
try {
|
||||
// پیدا کردن کاربر با استفاده از اطلاعات موجود در توکن
|
||||
const admin = await AdminModel.findOne({ _id: decodedToken.id })
|
||||
if (!admin) {
|
||||
return res.status(403).send({
|
||||
status: 'error',
|
||||
code: 403,
|
||||
message: 'Access denied!'
|
||||
})
|
||||
}
|
||||
|
||||
// ادامه مسیر در صورتی که کاربر ادمین باشد
|
||||
req.admin = admin
|
||||
next()
|
||||
} catch (error) {
|
||||
return res.status(500).send({
|
||||
status: 'error',
|
||||
code: 500,
|
||||
message: 'Internal Server Error',
|
||||
error: error.message
|
||||
})
|
||||
}
|
||||
}
|
||||
const AdminModel = require('../models/AdminModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'you are not authorized!'
|
||||
})
|
||||
}
|
||||
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
let decodedToken
|
||||
try {
|
||||
decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
} catch (err) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!',
|
||||
error: err.message
|
||||
})
|
||||
}
|
||||
if (!decodedToken) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!'
|
||||
})
|
||||
}
|
||||
try {
|
||||
// پیدا کردن کاربر با استفاده از اطلاعات موجود در توکن
|
||||
const admin = await AdminModel.findOne({ _id: decodedToken.id })
|
||||
if (!admin) {
|
||||
return res.status(403).send({
|
||||
status: 'error',
|
||||
code: 403,
|
||||
message: 'Access denied!'
|
||||
})
|
||||
}
|
||||
|
||||
// ادامه مسیر در صورتی که کاربر ادمین باشد
|
||||
req.admin = admin
|
||||
next()
|
||||
} catch (error) {
|
||||
return res.status(500).send({
|
||||
status: 'error',
|
||||
code: 500,
|
||||
message: 'Internal Server Error',
|
||||
error: error.message
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
const TokenService = require('../services/TokenService')
|
||||
module.exports = (req, res, next) => {
|
||||
console.log(1);
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'you are not authorized!'
|
||||
})
|
||||
}
|
||||
const [, tokenValue] = req.headers.authorization.split(' ')
|
||||
const token = TokenService.verify(tokenValue)
|
||||
if (!token) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'your token is not valid!'
|
||||
})
|
||||
}
|
||||
next()
|
||||
}
|
||||
const TokenService = require('../services/TokenService')
|
||||
module.exports = (req, res, next) => {
|
||||
console.log(1);
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'you are not authorized!'
|
||||
})
|
||||
}
|
||||
const [, tokenValue] = req.headers.authorization.split(' ')
|
||||
const token = TokenService.verify(tokenValue)
|
||||
if (!token) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'your token is not valid!'
|
||||
})
|
||||
}
|
||||
next()
|
||||
}
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
console.log(2);
|
||||
try {
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'You are not authorized!'
|
||||
})
|
||||
}
|
||||
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
|
||||
if (!decodedToken) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (user.block_status === true) {
|
||||
return res.status(403).send({
|
||||
status: 'error',
|
||||
code: 403,
|
||||
message: 'حساب کاربری شما مسدود شده است، برای اطلاعات بیشتر با پشتیبانی تماس بگیرید!',
|
||||
type: 'block'
|
||||
})
|
||||
}
|
||||
|
||||
req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود.
|
||||
next()
|
||||
} catch (error) {
|
||||
console.error('Error in blockCheck middleware:', error)
|
||||
res.status(500).send({
|
||||
status: 'error',
|
||||
code: 500,
|
||||
message: 'Server error'
|
||||
})
|
||||
}
|
||||
}
|
||||
const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
console.log(2);
|
||||
try {
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'You are not authorized!'
|
||||
})
|
||||
}
|
||||
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
|
||||
if (!decodedToken) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (user.block_status === true) {
|
||||
return res.status(403).send({
|
||||
status: 'error',
|
||||
code: 403,
|
||||
message: 'حساب کاربری شما مسدود شده است، برای اطلاعات بیشتر با پشتیبانی تماس بگیرید!',
|
||||
type: 'block'
|
||||
})
|
||||
}
|
||||
|
||||
req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود.
|
||||
next()
|
||||
} catch (error) {
|
||||
console.error('Error in blockCheck middleware:', error)
|
||||
res.status(500).send({
|
||||
status: 'error',
|
||||
code: 500,
|
||||
message: 'Server error'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
module.exports = (app) => {
|
||||
app.use((error, req, res, next) => {
|
||||
const status = error.status || 500
|
||||
res.status(500).send({
|
||||
code: 'Eception',
|
||||
status,
|
||||
en_message: error.message,
|
||||
message: 'خطایی در عملیات مورد نظر رخ داده است.'
|
||||
})
|
||||
})
|
||||
}
|
||||
module.exports = (app) => {
|
||||
app.use((error, req, res, next) => {
|
||||
const status = error.status || 500
|
||||
res.status(500).send({
|
||||
code: 'Eception',
|
||||
status,
|
||||
en_message: error.message,
|
||||
message: 'خطایی در عملیات مورد نظر رخ داده است.'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
const bodyParser = require('body-parser')
|
||||
const cors = require('cors')
|
||||
const formData = require('express-form-data')
|
||||
const session = require('express-session')
|
||||
const lastOnline = require('./lastOnline')
|
||||
module.exports = (app) => {
|
||||
app.use(cors()) // develop
|
||||
app.use(formData.parse())
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({ extended: true }))
|
||||
app.use(session({
|
||||
secret: 'your_secret_key', // کلید مخفی برای امنیت جلسات
|
||||
resave: false,
|
||||
saveUninitialized: false
|
||||
}))
|
||||
app.use(lastOnline)
|
||||
}
|
||||
const bodyParser = require('body-parser')
|
||||
const cors = require('cors')
|
||||
const formData = require('express-form-data')
|
||||
const session = require('express-session')
|
||||
const lastOnline = require('./lastOnline')
|
||||
module.exports = (app) => {
|
||||
app.use(cors()) // develop
|
||||
app.use(formData.parse())
|
||||
app.use(bodyParser.json())
|
||||
app.use(bodyParser.urlencoded({ extended: true }))
|
||||
app.use(session({
|
||||
secret: 'your_secret_key', // کلید مخفی برای امنیت جلسات
|
||||
resave: false,
|
||||
saveUninitialized: false
|
||||
}))
|
||||
app.use(lastOnline)
|
||||
}
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
console.log(3);
|
||||
try {
|
||||
console.log(31);
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'You are not authorized!'
|
||||
})
|
||||
}
|
||||
console.log(32);
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
|
||||
if (!decodedToken) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!'
|
||||
})
|
||||
}
|
||||
console.log(33);
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user.user_name ||
|
||||
!user.first_name ||
|
||||
!user.last_name ||
|
||||
!user.user_type ||
|
||||
!user.password) {
|
||||
return res.status(403).send({
|
||||
status: 'error',
|
||||
code: 403,
|
||||
message: 'لطفا از بخش تنظیمات، ثبت نام خود را کامل کنید',
|
||||
type: 'not_register'
|
||||
})
|
||||
}
|
||||
console.log(34);
|
||||
req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود.
|
||||
next()
|
||||
} catch (error) {
|
||||
console.log(35);
|
||||
console.error('not_register middleware:', error)
|
||||
res.status(500).send({
|
||||
status: 'error',
|
||||
code: 500,
|
||||
message: 'Server error'
|
||||
})
|
||||
}
|
||||
}
|
||||
const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
console.log(3);
|
||||
try {
|
||||
console.log(31);
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'You are not authorized!'
|
||||
})
|
||||
}
|
||||
console.log(32);
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
|
||||
if (!decodedToken) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!'
|
||||
})
|
||||
}
|
||||
console.log(33);
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user.user_name ||
|
||||
!user.first_name ||
|
||||
!user.last_name ||
|
||||
!user.user_type ||
|
||||
!user.password) {
|
||||
return res.status(403).send({
|
||||
status: 'error',
|
||||
code: 403,
|
||||
message: 'لطفا از بخش تنظیمات، ثبت نام خود را کامل کنید',
|
||||
type: 'not_register'
|
||||
})
|
||||
}
|
||||
console.log(34);
|
||||
req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود.
|
||||
next()
|
||||
} catch (error) {
|
||||
console.log(35);
|
||||
console.error('not_register middleware:', error)
|
||||
res.status(500).send({
|
||||
status: 'error',
|
||||
code: 500,
|
||||
message: 'Server error'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
try {
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'You are not authorized!'
|
||||
})
|
||||
}
|
||||
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
|
||||
if (!decodedToken) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user.user_name ||
|
||||
!user.first_name ||
|
||||
!user.last_name ||
|
||||
!user.password) {
|
||||
return res.status(403).send({
|
||||
status: 'error',
|
||||
code: 403,
|
||||
message: 'لطفا از بخش تنظیمات، ثبت نام خود را کامل کنید',
|
||||
type: 'not_register'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود.
|
||||
next()
|
||||
} catch (error) {
|
||||
console.error('not_register middleware:', error)
|
||||
res.status(500).send({
|
||||
status: 'error',
|
||||
code: 500,
|
||||
message: 'Server error'
|
||||
})
|
||||
}
|
||||
}
|
||||
const UserModel = require('../models/UserModel') // مسیر درست به مدل کاربر
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
try {
|
||||
if (!('authorization' in req.headers)) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'You are not authorized!'
|
||||
})
|
||||
}
|
||||
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
|
||||
if (!decodedToken) {
|
||||
return res.status(401).send({
|
||||
status: 'error',
|
||||
code: 401,
|
||||
message: 'Your token is not valid!'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user.user_name ||
|
||||
!user.first_name ||
|
||||
!user.last_name ||
|
||||
!user.password) {
|
||||
return res.status(403).send({
|
||||
status: 'error',
|
||||
code: 403,
|
||||
message: 'لطفا از بخش تنظیمات، ثبت نام خود را کامل کنید',
|
||||
type: 'not_register'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
req.user = user // کاربر را به درخواست اضافه کنید تا در سایر middleware ها و کنترلرها استفاده شود.
|
||||
next()
|
||||
} catch (error) {
|
||||
console.error('not_register middleware:', error)
|
||||
res.status(500).send({
|
||||
status: 'error',
|
||||
code: 500,
|
||||
message: 'Server error'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const UserModel = require('../models/UserModel')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
if (req.header && req.header('Authorization')) {
|
||||
const token = await req.header('Authorization').split(' ')[1]
|
||||
const decodedToken = await jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (user) {
|
||||
try {
|
||||
user.last_online = new Date()
|
||||
await user.save() // ذخیره تغییرات در دیتابیس
|
||||
} catch (error) {
|
||||
// بررسی و پردازش خطاها
|
||||
console.error('Error updating last online time:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
const jwt = require('jsonwebtoken')
|
||||
const UserModel = require('../models/UserModel')
|
||||
|
||||
module.exports = async (req, res, next) => {
|
||||
if (req.header && req.header('Authorization')) {
|
||||
const token = await req.header('Authorization').split(' ')[1]
|
||||
const decodedToken = await jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (user) {
|
||||
try {
|
||||
user.last_online = new Date()
|
||||
await user.save() // ذخیره تغییرات در دیتابیس
|
||||
} catch (error) {
|
||||
// بررسی و پردازش خطاها
|
||||
console.error('Error updating last online time:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
next()
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
const multer = require('multer');
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
const uploadDir = path.join(__dirname, '../storage/posts');
|
||||
fs.ensureDirSync(uploadDir); // مطمئن میشه مسیر وجود داره
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => cb(null, uploadDir),
|
||||
filename: (req, file, cb) => {
|
||||
const ext = path.extname(file.originalname);
|
||||
const name = file.originalname.replace(ext, '').replace(/\s/g, '_');
|
||||
cb(null, `${Date.now()}-${name}${ext}`);
|
||||
}
|
||||
});
|
||||
|
||||
const fileFilter = (req, file, cb) => {
|
||||
if (!file.mimetype.startsWith('image/')) return cb(new Error('فقط تصاویر مجاز است'));
|
||||
cb(null, true);
|
||||
};
|
||||
|
||||
const upload = multer({ storage, fileFilter, limits: { files: 10 } }); // حداکثر ۱۰ فایل
|
||||
|
||||
module.exports = upload;
|
||||
const multer = require('multer');
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
const uploadDir = path.join(__dirname, '../storage/posts');
|
||||
fs.ensureDirSync(uploadDir); // مطمئن میشه مسیر وجود داره
|
||||
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => cb(null, uploadDir),
|
||||
filename: (req, file, cb) => {
|
||||
const ext = path.extname(file.originalname);
|
||||
const name = file.originalname.replace(ext, '').replace(/\s/g, '_');
|
||||
cb(null, `${Date.now()}-${name}${ext}`);
|
||||
}
|
||||
});
|
||||
|
||||
const fileFilter = (req, file, cb) => {
|
||||
if (!file.mimetype.startsWith('image/')) return cb(new Error('فقط تصاویر مجاز است'));
|
||||
cb(null, true);
|
||||
};
|
||||
|
||||
const upload = multer({ storage, fileFilter, limits: { files: 10 } }); // حداکثر ۱۰ فایل
|
||||
|
||||
module.exports = upload;
|
||||
|
||||
@@ -1,190 +1,190 @@
|
||||
const mongoose = require('mongoose');
|
||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||
const timestamp = require('mongoose-timestamp');
|
||||
|
||||
const AcademyCategorySchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: [true, 'عنوان دستهبندی الزامی است'],
|
||||
trim: true,
|
||||
minLength: [2, 'عنوان باید حداقل ۲ کاراکتر باشد'],
|
||||
maxLength: [100, 'عنوان باید حداکثر ۱۰۰ کاراکتر باشد'],
|
||||
unique: true,
|
||||
index: true,
|
||||
},
|
||||
slug: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
lowercase: true,
|
||||
trim: true,
|
||||
index: true,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
maxLength: 500,
|
||||
default: null,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '#3B82F6',
|
||||
match: /^#[0-9A-F]{6}$/i,
|
||||
},
|
||||
parent: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'AcademyCategory',
|
||||
required: false,
|
||||
default: null,
|
||||
index: true,
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
min: 0,
|
||||
max: 3,
|
||||
},
|
||||
order: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
index: true,
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
course_count: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
min: 0,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['active', 'inactive', 'deleted'],
|
||||
required: true,
|
||||
default: 'active',
|
||||
index: true,
|
||||
},
|
||||
is_featured: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
index: true,
|
||||
},
|
||||
seo_title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
maxLength: 70,
|
||||
},
|
||||
seo_description: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
maxLength: 160,
|
||||
},
|
||||
created_by: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true,
|
||||
},
|
||||
updated_by: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: false,
|
||||
},
|
||||
}, {
|
||||
toJSON: { virtuals: true },
|
||||
toObject: { virtuals: true }
|
||||
});
|
||||
|
||||
// Virtual برای زیردستهها
|
||||
AcademyCategorySchema.virtual('children', {
|
||||
ref: 'AcademyCategory',
|
||||
localField: '_id',
|
||||
foreignField: 'parent',
|
||||
justOne: false,
|
||||
options: { sort: { order: 1, title: 1 } }
|
||||
});
|
||||
|
||||
// Virtual برای دورههای این دسته
|
||||
AcademyCategorySchema.virtual('courses', {
|
||||
ref: 'Course',
|
||||
localField: '_id',
|
||||
foreignField: 'category_id',
|
||||
justOne: false,
|
||||
match: { status: 'accept' }
|
||||
});
|
||||
|
||||
// Middleware: قبل از save
|
||||
AcademyCategorySchema.pre('save', async function(next) {
|
||||
if (this.isModified('title') || this.isNew) {
|
||||
// تولید slug
|
||||
this.slug = this.title
|
||||
.replace(/[^\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C\uFB8E\u0698a-zA-Z0-9\s]/g, '')
|
||||
.trim()
|
||||
.replace(/\s+/g, '-')
|
||||
.toLowerCase();
|
||||
|
||||
// اگه parent داره، سطح رو محاسبه کن
|
||||
if (this.parent) {
|
||||
const parent = await this.constructor.findById(this.parent);
|
||||
if (parent) {
|
||||
this.level = parent.level + 1;
|
||||
}
|
||||
} else {
|
||||
this.level = 0;
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
// استاتیک متدها
|
||||
AcademyCategorySchema.statics = {
|
||||
// دریافت درخت دستهبندیها
|
||||
async getTree() {
|
||||
const categories = await this.find({ status: 'active', parent: null })
|
||||
.sort({ order: 1, title: 1 })
|
||||
.populate({
|
||||
path: 'children',
|
||||
match: { status: 'active' },
|
||||
options: { sort: { order: 1, title: 1 } },
|
||||
populate: {
|
||||
path: 'children',
|
||||
match: { status: 'active' },
|
||||
options: { sort: { order: 1, title: 1 } }
|
||||
}
|
||||
});
|
||||
return categories;
|
||||
},
|
||||
|
||||
// افزایش تعداد دورهها
|
||||
async incrementCourseCount(categoryId, increment = 1) {
|
||||
return this.findByIdAndUpdate(categoryId, {
|
||||
$inc: { course_count: increment }
|
||||
});
|
||||
},
|
||||
|
||||
// دریافت دستهبندی با اسلاگ
|
||||
async getBySlug(slug) {
|
||||
return this.findOne({ slug, status: 'active' })
|
||||
.populate('children')
|
||||
.populate('parent');
|
||||
}
|
||||
};
|
||||
|
||||
AcademyCategorySchema.plugin(timestamp);
|
||||
AcademyCategorySchema.plugin(mongoosePaginate);
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||
const timestamp = require('mongoose-timestamp');
|
||||
|
||||
const AcademyCategorySchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: [true, 'عنوان دستهبندی الزامی است'],
|
||||
trim: true,
|
||||
minLength: [2, 'عنوان باید حداقل ۲ کاراکتر باشد'],
|
||||
maxLength: [100, 'عنوان باید حداکثر ۱۰۰ کاراکتر باشد'],
|
||||
unique: true,
|
||||
index: true,
|
||||
},
|
||||
slug: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true,
|
||||
lowercase: true,
|
||||
trim: true,
|
||||
index: true,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
maxLength: 500,
|
||||
default: null,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '#3B82F6',
|
||||
match: /^#[0-9A-F]{6}$/i,
|
||||
},
|
||||
parent: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'AcademyCategory',
|
||||
required: false,
|
||||
default: null,
|
||||
index: true,
|
||||
},
|
||||
level: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
min: 0,
|
||||
max: 3,
|
||||
},
|
||||
order: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
index: true,
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
course_count: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
min: 0,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['active', 'inactive', 'deleted'],
|
||||
required: true,
|
||||
default: 'active',
|
||||
index: true,
|
||||
},
|
||||
is_featured: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
index: true,
|
||||
},
|
||||
seo_title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
maxLength: 70,
|
||||
},
|
||||
seo_description: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
maxLength: 160,
|
||||
},
|
||||
created_by: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true,
|
||||
},
|
||||
updated_by: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: false,
|
||||
},
|
||||
}, {
|
||||
toJSON: { virtuals: true },
|
||||
toObject: { virtuals: true }
|
||||
});
|
||||
|
||||
// Virtual برای زیردستهها
|
||||
AcademyCategorySchema.virtual('children', {
|
||||
ref: 'AcademyCategory',
|
||||
localField: '_id',
|
||||
foreignField: 'parent',
|
||||
justOne: false,
|
||||
options: { sort: { order: 1, title: 1 } }
|
||||
});
|
||||
|
||||
// Virtual برای دورههای این دسته
|
||||
AcademyCategorySchema.virtual('courses', {
|
||||
ref: 'Course',
|
||||
localField: '_id',
|
||||
foreignField: 'category_id',
|
||||
justOne: false,
|
||||
match: { status: 'accept' }
|
||||
});
|
||||
|
||||
// Middleware: قبل از save
|
||||
AcademyCategorySchema.pre('save', async function(next) {
|
||||
if (this.isModified('title') || this.isNew) {
|
||||
// تولید slug
|
||||
this.slug = this.title
|
||||
.replace(/[^\u0600-\u06FF\uFB8A\u067E\u0686\u06AF\u200C\uFB8E\u0698a-zA-Z0-9\s]/g, '')
|
||||
.trim()
|
||||
.replace(/\s+/g, '-')
|
||||
.toLowerCase();
|
||||
|
||||
// اگه parent داره، سطح رو محاسبه کن
|
||||
if (this.parent) {
|
||||
const parent = await this.constructor.findById(this.parent);
|
||||
if (parent) {
|
||||
this.level = parent.level + 1;
|
||||
}
|
||||
} else {
|
||||
this.level = 0;
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
// استاتیک متدها
|
||||
AcademyCategorySchema.statics = {
|
||||
// دریافت درخت دستهبندیها
|
||||
async getTree() {
|
||||
const categories = await this.find({ status: 'active', parent: null })
|
||||
.sort({ order: 1, title: 1 })
|
||||
.populate({
|
||||
path: 'children',
|
||||
match: { status: 'active' },
|
||||
options: { sort: { order: 1, title: 1 } },
|
||||
populate: {
|
||||
path: 'children',
|
||||
match: { status: 'active' },
|
||||
options: { sort: { order: 1, title: 1 } }
|
||||
}
|
||||
});
|
||||
return categories;
|
||||
},
|
||||
|
||||
// افزایش تعداد دورهها
|
||||
async incrementCourseCount(categoryId, increment = 1) {
|
||||
return this.findByIdAndUpdate(categoryId, {
|
||||
$inc: { course_count: increment }
|
||||
});
|
||||
},
|
||||
|
||||
// دریافت دستهبندی با اسلاگ
|
||||
async getBySlug(slug) {
|
||||
return this.findOne({ slug, status: 'active' })
|
||||
.populate('children')
|
||||
.populate('parent');
|
||||
}
|
||||
};
|
||||
|
||||
AcademyCategorySchema.plugin(timestamp);
|
||||
AcademyCategorySchema.plugin(mongoosePaginate);
|
||||
|
||||
module.exports = mongoose.model('AcademyCategory', AcademyCategorySchema);
|
||||
@@ -1,71 +1,71 @@
|
||||
const mongoose = require('mongoose');
|
||||
const timestamp = require('mongoose-timestamp');
|
||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
course_images: {
|
||||
type: [String], // آرایهای از مسیرهای تصاویر
|
||||
required: false,
|
||||
default: [],
|
||||
},
|
||||
course_video: {
|
||||
type: String, // مسیر ویدئو
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null,
|
||||
},
|
||||
type: {
|
||||
type: String, // نوع پست: 'image' یا 'video'
|
||||
required: true,
|
||||
enum: ['image', 'video'],
|
||||
},
|
||||
files: [
|
||||
{
|
||||
path: { type: String, required: false },
|
||||
type: { type: String, enum: ['image', 'video'], required: false },
|
||||
}
|
||||
],
|
||||
caption: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
default: null,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['pending', 'accept', 'reject'],
|
||||
default: 'accept',
|
||||
},
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
},
|
||||
likes: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
}],
|
||||
comments: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
courseId: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
is_free: {
|
||||
type: Boolean,
|
||||
},
|
||||
file_name: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model('AcademyContent', modelSchema);
|
||||
const mongoose = require('mongoose');
|
||||
const timestamp = require('mongoose-timestamp');
|
||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
course_images: {
|
||||
type: [String], // آرایهای از مسیرهای تصاویر
|
||||
required: false,
|
||||
default: [],
|
||||
},
|
||||
course_video: {
|
||||
type: String, // مسیر ویدئو
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null,
|
||||
},
|
||||
type: {
|
||||
type: String, // نوع پست: 'image' یا 'video'
|
||||
required: true,
|
||||
enum: ['image', 'video'],
|
||||
},
|
||||
files: [
|
||||
{
|
||||
path: { type: String, required: false },
|
||||
type: { type: String, enum: ['image', 'video'], required: false },
|
||||
}
|
||||
],
|
||||
caption: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
default: null,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['pending', 'accept', 'reject'],
|
||||
default: 'accept',
|
||||
},
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
},
|
||||
likes: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
}],
|
||||
comments: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
courseId: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
is_free: {
|
||||
type: Boolean,
|
||||
},
|
||||
file_name: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model('AcademyContent', modelSchema);
|
||||
module.exports = PostModel;
|
||||
@@ -1,25 +1,25 @@
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
|
||||
user_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
course_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("Likes", modelSchema);
|
||||
module.exports = PostModel;
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
|
||||
user_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
course_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("Likes", modelSchema);
|
||||
module.exports = PostModel;
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
academy_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null,
|
||||
},
|
||||
academy_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null,
|
||||
},
|
||||
userId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
rate: {
|
||||
type: Number,
|
||||
trim: true,
|
||||
default: 0
|
||||
},
|
||||
number_of_rate: {
|
||||
type: Number,
|
||||
trim: true,
|
||||
default: 0
|
||||
},
|
||||
sheba: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
bio: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
tag: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("Academy", modelSchema);
|
||||
module.exports = PostModel;
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
academy_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null,
|
||||
},
|
||||
academy_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null,
|
||||
},
|
||||
userId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
rate: {
|
||||
type: Number,
|
||||
trim: true,
|
||||
default: 0
|
||||
},
|
||||
number_of_rate: {
|
||||
type: Number,
|
||||
trim: true,
|
||||
default: 0
|
||||
},
|
||||
sheba: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
bio: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
tag: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("Academy", modelSchema);
|
||||
module.exports = PostModel;
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
price: { type: Number, required: true }, // قیمت نهایی شامل مالیات
|
||||
discountAmount: { type: Number, default: 0 }, // مبلغ تخفیف
|
||||
taxAmount: { type: Number, default: 0 }, // مبلغ مالیات
|
||||
taxRate: { type: Number, default: 9 }, // درصد مالیات
|
||||
course_name: { type: String, required: true },
|
||||
course_id: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true },
|
||||
academy_id: { type: mongoose.Schema.Types.ObjectId, ref: "Academy", required: true },
|
||||
user_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
|
||||
payment_authority: { type: String },
|
||||
payment_ref_id: { type: String },
|
||||
status: { type: String, enum: ["pending", "success", "failed", "settled"], default: "success" },
|
||||
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("AcademyPayment", modelSchema);
|
||||
module.exports = PostModel;
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
price: { type: Number, required: true }, // قیمت نهایی شامل مالیات
|
||||
discountAmount: { type: Number, default: 0 }, // مبلغ تخفیف
|
||||
taxAmount: { type: Number, default: 0 }, // مبلغ مالیات
|
||||
taxRate: { type: Number, default: 9 }, // درصد مالیات
|
||||
course_name: { type: String, required: true },
|
||||
course_id: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true },
|
||||
academy_id: { type: mongoose.Schema.Types.ObjectId, ref: "Academy", required: true },
|
||||
user_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
|
||||
payment_authority: { type: String },
|
||||
payment_ref_id: { type: String },
|
||||
status: { type: String, enum: ["pending", "success", "failed", "settled"], default: "success" },
|
||||
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("AcademyPayment", modelSchema);
|
||||
module.exports = PostModel;
|
||||
|
||||
@@ -1,80 +1,80 @@
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const adminSchema = new mongoose.Schema({
|
||||
mobile: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
unique: true
|
||||
},
|
||||
otp: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 6,
|
||||
maxLength: 6
|
||||
},
|
||||
user_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
first_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
last_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
user_type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
profile_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
},
|
||||
gender: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
last_online: {
|
||||
type: Date, // ذخیره تاریخ و زمان آخرین بازدید
|
||||
default: Date.now // تنظیم تاریخ به تاریخ فعلی
|
||||
}
|
||||
})
|
||||
|
||||
adminSchema.plugin(timestamp)
|
||||
adminSchema.plugin(mongoosePaginate)
|
||||
const AdminModel = mongoose.model('Admin', adminSchema)
|
||||
module.exports = AdminModel
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const adminSchema = new mongoose.Schema({
|
||||
mobile: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
unique: true
|
||||
},
|
||||
otp: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 6,
|
||||
maxLength: 6
|
||||
},
|
||||
user_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
first_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
last_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
user_type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
profile_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
},
|
||||
gender: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
last_online: {
|
||||
type: Date, // ذخیره تاریخ و زمان آخرین بازدید
|
||||
default: Date.now // تنظیم تاریخ به تاریخ فعلی
|
||||
}
|
||||
})
|
||||
|
||||
adminSchema.plugin(timestamp)
|
||||
adminSchema.plugin(mongoosePaginate)
|
||||
const AdminModel = mongoose.model('Admin', adminSchema)
|
||||
module.exports = AdminModel
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const advertisingCategorySchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
status: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
advertisingCategorySchema.plugin(timestamp)
|
||||
advertisingCategorySchema.plugin(mongoosePaginate)
|
||||
const AdvertisingCategoryModel = mongoose.model('AdvertisingCategory', advertisingCategorySchema)
|
||||
module.exports = AdvertisingCategoryModel
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const advertisingCategorySchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
status: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
}
|
||||
})
|
||||
|
||||
advertisingCategorySchema.plugin(timestamp)
|
||||
advertisingCategorySchema.plugin(mongoosePaginate)
|
||||
const AdvertisingCategoryModel = mongoose.model('AdvertisingCategory', advertisingCategorySchema)
|
||||
module.exports = AdvertisingCategoryModel
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const advertisingCommentSchema = new mongoose.Schema({
|
||||
advertisingId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Advertising',
|
||||
required: true
|
||||
},
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'],
|
||||
default: 'pending'
|
||||
}
|
||||
})
|
||||
|
||||
advertisingCommentSchema.plugin(timestamp)
|
||||
advertisingCommentSchema.plugin(mongoosePaginate)
|
||||
const AdvertisingComment = mongoose.model('AdvertisingComment', advertisingCommentSchema)
|
||||
|
||||
module.exports = AdvertisingComment
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const advertisingCommentSchema = new mongoose.Schema({
|
||||
advertisingId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Advertising',
|
||||
required: true
|
||||
},
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'],
|
||||
default: 'pending'
|
||||
}
|
||||
})
|
||||
|
||||
advertisingCommentSchema.plugin(timestamp)
|
||||
advertisingCommentSchema.plugin(mongoosePaginate)
|
||||
const AdvertisingComment = mongoose.model('AdvertisingComment', advertisingCommentSchema)
|
||||
|
||||
module.exports = AdvertisingComment
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const advertisingFeaturesSchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
status: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'boolean'
|
||||
}
|
||||
})
|
||||
|
||||
advertisingFeaturesSchema.plugin(timestamp)
|
||||
advertisingFeaturesSchema.plugin(mongoosePaginate)
|
||||
const AdvertisingFeaturesModel = mongoose.model('AdvertisingFeatures', advertisingFeaturesSchema)
|
||||
module.exports = AdvertisingFeaturesModel
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const advertisingFeaturesSchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
status: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'boolean'
|
||||
}
|
||||
})
|
||||
|
||||
advertisingFeaturesSchema.plugin(timestamp)
|
||||
advertisingFeaturesSchema.plugin(mongoosePaginate)
|
||||
const AdvertisingFeaturesModel = mongoose.model('AdvertisingFeatures', advertisingFeaturesSchema)
|
||||
module.exports = AdvertisingFeaturesModel
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const advertisingLikeSchema = new mongoose.Schema({
|
||||
advertisingId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Advertising',
|
||||
required: true
|
||||
},
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// تعریف مدل AdvertisingLikeModel
|
||||
const AdvertisingLikeModel = mongoose.model('AdvertisingLike', advertisingLikeSchema)
|
||||
|
||||
module.exports = AdvertisingLikeModel
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const advertisingLikeSchema = new mongoose.Schema({
|
||||
advertisingId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Advertising',
|
||||
required: true
|
||||
},
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
// تعریف مدل AdvertisingLikeModel
|
||||
const AdvertisingLikeModel = mongoose.model('AdvertisingLike', advertisingLikeSchema)
|
||||
|
||||
module.exports = AdvertisingLikeModel
|
||||
|
||||
@@ -1,230 +1,230 @@
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const advertisingSchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
province: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
city: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
neighbourhood: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
lat: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 256,
|
||||
default: null
|
||||
},
|
||||
lng: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 256,
|
||||
default: null
|
||||
},
|
||||
images: [{
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
}],
|
||||
services: [{
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
originalPrice: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
discountPrice: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
discountPercentage: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: "UnderReview",
|
||||
required: false
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
}
|
||||
}],
|
||||
features: [{
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
},
|
||||
value: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
}],
|
||||
contactInfo: {
|
||||
phone: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
mobile: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
telegramLink: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
whatsappNumber: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
instagramLink: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
saveInfoForNextAds: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: ['free', 'normal', 'special', 'highlight'],
|
||||
default: 'normal'
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pre_payment', 'paid', 'accepted', 'rejected', 'expired'],
|
||||
default: 'pre_payment'
|
||||
},
|
||||
payment_status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
creator_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
},
|
||||
reject_reason: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
mostDiscountPercentage: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
showDiscount: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
likesCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
commentsCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
ratings: [{
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 5
|
||||
}
|
||||
}],
|
||||
averageRating: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
ratingsCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
viewCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
acceptedAt: {
|
||||
type: Date,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
advertisingSchema.plugin(timestamp)
|
||||
advertisingSchema.plugin(mongoosePaginate)
|
||||
const AdvertisingModel = mongoose.model('Advertising', advertisingSchema)
|
||||
module.exports = AdvertisingModel
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const advertisingSchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
province: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
city: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
neighbourhood: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
lat: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 256,
|
||||
default: null
|
||||
},
|
||||
lng: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 256,
|
||||
default: null
|
||||
},
|
||||
images: [{
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
}],
|
||||
services: [{
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
originalPrice: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
discountPrice: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
discountPercentage: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: "UnderReview",
|
||||
required: false
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
}
|
||||
}],
|
||||
features: [{
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
},
|
||||
value: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
}],
|
||||
contactInfo: {
|
||||
phone: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
mobile: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
telegramLink: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
whatsappNumber: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
instagramLink: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
saveInfoForNextAds: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: ['free', 'normal', 'special', 'highlight'],
|
||||
default: 'normal'
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pre_payment', 'paid', 'accepted', 'rejected', 'expired'],
|
||||
default: 'pre_payment'
|
||||
},
|
||||
payment_status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
creator_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
},
|
||||
reject_reason: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
mostDiscountPercentage: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
showDiscount: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
likesCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
commentsCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
ratings: [{
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 5
|
||||
}
|
||||
}],
|
||||
averageRating: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
ratingsCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
viewCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
acceptedAt: {
|
||||
type: Date,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
advertisingSchema.plugin(timestamp)
|
||||
advertisingSchema.plugin(mongoosePaginate)
|
||||
const AdvertisingModel = mongoose.model('Advertising', advertisingSchema)
|
||||
module.exports = AdvertisingModel
|
||||
|
||||
@@ -1,113 +1,113 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const advertisingProfileSchema = new mongoose.Schema({
|
||||
user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
profile_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
image_count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
like_count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
comment_count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
vitrine_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
about_us: {
|
||||
type: String,
|
||||
required: false,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
province: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
city: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
lat: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
lng: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
neighbourhood: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
adTotalRatings: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
adRatingsCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
adAverageRating: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
contactInfo: {
|
||||
phone: String,
|
||||
mobile: String,
|
||||
telegramLink: String,
|
||||
whatsappNumber: String,
|
||||
instagramLink: String,
|
||||
saveInfoForNextAds: { type: Boolean, default: false }
|
||||
}
|
||||
})
|
||||
|
||||
advertisingProfileSchema.plugin(timestamp)
|
||||
advertisingProfileSchema.plugin(mongoosePaginate)
|
||||
|
||||
const AdvertisingProfileModel = mongoose.model('AdvertisingProfile', advertisingProfileSchema)
|
||||
|
||||
module.exports = AdvertisingProfileModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const advertisingProfileSchema = new mongoose.Schema({
|
||||
user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
profile_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
image_count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
like_count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
comment_count: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
vitrine_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
category: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
about_us: {
|
||||
type: String,
|
||||
required: false,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
province: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
city: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
lat: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
lng: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
neighbourhood: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
adTotalRatings: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
adRatingsCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
adAverageRating: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
contactInfo: {
|
||||
phone: String,
|
||||
mobile: String,
|
||||
telegramLink: String,
|
||||
whatsappNumber: String,
|
||||
instagramLink: String,
|
||||
saveInfoForNextAds: { type: Boolean, default: false }
|
||||
}
|
||||
})
|
||||
|
||||
advertisingProfileSchema.plugin(timestamp)
|
||||
advertisingProfileSchema.plugin(mongoosePaginate)
|
||||
|
||||
const AdvertisingProfileModel = mongoose.model('AdvertisingProfile', advertisingProfileSchema)
|
||||
|
||||
module.exports = AdvertisingProfileModel
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const advertisingRatingSchema = new mongoose.Schema({
|
||||
advertisingId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Advertising',
|
||||
required: true
|
||||
},
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 5
|
||||
}
|
||||
})
|
||||
|
||||
advertisingRatingSchema.plugin(timestamp)
|
||||
|
||||
const AdvertisingRatingModel = mongoose.model('AdvertisingRating', advertisingRatingSchema)
|
||||
module.exports = AdvertisingRatingModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const advertisingRatingSchema = new mongoose.Schema({
|
||||
advertisingId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Advertising',
|
||||
required: true
|
||||
},
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 5
|
||||
}
|
||||
})
|
||||
|
||||
advertisingRatingSchema.plugin(timestamp)
|
||||
|
||||
const AdvertisingRatingModel = mongoose.model('AdvertisingRating', advertisingRatingSchema)
|
||||
module.exports = AdvertisingRatingModel
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const advertisingTypeSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: 'active'
|
||||
}
|
||||
})
|
||||
|
||||
const AdvertisingTypeModel = mongoose.model('AdvertisingType', advertisingTypeSchema)
|
||||
module.exports = AdvertisingTypeModel
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const advertisingTypeSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: 'active'
|
||||
}
|
||||
})
|
||||
|
||||
const AdvertisingTypeModel = mongoose.model('AdvertisingType', advertisingTypeSchema)
|
||||
module.exports = AdvertisingTypeModel
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const commentSchema = new mongoose.Schema({
|
||||
user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
project: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Project',
|
||||
required: false
|
||||
},
|
||||
offer: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Offer',
|
||||
required: false
|
||||
},
|
||||
creator: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
comment: {
|
||||
type: String,
|
||||
trim: true
|
||||
},
|
||||
post: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Post',
|
||||
required: false
|
||||
},
|
||||
comment_for: {
|
||||
type: String,
|
||||
enum: ['user', 'project', 'post'],
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'],
|
||||
default: 'pending'
|
||||
}
|
||||
})
|
||||
|
||||
commentSchema.plugin(timestamp)
|
||||
commentSchema.plugin(mongoosePaginate)
|
||||
const CommentModel = mongoose.model('Comment', commentSchema)
|
||||
module.exports = CommentModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const commentSchema = new mongoose.Schema({
|
||||
user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
project: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Project',
|
||||
required: false
|
||||
},
|
||||
offer: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Offer',
|
||||
required: false
|
||||
},
|
||||
creator: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
comment: {
|
||||
type: String,
|
||||
trim: true
|
||||
},
|
||||
post: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Post',
|
||||
required: false
|
||||
},
|
||||
comment_for: {
|
||||
type: String,
|
||||
enum: ['user', 'project', 'post'],
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'],
|
||||
default: 'pending'
|
||||
}
|
||||
})
|
||||
|
||||
commentSchema.plugin(timestamp)
|
||||
commentSchema.plugin(mongoosePaginate)
|
||||
const CommentModel = mongoose.model('Comment', commentSchema)
|
||||
module.exports = CommentModel
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
|
||||
user_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
course_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
comment: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
rate: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'],
|
||||
default: 'accepted'
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("CourseComment", modelSchema);
|
||||
module.exports = PostModel;
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
|
||||
user_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
course_id: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
comment: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
rate: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'],
|
||||
default: 'accepted'
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("CourseComment", modelSchema);
|
||||
module.exports = PostModel;
|
||||
|
||||
@@ -1,79 +1,79 @@
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
price: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
cuorse_name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
category:{
|
||||
type: String
|
||||
},
|
||||
offer: {
|
||||
type: String
|
||||
},
|
||||
academyId:{
|
||||
type: String
|
||||
},
|
||||
caption: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
default: null,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['pending', 'accept', 'reject'],
|
||||
default: 'accept',
|
||||
},
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
},
|
||||
likes: {
|
||||
type: Number,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
comments: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['normal', 'pro', 'legend'],
|
||||
default: "normal",
|
||||
},
|
||||
course_time: {
|
||||
type: String
|
||||
},
|
||||
number_of_course_content: {
|
||||
type: String
|
||||
},
|
||||
teacher_number: {
|
||||
type: String
|
||||
},
|
||||
course_image: {
|
||||
type: String
|
||||
},
|
||||
teacher_name: {
|
||||
type: String
|
||||
},
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("Course", modelSchema);
|
||||
module.exports = PostModel;
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
price: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
cuorse_name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
category:{
|
||||
type: String
|
||||
},
|
||||
offer: {
|
||||
type: String
|
||||
},
|
||||
academyId:{
|
||||
type: String
|
||||
},
|
||||
caption: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
default: null,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['pending', 'accept', 'reject'],
|
||||
default: 'accept',
|
||||
},
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
},
|
||||
likes: {
|
||||
type: Number,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: 0,
|
||||
},
|
||||
comments: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['normal', 'pro', 'legend'],
|
||||
default: "normal",
|
||||
},
|
||||
course_time: {
|
||||
type: String
|
||||
},
|
||||
number_of_course_content: {
|
||||
type: String
|
||||
},
|
||||
teacher_number: {
|
||||
type: String
|
||||
},
|
||||
course_image: {
|
||||
type: String
|
||||
},
|
||||
teacher_name: {
|
||||
type: String
|
||||
},
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("Course", modelSchema);
|
||||
module.exports = PostModel;
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
price: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
cuorse_type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['normal', 'pro', 'legend'],
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("CoursePayment", modelSchema);
|
||||
module.exports = PostModel;
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
price: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
cuorse_type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['normal', 'pro', 'legend'],
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("CoursePayment", modelSchema);
|
||||
module.exports = PostModel;
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
// const mongoose = require('mongoose')
|
||||
// const timestamp = require('mongoose-timestamp')
|
||||
|
||||
// const subExpertiseSchema = new mongoose.Schema({
|
||||
// id: {
|
||||
// type: mongoose.Schema.Types.ObjectId,
|
||||
// ref: 'ExpertiseModel'
|
||||
// },
|
||||
// name: {
|
||||
// type: String
|
||||
// }
|
||||
// })
|
||||
|
||||
// const expertiseSchema = new mongoose.Schema({
|
||||
// expertise: {
|
||||
// type: String,
|
||||
// unique: true
|
||||
// },
|
||||
// sub_expertise: [subExpertiseSchema]
|
||||
// })
|
||||
|
||||
// expertiseSchema.plugin(timestamp)
|
||||
|
||||
// const ExpertiseModel = mongoose.model('Expertise', expertiseSchema)
|
||||
// module.exports = ExpertiseModel
|
||||
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const subExpertiseSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String
|
||||
}
|
||||
})
|
||||
|
||||
const expertiseSchema = new mongoose.Schema({
|
||||
expertise: {
|
||||
type: String,
|
||||
unique: true
|
||||
},
|
||||
sub_expertise: [subExpertiseSchema]
|
||||
})
|
||||
|
||||
expertiseSchema.plugin(timestamp)
|
||||
|
||||
const ExpertiseModel = mongoose.model('Expertise', expertiseSchema)
|
||||
module.exports = ExpertiseModel
|
||||
// const mongoose = require('mongoose')
|
||||
// const timestamp = require('mongoose-timestamp')
|
||||
|
||||
// const subExpertiseSchema = new mongoose.Schema({
|
||||
// id: {
|
||||
// type: mongoose.Schema.Types.ObjectId,
|
||||
// ref: 'ExpertiseModel'
|
||||
// },
|
||||
// name: {
|
||||
// type: String
|
||||
// }
|
||||
// })
|
||||
|
||||
// const expertiseSchema = new mongoose.Schema({
|
||||
// expertise: {
|
||||
// type: String,
|
||||
// unique: true
|
||||
// },
|
||||
// sub_expertise: [subExpertiseSchema]
|
||||
// })
|
||||
|
||||
// expertiseSchema.plugin(timestamp)
|
||||
|
||||
// const ExpertiseModel = mongoose.model('Expertise', expertiseSchema)
|
||||
// module.exports = ExpertiseModel
|
||||
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const subExpertiseSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String
|
||||
}
|
||||
})
|
||||
|
||||
const expertiseSchema = new mongoose.Schema({
|
||||
expertise: {
|
||||
type: String,
|
||||
unique: true
|
||||
},
|
||||
sub_expertise: [subExpertiseSchema]
|
||||
})
|
||||
|
||||
expertiseSchema.plugin(timestamp)
|
||||
|
||||
const ExpertiseModel = mongoose.model('Expertise', expertiseSchema)
|
||||
module.exports = ExpertiseModel
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
user_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
|
||||
course_id: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true },
|
||||
price_paid: { type: Number, required: true }, // قیمت پرداخت شده
|
||||
purchased_at: { type: Date, default: Date.now },
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("IsPaymentCourse", modelSchema);
|
||||
module.exports = PostModel;
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
user_id: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
|
||||
course_id: { type: mongoose.Schema.Types.ObjectId, ref: "Course", required: true },
|
||||
price_paid: { type: Number, required: true }, // قیمت پرداخت شده
|
||||
purchased_at: { type: Date, default: Date.now },
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("IsPaymentCourse", modelSchema);
|
||||
module.exports = PostModel;
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const likeSchema = new mongoose.Schema({
|
||||
postId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Post',
|
||||
required: true
|
||||
},
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
likes: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}]
|
||||
})
|
||||
|
||||
// تعریف مدل LikeModel
|
||||
likeSchema.plugin(timestamp)
|
||||
const LikeModel = mongoose.model('Like', likeSchema)
|
||||
|
||||
module.exports = LikeModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const likeSchema = new mongoose.Schema({
|
||||
postId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Post',
|
||||
required: true
|
||||
},
|
||||
userId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
likes: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}]
|
||||
})
|
||||
|
||||
// تعریف مدل LikeModel
|
||||
likeSchema.plugin(timestamp)
|
||||
const LikeModel = mongoose.model('Like', likeSchema)
|
||||
|
||||
module.exports = LikeModel
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
const mongoose = require('mongoose')
|
||||
const { Schema } = mongoose
|
||||
|
||||
const messageSchema = new Schema({
|
||||
senderId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
receiverId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
},
|
||||
file: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
fileType: {
|
||||
type: String,
|
||||
enum: ['image', 'video', 'file', 'voice', 'location'],
|
||||
required: false
|
||||
},
|
||||
replyToId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Message',
|
||||
required: false
|
||||
},
|
||||
forwardedFrom: {
|
||||
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
|
||||
userName: String,
|
||||
displayName: String
|
||||
},
|
||||
createdAt: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
readStatus: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
})
|
||||
|
||||
const MessageModel = mongoose.model('Message', messageSchema)
|
||||
|
||||
module.exports = MessageModel
|
||||
const mongoose = require('mongoose')
|
||||
const { Schema } = mongoose
|
||||
|
||||
const messageSchema = new Schema({
|
||||
senderId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
receiverId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
},
|
||||
file: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
fileType: {
|
||||
type: String,
|
||||
enum: ['image', 'video', 'file', 'voice', 'location'],
|
||||
required: false
|
||||
},
|
||||
replyToId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Message',
|
||||
required: false
|
||||
},
|
||||
forwardedFrom: {
|
||||
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
|
||||
userName: String,
|
||||
displayName: String
|
||||
},
|
||||
createdAt: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
readStatus: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
})
|
||||
|
||||
const MessageModel = mongoose.model('Message', messageSchema)
|
||||
|
||||
module.exports = MessageModel
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const notificationSchema = new mongoose.Schema({
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User', // مرجع به مدل کاربر
|
||||
required: true
|
||||
},
|
||||
project_post_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
required: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
read: {
|
||||
type: Boolean,
|
||||
default: false // وضعیت خوانده شده یا نشده
|
||||
}
|
||||
})
|
||||
|
||||
notificationSchema.plugin(timestamp)
|
||||
notificationSchema.plugin(mongoosePaginate)
|
||||
|
||||
const NotificationModel = mongoose.model('Notification', notificationSchema)
|
||||
module.exports = NotificationModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const notificationSchema = new mongoose.Schema({
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User', // مرجع به مدل کاربر
|
||||
required: true
|
||||
},
|
||||
project_post_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
required: false
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
read: {
|
||||
type: Boolean,
|
||||
default: false // وضعیت خوانده شده یا نشده
|
||||
}
|
||||
})
|
||||
|
||||
notificationSchema.plugin(timestamp)
|
||||
notificationSchema.plugin(mongoosePaginate)
|
||||
|
||||
const NotificationModel = mongoose.model('Notification', notificationSchema)
|
||||
module.exports = NotificationModel
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const offerSchema = new mongoose.Schema({
|
||||
sender: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
receiver: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'], // وضعیت درخواست
|
||||
default: 'pending'
|
||||
},
|
||||
transaction_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Payment',
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
offerSchema.plugin(timestamp)
|
||||
offerSchema.plugin(mongoosePaginate)
|
||||
|
||||
const OfferModel = mongoose.model('Offer', offerSchema)
|
||||
module.exports = OfferModel
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const offerSchema = new mongoose.Schema({
|
||||
sender: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
receiver: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'], // وضعیت درخواست
|
||||
default: 'pending'
|
||||
},
|
||||
transaction_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Payment',
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
offerSchema.plugin(timestamp)
|
||||
offerSchema.plugin(mongoosePaginate)
|
||||
|
||||
const OfferModel = mongoose.model('Offer', offerSchema)
|
||||
module.exports = OfferModel
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const offerTypeModelSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
}
|
||||
})
|
||||
|
||||
const OfferTypeModel = mongoose.model('OfferTypeModel', offerTypeModelSchema)
|
||||
module.exports = OfferTypeModel
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const offerTypeModelSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
}
|
||||
})
|
||||
|
||||
const OfferTypeModel = mongoose.model('OfferTypeModel', offerTypeModelSchema)
|
||||
module.exports = OfferTypeModel
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const paymentSchema = new mongoose.Schema({
|
||||
amount: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'successful', 'failed'],
|
||||
default: 'pending'
|
||||
},
|
||||
authority: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
},
|
||||
project_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Project'
|
||||
},
|
||||
advertising_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Advertising'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
installment_step: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
paymentSchema.plugin(timestamp)
|
||||
paymentSchema.plugin(mongoosePaginate)
|
||||
|
||||
const PaymentModel = mongoose.model('Payment', paymentSchema)
|
||||
module.exports = PaymentModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const paymentSchema = new mongoose.Schema({
|
||||
amount: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'successful', 'failed'],
|
||||
default: 'pending'
|
||||
},
|
||||
authority: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
},
|
||||
project_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Project'
|
||||
},
|
||||
advertising_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Advertising'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
installment_step: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
|
||||
paymentSchema.plugin(timestamp)
|
||||
paymentSchema.plugin(mongoosePaginate)
|
||||
|
||||
const PaymentModel = mongoose.model('Payment', paymentSchema)
|
||||
module.exports = PaymentModel
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
const mongoose = require('mongoose');
|
||||
const timestamp = require('mongoose-timestamp');
|
||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
post_images: {
|
||||
type: [String], // آرایهای از مسیرهای تصاویر
|
||||
required: false,
|
||||
default: [],
|
||||
},
|
||||
post_video: {
|
||||
type: String, // مسیر ویدئو
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null,
|
||||
},
|
||||
type: {
|
||||
type: String, // نوع پست: 'image' یا 'video'
|
||||
required: true,
|
||||
enum: ['image', 'video'],
|
||||
},
|
||||
files: [
|
||||
{
|
||||
path: { type: String, required: true },
|
||||
type: { type: String, enum: ['image', 'video'], required: true },
|
||||
}
|
||||
],
|
||||
caption: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
default: null,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['pending', 'accept', 'reject'],
|
||||
default: 'pending',
|
||||
},
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
},
|
||||
likes: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
}],
|
||||
comments: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model('Post', modelSchema);
|
||||
const mongoose = require('mongoose');
|
||||
const timestamp = require('mongoose-timestamp');
|
||||
const mongoosePaginate = require('mongoose-paginate-v2');
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
post_images: {
|
||||
type: [String], // آرایهای از مسیرهای تصاویر
|
||||
required: false,
|
||||
default: [],
|
||||
},
|
||||
post_video: {
|
||||
type: String, // مسیر ویدئو
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null,
|
||||
},
|
||||
type: {
|
||||
type: String, // نوع پست: 'image' یا 'video'
|
||||
required: true,
|
||||
enum: ['image', 'video'],
|
||||
},
|
||||
files: [
|
||||
{
|
||||
path: { type: String, required: true },
|
||||
type: { type: String, enum: ['image', 'video'], required: true },
|
||||
}
|
||||
],
|
||||
caption: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1000,
|
||||
default: null,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
enum: ['pending', 'accept', 'reject'],
|
||||
default: 'pending',
|
||||
},
|
||||
user_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
},
|
||||
likes: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
}],
|
||||
comments: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model('Post', modelSchema);
|
||||
module.exports = PostModel;
|
||||
@@ -1,186 +1,186 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const projectSchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
expertise: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
sub_expertise: {
|
||||
type: [String], // تغییر نوع به آرایه از استرینگ
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
gender: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
age: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
conversation_projects: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
province: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
city: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
offer_time: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
offer_price: {
|
||||
type: Number,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
project_type: {
|
||||
type: String,
|
||||
enum: ['free', 'normal', 'force', 'highlight'],
|
||||
default: 'normal'
|
||||
},
|
||||
payment_status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
// فیلد برای وضعیت پروژه
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pre_payment', 'paid', 'accepted', 'rejected', 'done', 'cancled', 'ongoing'],
|
||||
default: 'pre_payment'
|
||||
},
|
||||
public_status: {
|
||||
type: String,
|
||||
enum: ['public', 'private'],
|
||||
default: 'public'
|
||||
},
|
||||
created_for_user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
default: null
|
||||
},
|
||||
creator_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
},
|
||||
requested_users: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}],
|
||||
selected_user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
default: null
|
||||
},
|
||||
final_price: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
final_time: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
installments: [{
|
||||
installment_number: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
amount: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
due_date: {
|
||||
type: Date,
|
||||
required: true
|
||||
}
|
||||
}],
|
||||
reject_reason: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
ratings: [{
|
||||
creator_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
comment: {
|
||||
type: String,
|
||||
trim: true
|
||||
}
|
||||
}],
|
||||
acceptedAt: {
|
||||
type: Date,
|
||||
default: null
|
||||
},
|
||||
isExpired: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
projectSchema.plugin(timestamp)
|
||||
// اضافه کردن پیجینیشن به مدل
|
||||
projectSchema.plugin(mongoosePaginate)
|
||||
const ProjectModel = mongoose.model('Project', projectSchema)
|
||||
module.exports = ProjectModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const projectSchema = new mongoose.Schema({
|
||||
title: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
expertise: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
sub_expertise: {
|
||||
type: [String], // تغییر نوع به آرایه از استرینگ
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
gender: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
age: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
conversation_projects: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
province: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
city: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
offer_time: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
offer_price: {
|
||||
type: Number,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
project_type: {
|
||||
type: String,
|
||||
enum: ['free', 'normal', 'force', 'highlight'],
|
||||
default: 'normal'
|
||||
},
|
||||
payment_status: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
// فیلد برای وضعیت پروژه
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pre_payment', 'paid', 'accepted', 'rejected', 'done', 'cancled', 'ongoing'],
|
||||
default: 'pre_payment'
|
||||
},
|
||||
public_status: {
|
||||
type: String,
|
||||
enum: ['public', 'private'],
|
||||
default: 'public'
|
||||
},
|
||||
created_for_user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
default: null
|
||||
},
|
||||
creator_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
},
|
||||
requested_users: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}],
|
||||
selected_user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
default: null
|
||||
},
|
||||
final_price: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
final_time: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
installments: [{
|
||||
installment_number: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
amount: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
due_date: {
|
||||
type: Date,
|
||||
required: true
|
||||
}
|
||||
}],
|
||||
reject_reason: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
ratings: [{
|
||||
creator_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
comment: {
|
||||
type: String,
|
||||
trim: true
|
||||
}
|
||||
}],
|
||||
acceptedAt: {
|
||||
type: Date,
|
||||
default: null
|
||||
},
|
||||
isExpired: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
projectSchema.plugin(timestamp)
|
||||
// اضافه کردن پیجینیشن به مدل
|
||||
projectSchema.plugin(mongoosePaginate)
|
||||
const ProjectModel = mongoose.model('Project', projectSchema)
|
||||
module.exports = ProjectModel
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const requestSchema = new mongoose.Schema({
|
||||
project: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Project',
|
||||
required: true
|
||||
},
|
||||
user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
time: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'],
|
||||
default: 'pending'
|
||||
}
|
||||
})
|
||||
|
||||
requestSchema.plugin(timestamp)
|
||||
|
||||
const RequestModel = mongoose.model('Request', requestSchema)
|
||||
module.exports = RequestModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const requestSchema = new mongoose.Schema({
|
||||
project: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Project',
|
||||
required: true
|
||||
},
|
||||
user: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User',
|
||||
required: true
|
||||
},
|
||||
time: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['pending', 'accepted', 'rejected'],
|
||||
default: 'pending'
|
||||
}
|
||||
})
|
||||
|
||||
requestSchema.plugin(timestamp)
|
||||
|
||||
const RequestModel = mongoose.model('Request', requestSchema)
|
||||
module.exports = RequestModel
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
// models/Setting.js
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const settingSchema = new mongoose.Schema({
|
||||
key: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
settingSchema.plugin(timestamp)
|
||||
|
||||
const SettingModel = mongoose.model('Setting', settingSchema)
|
||||
module.exports = SettingModel
|
||||
// models/Setting.js
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
|
||||
const settingSchema = new mongoose.Schema({
|
||||
key: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
settingSchema.plugin(timestamp)
|
||||
|
||||
const SettingModel = mongoose.model('Setting', settingSchema)
|
||||
module.exports = SettingModel
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const provincesSchema = new mongoose.Schema({
|
||||
id: Number,
|
||||
name: String,
|
||||
slug: String
|
||||
})
|
||||
|
||||
const citiesSchema = new mongoose.Schema({
|
||||
id: Number,
|
||||
name: String,
|
||||
slug: String,
|
||||
province_id: Number
|
||||
})
|
||||
|
||||
const ProvinceModel = mongoose.model('Province', provincesSchema)
|
||||
const CityModel = mongoose.model('City', citiesSchema)
|
||||
|
||||
module.exports = { ProvinceModel, CityModel }
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const provincesSchema = new mongoose.Schema({
|
||||
id: Number,
|
||||
name: String,
|
||||
slug: String
|
||||
})
|
||||
|
||||
const citiesSchema = new mongoose.Schema({
|
||||
id: Number,
|
||||
name: String,
|
||||
slug: String,
|
||||
province_id: Number
|
||||
})
|
||||
|
||||
const ProvinceModel = mongoose.model('Province', provincesSchema)
|
||||
const CityModel = mongoose.model('City', citiesSchema)
|
||||
|
||||
module.exports = { ProvinceModel, CityModel }
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
type: { type: String, enum: ["course", "product", "service"], required: true },
|
||||
tax: { type: Number, required: true, default: 9 }, // درصد مالیات
|
||||
is_active: { type: Boolean, default: true },
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("Tax", modelSchema);
|
||||
module.exports = PostModel;
|
||||
const mongoose = require("mongoose");
|
||||
const timestamp = require("mongoose-timestamp");
|
||||
const mongoosePaginate = require("mongoose-paginate-v2");
|
||||
|
||||
const modelSchema = new mongoose.Schema({
|
||||
type: { type: String, enum: ["course", "product", "service"], required: true },
|
||||
tax: { type: Number, required: true, default: 9 }, // درصد مالیات
|
||||
is_active: { type: Boolean, default: true },
|
||||
|
||||
});
|
||||
|
||||
modelSchema.plugin(timestamp);
|
||||
modelSchema.plugin(mongoosePaginate);
|
||||
const PostModel = mongoose.model("Tax", modelSchema);
|
||||
module.exports = PostModel;
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const ticketMessageSchema = new mongoose.Schema({
|
||||
text: { type: String, required: false },
|
||||
file: {
|
||||
type: String, // مسیر فایل در ذخیره شود
|
||||
required: false // فایل اختیاری است
|
||||
},
|
||||
senderType: { type: String, enum: ['User', 'Admin'], required: true },
|
||||
senderId: { type: mongoose.Schema.Types.ObjectId, refPath: 'senderType', required: true },
|
||||
ticket: { type: mongoose.Schema.Types.ObjectId, ref: 'Ticket', required: true }
|
||||
})
|
||||
|
||||
ticketMessageSchema.plugin(timestamp)
|
||||
// اضافه کردن پیجینیشن به مدل
|
||||
ticketMessageSchema.plugin(mongoosePaginate)
|
||||
const TicketMessageModel = mongoose.model('TicketMessage', ticketMessageSchema)
|
||||
module.exports = TicketMessageModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const ticketMessageSchema = new mongoose.Schema({
|
||||
text: { type: String, required: false },
|
||||
file: {
|
||||
type: String, // مسیر فایل در ذخیره شود
|
||||
required: false // فایل اختیاری است
|
||||
},
|
||||
senderType: { type: String, enum: ['User', 'Admin'], required: true },
|
||||
senderId: { type: mongoose.Schema.Types.ObjectId, refPath: 'senderType', required: true },
|
||||
ticket: { type: mongoose.Schema.Types.ObjectId, ref: 'Ticket', required: true }
|
||||
})
|
||||
|
||||
ticketMessageSchema.plugin(timestamp)
|
||||
// اضافه کردن پیجینیشن به مدل
|
||||
ticketMessageSchema.plugin(mongoosePaginate)
|
||||
const TicketMessageModel = mongoose.model('TicketMessage', ticketMessageSchema)
|
||||
module.exports = TicketMessageModel
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const ticketSchema = new mongoose.Schema({
|
||||
title: { type: String, required: true },
|
||||
status: { type: String, enum: ['Pending', 'Answered', 'Customer Response', 'Closed'], default: 'Pending' },
|
||||
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
|
||||
new_message: {
|
||||
type: Boolean,
|
||||
default: false // وضعیت خوانده شده یا نشده
|
||||
}
|
||||
})
|
||||
|
||||
ticketSchema.pre('save', function (next) {
|
||||
this.updatedAt = Date.now()
|
||||
next()
|
||||
})
|
||||
|
||||
ticketSchema.plugin(timestamp)
|
||||
// اضافه کردن پیجینیشن به مدل
|
||||
ticketSchema.plugin(mongoosePaginate)
|
||||
const TicketModel = mongoose.model('Ticket', ticketSchema)
|
||||
module.exports = TicketModel
|
||||
const mongoose = require('mongoose')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
|
||||
const ticketSchema = new mongoose.Schema({
|
||||
title: { type: String, required: true },
|
||||
status: { type: String, enum: ['Pending', 'Answered', 'Customer Response', 'Closed'], default: 'Pending' },
|
||||
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
|
||||
new_message: {
|
||||
type: Boolean,
|
||||
default: false // وضعیت خوانده شده یا نشده
|
||||
}
|
||||
})
|
||||
|
||||
ticketSchema.pre('save', function (next) {
|
||||
this.updatedAt = Date.now()
|
||||
next()
|
||||
})
|
||||
|
||||
ticketSchema.plugin(timestamp)
|
||||
// اضافه کردن پیجینیشن به مدل
|
||||
ticketSchema.plugin(mongoosePaginate)
|
||||
const TicketModel = mongoose.model('Ticket', ticketSchema)
|
||||
module.exports = TicketModel
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const typeAndPriceSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
}
|
||||
})
|
||||
|
||||
const TypeAndPriceModel = mongoose.model('TypeAndPrice', typeAndPriceSchema)
|
||||
module.exports = TypeAndPriceModel
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const typeAndPriceSchema = new mongoose.Schema({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
required: true,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255
|
||||
}
|
||||
})
|
||||
|
||||
const TypeAndPriceModel = mongoose.model('TypeAndPrice', typeAndPriceSchema)
|
||||
module.exports = TypeAndPriceModel
|
||||
|
||||
@@ -1,381 +1,381 @@
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const userSchema = new mongoose.Schema({
|
||||
mobile: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
unique: true
|
||||
},
|
||||
otp: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 6,
|
||||
maxLength: 6,
|
||||
default: null
|
||||
},
|
||||
user_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
first_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
last_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
user_type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
is_verified: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: 'none'
|
||||
},
|
||||
profile_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
national_card_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
expertise: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
sub_expertise: {
|
||||
type: [String], // تغییر نوع به آرایه از استرینگ
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
gender: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
weight: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
eye_color: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
hair_color: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
cooperation_type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
cooperation_abroad: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
conversation_projects: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
bio: {
|
||||
type: String,
|
||||
required: false,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
national_code: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
birthday: {
|
||||
type: Date,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
is_Register: {
|
||||
type: String,
|
||||
|
||||
default: false
|
||||
},
|
||||
shaba: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
province: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
city: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
lat: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
lng: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
show_location: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
rate: {
|
||||
type: String,
|
||||
trim: true,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
referral_code: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
shop_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Shop',
|
||||
default: null
|
||||
},
|
||||
last_online: {
|
||||
type: Date, // ذخیره تاریخ و زمان آخرین بازدید
|
||||
default: Date.now // تنظیم تاریخ به تاریخ فعلی
|
||||
},
|
||||
business_license: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
user_level: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
user_score: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
last_post: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
// user_ratings: [{
|
||||
// project_id: {
|
||||
// type: mongoose.Schema.Types.ObjectId,
|
||||
// ref: 'Project',
|
||||
// required: true
|
||||
// },
|
||||
// creator_id: {
|
||||
// type: mongoose.Schema.Types.ObjectId,
|
||||
// ref: 'User',
|
||||
// required: true
|
||||
// },
|
||||
// rating: {
|
||||
// type: Number,
|
||||
// required: true
|
||||
// },
|
||||
// comment: {
|
||||
// type: String,
|
||||
// trim: true
|
||||
// }
|
||||
// }],
|
||||
daily_free_request: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
last_free_request_date: {
|
||||
type: Date,
|
||||
default: null
|
||||
},
|
||||
blocked_by: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}],
|
||||
blocked_users: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}],
|
||||
block_status: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
advertising_profiles: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'AdvertisingProfile'
|
||||
}],
|
||||
services: [{
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
originalPrice: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
discountPrice: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
discountPercentage: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: "UnderReview",
|
||||
required: false
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
}
|
||||
}],
|
||||
monthly_free_offer: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
last_free_offer_date: {
|
||||
type: Date,
|
||||
default: null
|
||||
}
|
||||
// contactInfo: {
|
||||
// phone: String,
|
||||
// mobile: String,
|
||||
// telegramLink: String,
|
||||
// whatsappNumber: String,
|
||||
// instagramLink: String,
|
||||
// saveInfoForNextAds: { type: Boolean, default: false }
|
||||
// },
|
||||
// adTotalRatings: {
|
||||
// type: Number,
|
||||
// default: 0
|
||||
// },
|
||||
// adRatingsCount: {
|
||||
// type: Number,
|
||||
// default: 0
|
||||
// },
|
||||
// adAverageRating: {
|
||||
// type: Number,
|
||||
// default: 0
|
||||
// }
|
||||
})
|
||||
|
||||
userSchema.plugin(timestamp)
|
||||
userSchema.plugin(mongoosePaginate)
|
||||
const UserModel = mongoose.model('User', userSchema)
|
||||
module.exports = UserModel
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const userSchema = new mongoose.Schema({
|
||||
mobile: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
unique: true
|
||||
},
|
||||
otp: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 6,
|
||||
maxLength: 6,
|
||||
default: null
|
||||
},
|
||||
user_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
first_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
last_name: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
user_type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
is_verified: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: 'none'
|
||||
},
|
||||
profile_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
national_card_image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
expertise: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
sub_expertise: {
|
||||
type: [String], // تغییر نوع به آرایه از استرینگ
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
gender: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
weight: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
eye_color: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
hair_color: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
cooperation_type: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
cooperation_abroad: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
conversation_projects: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
bio: {
|
||||
type: String,
|
||||
required: false,
|
||||
minLength: 1,
|
||||
maxLength: 1024,
|
||||
default: null
|
||||
},
|
||||
national_code: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
birthday: {
|
||||
type: Date,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
is_Register: {
|
||||
type: String,
|
||||
|
||||
default: false
|
||||
},
|
||||
shaba: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 255,
|
||||
default: null
|
||||
},
|
||||
address: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
province: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
city: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
lat: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
lng: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
show_location: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
rate: {
|
||||
type: String,
|
||||
trim: true,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
referral_code: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
shop_id: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'Shop',
|
||||
default: null
|
||||
},
|
||||
last_online: {
|
||||
type: Date, // ذخیره تاریخ و زمان آخرین بازدید
|
||||
default: Date.now // تنظیم تاریخ به تاریخ فعلی
|
||||
},
|
||||
business_license: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
default: null
|
||||
},
|
||||
user_level: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
user_score: {
|
||||
type: String,
|
||||
trim: true,
|
||||
minLength: 1,
|
||||
maxLength: 512,
|
||||
default: null
|
||||
},
|
||||
last_post: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
// user_ratings: [{
|
||||
// project_id: {
|
||||
// type: mongoose.Schema.Types.ObjectId,
|
||||
// ref: 'Project',
|
||||
// required: true
|
||||
// },
|
||||
// creator_id: {
|
||||
// type: mongoose.Schema.Types.ObjectId,
|
||||
// ref: 'User',
|
||||
// required: true
|
||||
// },
|
||||
// rating: {
|
||||
// type: Number,
|
||||
// required: true
|
||||
// },
|
||||
// comment: {
|
||||
// type: String,
|
||||
// trim: true
|
||||
// }
|
||||
// }],
|
||||
daily_free_request: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
last_free_request_date: {
|
||||
type: Date,
|
||||
default: null
|
||||
},
|
||||
blocked_by: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}],
|
||||
blocked_users: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'User'
|
||||
}],
|
||||
block_status: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
advertising_profiles: [{
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: 'AdvertisingProfile'
|
||||
}],
|
||||
services: [{
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true
|
||||
},
|
||||
originalPrice: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
discountPrice: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
discountPercentage: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: "UnderReview",
|
||||
required: false
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true
|
||||
}
|
||||
}],
|
||||
monthly_free_offer: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
last_free_offer_date: {
|
||||
type: Date,
|
||||
default: null
|
||||
}
|
||||
// contactInfo: {
|
||||
// phone: String,
|
||||
// mobile: String,
|
||||
// telegramLink: String,
|
||||
// whatsappNumber: String,
|
||||
// instagramLink: String,
|
||||
// saveInfoForNextAds: { type: Boolean, default: false }
|
||||
// },
|
||||
// adTotalRatings: {
|
||||
// type: Number,
|
||||
// default: 0
|
||||
// },
|
||||
// adRatingsCount: {
|
||||
// type: Number,
|
||||
// default: 0
|
||||
// },
|
||||
// adAverageRating: {
|
||||
// type: Number,
|
||||
// default: 0
|
||||
// }
|
||||
})
|
||||
|
||||
userSchema.plugin(timestamp)
|
||||
userSchema.plugin(mongoosePaginate)
|
||||
const UserModel = mongoose.model('User', userSchema)
|
||||
module.exports = UserModel
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// models/VersionModel.js
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const versionSchema = new mongoose.Schema({
|
||||
version: { type: String, required: true },
|
||||
mandatory: { type: Boolean, required: true },
|
||||
releaseNotes: { type: String },
|
||||
updateUrls: { type: [String], required: true } // لینکهای آپدیت
|
||||
})
|
||||
|
||||
const VersionModel = mongoose.model('Version', versionSchema)
|
||||
module.exports = VersionModel
|
||||
// models/VersionModel.js
|
||||
const mongoose = require('mongoose')
|
||||
|
||||
const versionSchema = new mongoose.Schema({
|
||||
version: { type: String, required: true },
|
||||
mandatory: { type: Boolean, required: true },
|
||||
releaseNotes: { type: String },
|
||||
updateUrls: { type: [String], required: true } // لینکهای آپدیت
|
||||
})
|
||||
|
||||
const VersionModel = mongoose.model('Version', versionSchema)
|
||||
module.exports = VersionModel
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const license = new mongoose.Schema({
|
||||
|
||||
userId : String,
|
||||
Confirmation : { type : Boolean, default : false},
|
||||
licenseImg : { type : String },
|
||||
})
|
||||
|
||||
license.plugin(timestamp)
|
||||
license.plugin(mongoosePaginate)
|
||||
const LicenseMoldel = mongoose.model('license', license)
|
||||
module.exports = LicenseMoldel
|
||||
const mongoose = require('mongoose')
|
||||
const mongoosePaginate = require('mongoose-paginate-v2')
|
||||
const timestamp = require('mongoose-timestamp')
|
||||
const license = new mongoose.Schema({
|
||||
|
||||
userId : String,
|
||||
Confirmation : { type : Boolean, default : false},
|
||||
licenseImg : { type : String },
|
||||
})
|
||||
|
||||
license.plugin(timestamp)
|
||||
license.plugin(mongoosePaginate)
|
||||
const LicenseMoldel = mongoose.model('license', license)
|
||||
module.exports = LicenseMoldel
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,16 @@
|
||||
const { CityModel } = require('../../models/StateCity')
|
||||
const getCities = async (req, res, next) => {
|
||||
try {
|
||||
const { id } = req.params
|
||||
const cities = await CityModel.find({ province_id: id })
|
||||
|
||||
res.status(200).json({
|
||||
cities
|
||||
})
|
||||
} catch (err) {
|
||||
res.status(500).send('Internal Server Error')
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getCities
|
||||
}
|
||||
const { CityModel } = require('../../models/StateCity')
|
||||
const getCities = async (req, res, next) => {
|
||||
try {
|
||||
const { id } = req.params
|
||||
const cities = await CityModel.find({ province_id: id })
|
||||
|
||||
res.status(200).json({
|
||||
cities
|
||||
})
|
||||
} catch (err) {
|
||||
res.status(500).send('Internal Server Error')
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getCities
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/* eslint-disable camelcase */
|
||||
const ExpertiseModel = require('../../../models/ExpertiseModel')
|
||||
const getExpertise = async (req, res, next) => {
|
||||
try {
|
||||
const expertises = await ExpertiseModel.find().select('expertise sub_expertise')
|
||||
res.json({ expertises })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getExpertise
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const ExpertiseModel = require('../../../models/ExpertiseModel')
|
||||
const getExpertise = async (req, res, next) => {
|
||||
try {
|
||||
const expertises = await ExpertiseModel.find().select('expertise sub_expertise')
|
||||
res.json({ expertises })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getExpertise
|
||||
}
|
||||
|
||||
@@ -1,65 +1,65 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const PaymentModel = require('../../../models/PaymentModel')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const moment = require('moment-jalaali')
|
||||
|
||||
const getFinancial = async (req, res) => {
|
||||
try {
|
||||
// Extract user ID from JWT token
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
// Find all payments associated with the user
|
||||
const financial = await PaymentModel.paginate(
|
||||
{ user_id: userId }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
// Prepare the data to be sent back
|
||||
const userPayments = await Promise.all(financial.docs.map(async (payment) => {
|
||||
// Find the project associated with the payment
|
||||
const project = await ProjectModel.findById(payment.project_id)
|
||||
|
||||
if (!project) {
|
||||
return null
|
||||
}
|
||||
// استفاده از کتابخانه moment-jalaali برای تبدیل تاریخ و زمان به شمسی
|
||||
const shamsiDate = moment(payment.createdAt).format('jYYYY-jMM-jDD')
|
||||
const shamsiTime = moment(payment.createdAt).format('HH:mm')
|
||||
|
||||
// Extract the required information
|
||||
const userPayment = {
|
||||
_id: payment._id,
|
||||
project_title: project.title,
|
||||
project_id: project._id,
|
||||
payment_date: shamsiDate, // Format date as YYYY-MM-DD
|
||||
payment_time: shamsiTime,
|
||||
iban: project.creator_id ? project.creator_id.iban : null, // Check if creator_id exists before accessing iban
|
||||
amount: payment.amount,
|
||||
payment_status: payment.status
|
||||
}
|
||||
|
||||
return userPayment
|
||||
}))
|
||||
|
||||
// Filter out null values
|
||||
const validUserPayments = userPayments.filter(payment => payment !== null)
|
||||
|
||||
// Send the payments back to the client
|
||||
res.status(200).json({
|
||||
financial: financial,
|
||||
totalPages: financial.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: financial.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error occurred:', error)
|
||||
res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getFinancial }
|
||||
const jwt = require('jsonwebtoken')
|
||||
const PaymentModel = require('../../../models/PaymentModel')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const moment = require('moment-jalaali')
|
||||
|
||||
const getFinancial = async (req, res) => {
|
||||
try {
|
||||
// Extract user ID from JWT token
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
// Find all payments associated with the user
|
||||
const financial = await PaymentModel.paginate(
|
||||
{ user_id: userId }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
// Prepare the data to be sent back
|
||||
const userPayments = await Promise.all(financial.docs.map(async (payment) => {
|
||||
// Find the project associated with the payment
|
||||
const project = await ProjectModel.findById(payment.project_id)
|
||||
|
||||
if (!project) {
|
||||
return null
|
||||
}
|
||||
// استفاده از کتابخانه moment-jalaali برای تبدیل تاریخ و زمان به شمسی
|
||||
const shamsiDate = moment(payment.createdAt).format('jYYYY-jMM-jDD')
|
||||
const shamsiTime = moment(payment.createdAt).format('HH:mm')
|
||||
|
||||
// Extract the required information
|
||||
const userPayment = {
|
||||
_id: payment._id,
|
||||
project_title: project.title,
|
||||
project_id: project._id,
|
||||
payment_date: shamsiDate, // Format date as YYYY-MM-DD
|
||||
payment_time: shamsiTime,
|
||||
iban: project.creator_id ? project.creator_id.iban : null, // Check if creator_id exists before accessing iban
|
||||
amount: payment.amount,
|
||||
payment_status: payment.status
|
||||
}
|
||||
|
||||
return userPayment
|
||||
}))
|
||||
|
||||
// Filter out null values
|
||||
const validUserPayments = userPayments.filter(payment => payment !== null)
|
||||
|
||||
// Send the payments back to the client
|
||||
res.status(200).json({
|
||||
financial: financial,
|
||||
totalPages: financial.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: financial.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error occurred:', error)
|
||||
res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getFinancial }
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
/* eslint-disable camelcase */
|
||||
const bcrypt = require('bcryptjs')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
|
||||
const jwt = require('jsonwebtoken')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
|
||||
const changePasswordValidationRules = () => {
|
||||
return [
|
||||
check('new_password')
|
||||
.notEmpty().withMessage('رمز عبور نمیتواند خالی باشد')
|
||||
.isLength({ min: 8, max: 25 }).withMessage('رمز عبور نباید کوتاه تر از 8 کاراکتر باشد')
|
||||
.matches(/^(?=.*[a-zA-Zآ-ی])(?=.*\d).{8,}$/u).withMessage('رمز عبور باید شامل حروف و اعداد باشد')
|
||||
]
|
||||
}
|
||||
const changePasswordUser = async (req, res, next) => {
|
||||
try {
|
||||
const { new_password } = req.body
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// اعتبارسنجی ورودی ها
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
// یافتن کاربر با شماره موبایل
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
// هش کردن پسورد جدید و ذخیره در دیتابیس
|
||||
const hashedPassword = await bcrypt.hash(new_password, 10)
|
||||
user.password = hashedPassword
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'کلمه عبور با موفقیت ذخیره شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const editChangePasswordUser = async (req, res, next) => {
|
||||
try {
|
||||
const { mobile, new_password } = req.body
|
||||
const user = await UserModel.findOne({ mobile })
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// هش کردن پسورد جدید و ذخیره در دیتابیس
|
||||
const hashedPassword = await bcrypt.hash(new_password, 10)
|
||||
user.password = hashedPassword
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'کلمه عبور با موفقیت تغییر یافت'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
changePasswordUser, changePasswordValidationRules, editChangePasswordUser
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const bcrypt = require('bcryptjs')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
|
||||
const jwt = require('jsonwebtoken')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
|
||||
const changePasswordValidationRules = () => {
|
||||
return [
|
||||
check('new_password')
|
||||
.notEmpty().withMessage('رمز عبور نمیتواند خالی باشد')
|
||||
.isLength({ min: 8, max: 25 }).withMessage('رمز عبور نباید کوتاه تر از 8 کاراکتر باشد')
|
||||
.matches(/^(?=.*[a-zA-Zآ-ی])(?=.*\d).{8,}$/u).withMessage('رمز عبور باید شامل حروف و اعداد باشد')
|
||||
]
|
||||
}
|
||||
const changePasswordUser = async (req, res, next) => {
|
||||
try {
|
||||
const { new_password } = req.body
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// اعتبارسنجی ورودی ها
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
// یافتن کاربر با شماره موبایل
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
// هش کردن پسورد جدید و ذخیره در دیتابیس
|
||||
const hashedPassword = await bcrypt.hash(new_password, 10)
|
||||
user.password = hashedPassword
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'کلمه عبور با موفقیت ذخیره شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const editChangePasswordUser = async (req, res, next) => {
|
||||
try {
|
||||
const { mobile, new_password } = req.body
|
||||
const user = await UserModel.findOne({ mobile })
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// هش کردن پسورد جدید و ذخیره در دیتابیس
|
||||
const hashedPassword = await bcrypt.hash(new_password, 10)
|
||||
user.password = hashedPassword
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'کلمه عبور با موفقیت تغییر یافت'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
changePasswordUser, changePasswordValidationRules, editChangePasswordUser
|
||||
}
|
||||
|
||||
@@ -1,87 +1,87 @@
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const { default: axios } = require('axios')
|
||||
const loginValidationRules = () => {
|
||||
return [
|
||||
check('mobile')
|
||||
.notEmpty().withMessage('شماره موبایل نمیتواند خالی باشد')
|
||||
.isLength({ min: 11, max: 11 }).withMessage('شماره موبایل باید دقیقاً 11 رقم باشد')
|
||||
.matches(/^09[0-9]{9}$/).withMessage('فرمت شماره موبایل صحیح نیست')
|
||||
]
|
||||
}
|
||||
|
||||
const loginUser = async (req, res, next) => {
|
||||
try {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
const { mobile } = req.body
|
||||
if (!mobile) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شماره موبایل نمیتواند خالی باشد'
|
||||
})
|
||||
}
|
||||
|
||||
// const existingUser = await UserModel.findOne({ mobile })
|
||||
// if (!existingUser) {
|
||||
// return res.status(422).json({ error: true, message: 'کاربری با این شماره موبایل یافت نشد' })
|
||||
// }
|
||||
function generateOTP () {
|
||||
return Math.floor(100000 + Math.random() * 900000)
|
||||
}
|
||||
|
||||
const otp = generateOTP()
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const user = await UserModel.findOneAndUpdate(
|
||||
{ mobile },
|
||||
{ $set: { mobile, otp } },
|
||||
{ upsert: true, new: true, lean: true }
|
||||
)
|
||||
// زمانبندی تنظیم مقدار otp به null پس از 10 دقیقه
|
||||
setTimeout(() => {
|
||||
UserModel.findOneAndUpdate({ mobile }, { $set: { otp: null } }, { new: true })
|
||||
.then(() => {})
|
||||
.catch(error => console.error('Error setting OTP to null:', error))
|
||||
}, 5 * 60 * 1000)
|
||||
const data = JSON.stringify({
|
||||
mobile,
|
||||
templateId: '930719',
|
||||
parameters: [
|
||||
{ name: 'CODE', value: otp.toString() }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'کد تایید ارسال شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loginValidationRules,
|
||||
loginUser
|
||||
}
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const { default: axios } = require('axios')
|
||||
const loginValidationRules = () => {
|
||||
return [
|
||||
check('mobile')
|
||||
.notEmpty().withMessage('شماره موبایل نمیتواند خالی باشد')
|
||||
.isLength({ min: 11, max: 11 }).withMessage('شماره موبایل باید دقیقاً 11 رقم باشد')
|
||||
.matches(/^09[0-9]{9}$/).withMessage('فرمت شماره موبایل صحیح نیست')
|
||||
]
|
||||
}
|
||||
|
||||
const loginUser = async (req, res, next) => {
|
||||
try {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
const { mobile } = req.body
|
||||
if (!mobile) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شماره موبایل نمیتواند خالی باشد'
|
||||
})
|
||||
}
|
||||
|
||||
// const existingUser = await UserModel.findOne({ mobile })
|
||||
// if (!existingUser) {
|
||||
// return res.status(422).json({ error: true, message: 'کاربری با این شماره موبایل یافت نشد' })
|
||||
// }
|
||||
function generateOTP () {
|
||||
return Math.floor(100000 + Math.random() * 900000)
|
||||
}
|
||||
|
||||
const otp = generateOTP()
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const user = await UserModel.findOneAndUpdate(
|
||||
{ mobile },
|
||||
{ $set: { mobile, otp } },
|
||||
{ upsert: true, new: true, lean: true }
|
||||
)
|
||||
// زمانبندی تنظیم مقدار otp به null پس از 10 دقیقه
|
||||
setTimeout(() => {
|
||||
UserModel.findOneAndUpdate({ mobile }, { $set: { otp: null } }, { new: true })
|
||||
.then(() => {})
|
||||
.catch(error => console.error('Error setting OTP to null:', error))
|
||||
}, 5 * 60 * 1000)
|
||||
const data = JSON.stringify({
|
||||
mobile,
|
||||
templateId: '930719',
|
||||
parameters: [
|
||||
{ name: 'CODE', value: otp.toString() }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'کد تایید ارسال شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loginValidationRules,
|
||||
loginUser
|
||||
}
|
||||
|
||||
@@ -1,92 +1,92 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const bcrypt = require('bcryptjs')
|
||||
const TokenService = require('../../../services/TokenService')
|
||||
// const jwt = require('jsonwebtoken')
|
||||
|
||||
const loginWithUserName = async (req, res, next) => {
|
||||
try {
|
||||
// اعتبارسنجی ورودی ها
|
||||
const { user_name, password } = req.body
|
||||
if (!user_name || !password) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
// یافتن کاربر با نام کاربری
|
||||
const userLow = user_name.toLowerCase()
|
||||
const user = await UserModel.findOne({ user_name: userLow })
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این نام کاربری یافت نشد'
|
||||
})
|
||||
}
|
||||
if (!user.password) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'رمز عبور برای این کاربر تنظیم نشده است'
|
||||
})
|
||||
}
|
||||
const isPasswordValid = await bcrypt.compare(password, user.password)
|
||||
if (!isPasswordValid) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نام کاربری یا رمز عبور اشتباه است'
|
||||
})
|
||||
}
|
||||
// اگر هم نام کاربری و هم رمز عبور درست بود، ارسال پیام موفقیت آمیز
|
||||
const token = TokenService.sign({ id: user._id })
|
||||
// if (user.user_name === null) {
|
||||
// return res.json({
|
||||
// message: 'ورود با موفقیت',
|
||||
// page: 'username'
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (!user.first_name && !user.last_name) {
|
||||
// return res.json({
|
||||
// message: 'ورود با موفقیت',
|
||||
// page: 'name'
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (!user.user_type) {
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// page: 'usertype'
|
||||
// })
|
||||
// }
|
||||
let step = ''
|
||||
if (user.user_name === null) { step = 'user_name' } else if
|
||||
(!user.password) { step = 'password' } else if
|
||||
(!user.first_name) { step = 'first_name' } else if
|
||||
(!user.user_type) { step = 'user_type' }
|
||||
if (!user.user_type || user.user_name === null || !user.first_name || !user.last_name) {
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
step,
|
||||
user_type: null,
|
||||
page: 'auth-page',
|
||||
id: user._id
|
||||
})
|
||||
}
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
page: 'home',
|
||||
step,
|
||||
user_type: user.user_type,
|
||||
id: user._id
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loginWithUserName
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const bcrypt = require('bcryptjs')
|
||||
const TokenService = require('../../../services/TokenService')
|
||||
// const jwt = require('jsonwebtoken')
|
||||
|
||||
const loginWithUserName = async (req, res, next) => {
|
||||
try {
|
||||
// اعتبارسنجی ورودی ها
|
||||
const { user_name, password } = req.body
|
||||
if (!user_name || !password) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
// یافتن کاربر با نام کاربری
|
||||
const userLow = user_name.toLowerCase()
|
||||
const user = await UserModel.findOne({ user_name: userLow })
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این نام کاربری یافت نشد'
|
||||
})
|
||||
}
|
||||
if (!user.password) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'رمز عبور برای این کاربر تنظیم نشده است'
|
||||
})
|
||||
}
|
||||
const isPasswordValid = await bcrypt.compare(password, user.password)
|
||||
if (!isPasswordValid) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نام کاربری یا رمز عبور اشتباه است'
|
||||
})
|
||||
}
|
||||
// اگر هم نام کاربری و هم رمز عبور درست بود، ارسال پیام موفقیت آمیز
|
||||
const token = TokenService.sign({ id: user._id })
|
||||
// if (user.user_name === null) {
|
||||
// return res.json({
|
||||
// message: 'ورود با موفقیت',
|
||||
// page: 'username'
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (!user.first_name && !user.last_name) {
|
||||
// return res.json({
|
||||
// message: 'ورود با موفقیت',
|
||||
// page: 'name'
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (!user.user_type) {
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// page: 'usertype'
|
||||
// })
|
||||
// }
|
||||
let step = ''
|
||||
if (user.user_name === null) { step = 'user_name' } else if
|
||||
(!user.password) { step = 'password' } else if
|
||||
(!user.first_name) { step = 'first_name' } else if
|
||||
(!user.user_type) { step = 'user_type' }
|
||||
if (!user.user_type || user.user_name === null || !user.first_name || !user.last_name) {
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
step,
|
||||
user_type: null,
|
||||
page: 'auth-page',
|
||||
id: user._id
|
||||
})
|
||||
}
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
page: 'home',
|
||||
step,
|
||||
user_type: user.user_type,
|
||||
id: user._id
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
loginWithUserName
|
||||
}
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const TokenService = require('../../../services/TokenService')
|
||||
// const jwt = require('jsonwebtoken')
|
||||
|
||||
const verifyUser = async (req, res, next) => {
|
||||
try {
|
||||
const { mobile, otp } = req.body
|
||||
if (!mobile || !otp) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findOne({ mobile })
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
const token = TokenService.sign({ id: user._id })
|
||||
if (user.otp === otp) {
|
||||
// if (user.user_name === null) {
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// page: 'username'
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (!user.first_name && !user.last_name) {
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// page: 'name'
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (!user.user_type) {
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// page: 'usertype'
|
||||
// })
|
||||
// }
|
||||
|
||||
// اگر همه فیلدها پر بودند
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// token,
|
||||
// user_type: user.user_type,
|
||||
// page: 'home',
|
||||
// id: user._id
|
||||
// })
|
||||
let step = ''
|
||||
if (user.user_name === null) { step = 'user_name' } else if
|
||||
(!user.password) { step = 'password' } else if
|
||||
(!user.first_name) { step = 'first_name' } else if
|
||||
(!user.user_type) { step = 'user_type' } else { step = 'profile_image' }
|
||||
if (!user.user_type || user.user_name === null || !user.first_name || !user.last_name) {
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
step,
|
||||
user_type: null,
|
||||
page: 'auth-page',
|
||||
id: user._id
|
||||
})
|
||||
}
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
user_type: user.user_type,
|
||||
step,
|
||||
page: 'home',
|
||||
id: user._id
|
||||
})
|
||||
}
|
||||
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'کد تایید اشتباه است'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
verifyUser
|
||||
}
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const TokenService = require('../../../services/TokenService')
|
||||
// const jwt = require('jsonwebtoken')
|
||||
|
||||
const verifyUser = async (req, res, next) => {
|
||||
try {
|
||||
const { mobile, otp } = req.body
|
||||
if (!mobile || !otp) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findOne({ mobile })
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
const token = TokenService.sign({ id: user._id })
|
||||
if (user.otp === otp) {
|
||||
// if (user.user_name === null) {
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// page: 'username'
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (!user.first_name && !user.last_name) {
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// page: 'name'
|
||||
// })
|
||||
// }
|
||||
|
||||
// if (!user.user_type) {
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// page: 'usertype'
|
||||
// })
|
||||
// }
|
||||
|
||||
// اگر همه فیلدها پر بودند
|
||||
// return res.json({
|
||||
// message: 'کد تایید صحیح بود',
|
||||
// token,
|
||||
// user_type: user.user_type,
|
||||
// page: 'home',
|
||||
// id: user._id
|
||||
// })
|
||||
let step = ''
|
||||
if (user.user_name === null) { step = 'user_name' } else if
|
||||
(!user.password) { step = 'password' } else if
|
||||
(!user.first_name) { step = 'first_name' } else if
|
||||
(!user.user_type) { step = 'user_type' } else { step = 'profile_image' }
|
||||
if (!user.user_type || user.user_name === null || !user.first_name || !user.last_name) {
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
step,
|
||||
user_type: null,
|
||||
page: 'auth-page',
|
||||
id: user._id
|
||||
})
|
||||
}
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
user_type: user.user_type,
|
||||
step,
|
||||
page: 'home',
|
||||
id: user._id
|
||||
})
|
||||
}
|
||||
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'کد تایید اشتباه است'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
verifyUser
|
||||
}
|
||||
|
||||
@@ -1,127 +1,127 @@
|
||||
const MessageModel = require('../../../models/MessageModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const moment = require('moment-jalaali')
|
||||
const getMessages = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { search } = req.query
|
||||
|
||||
// پیدا کردن تمام پیامهایی که کاربر مورد نظر آنها فرستنده یا گیرنده بوده است
|
||||
const messageFilter = {
|
||||
$or: [
|
||||
{ senderId: userId },
|
||||
{ receiverId: userId }
|
||||
]
|
||||
}
|
||||
|
||||
// پیدا کردن تمام پیامها با فیلتر و سورت براساس جدیدترین پیام
|
||||
const messages = await MessageModel.find(messageFilter).sort({ createdAt: -1 })
|
||||
|
||||
// استخراج شناسههای تمام کاربران مرتبط با این پیامها (بدون تکرار)
|
||||
const userIdToLastMessageDate = {}
|
||||
messages.forEach(message => {
|
||||
if (!userIdToLastMessageDate[message.senderId]) {
|
||||
userIdToLastMessageDate[message.senderId] = message.createdAt
|
||||
}
|
||||
if (!userIdToLastMessageDate[message.receiverId]) {
|
||||
userIdToLastMessageDate[message.receiverId] = message.createdAt
|
||||
}
|
||||
})
|
||||
|
||||
// تبدیل مجموعه شناسههای کاربر به آرایه
|
||||
const userIdsArray = Object.keys(userIdToLastMessageDate)
|
||||
|
||||
// ساخت فیلتر جستجو برای کاربران مرتبط
|
||||
const userFilter = { _id: { $in: userIdsArray } }
|
||||
|
||||
if (search) {
|
||||
userFilter.$and = [
|
||||
{ _id: { $in: userIdsArray } }, // فقط کاربران مرتبط
|
||||
{
|
||||
$or: [
|
||||
{ first_name: { $regex: search, $options: 'i' } },
|
||||
{ last_name: { $regex: search, $options: 'i' } },
|
||||
{ user_name: { $regex: search, $options: 'i' } }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// پیدا کردن اطلاعات کاربران مرتبط بر اساس فیلتر جستجو و شمارش تعداد پیامهای خوانده نشده برای هر کاربر
|
||||
const usersData = await UserModel.find(userFilter)
|
||||
const usersWithUnreadCount = await Promise.all(usersData.map(async (user) => {
|
||||
const unreadMessagesCount = await MessageModel.countDocuments({ receiverId: userId, senderId: user._id, readStatus: 0 })
|
||||
|
||||
let lastOnlineStatus
|
||||
const now = moment()
|
||||
const lastOnline = moment(user.last_online)
|
||||
const diffMinutes = now.diff(lastOnline, 'minutes')
|
||||
|
||||
if (diffMinutes < 1) {
|
||||
lastOnlineStatus = 'آنلاین'
|
||||
} else if (diffMinutes < 60) {
|
||||
lastOnlineStatus = `${diffMinutes} دقیقه پیش`
|
||||
} else if (diffMinutes < 1440) {
|
||||
lastOnlineStatus = `${Math.floor(diffMinutes / 60)} ساعت پیش`
|
||||
} else {
|
||||
lastOnlineStatus = `${Math.floor(diffMinutes / 1440)} روز پیش`
|
||||
}
|
||||
|
||||
// بررسی آیا کاربر فعلی در لیست بلاکشدههای این کاربر است یا خیر
|
||||
const blockedByCurrentUser = user.blocked_by.includes(userId)
|
||||
const blockedYou = user.blocked_users.includes(userId)
|
||||
|
||||
return {
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
user_name: user.user_name,
|
||||
is_verified: user.is_verified,
|
||||
profile_image: user.profile_image,
|
||||
last_online: lastOnlineStatus,
|
||||
_id: user._id,
|
||||
unread_messages_count: unreadMessagesCount,
|
||||
is_blocked: blockedByCurrentUser,
|
||||
blocked_you: blockedYou,
|
||||
last_message_date: userIdToLastMessageDate[user._id]
|
||||
}
|
||||
}))
|
||||
|
||||
// حذف کاربر فعلی از آرایه و سورت کردن کاربران براساس آخرین پیام
|
||||
const filteredUsersData = usersWithUnreadCount
|
||||
.filter(user => user._id.toString() !== userId)
|
||||
.sort((a, b) => new Date(b.last_message_date) - new Date(a.last_message_date))
|
||||
|
||||
res.status(200).json({
|
||||
filteredUsersData,
|
||||
totalMessages: messages.length
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const getUnreadMessages = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// پیدا کردن تمام پیامهای کاربر که هنوز خوانده نشدهاند
|
||||
const unreadMessagesCount = await MessageModel.countDocuments({ receiverId: userId, readStatus: 0 })
|
||||
|
||||
res.status(200).json({ unread_messages_count: unreadMessagesCount })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getMessages, getUnreadMessages
|
||||
}
|
||||
const MessageModel = require('../../../models/MessageModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const moment = require('moment-jalaali')
|
||||
const getMessages = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { search } = req.query
|
||||
|
||||
// پیدا کردن تمام پیامهایی که کاربر مورد نظر آنها فرستنده یا گیرنده بوده است
|
||||
const messageFilter = {
|
||||
$or: [
|
||||
{ senderId: userId },
|
||||
{ receiverId: userId }
|
||||
]
|
||||
}
|
||||
|
||||
// پیدا کردن تمام پیامها با فیلتر و سورت براساس جدیدترین پیام
|
||||
const messages = await MessageModel.find(messageFilter).sort({ createdAt: -1 })
|
||||
|
||||
// استخراج شناسههای تمام کاربران مرتبط با این پیامها (بدون تکرار)
|
||||
const userIdToLastMessageDate = {}
|
||||
messages.forEach(message => {
|
||||
if (!userIdToLastMessageDate[message.senderId]) {
|
||||
userIdToLastMessageDate[message.senderId] = message.createdAt
|
||||
}
|
||||
if (!userIdToLastMessageDate[message.receiverId]) {
|
||||
userIdToLastMessageDate[message.receiverId] = message.createdAt
|
||||
}
|
||||
})
|
||||
|
||||
// تبدیل مجموعه شناسههای کاربر به آرایه
|
||||
const userIdsArray = Object.keys(userIdToLastMessageDate)
|
||||
|
||||
// ساخت فیلتر جستجو برای کاربران مرتبط
|
||||
const userFilter = { _id: { $in: userIdsArray } }
|
||||
|
||||
if (search) {
|
||||
userFilter.$and = [
|
||||
{ _id: { $in: userIdsArray } }, // فقط کاربران مرتبط
|
||||
{
|
||||
$or: [
|
||||
{ first_name: { $regex: search, $options: 'i' } },
|
||||
{ last_name: { $regex: search, $options: 'i' } },
|
||||
{ user_name: { $regex: search, $options: 'i' } }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// پیدا کردن اطلاعات کاربران مرتبط بر اساس فیلتر جستجو و شمارش تعداد پیامهای خوانده نشده برای هر کاربر
|
||||
const usersData = await UserModel.find(userFilter)
|
||||
const usersWithUnreadCount = await Promise.all(usersData.map(async (user) => {
|
||||
const unreadMessagesCount = await MessageModel.countDocuments({ receiverId: userId, senderId: user._id, readStatus: 0 })
|
||||
|
||||
let lastOnlineStatus
|
||||
const now = moment()
|
||||
const lastOnline = moment(user.last_online)
|
||||
const diffMinutes = now.diff(lastOnline, 'minutes')
|
||||
|
||||
if (diffMinutes < 1) {
|
||||
lastOnlineStatus = 'آنلاین'
|
||||
} else if (diffMinutes < 60) {
|
||||
lastOnlineStatus = `${diffMinutes} دقیقه پیش`
|
||||
} else if (diffMinutes < 1440) {
|
||||
lastOnlineStatus = `${Math.floor(diffMinutes / 60)} ساعت پیش`
|
||||
} else {
|
||||
lastOnlineStatus = `${Math.floor(diffMinutes / 1440)} روز پیش`
|
||||
}
|
||||
|
||||
// بررسی آیا کاربر فعلی در لیست بلاکشدههای این کاربر است یا خیر
|
||||
const blockedByCurrentUser = user.blocked_by.includes(userId)
|
||||
const blockedYou = user.blocked_users.includes(userId)
|
||||
|
||||
return {
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
user_name: user.user_name,
|
||||
is_verified: user.is_verified,
|
||||
profile_image: user.profile_image,
|
||||
last_online: lastOnlineStatus,
|
||||
_id: user._id,
|
||||
unread_messages_count: unreadMessagesCount,
|
||||
is_blocked: blockedByCurrentUser,
|
||||
blocked_you: blockedYou,
|
||||
last_message_date: userIdToLastMessageDate[user._id]
|
||||
}
|
||||
}))
|
||||
|
||||
// حذف کاربر فعلی از آرایه و سورت کردن کاربران براساس آخرین پیام
|
||||
const filteredUsersData = usersWithUnreadCount
|
||||
.filter(user => user._id.toString() !== userId)
|
||||
.sort((a, b) => new Date(b.last_message_date) - new Date(a.last_message_date))
|
||||
|
||||
res.status(200).json({
|
||||
filteredUsersData,
|
||||
totalMessages: messages.length
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const getUnreadMessages = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// پیدا کردن تمام پیامهای کاربر که هنوز خوانده نشدهاند
|
||||
const unreadMessagesCount = await MessageModel.countDocuments({ receiverId: userId, readStatus: 0 })
|
||||
|
||||
res.status(200).json({ unread_messages_count: unreadMessagesCount })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getMessages, getUnreadMessages
|
||||
}
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
|
||||
const getNotifications = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const { page = 1, limit = 10, search } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
const filter = { user_id: userId }
|
||||
if (search) {
|
||||
filter.$or = [
|
||||
{ title: { $regex: search, $options: 'i' } },
|
||||
{ description: { $regex: search, $options: 'i' } }
|
||||
]
|
||||
}
|
||||
// استفاده از مدل پیجینیت شده برای دریافت نتایج صفحهبندی شده
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { createdAt: -1 } // بر اساس زمان ایجاد (createdAt) مرتب کنید (نزولی)
|
||||
}
|
||||
|
||||
// دریافت اعلانهای مربوط به کاربر با استفاده از userId
|
||||
let notifications = await NotificationModel.paginate(filter, options)
|
||||
const totalPages = notifications.totalPages
|
||||
const totalItems = notifications.totalDocs
|
||||
notifications = notifications?.docs.map(notification => {
|
||||
const jDate = jMoment(notification.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
return {
|
||||
...notification._doc,
|
||||
createdAt: jDate
|
||||
}
|
||||
})
|
||||
// تغییر وضعیت "read" اعلانها به "true"
|
||||
await NotificationModel.updateMany({ user_id: userId }, { read: true })
|
||||
res.json({
|
||||
notifications,
|
||||
totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const unreadNotifications = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// دریافت تعداد اعلانهای جدید برای کاربر
|
||||
const newNotificationsCount = await NotificationModel.countDocuments({ user_id: userId, read: false }).exec()
|
||||
|
||||
res.json({ newNotificationsCount })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getNotifications, unreadNotifications
|
||||
}
|
||||
const jwt = require('jsonwebtoken')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
|
||||
const getNotifications = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const { page = 1, limit = 10, search } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
const filter = { user_id: userId }
|
||||
if (search) {
|
||||
filter.$or = [
|
||||
{ title: { $regex: search, $options: 'i' } },
|
||||
{ description: { $regex: search, $options: 'i' } }
|
||||
]
|
||||
}
|
||||
// استفاده از مدل پیجینیت شده برای دریافت نتایج صفحهبندی شده
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { createdAt: -1 } // بر اساس زمان ایجاد (createdAt) مرتب کنید (نزولی)
|
||||
}
|
||||
|
||||
// دریافت اعلانهای مربوط به کاربر با استفاده از userId
|
||||
let notifications = await NotificationModel.paginate(filter, options)
|
||||
const totalPages = notifications.totalPages
|
||||
const totalItems = notifications.totalDocs
|
||||
notifications = notifications?.docs.map(notification => {
|
||||
const jDate = jMoment(notification.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
return {
|
||||
...notification._doc,
|
||||
createdAt: jDate
|
||||
}
|
||||
})
|
||||
// تغییر وضعیت "read" اعلانها به "true"
|
||||
await NotificationModel.updateMany({ user_id: userId }, { read: true })
|
||||
res.json({
|
||||
notifications,
|
||||
totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const unreadNotifications = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// دریافت تعداد اعلانهای جدید برای کاربر
|
||||
const newNotificationsCount = await NotificationModel.countDocuments({ user_id: userId, read: false }).exec()
|
||||
|
||||
res.json({ newNotificationsCount })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getNotifications, unreadNotifications
|
||||
}
|
||||
|
||||
@@ -1,439 +1,439 @@
|
||||
/* eslint-disable camelcase */
|
||||
const jwt = require('jsonwebtoken')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const OfferModel = require('../../../models/OfferModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const OfferTypeModel = require('../../../models/OfferTypeModel')
|
||||
const PaymentModel = require('../../../models/PaymentModel')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const { default: axios } = require('axios')
|
||||
const CommentModel = require('../../../models/CommentModel')
|
||||
|
||||
const getOfferPriceFromDatabase = async (itemName) => {
|
||||
const item = await OfferTypeModel.findOne({ name: itemName })
|
||||
if (!item) {
|
||||
throw new Error('Item not found in database')
|
||||
}
|
||||
return item.price
|
||||
}
|
||||
|
||||
const getOfferTypes = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
let offerTypes = await OfferTypeModel.find({}, 'name price')
|
||||
|
||||
// بررسی برای مواردی مانند پیدا نشدن انواع پروژه
|
||||
if (!offerTypes) {
|
||||
return res.status(404).json({ message: 'انواع پروژه یافت نشد.' })
|
||||
}
|
||||
// اگر کاربر درخواست ماهانه نداشته باشد، نوع پروژه ماهانه را حذف کنید
|
||||
if (user.monthly_free_offer <= 0) {
|
||||
offerTypes = offerTypes.filter(projectType => projectType.name !== 'free')
|
||||
}
|
||||
// ارسال انواع پروژه به کاربر
|
||||
res.status(200).json({ offerTypes })
|
||||
} catch (error) {
|
||||
// در صورت بروز خطا، ارسال پیام خطا به کاربر
|
||||
console.error('Error in getOfferTypes:', error)
|
||||
res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' })
|
||||
}
|
||||
}
|
||||
const getUserOffers = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const { page = 1, limit = 10, status_filter, id } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
let filter = {}
|
||||
let filterbyid = {receiver: id}
|
||||
let filterbyidsender = {sender: id}
|
||||
if (status_filter === 'درخواست') {
|
||||
filter = { sender: userId }
|
||||
} else {
|
||||
filter = { receiver: userId }
|
||||
}
|
||||
|
||||
// تنظیم گزینههای صفحهبندی
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { createdAt: -1 }, // بر اساس زمان ایجاد (createdAt) مرتب کنید (نزولی)
|
||||
populate: [
|
||||
{
|
||||
path: 'sender',
|
||||
select: 'profile_image user_level first_name last_name user_name is_verified user_score rate'
|
||||
},
|
||||
{
|
||||
path: 'receiver',
|
||||
select: 'profile_image user_level first_name last_name user_name is_verified user_score rate'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// دریافت آفرهای صفحهبندی شده
|
||||
let offer = await OfferModel.paginate(filter, options)
|
||||
let offerbyid = await OfferModel.paginate(filterbyid, options)
|
||||
let offerbyidsender = await OfferModel.paginate(filterbyidsender, options)
|
||||
|
||||
const totalPages = offer.totalPages
|
||||
const totalItems = offer.totalDocs
|
||||
|
||||
// فرمت کردن تاریخ و ارسال پاسخ
|
||||
offer = offer?.docs.map(offer => {
|
||||
const jDate = jMoment(offer.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
return {
|
||||
...offer._doc,
|
||||
createdAt: jDate
|
||||
}
|
||||
})
|
||||
res.json({
|
||||
offerbyidsender,
|
||||
offerbyid,
|
||||
offer,
|
||||
totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateOfferStatus = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id // ID کاربری که درخواست را بهروزرسانی میکند
|
||||
const reciverUser = await UserModel.findById(userId)
|
||||
|
||||
const { offerId, action } = req.body // آیدی آفر و اکشن (accept یا reject)
|
||||
|
||||
// بررسی اعتبار ورودیها
|
||||
if (!offerId || !['accept', 'reject'].includes(action)) {
|
||||
return res.status(400).json({ error: 'Invalid input' })
|
||||
}
|
||||
|
||||
// یافتن آفر موردنظر
|
||||
const offer = await OfferModel.findById(offerId)
|
||||
const senderUser = await UserModel.findById(offer?.sender)
|
||||
|
||||
if (!offer) {
|
||||
return res.status(404).json({ error: 'Offer not found' })
|
||||
}
|
||||
|
||||
// بررسی اینکه آیا کاربر گیرنده این آفر است یا خیر
|
||||
if (offer.receiver.toString() !== userId) {
|
||||
return res.status(403).json({ error: 'You are not authorized to update this offer' })
|
||||
}
|
||||
|
||||
// بررسی اینکه آیا آفر قبلاً بهروزرسانی شده یا نه
|
||||
if (offer.status !== 'pending') {
|
||||
return res.status(400).json({ error: 'Offer has already been updated', message: 'وضعیت این درخواست قبلا تغییر کرده است.' })
|
||||
}
|
||||
|
||||
// بهروزرسانی وضعیت آفر بر اساس اکشن
|
||||
offer.status = action === 'accept' ? 'accepted' : 'rejected'
|
||||
await offer.save()
|
||||
|
||||
if (action === 'accept') {
|
||||
const data = JSON.stringify({
|
||||
mobile: senderUser?.mobile,
|
||||
templateId: '633448',
|
||||
parameters: [
|
||||
{ name: 'USER', value: reciverUser?.first_name + ' ' + reciverUser?.last_name },
|
||||
{ name: 'EMPLOYER', value: senderUser?.first_name + ' ' + senderUser?.last_name }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
} else {
|
||||
const data = JSON.stringify({
|
||||
mobile: senderUser?.mobile,
|
||||
templateId: '682678',
|
||||
parameters: [
|
||||
{ name: 'USER', value: reciverUser?.first_name + ' ' + reciverUser?.last_name },
|
||||
{ name: 'EMPLOYER', value: senderUser?.first_name + ' ' + senderUser?.last_name }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
res.status(200).json({
|
||||
message: `Offer has been ${offer.status} successfully`,
|
||||
offerId: offer._id,
|
||||
status: offer.status
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// Controller function for handling successful advertising payment
|
||||
const handleSuccessfulOfferPayment = async (req, res) => {
|
||||
try {
|
||||
const { reciverId, offerType } = req.body
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// Check user's free offer eligibility
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) return res.status(404).json({ error: 'User not found' })
|
||||
// Check user's free offer eligibility
|
||||
const reciverUser = await UserModel.findById(reciverId)
|
||||
if (!user) return res.status(404).json({ error: 'User not found' })
|
||||
|
||||
let price
|
||||
if (user.monthly_free_offer > 0 && offerType === 'free') {
|
||||
// Use free offer and decrement counter
|
||||
price = 0
|
||||
user.monthly_free_offer -= 1
|
||||
await user.save()
|
||||
} else {
|
||||
// Retrieve offer price based on type
|
||||
price = await getOfferPriceFromDatabase(offerType)
|
||||
|
||||
// Create a new payment entry
|
||||
const payment = new PaymentModel({
|
||||
amount: Number(price),
|
||||
status: 'successful',
|
||||
authority: '', // Add authority if available
|
||||
user_id: userId,
|
||||
type: 'offer',
|
||||
installment_step: null
|
||||
})
|
||||
await payment.save()
|
||||
}
|
||||
// Create a new payment entry
|
||||
const payment = new PaymentModel({
|
||||
amount: Number(price),
|
||||
status: 'successful',
|
||||
authority: '', // Add authority if available
|
||||
user_id: userId,
|
||||
type: 'offer',
|
||||
installment_step: null
|
||||
})
|
||||
await payment.save()
|
||||
|
||||
// Create a new offer
|
||||
const offer = new OfferModel({
|
||||
sender: userId,
|
||||
receiver: reciverId,
|
||||
transaction_id: payment._id // Link the payment to the offer
|
||||
})
|
||||
await offer.save()
|
||||
console.log(reciverUser?.first_name)
|
||||
|
||||
// Send notification to selected user
|
||||
const notification = new NotificationModel({
|
||||
user_id: reciverId,
|
||||
project_post_id: offer?._id,
|
||||
type: 'new_offer',
|
||||
title: 'درخواست همکاری جدید',
|
||||
description: `${reciverUser?.first_name} عزیز یک درخواست همکاری برای شما در مجموعه مدستاگرام ثبت شد`
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
// Send Sms
|
||||
const data = JSON.stringify({
|
||||
mobile: reciverUser?.mobile,
|
||||
templateId: '569006',
|
||||
parameters: [
|
||||
{ name: 'FIRSTNAME', value: reciverUser?.first_name },
|
||||
{ name: 'LASTNAME', value: reciverUser?.last_name }
|
||||
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Send event based on payment status
|
||||
|
||||
// Emit a success event
|
||||
if ('eventEmitter' in req.app) {
|
||||
req.app.get('eventEmitter').emit('paymentSuccess', {
|
||||
message: 'Payment and offer created successfully',
|
||||
offerId: offer._id
|
||||
})
|
||||
} else {
|
||||
console.error('Error: eventEmitter is not defined or not properly configured.')
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
message: 'Payment and offer recorded successfully',
|
||||
offerId: offer._id,
|
||||
price
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error occurred:', error)
|
||||
res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
}
|
||||
// Controller function for handling failed advertising payment
|
||||
const handleFailedOfferPayment = async (req, res) => {
|
||||
try {
|
||||
const { offerType } = req.body
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const price = await getOfferPriceFromDatabase(offerType)
|
||||
|
||||
// Create a new payment entry
|
||||
const payment = new PaymentModel({
|
||||
amount: Number(price),
|
||||
status: 'failed',
|
||||
authority: '', // Add authority if available
|
||||
user_id: userId,
|
||||
type: 'offer',
|
||||
installment_step: null
|
||||
})
|
||||
await payment.save()
|
||||
|
||||
// Emit a failure event
|
||||
if ('eventEmitter' in req.app) {
|
||||
req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment failed' })
|
||||
} else {
|
||||
console.error('Error: eventEmitter is not defined or not properly configured.')
|
||||
}
|
||||
|
||||
res.status(200).json({ message: 'Payment failed', price })
|
||||
} catch (error) {
|
||||
console.error('Error occurred:', error)
|
||||
res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
}
|
||||
|
||||
const createOfferComment = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { offerId, comment, rate, user_id } = req.body
|
||||
if (!offerId || !comment || !rate || !user_id) {
|
||||
return res.status(400).send({ message: 'All fields are required' })
|
||||
}
|
||||
// بررسی اینکه آیا کاربر قبلاً برای این پیشنهاد نظر داده است
|
||||
const existingComment = await CommentModel.findOne({
|
||||
offer: offerId,
|
||||
creator: userId
|
||||
})
|
||||
if (existingComment) {
|
||||
return res.status(400).send({ message: 'شما قبلاً نظر خود را برای این درخواست ثبت کردهاید' })
|
||||
}
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
offer: offerId,
|
||||
creator: userId,
|
||||
rating: rate,
|
||||
comment,
|
||||
comment_for: 'user',
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
// پیدا کردن کامنتها و محاسبهی امتیاز کل
|
||||
const comments = await CommentModel.find({ user: user_id, comment_for: 'user' })
|
||||
const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0))
|
||||
|
||||
let userLevel
|
||||
if (user.expertise === 'مدل') {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
} else if (['زیبایی', 'عکاس'].includes(user.expertise)) {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
}
|
||||
|
||||
user.user_score = totalRating
|
||||
user.user_level = userLevel
|
||||
|
||||
const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' })
|
||||
const averageRating = totalRating / totalComments
|
||||
user.rate = averageRating.toFixed(1)
|
||||
await user.save()
|
||||
|
||||
res.status(200).json({ message: 'نظر شما با موفقیت ثبت شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getUserOffers,
|
||||
getOfferTypes,
|
||||
handleSuccessfulOfferPayment,
|
||||
handleFailedOfferPayment,
|
||||
updateOfferStatus,
|
||||
createOfferComment
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const jwt = require('jsonwebtoken')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const OfferModel = require('../../../models/OfferModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const OfferTypeModel = require('../../../models/OfferTypeModel')
|
||||
const PaymentModel = require('../../../models/PaymentModel')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const { default: axios } = require('axios')
|
||||
const CommentModel = require('../../../models/CommentModel')
|
||||
|
||||
const getOfferPriceFromDatabase = async (itemName) => {
|
||||
const item = await OfferTypeModel.findOne({ name: itemName })
|
||||
if (!item) {
|
||||
throw new Error('Item not found in database')
|
||||
}
|
||||
return item.price
|
||||
}
|
||||
|
||||
const getOfferTypes = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
let offerTypes = await OfferTypeModel.find({}, 'name price')
|
||||
|
||||
// بررسی برای مواردی مانند پیدا نشدن انواع پروژه
|
||||
if (!offerTypes) {
|
||||
return res.status(404).json({ message: 'انواع پروژه یافت نشد.' })
|
||||
}
|
||||
// اگر کاربر درخواست ماهانه نداشته باشد، نوع پروژه ماهانه را حذف کنید
|
||||
if (user.monthly_free_offer <= 0) {
|
||||
offerTypes = offerTypes.filter(projectType => projectType.name !== 'free')
|
||||
}
|
||||
// ارسال انواع پروژه به کاربر
|
||||
res.status(200).json({ offerTypes })
|
||||
} catch (error) {
|
||||
// در صورت بروز خطا، ارسال پیام خطا به کاربر
|
||||
console.error('Error in getOfferTypes:', error)
|
||||
res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' })
|
||||
}
|
||||
}
|
||||
const getUserOffers = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const { page = 1, limit = 10, status_filter, id } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
let filter = {}
|
||||
let filterbyid = {receiver: id}
|
||||
let filterbyidsender = {sender: id}
|
||||
if (status_filter === 'درخواست') {
|
||||
filter = { sender: userId }
|
||||
} else {
|
||||
filter = { receiver: userId }
|
||||
}
|
||||
|
||||
// تنظیم گزینههای صفحهبندی
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { createdAt: -1 }, // بر اساس زمان ایجاد (createdAt) مرتب کنید (نزولی)
|
||||
populate: [
|
||||
{
|
||||
path: 'sender',
|
||||
select: 'profile_image user_level first_name last_name user_name is_verified user_score rate'
|
||||
},
|
||||
{
|
||||
path: 'receiver',
|
||||
select: 'profile_image user_level first_name last_name user_name is_verified user_score rate'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
// دریافت آفرهای صفحهبندی شده
|
||||
let offer = await OfferModel.paginate(filter, options)
|
||||
let offerbyid = await OfferModel.paginate(filterbyid, options)
|
||||
let offerbyidsender = await OfferModel.paginate(filterbyidsender, options)
|
||||
|
||||
const totalPages = offer.totalPages
|
||||
const totalItems = offer.totalDocs
|
||||
|
||||
// فرمت کردن تاریخ و ارسال پاسخ
|
||||
offer = offer?.docs.map(offer => {
|
||||
const jDate = jMoment(offer.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
return {
|
||||
...offer._doc,
|
||||
createdAt: jDate
|
||||
}
|
||||
})
|
||||
res.json({
|
||||
offerbyidsender,
|
||||
offerbyid,
|
||||
offer,
|
||||
totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateOfferStatus = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id // ID کاربری که درخواست را بهروزرسانی میکند
|
||||
const reciverUser = await UserModel.findById(userId)
|
||||
|
||||
const { offerId, action } = req.body // آیدی آفر و اکشن (accept یا reject)
|
||||
|
||||
// بررسی اعتبار ورودیها
|
||||
if (!offerId || !['accept', 'reject'].includes(action)) {
|
||||
return res.status(400).json({ error: 'Invalid input' })
|
||||
}
|
||||
|
||||
// یافتن آفر موردنظر
|
||||
const offer = await OfferModel.findById(offerId)
|
||||
const senderUser = await UserModel.findById(offer?.sender)
|
||||
|
||||
if (!offer) {
|
||||
return res.status(404).json({ error: 'Offer not found' })
|
||||
}
|
||||
|
||||
// بررسی اینکه آیا کاربر گیرنده این آفر است یا خیر
|
||||
if (offer.receiver.toString() !== userId) {
|
||||
return res.status(403).json({ error: 'You are not authorized to update this offer' })
|
||||
}
|
||||
|
||||
// بررسی اینکه آیا آفر قبلاً بهروزرسانی شده یا نه
|
||||
if (offer.status !== 'pending') {
|
||||
return res.status(400).json({ error: 'Offer has already been updated', message: 'وضعیت این درخواست قبلا تغییر کرده است.' })
|
||||
}
|
||||
|
||||
// بهروزرسانی وضعیت آفر بر اساس اکشن
|
||||
offer.status = action === 'accept' ? 'accepted' : 'rejected'
|
||||
await offer.save()
|
||||
|
||||
if (action === 'accept') {
|
||||
const data = JSON.stringify({
|
||||
mobile: senderUser?.mobile,
|
||||
templateId: '633448',
|
||||
parameters: [
|
||||
{ name: 'USER', value: reciverUser?.first_name + ' ' + reciverUser?.last_name },
|
||||
{ name: 'EMPLOYER', value: senderUser?.first_name + ' ' + senderUser?.last_name }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
} else {
|
||||
const data = JSON.stringify({
|
||||
mobile: senderUser?.mobile,
|
||||
templateId: '682678',
|
||||
parameters: [
|
||||
{ name: 'USER', value: reciverUser?.first_name + ' ' + reciverUser?.last_name },
|
||||
{ name: 'EMPLOYER', value: senderUser?.first_name + ' ' + senderUser?.last_name }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
}
|
||||
res.status(200).json({
|
||||
message: `Offer has been ${offer.status} successfully`,
|
||||
offerId: offer._id,
|
||||
status: offer.status
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// Controller function for handling successful advertising payment
|
||||
const handleSuccessfulOfferPayment = async (req, res) => {
|
||||
try {
|
||||
const { reciverId, offerType } = req.body
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// Check user's free offer eligibility
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) return res.status(404).json({ error: 'User not found' })
|
||||
// Check user's free offer eligibility
|
||||
const reciverUser = await UserModel.findById(reciverId)
|
||||
if (!user) return res.status(404).json({ error: 'User not found' })
|
||||
|
||||
let price
|
||||
if (user.monthly_free_offer > 0 && offerType === 'free') {
|
||||
// Use free offer and decrement counter
|
||||
price = 0
|
||||
user.monthly_free_offer -= 1
|
||||
await user.save()
|
||||
} else {
|
||||
// Retrieve offer price based on type
|
||||
price = await getOfferPriceFromDatabase(offerType)
|
||||
|
||||
// Create a new payment entry
|
||||
const payment = new PaymentModel({
|
||||
amount: Number(price),
|
||||
status: 'successful',
|
||||
authority: '', // Add authority if available
|
||||
user_id: userId,
|
||||
type: 'offer',
|
||||
installment_step: null
|
||||
})
|
||||
await payment.save()
|
||||
}
|
||||
// Create a new payment entry
|
||||
const payment = new PaymentModel({
|
||||
amount: Number(price),
|
||||
status: 'successful',
|
||||
authority: '', // Add authority if available
|
||||
user_id: userId,
|
||||
type: 'offer',
|
||||
installment_step: null
|
||||
})
|
||||
await payment.save()
|
||||
|
||||
// Create a new offer
|
||||
const offer = new OfferModel({
|
||||
sender: userId,
|
||||
receiver: reciverId,
|
||||
transaction_id: payment._id // Link the payment to the offer
|
||||
})
|
||||
await offer.save()
|
||||
console.log(reciverUser?.first_name)
|
||||
|
||||
// Send notification to selected user
|
||||
const notification = new NotificationModel({
|
||||
user_id: reciverId,
|
||||
project_post_id: offer?._id,
|
||||
type: 'new_offer',
|
||||
title: 'درخواست همکاری جدید',
|
||||
description: `${reciverUser?.first_name} عزیز یک درخواست همکاری برای شما در مجموعه مدستاگرام ثبت شد`
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
// Send Sms
|
||||
const data = JSON.stringify({
|
||||
mobile: reciverUser?.mobile,
|
||||
templateId: '569006',
|
||||
parameters: [
|
||||
{ name: 'FIRSTNAME', value: reciverUser?.first_name },
|
||||
{ name: 'LASTNAME', value: reciverUser?.last_name }
|
||||
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// Send event based on payment status
|
||||
|
||||
// Emit a success event
|
||||
if ('eventEmitter' in req.app) {
|
||||
req.app.get('eventEmitter').emit('paymentSuccess', {
|
||||
message: 'Payment and offer created successfully',
|
||||
offerId: offer._id
|
||||
})
|
||||
} else {
|
||||
console.error('Error: eventEmitter is not defined or not properly configured.')
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
message: 'Payment and offer recorded successfully',
|
||||
offerId: offer._id,
|
||||
price
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Error occurred:', error)
|
||||
res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
}
|
||||
// Controller function for handling failed advertising payment
|
||||
const handleFailedOfferPayment = async (req, res) => {
|
||||
try {
|
||||
const { offerType } = req.body
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const price = await getOfferPriceFromDatabase(offerType)
|
||||
|
||||
// Create a new payment entry
|
||||
const payment = new PaymentModel({
|
||||
amount: Number(price),
|
||||
status: 'failed',
|
||||
authority: '', // Add authority if available
|
||||
user_id: userId,
|
||||
type: 'offer',
|
||||
installment_step: null
|
||||
})
|
||||
await payment.save()
|
||||
|
||||
// Emit a failure event
|
||||
if ('eventEmitter' in req.app) {
|
||||
req.app.get('eventEmitter').emit('paymentFailed', { message: 'Payment failed' })
|
||||
} else {
|
||||
console.error('Error: eventEmitter is not defined or not properly configured.')
|
||||
}
|
||||
|
||||
res.status(200).json({ message: 'Payment failed', price })
|
||||
} catch (error) {
|
||||
console.error('Error occurred:', error)
|
||||
res.status(500).json({ error: 'Internal server error' })
|
||||
}
|
||||
}
|
||||
|
||||
const createOfferComment = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { offerId, comment, rate, user_id } = req.body
|
||||
if (!offerId || !comment || !rate || !user_id) {
|
||||
return res.status(400).send({ message: 'All fields are required' })
|
||||
}
|
||||
// بررسی اینکه آیا کاربر قبلاً برای این پیشنهاد نظر داده است
|
||||
const existingComment = await CommentModel.findOne({
|
||||
offer: offerId,
|
||||
creator: userId
|
||||
})
|
||||
if (existingComment) {
|
||||
return res.status(400).send({ message: 'شما قبلاً نظر خود را برای این درخواست ثبت کردهاید' })
|
||||
}
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
offer: offerId,
|
||||
creator: userId,
|
||||
rating: rate,
|
||||
comment,
|
||||
comment_for: 'user',
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
// پیدا کردن کامنتها و محاسبهی امتیاز کل
|
||||
const comments = await CommentModel.find({ user: user_id, comment_for: 'user' })
|
||||
const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0))
|
||||
|
||||
let userLevel
|
||||
if (user.expertise === 'مدل') {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
} else if (['زیبایی', 'عکاس'].includes(user.expertise)) {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
}
|
||||
|
||||
user.user_score = totalRating
|
||||
user.user_level = userLevel
|
||||
|
||||
const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' })
|
||||
const averageRating = totalRating / totalComments
|
||||
user.rate = averageRating.toFixed(1)
|
||||
await user.save()
|
||||
|
||||
res.status(200).json({ message: 'نظر شما با موفقیت ثبت شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getUserOffers,
|
||||
getOfferTypes,
|
||||
handleSuccessfulOfferPayment,
|
||||
handleFailedOfferPayment,
|
||||
updateOfferStatus,
|
||||
createOfferComment
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,64 +1,64 @@
|
||||
/* eslint-disable camelcase */
|
||||
const PostModel = require('../../../models/PostModel');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const UserModel = require('../../../models/UserModel');
|
||||
const LikeModel = require('../../../models/LikeModel');
|
||||
|
||||
const toggleLike = async (req, res, next) => {
|
||||
try {
|
||||
const { postId } = req.body;
|
||||
const token = req.header('Authorization')?.split(' ')[1];
|
||||
|
||||
if (!token) {
|
||||
return res.status(401).json({ message: 'توکن ارائه نشده است' });
|
||||
}
|
||||
|
||||
let userId;
|
||||
try {
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET);
|
||||
userId = decodedToken.id;
|
||||
} catch (err) {
|
||||
return res.status(401).json({ message: 'توکن نامعتبر است' });
|
||||
}
|
||||
|
||||
if (!postId) {
|
||||
return res.status(400).json({ message: 'شناسه پست الزامی است' });
|
||||
}
|
||||
|
||||
const post = await PostModel.findById(postId);
|
||||
if (!post) {
|
||||
return res.status(404).json({ message: 'پست مورد نظر یافت نشد' });
|
||||
}
|
||||
|
||||
const isLiked = post.likes.includes(userId);
|
||||
if (isLiked) {
|
||||
// unlike
|
||||
post.likes.pull(userId);
|
||||
await post.save();
|
||||
await LikeModel.findOneAndDelete({ postId, userId });
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'لایک با موفقیت حذف شد',
|
||||
is_liked: false,
|
||||
likesCount: post.likes.length,
|
||||
});
|
||||
} else {
|
||||
// like
|
||||
post.likes.push(userId);
|
||||
await post.save();
|
||||
await LikeModel.create({ postId, userId });
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'پست با موفقیت لایک شد',
|
||||
is_liked: true,
|
||||
likesCount: post.likes.length,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('خطا در toggleLike:', error);
|
||||
res.status(500).json({ message: 'خطا در سرور' });
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
const PostModel = require('../../../models/PostModel');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const UserModel = require('../../../models/UserModel');
|
||||
const LikeModel = require('../../../models/LikeModel');
|
||||
|
||||
const toggleLike = async (req, res, next) => {
|
||||
try {
|
||||
const { postId } = req.body;
|
||||
const token = req.header('Authorization')?.split(' ')[1];
|
||||
|
||||
if (!token) {
|
||||
return res.status(401).json({ message: 'توکن ارائه نشده است' });
|
||||
}
|
||||
|
||||
let userId;
|
||||
try {
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET);
|
||||
userId = decodedToken.id;
|
||||
} catch (err) {
|
||||
return res.status(401).json({ message: 'توکن نامعتبر است' });
|
||||
}
|
||||
|
||||
if (!postId) {
|
||||
return res.status(400).json({ message: 'شناسه پست الزامی است' });
|
||||
}
|
||||
|
||||
const post = await PostModel.findById(postId);
|
||||
if (!post) {
|
||||
return res.status(404).json({ message: 'پست مورد نظر یافت نشد' });
|
||||
}
|
||||
|
||||
const isLiked = post.likes.includes(userId);
|
||||
if (isLiked) {
|
||||
// unlike
|
||||
post.likes.pull(userId);
|
||||
await post.save();
|
||||
await LikeModel.findOneAndDelete({ postId, userId });
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'لایک با موفقیت حذف شد',
|
||||
is_liked: false,
|
||||
likesCount: post.likes.length,
|
||||
});
|
||||
} else {
|
||||
// like
|
||||
post.likes.push(userId);
|
||||
await post.save();
|
||||
await LikeModel.create({ postId, userId });
|
||||
|
||||
return res.status(200).json({
|
||||
message: 'پست با موفقیت لایک شد',
|
||||
is_liked: true,
|
||||
likesCount: post.likes.length,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('خطا در toggleLike:', error);
|
||||
res.status(500).json({ message: 'خطا در سرور' });
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { toggleLike };
|
||||
@@ -1,182 +1,182 @@
|
||||
/* eslint-disable camelcase */
|
||||
const PostModel = require('../../../models/PostModel');
|
||||
const UserModel = require('../../../models/UserModel');
|
||||
const { check, validationResult } = require('express-validator');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const path = require('path');
|
||||
const { default: mongoose } = require('mongoose');
|
||||
|
||||
const createPostValidationRules = () => {
|
||||
console.log(4);
|
||||
return [
|
||||
check('caption')
|
||||
.notEmpty().withMessage('توضیحات نمیتواند خالی باشد'),
|
||||
];
|
||||
};
|
||||
|
||||
const createPost = async (req, res) => {
|
||||
try {
|
||||
console.log('DEBUG: createPost called');
|
||||
console.log('DEBUG: req.files:', req.files);
|
||||
console.log('DEBUG: req.body:', req.body);
|
||||
|
||||
const { caption } = req.body;
|
||||
const files = req.files || [];
|
||||
const userId = req.user.id; // از میدلویر auth
|
||||
|
||||
if (!files || files.length === 0) {
|
||||
console.log('DEBUG: No files provided');
|
||||
return res.status(400).json({ error: true, message: 'هیچ فایلی آپلود نشده است' });
|
||||
}
|
||||
|
||||
if (!caption) {
|
||||
console.log('DEBUG: No caption provided');
|
||||
return res.status(400).json({ error: true, message: 'کپشن الزامی است' });
|
||||
}
|
||||
|
||||
const filePaths = files.map((file) => ({
|
||||
path: file.path,
|
||||
type: file.mimetype.startsWith('video/') ? 'video' : 'image',
|
||||
}));
|
||||
|
||||
console.log('DEBUG: Saving post to MongoDB, filePaths:', filePaths);
|
||||
const post = new PostModel({
|
||||
user_id: userId,
|
||||
caption,
|
||||
files: filePaths,
|
||||
type: files[0].mimetype.startsWith('video/') ? 'video' : 'image', // اضافه کردن فیلد type
|
||||
createdAt: new Date(),
|
||||
});
|
||||
|
||||
await post.save();
|
||||
console.log('DEBUG: Post saved:', post._id);
|
||||
res.status(201).json({ message: 'پست با موفقیت ایجاد شد', postId: post._id });
|
||||
} catch (err) {
|
||||
console.error('DEBUG: createPost error:', err.message);
|
||||
res.status(500).json({ error: true, message: `خطا در سرور: ${err.message}` });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const getUserPosts = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const user_id = req.query.user_id
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userReqId = decodedToken.id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(user_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
|
||||
}
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
const response = {}
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
if (user_id.toString() === userReqId.toString()) {
|
||||
// کاربر خودش است، همه پستهایش را بررسی میکند
|
||||
const posts = await PostModel.paginate(
|
||||
{ user_id: user._id, status: { $in: ['pending', 'accept'] } }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
response.posts = posts.docs
|
||||
response.postsCount = posts.totalDocs
|
||||
response.totalPages = posts.totalPages // ارسال تعداد کل صفحات
|
||||
response.totalItems = posts.totalDocs
|
||||
} else {
|
||||
// دیگران، فقط پستهایی که وضعیتشان "accept" است را ببینند
|
||||
const posts = await PostModel.paginate(
|
||||
{ user_id: user._id, status: 'accept' }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
response.posts = posts.docs
|
||||
response.postsCount = posts.totalDocs
|
||||
response.totalPages = posts.totalPages // ارسال تعداد کل صفحات
|
||||
response.totalItems = posts.totalDocs
|
||||
}
|
||||
return res.status(200).json({ data: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getUserPostsWeb = async (req, res, next) => {
|
||||
try {
|
||||
let userReqId = null
|
||||
|
||||
// دریافت توکن و بررسی معتبر بودنش (اگر وجود داشت)
|
||||
const authHeader = req.header('Authorization')
|
||||
if (authHeader) {
|
||||
const token = authHeader.split(' ')[1]
|
||||
try {
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
userReqId = decodedToken.id
|
||||
} catch (err) {
|
||||
console.warn('توکن نامعتبر است، ادامه بدون احراز هویت') // فقط هشدار، نه ارور
|
||||
}
|
||||
}
|
||||
|
||||
const user_id = req.query.user_id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(user_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
const data = {}
|
||||
const options = {
|
||||
page: req.query.page || 1,
|
||||
limit: req.query.limit || 10,
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
if (userReqId && user_id.toString() === userReqId.toString()) {
|
||||
// اگر کاربر لاگین کرده و درخواست برای خودش است، همه پستهایش را ببیند
|
||||
const posts = await PostModel.paginate(
|
||||
{ user_id: user._id, status: { $in: ['pending', 'accept'] } },
|
||||
options
|
||||
)
|
||||
data.posts = posts.docs
|
||||
data.postsCount = posts.totalDocs
|
||||
data.totalPages = posts.totalPages
|
||||
data.totalItems = posts.totalDocs
|
||||
} else {
|
||||
// برای بقیه، فقط پستهایی که وضعیتشان "accept" است نمایش داده شود
|
||||
const posts = await PostModel.paginate(
|
||||
{ user_id: user._id, status: 'accept' },
|
||||
options
|
||||
)
|
||||
data.posts = posts.docs
|
||||
data.postsCount = posts.totalDocs
|
||||
data.totalPages = posts.totalPages
|
||||
data.totalItems = posts.totalDocs
|
||||
}
|
||||
|
||||
return res.status(200).json(data)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createPostValidationRules,
|
||||
createPost,
|
||||
getUserPosts,
|
||||
getUserPostsWeb
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const PostModel = require('../../../models/PostModel');
|
||||
const UserModel = require('../../../models/UserModel');
|
||||
const { check, validationResult } = require('express-validator');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const path = require('path');
|
||||
const { default: mongoose } = require('mongoose');
|
||||
|
||||
const createPostValidationRules = () => {
|
||||
console.log(4);
|
||||
return [
|
||||
check('caption')
|
||||
.notEmpty().withMessage('توضیحات نمیتواند خالی باشد'),
|
||||
];
|
||||
};
|
||||
|
||||
const createPost = async (req, res) => {
|
||||
try {
|
||||
console.log('DEBUG: createPost called');
|
||||
console.log('DEBUG: req.files:', req.files);
|
||||
console.log('DEBUG: req.body:', req.body);
|
||||
|
||||
const { caption } = req.body;
|
||||
const files = req.files || [];
|
||||
const userId = req.user.id; // از میدلویر auth
|
||||
|
||||
if (!files || files.length === 0) {
|
||||
console.log('DEBUG: No files provided');
|
||||
return res.status(400).json({ error: true, message: 'هیچ فایلی آپلود نشده است' });
|
||||
}
|
||||
|
||||
if (!caption) {
|
||||
console.log('DEBUG: No caption provided');
|
||||
return res.status(400).json({ error: true, message: 'کپشن الزامی است' });
|
||||
}
|
||||
|
||||
const filePaths = files.map((file) => ({
|
||||
path: file.path,
|
||||
type: file.mimetype.startsWith('video/') ? 'video' : 'image',
|
||||
}));
|
||||
|
||||
console.log('DEBUG: Saving post to MongoDB, filePaths:', filePaths);
|
||||
const post = new PostModel({
|
||||
user_id: userId,
|
||||
caption,
|
||||
files: filePaths,
|
||||
type: files[0].mimetype.startsWith('video/') ? 'video' : 'image', // اضافه کردن فیلد type
|
||||
createdAt: new Date(),
|
||||
});
|
||||
|
||||
await post.save();
|
||||
console.log('DEBUG: Post saved:', post._id);
|
||||
res.status(201).json({ message: 'پست با موفقیت ایجاد شد', postId: post._id });
|
||||
} catch (err) {
|
||||
console.error('DEBUG: createPost error:', err.message);
|
||||
res.status(500).json({ error: true, message: `خطا در سرور: ${err.message}` });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const getUserPosts = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const user_id = req.query.user_id
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userReqId = decodedToken.id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(user_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
|
||||
}
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
const response = {}
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
if (user_id.toString() === userReqId.toString()) {
|
||||
// کاربر خودش است، همه پستهایش را بررسی میکند
|
||||
const posts = await PostModel.paginate(
|
||||
{ user_id: user._id, status: { $in: ['pending', 'accept'] } }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
response.posts = posts.docs
|
||||
response.postsCount = posts.totalDocs
|
||||
response.totalPages = posts.totalPages // ارسال تعداد کل صفحات
|
||||
response.totalItems = posts.totalDocs
|
||||
} else {
|
||||
// دیگران، فقط پستهایی که وضعیتشان "accept" است را ببینند
|
||||
const posts = await PostModel.paginate(
|
||||
{ user_id: user._id, status: 'accept' }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
response.posts = posts.docs
|
||||
response.postsCount = posts.totalDocs
|
||||
response.totalPages = posts.totalPages // ارسال تعداد کل صفحات
|
||||
response.totalItems = posts.totalDocs
|
||||
}
|
||||
return res.status(200).json({ data: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getUserPostsWeb = async (req, res, next) => {
|
||||
try {
|
||||
let userReqId = null
|
||||
|
||||
// دریافت توکن و بررسی معتبر بودنش (اگر وجود داشت)
|
||||
const authHeader = req.header('Authorization')
|
||||
if (authHeader) {
|
||||
const token = authHeader.split(' ')[1]
|
||||
try {
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
userReqId = decodedToken.id
|
||||
} catch (err) {
|
||||
console.warn('توکن نامعتبر است، ادامه بدون احراز هویت') // فقط هشدار، نه ارور
|
||||
}
|
||||
}
|
||||
|
||||
const user_id = req.query.user_id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(user_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
const data = {}
|
||||
const options = {
|
||||
page: req.query.page || 1,
|
||||
limit: req.query.limit || 10,
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
if (userReqId && user_id.toString() === userReqId.toString()) {
|
||||
// اگر کاربر لاگین کرده و درخواست برای خودش است، همه پستهایش را ببیند
|
||||
const posts = await PostModel.paginate(
|
||||
{ user_id: user._id, status: { $in: ['pending', 'accept'] } },
|
||||
options
|
||||
)
|
||||
data.posts = posts.docs
|
||||
data.postsCount = posts.totalDocs
|
||||
data.totalPages = posts.totalPages
|
||||
data.totalItems = posts.totalDocs
|
||||
} else {
|
||||
// برای بقیه، فقط پستهایی که وضعیتشان "accept" است نمایش داده شود
|
||||
const posts = await PostModel.paginate(
|
||||
{ user_id: user._id, status: 'accept' },
|
||||
options
|
||||
)
|
||||
data.posts = posts.docs
|
||||
data.postsCount = posts.totalDocs
|
||||
data.totalPages = posts.totalPages
|
||||
data.totalItems = posts.totalDocs
|
||||
}
|
||||
|
||||
return res.status(200).json(data)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createPostValidationRules,
|
||||
createPost,
|
||||
getUserPosts,
|
||||
getUserPostsWeb
|
||||
}
|
||||
|
||||
@@ -1,139 +1,139 @@
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
|
||||
// GET user by ID from URL
|
||||
const getUserById = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.params.id; // گرفتن آیدی از پارامتر URL
|
||||
const service = req.query.services;
|
||||
|
||||
const user = await UserModel.findById(userId);
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: "کاربر مورد نظر یافت نشد" });
|
||||
}
|
||||
|
||||
let isRegister = true;
|
||||
// if (
|
||||
// !user.user_name ||
|
||||
// !user.first_name ||
|
||||
// !user.last_name ||
|
||||
// !user.user_type ||
|
||||
// !user.national_card_image ||
|
||||
// !user.password ||
|
||||
// !user.national_code
|
||||
// ) {
|
||||
// isRegister = false;
|
||||
// }
|
||||
|
||||
const response = {
|
||||
_id: user._id,
|
||||
user_type: user.user_type,
|
||||
user_level: user.user_level,
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
user_name: user.user_name,
|
||||
show_location: user.show_location,
|
||||
is_verified: user.is_verified,
|
||||
user_score: user.user_score,
|
||||
rate: user.rate,
|
||||
bio: user.bio,
|
||||
height: user.height,
|
||||
weight: user.weight,
|
||||
size: user.size,
|
||||
eye_color: user.eye_color,
|
||||
hair_color: user.hair_color,
|
||||
profile_image: user.profile_image,
|
||||
lat: user.lat,
|
||||
lng: user.lng,
|
||||
address: user.address,
|
||||
province: user.province,
|
||||
city: user.city,
|
||||
shaba: user.shaba,
|
||||
national_code: user.national_code,
|
||||
mobile: user.mobile,
|
||||
cooperation_abroad: user.cooperation_abroad,
|
||||
cooperation_type: user.cooperation_type,
|
||||
conversation_projects: user.conversation_projects,
|
||||
expertise: user.expertise,
|
||||
sub_expertise: user.sub_expertise,
|
||||
isRegister,
|
||||
user,
|
||||
services: service === "1" ? user.services : null
|
||||
};
|
||||
|
||||
return res.status(200).json({ user: response });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
const getProfile = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const service = req.query.services
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const user = await UserModel.findById(userId)
|
||||
let isRegister = true
|
||||
if (!user.user_name ||
|
||||
!user.first_name ||
|
||||
!user.last_name ||
|
||||
!user.user_type ||
|
||||
!user.national_card_image ||
|
||||
!user.password ||
|
||||
!user.national_code
|
||||
) {
|
||||
isRegister = false
|
||||
}
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
const response = {
|
||||
_id: user._id,
|
||||
user_type: user.user_type,
|
||||
user_level: user.user_level,
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
user_name: user.user_name,
|
||||
show_location: user.show_location,
|
||||
is_verified: user.is_verified,
|
||||
is_Register: user.is_Register,
|
||||
user_score: user.user_score,
|
||||
rate: user.rate,
|
||||
bio: user.bio,
|
||||
height: user.height,
|
||||
weight: user.weight,
|
||||
size: user.size,
|
||||
eye_color: user.eye_color,
|
||||
hair_color: user.hair_color,
|
||||
profile_image: user.profile_image,
|
||||
lat: user.lat,
|
||||
lng: user.lng,
|
||||
address: user.address,
|
||||
province: user.province,
|
||||
city: user.city,
|
||||
shaba: user.shaba,
|
||||
national_code: user.national_code,
|
||||
mobile: user.mobile,
|
||||
cooperation_abroad: user.cooperation_abroad,
|
||||
cooperation_type: user.cooperation_type,
|
||||
conversation_projects: user.conversation_projects,
|
||||
expertise: user.expertise,
|
||||
sub_expertise: user.sub_expertise,
|
||||
isRegister,
|
||||
services: service === '1' ? user.services : null
|
||||
}
|
||||
return res.status(200).json({ user: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getProfile,
|
||||
getUserById
|
||||
};
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
|
||||
// GET user by ID from URL
|
||||
const getUserById = async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.params.id; // گرفتن آیدی از پارامتر URL
|
||||
const service = req.query.services;
|
||||
|
||||
const user = await UserModel.findById(userId);
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: "کاربر مورد نظر یافت نشد" });
|
||||
}
|
||||
|
||||
let isRegister = true;
|
||||
// if (
|
||||
// !user.user_name ||
|
||||
// !user.first_name ||
|
||||
// !user.last_name ||
|
||||
// !user.user_type ||
|
||||
// !user.national_card_image ||
|
||||
// !user.password ||
|
||||
// !user.national_code
|
||||
// ) {
|
||||
// isRegister = false;
|
||||
// }
|
||||
|
||||
const response = {
|
||||
_id: user._id,
|
||||
user_type: user.user_type,
|
||||
user_level: user.user_level,
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
user_name: user.user_name,
|
||||
show_location: user.show_location,
|
||||
is_verified: user.is_verified,
|
||||
user_score: user.user_score,
|
||||
rate: user.rate,
|
||||
bio: user.bio,
|
||||
height: user.height,
|
||||
weight: user.weight,
|
||||
size: user.size,
|
||||
eye_color: user.eye_color,
|
||||
hair_color: user.hair_color,
|
||||
profile_image: user.profile_image,
|
||||
lat: user.lat,
|
||||
lng: user.lng,
|
||||
address: user.address,
|
||||
province: user.province,
|
||||
city: user.city,
|
||||
shaba: user.shaba,
|
||||
national_code: user.national_code,
|
||||
mobile: user.mobile,
|
||||
cooperation_abroad: user.cooperation_abroad,
|
||||
cooperation_type: user.cooperation_type,
|
||||
conversation_projects: user.conversation_projects,
|
||||
expertise: user.expertise,
|
||||
sub_expertise: user.sub_expertise,
|
||||
isRegister,
|
||||
user,
|
||||
services: service === "1" ? user.services : null
|
||||
};
|
||||
|
||||
return res.status(200).json({ user: response });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
const getProfile = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const service = req.query.services
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const user = await UserModel.findById(userId)
|
||||
let isRegister = true
|
||||
if (!user.user_name ||
|
||||
!user.first_name ||
|
||||
!user.last_name ||
|
||||
!user.user_type ||
|
||||
!user.national_card_image ||
|
||||
!user.password ||
|
||||
!user.national_code
|
||||
) {
|
||||
isRegister = false
|
||||
}
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
const response = {
|
||||
_id: user._id,
|
||||
user_type: user.user_type,
|
||||
user_level: user.user_level,
|
||||
first_name: user.first_name,
|
||||
last_name: user.last_name,
|
||||
user_name: user.user_name,
|
||||
show_location: user.show_location,
|
||||
is_verified: user.is_verified,
|
||||
is_Register: user.is_Register,
|
||||
user_score: user.user_score,
|
||||
rate: user.rate,
|
||||
bio: user.bio,
|
||||
height: user.height,
|
||||
weight: user.weight,
|
||||
size: user.size,
|
||||
eye_color: user.eye_color,
|
||||
hair_color: user.hair_color,
|
||||
profile_image: user.profile_image,
|
||||
lat: user.lat,
|
||||
lng: user.lng,
|
||||
address: user.address,
|
||||
province: user.province,
|
||||
city: user.city,
|
||||
shaba: user.shaba,
|
||||
national_code: user.national_code,
|
||||
mobile: user.mobile,
|
||||
cooperation_abroad: user.cooperation_abroad,
|
||||
cooperation_type: user.cooperation_type,
|
||||
conversation_projects: user.conversation_projects,
|
||||
expertise: user.expertise,
|
||||
sub_expertise: user.sub_expertise,
|
||||
isRegister,
|
||||
services: service === '1' ? user.services : null
|
||||
}
|
||||
return res.status(200).json({ user: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getProfile,
|
||||
getUserById
|
||||
};
|
||||
|
||||
@@ -1,220 +1,220 @@
|
||||
/* eslint-disable camelcase */
|
||||
const { ProvinceModel, CityModel } = require('../../../models/StateCity')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const createProjectValidationRules = () => {
|
||||
return [
|
||||
check('title').notEmpty().withMessage('عنوان نمیتواند خالی باشد'),
|
||||
|
||||
check('expertise').notEmpty().withMessage('تخصص نمیتواند خالی باشد'),
|
||||
|
||||
check('gender')
|
||||
.isIn(['male', 'female'])
|
||||
.withMessage('جنسیت باید male یا female باشد'),
|
||||
|
||||
check('age').notEmpty().withMessage('سن نمیتواند خالی باشد'),
|
||||
|
||||
check('conversation_projects')
|
||||
.notEmpty()
|
||||
.withMessage('پروژههای مکالمه نمیتواند خالی باشد')
|
||||
.isBoolean()
|
||||
.withMessage('مقدار پروژههای مکالمه باید یک مقدار boolean باشد'),
|
||||
|
||||
check('province').notEmpty().withMessage('استان نمیتواند خالی باشد'),
|
||||
|
||||
check('city').notEmpty().withMessage('شهر نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_time')
|
||||
.notEmpty()
|
||||
.withMessage('زمان پروژه نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_price')
|
||||
.notEmpty()
|
||||
.withMessage('قیمت پیشنهادی نمیتواند خالی باشد'),
|
||||
|
||||
check('description')
|
||||
.notEmpty()
|
||||
.withMessage('توضیحات نمیتواند خالی باشد'),
|
||||
|
||||
check('project_type')
|
||||
.notEmpty()
|
||||
.withMessage('نوع پروژه نمیتواند خالی باشد')
|
||||
.isIn(['free', 'normal', 'force', 'highlight'])
|
||||
.withMessage('نوع پروژه باید normal یا force یا highlight باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const createProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
if (user.is_verified !== 'verified') {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'مدارک شما تایید نشده است'
|
||||
})
|
||||
}
|
||||
// اعتبارسنجی درخواست
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const {
|
||||
title,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province,
|
||||
city,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
project_type,
|
||||
public_status,
|
||||
created_for_user,
|
||||
number_of_person
|
||||
} = req.body
|
||||
if (
|
||||
!title ||
|
||||
!expertise ||
|
||||
!age ||
|
||||
conversation_projects === null ||
|
||||
!province ||
|
||||
!city ||
|
||||
!offer_time ||
|
||||
!offer_price ||
|
||||
!description ||
|
||||
!project_type
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const provinceFind = await ProvinceModel.findOne(
|
||||
{ id: province },
|
||||
{ _id: 0 }
|
||||
)
|
||||
const cityFind = await CityModel.findOne({ id: city })
|
||||
// اگر پروژه برای یک کاربر خاص باید ساخته شود
|
||||
if (public_status && public_status === 'private' && created_for_user) {
|
||||
const createdUser = await UserModel.findById(created_for_user)
|
||||
if (!createdUser) {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'کاربر مورد نظر برای ساخت پروژه یافت نشد'
|
||||
})
|
||||
}
|
||||
// ایجاد شیء پروژه
|
||||
const projectData = {
|
||||
title,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province,
|
||||
city,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
project_type,
|
||||
creator_id: user._id, // ارتباط با کاربر
|
||||
public_status,
|
||||
created_for_user
|
||||
}
|
||||
|
||||
// ساخت شیء پروژه
|
||||
const project = new ProjectModel(projectData)
|
||||
|
||||
// ذخیره کردن رکورد در پایگاه داده
|
||||
await project.save()
|
||||
|
||||
res.status(201).json({ message: 'پروژه با موفقیت ساخته شد', id: project._id }
|
||||
)
|
||||
} else {
|
||||
if (number_of_person > 1) {
|
||||
for (let i = 1; i <= number_of_person; i++) {
|
||||
let currentProjectType
|
||||
|
||||
if (project_type === 'free' && i === 1) {
|
||||
currentProjectType = 'free'
|
||||
} else if (project_type === 'highlight' || project_type === 'force') {
|
||||
currentProjectType = project_type
|
||||
} else {
|
||||
currentProjectType = 'normal'
|
||||
}
|
||||
|
||||
const newProject = new ProjectModel({
|
||||
title: `${title}_${i}`,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province: provinceFind,
|
||||
city: cityFind,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
creator_id: user._id, // ارتباط با کاربر
|
||||
project_type: currentProjectType,
|
||||
public_status,
|
||||
created_for_user
|
||||
})
|
||||
|
||||
// ذخیره کردن رکورد در پایگاه داده
|
||||
await newProject.save()
|
||||
}
|
||||
|
||||
res.status(201).json({
|
||||
message: 'پروژهها با موفقیت ساخته شدند'
|
||||
})
|
||||
} else {
|
||||
const project = new ProjectModel({
|
||||
title,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province: provinceFind,
|
||||
city: cityFind,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
creator_id: user._id, // ارتباط با کاربر
|
||||
project_type
|
||||
})
|
||||
|
||||
// ذخیره کردن رکورد در پایگاه داده
|
||||
await project.save()
|
||||
|
||||
res.status(201).json({
|
||||
message: 'پروژه با موفقیت ساخته شد',
|
||||
id: project._id
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createProjectValidationRules,
|
||||
createProject
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const { ProvinceModel, CityModel } = require('../../../models/StateCity')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const createProjectValidationRules = () => {
|
||||
return [
|
||||
check('title').notEmpty().withMessage('عنوان نمیتواند خالی باشد'),
|
||||
|
||||
check('expertise').notEmpty().withMessage('تخصص نمیتواند خالی باشد'),
|
||||
|
||||
check('gender')
|
||||
.isIn(['male', 'female'])
|
||||
.withMessage('جنسیت باید male یا female باشد'),
|
||||
|
||||
check('age').notEmpty().withMessage('سن نمیتواند خالی باشد'),
|
||||
|
||||
check('conversation_projects')
|
||||
.notEmpty()
|
||||
.withMessage('پروژههای مکالمه نمیتواند خالی باشد')
|
||||
.isBoolean()
|
||||
.withMessage('مقدار پروژههای مکالمه باید یک مقدار boolean باشد'),
|
||||
|
||||
check('province').notEmpty().withMessage('استان نمیتواند خالی باشد'),
|
||||
|
||||
check('city').notEmpty().withMessage('شهر نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_time')
|
||||
.notEmpty()
|
||||
.withMessage('زمان پروژه نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_price')
|
||||
.notEmpty()
|
||||
.withMessage('قیمت پیشنهادی نمیتواند خالی باشد'),
|
||||
|
||||
check('description')
|
||||
.notEmpty()
|
||||
.withMessage('توضیحات نمیتواند خالی باشد'),
|
||||
|
||||
check('project_type')
|
||||
.notEmpty()
|
||||
.withMessage('نوع پروژه نمیتواند خالی باشد')
|
||||
.isIn(['free', 'normal', 'force', 'highlight'])
|
||||
.withMessage('نوع پروژه باید normal یا force یا highlight باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const createProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
if (user.is_verified !== 'verified') {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'مدارک شما تایید نشده است'
|
||||
})
|
||||
}
|
||||
// اعتبارسنجی درخواست
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const {
|
||||
title,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province,
|
||||
city,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
project_type,
|
||||
public_status,
|
||||
created_for_user,
|
||||
number_of_person
|
||||
} = req.body
|
||||
if (
|
||||
!title ||
|
||||
!expertise ||
|
||||
!age ||
|
||||
conversation_projects === null ||
|
||||
!province ||
|
||||
!city ||
|
||||
!offer_time ||
|
||||
!offer_price ||
|
||||
!description ||
|
||||
!project_type
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const provinceFind = await ProvinceModel.findOne(
|
||||
{ id: province },
|
||||
{ _id: 0 }
|
||||
)
|
||||
const cityFind = await CityModel.findOne({ id: city })
|
||||
// اگر پروژه برای یک کاربر خاص باید ساخته شود
|
||||
if (public_status && public_status === 'private' && created_for_user) {
|
||||
const createdUser = await UserModel.findById(created_for_user)
|
||||
if (!createdUser) {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'کاربر مورد نظر برای ساخت پروژه یافت نشد'
|
||||
})
|
||||
}
|
||||
// ایجاد شیء پروژه
|
||||
const projectData = {
|
||||
title,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province,
|
||||
city,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
project_type,
|
||||
creator_id: user._id, // ارتباط با کاربر
|
||||
public_status,
|
||||
created_for_user
|
||||
}
|
||||
|
||||
// ساخت شیء پروژه
|
||||
const project = new ProjectModel(projectData)
|
||||
|
||||
// ذخیره کردن رکورد در پایگاه داده
|
||||
await project.save()
|
||||
|
||||
res.status(201).json({ message: 'پروژه با موفقیت ساخته شد', id: project._id }
|
||||
)
|
||||
} else {
|
||||
if (number_of_person > 1) {
|
||||
for (let i = 1; i <= number_of_person; i++) {
|
||||
let currentProjectType
|
||||
|
||||
if (project_type === 'free' && i === 1) {
|
||||
currentProjectType = 'free'
|
||||
} else if (project_type === 'highlight' || project_type === 'force') {
|
||||
currentProjectType = project_type
|
||||
} else {
|
||||
currentProjectType = 'normal'
|
||||
}
|
||||
|
||||
const newProject = new ProjectModel({
|
||||
title: `${title}_${i}`,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province: provinceFind,
|
||||
city: cityFind,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
creator_id: user._id, // ارتباط با کاربر
|
||||
project_type: currentProjectType,
|
||||
public_status,
|
||||
created_for_user
|
||||
})
|
||||
|
||||
// ذخیره کردن رکورد در پایگاه داده
|
||||
await newProject.save()
|
||||
}
|
||||
|
||||
res.status(201).json({
|
||||
message: 'پروژهها با موفقیت ساخته شدند'
|
||||
})
|
||||
} else {
|
||||
const project = new ProjectModel({
|
||||
title,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province: provinceFind,
|
||||
city: cityFind,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
creator_id: user._id, // ارتباط با کاربر
|
||||
project_type
|
||||
})
|
||||
|
||||
// ذخیره کردن رکورد در پایگاه داده
|
||||
await project.save()
|
||||
|
||||
res.status(201).json({
|
||||
message: 'پروژه با موفقیت ساخته شد',
|
||||
id: project._id
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createProjectValidationRules,
|
||||
createProject
|
||||
}
|
||||
|
||||
@@ -1,406 +1,406 @@
|
||||
/* eslint-disable camelcase */
|
||||
const { default: mongoose } = require('mongoose')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const RequestModel = require('../../../models/RequestModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const calculateRemainingTime = (milliseconds) => {
|
||||
const days = Math.floor(milliseconds / (1000 * 60 * 60 * 24))
|
||||
const hours = Math.floor((milliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
|
||||
|
||||
return `${days} روز و ${hours} ساعت`
|
||||
}
|
||||
const getProjects = async (req, res, next) => {
|
||||
try {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { expertise, page = 1, limit = 10, most_price, most_requests, age, gender } = req.query
|
||||
// ساخت فیلتر برای استفاده در جستجوی MongoDB
|
||||
const filter = {
|
||||
payment_status: 'done',
|
||||
status: 'accepted',
|
||||
public_status: 'public',
|
||||
$or: [
|
||||
{ isExpired: false }, // پروژههایی که isExpired برابر با false است
|
||||
{ isExpired: { $exists: false } } // پروژههایی که فیلد isExpired وجود ندارد
|
||||
]
|
||||
}
|
||||
if (expertise) {
|
||||
filter.expertise = expertise
|
||||
}
|
||||
if (age) {
|
||||
filter.age = age
|
||||
}
|
||||
if (gender) {
|
||||
filter.gender = gender
|
||||
}
|
||||
// استفاده از مدل پیجینیت شده برای دریافت نتایج صفحهبندی شده
|
||||
|
||||
if (most_price || most_requests) {
|
||||
// دریافت لیست پروژهها با استفاده از فیلتر و گزینههای صفحهبندی
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: most_price === 'true' ? { offer_price: -1 } : { requested_users: 'desc' }
|
||||
}
|
||||
const projects = await ProjectModel.paginate(filter, options)
|
||||
|
||||
const newProj = projects.docs
|
||||
res.status(200).json({
|
||||
projects: newProj,
|
||||
totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} else {
|
||||
// دریافت لیست پروژهها با استفاده از فیلتر و گزینههای صفحهبندی
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { acceptedAt: -1, createdAt: -1 } // مرتبسازی بر اساس acceptedAt و سپس createdAt
|
||||
}
|
||||
const projects = await ProjectModel.paginate(filter, options)
|
||||
const newProj = projects.docs
|
||||
res.status(200).json({
|
||||
projects: newProj,
|
||||
totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
// try {
|
||||
// const token = req.header('Authorization').split(' ')[1]
|
||||
// if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
// // eslint-disable-next-line no-unused-vars
|
||||
// const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
|
||||
// const { expertise, page = 1, limit = 10 } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
|
||||
// // ساخت فیلتر برای استفاده در جستجوی MongoDB
|
||||
// const filter = {
|
||||
// payment_status: 'done',
|
||||
// status: 'accepted',
|
||||
// public_status: 'public'
|
||||
// } // افزودن شرطهای دیگر برای فیلتر
|
||||
|
||||
// if (expertise) {
|
||||
// filter.expertise = expertise
|
||||
// }
|
||||
|
||||
// // استفاده از مدل پیجینیت شده برای دریافت نتایج صفحهبندی شده
|
||||
// const options = {
|
||||
// page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
// limit: parseInt(limit) // تبدیل محدودیت به عدد صحیح
|
||||
// }
|
||||
|
||||
// // دریافت لیست پروژهها با استفاده از فیلتر و گزینههای صفحهبندی
|
||||
// const projects = await ProjectModel.paginate(filter, options)
|
||||
|
||||
// // تبدیل نتایج به فرمت مورد نیاز
|
||||
// const projectsWithUserInfo = await Promise.all(projects.docs.map(async project => {
|
||||
// const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
// const projectWithUserInfo = {
|
||||
// ...project.toJSON(), // تبدیل آبجکت پروژه به JSON
|
||||
// creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه
|
||||
// }
|
||||
|
||||
// // محاسبه مدت زمان باقیمانده برای هر پروژه
|
||||
// const currentTime = new Date()
|
||||
// const projectCreatedAt = new Date(project.createdAt)
|
||||
// const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
// const remainingTime = calculateRemainingTime(timeDiff)
|
||||
// projectWithUserInfo.remainingTime = remainingTime
|
||||
|
||||
// return projectWithUserInfo
|
||||
// }))
|
||||
|
||||
// res.status(200).json({
|
||||
// projects: projectsWithUserInfo,
|
||||
// totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
// totalItems: projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
// })
|
||||
// } catch (error) {
|
||||
// next(error)
|
||||
// }
|
||||
}
|
||||
const getUserProjects = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const user_id = req.query.user_id
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
// const userReqId = decodedToken.id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(user_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
|
||||
}
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
const response = {}
|
||||
if (user.user_type === 'user') {
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ selected_user: user._id, status: 'done' }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
response.projects = projects.docs
|
||||
response.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
response.totalItems = projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
response.allProjectsCount = await ProjectModel.countDocuments({ selected_user: user._id })
|
||||
const completedProjects = await Promise.all([
|
||||
ProjectModel.countDocuments({ selected_user: user._id, status: 'done' })
|
||||
])
|
||||
response.successfulProjects = completedProjects
|
||||
} else {
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ creator_id: user._id, status: { $in: ['done', 'accepted'] } }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
response.projects = projects.docs
|
||||
response.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
response.totalItems = projects.totalDocs
|
||||
response.allProjectsCount = await ProjectModel.countDocuments({ creator_id: user._id, payment_status: 'done' })
|
||||
// تعداد پروژههای موفق را به دست آورید
|
||||
const successfulProjects = await ProjectModel.countDocuments({ creator_id: user._id, status: 'done' })
|
||||
response.successfulProjects = successfulProjects
|
||||
}
|
||||
return res.status(200).json({ data: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getUserProjectsWeb = async (req, res, next) => {
|
||||
try {
|
||||
const user_id = req.query.user_id
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(user_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
|
||||
}
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
const data = {}
|
||||
if (user.user_type === 'user') {
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ selected_user: user._id, status: 'done' }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
data.projects = projects.docs
|
||||
data.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
data.totalItems = projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
data.allProjectsCount = await ProjectModel.countDocuments({ selected_user: user._id })
|
||||
const completedProjects = await Promise.all([
|
||||
ProjectModel.countDocuments({ selected_user: user._id, status: 'done' })
|
||||
])
|
||||
data.successfulProjects = completedProjects
|
||||
} else {
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ creator_id: user._id, status: { $in: ['done', 'accepted'] } }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
data.projects = projects.docs
|
||||
data.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
data.totalItems = projects.totalDocs
|
||||
data.allProjectsCount = await ProjectModel.countDocuments({ creator_id: user._id, payment_status: 'done' })
|
||||
// تعداد پروژههای موفق را به دست آورید
|
||||
const successfulProjects = await ProjectModel.countDocuments({ creator_id: user._id, status: 'done' })
|
||||
data.successfulProjects = successfulProjects
|
||||
}
|
||||
return res.status(200).json(data)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getSingleProjects = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const projectId = req.params.projectId
|
||||
const projectRequests = await RequestModel.find({ project: projectId })
|
||||
.populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image')
|
||||
.sort({ status: 1 })
|
||||
.lean()
|
||||
const modifiedRequests = projectRequests.map(request => ({
|
||||
...request,
|
||||
time: request.user._id.toString() === userId ? request.time : null,
|
||||
price: request.user._id.toString() === userId ? request.price : null
|
||||
}))
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' })
|
||||
}
|
||||
// محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده
|
||||
// تابع محاسبه مبلغ پرداخت شده
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
let totalPaidAmount = 0
|
||||
installments.forEach(installment => {
|
||||
totalPaidAmount += installment.amount
|
||||
})
|
||||
return totalPaidAmount
|
||||
}
|
||||
|
||||
// تابع محاسبه مبلغ باقیمانده
|
||||
const getRemainingAmount = (project) => {
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = project.final_price - totalPaidAmount
|
||||
return remainingAmount
|
||||
}
|
||||
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
// اطلاعات کاربر سازنده را نیز دریافت کنید و به آبجکت پروژه اضافه کنید
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
|
||||
const projectWithUserInfo = {
|
||||
...project._doc,
|
||||
creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه
|
||||
}
|
||||
const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score')
|
||||
projectWithUserInfo.selected_user = selectedUser
|
||||
// محاسبه مدت زمان باقیمانده برای پروژه
|
||||
const currentTime = new Date()
|
||||
const projectCreatedAt = new Date(project.createdAt)
|
||||
const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
const remainingTime = calculateRemainingTime(timeDiff)
|
||||
projectWithUserInfo.remainingTime = remainingTime
|
||||
let projectDetails = projectWithUserInfo
|
||||
if ((project.selected_user && project.selected_user.toString()) === userId || project.creator_id.toString() === userId) {
|
||||
projectDetails = {
|
||||
...projectWithUserInfo,
|
||||
total_paid_amount: totalPaidAmount,
|
||||
remaining_amount: remainingAmount
|
||||
}
|
||||
} else {
|
||||
projectDetails =
|
||||
projectWithUserInfo
|
||||
}
|
||||
// }
|
||||
res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getSingleProjectsWeb = async (req, res, next) => {
|
||||
try {
|
||||
let userId = null
|
||||
let token = req.header('Authorization')
|
||||
|
||||
if (token) {
|
||||
try {
|
||||
token = token.split(' ')[1]
|
||||
if (token) {
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
userId = decodedToken.id
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Invalid token:', err.message)
|
||||
}
|
||||
}
|
||||
|
||||
const projectId = req.params.projectId
|
||||
const projectRequests = await RequestModel.find({ project: projectId })
|
||||
.populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image')
|
||||
.sort({ status: 1 })
|
||||
.lean()
|
||||
|
||||
// اگر کاربر لاگین کرده باشد، زمان و قیمت را نشان بده، در غیر این صورت حذف کن
|
||||
const modifiedRequests = projectRequests.map(request => ({
|
||||
...request,
|
||||
time: userId && request.user._id.toString() === userId ? request.time : null,
|
||||
price: userId && request.user._id.toString() === userId ? request.price : null
|
||||
}))
|
||||
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
// محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
return installments.reduce((total, installment) => total + installment.amount, 0)
|
||||
}
|
||||
|
||||
const getRemainingAmount = (project) => {
|
||||
return project.final_price - getTotalPaidAmount(project.installments)
|
||||
}
|
||||
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
|
||||
// دریافت اطلاعات سازنده پروژه
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
|
||||
const projectWithUserInfo = {
|
||||
...project._doc,
|
||||
creator
|
||||
}
|
||||
|
||||
// دریافت اطلاعات کاربر منتخب در صورت وجود
|
||||
const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score')
|
||||
projectWithUserInfo.selected_user = selectedUser
|
||||
|
||||
// محاسبه زمان باقیمانده برای پیشنهادات پروژه
|
||||
const currentTime = new Date()
|
||||
const projectCreatedAt = new Date(project.createdAt)
|
||||
const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
projectWithUserInfo.remainingTime = calculateRemainingTime(timeDiff)
|
||||
|
||||
let projectDetails = projectWithUserInfo
|
||||
|
||||
// فقط اگر کاربر احراز هویت شده باشد و سازنده یا برنده پروژه باشد، اطلاعات مالی را برگردان
|
||||
if (userId && (project.selected_user?.toString() === userId || project.creator_id.toString() === userId)) {
|
||||
projectDetails = {
|
||||
...projectWithUserInfo,
|
||||
total_paid_amount: totalPaidAmount,
|
||||
remaining_amount: remainingAmount
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// const projectDetails = await ProjectModel.findById(projectId).populate('requested_users', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image') // جزییات درخواستهای کاربران
|
||||
|
||||
module.exports = {
|
||||
getProjects, getSingleProjects, getUserProjects, getUserProjectsWeb, getSingleProjectsWeb
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const { default: mongoose } = require('mongoose')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const RequestModel = require('../../../models/RequestModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const calculateRemainingTime = (milliseconds) => {
|
||||
const days = Math.floor(milliseconds / (1000 * 60 * 60 * 24))
|
||||
const hours = Math.floor((milliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
|
||||
|
||||
return `${days} روز و ${hours} ساعت`
|
||||
}
|
||||
const getProjects = async (req, res, next) => {
|
||||
try {
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { expertise, page = 1, limit = 10, most_price, most_requests, age, gender } = req.query
|
||||
// ساخت فیلتر برای استفاده در جستجوی MongoDB
|
||||
const filter = {
|
||||
payment_status: 'done',
|
||||
status: 'accepted',
|
||||
public_status: 'public',
|
||||
$or: [
|
||||
{ isExpired: false }, // پروژههایی که isExpired برابر با false است
|
||||
{ isExpired: { $exists: false } } // پروژههایی که فیلد isExpired وجود ندارد
|
||||
]
|
||||
}
|
||||
if (expertise) {
|
||||
filter.expertise = expertise
|
||||
}
|
||||
if (age) {
|
||||
filter.age = age
|
||||
}
|
||||
if (gender) {
|
||||
filter.gender = gender
|
||||
}
|
||||
// استفاده از مدل پیجینیت شده برای دریافت نتایج صفحهبندی شده
|
||||
|
||||
if (most_price || most_requests) {
|
||||
// دریافت لیست پروژهها با استفاده از فیلتر و گزینههای صفحهبندی
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: most_price === 'true' ? { offer_price: -1 } : { requested_users: 'desc' }
|
||||
}
|
||||
const projects = await ProjectModel.paginate(filter, options)
|
||||
|
||||
const newProj = projects.docs
|
||||
res.status(200).json({
|
||||
projects: newProj,
|
||||
totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} else {
|
||||
// دریافت لیست پروژهها با استفاده از فیلتر و گزینههای صفحهبندی
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { acceptedAt: -1, createdAt: -1 } // مرتبسازی بر اساس acceptedAt و سپس createdAt
|
||||
}
|
||||
const projects = await ProjectModel.paginate(filter, options)
|
||||
const newProj = projects.docs
|
||||
res.status(200).json({
|
||||
projects: newProj,
|
||||
totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
// try {
|
||||
// const token = req.header('Authorization').split(' ')[1]
|
||||
// if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
// // eslint-disable-next-line no-unused-vars
|
||||
// const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
|
||||
// const { expertise, page = 1, limit = 10 } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
|
||||
// // ساخت فیلتر برای استفاده در جستجوی MongoDB
|
||||
// const filter = {
|
||||
// payment_status: 'done',
|
||||
// status: 'accepted',
|
||||
// public_status: 'public'
|
||||
// } // افزودن شرطهای دیگر برای فیلتر
|
||||
|
||||
// if (expertise) {
|
||||
// filter.expertise = expertise
|
||||
// }
|
||||
|
||||
// // استفاده از مدل پیجینیت شده برای دریافت نتایج صفحهبندی شده
|
||||
// const options = {
|
||||
// page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
// limit: parseInt(limit) // تبدیل محدودیت به عدد صحیح
|
||||
// }
|
||||
|
||||
// // دریافت لیست پروژهها با استفاده از فیلتر و گزینههای صفحهبندی
|
||||
// const projects = await ProjectModel.paginate(filter, options)
|
||||
|
||||
// // تبدیل نتایج به فرمت مورد نیاز
|
||||
// const projectsWithUserInfo = await Promise.all(projects.docs.map(async project => {
|
||||
// const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
// const projectWithUserInfo = {
|
||||
// ...project.toJSON(), // تبدیل آبجکت پروژه به JSON
|
||||
// creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه
|
||||
// }
|
||||
|
||||
// // محاسبه مدت زمان باقیمانده برای هر پروژه
|
||||
// const currentTime = new Date()
|
||||
// const projectCreatedAt = new Date(project.createdAt)
|
||||
// const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
// const remainingTime = calculateRemainingTime(timeDiff)
|
||||
// projectWithUserInfo.remainingTime = remainingTime
|
||||
|
||||
// return projectWithUserInfo
|
||||
// }))
|
||||
|
||||
// res.status(200).json({
|
||||
// projects: projectsWithUserInfo,
|
||||
// totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
// totalItems: projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
// })
|
||||
// } catch (error) {
|
||||
// next(error)
|
||||
// }
|
||||
}
|
||||
const getUserProjects = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const user_id = req.query.user_id
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
// const userReqId = decodedToken.id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(user_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
|
||||
}
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
const response = {}
|
||||
if (user.user_type === 'user') {
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ selected_user: user._id, status: 'done' }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
response.projects = projects.docs
|
||||
response.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
response.totalItems = projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
response.allProjectsCount = await ProjectModel.countDocuments({ selected_user: user._id })
|
||||
const completedProjects = await Promise.all([
|
||||
ProjectModel.countDocuments({ selected_user: user._id, status: 'done' })
|
||||
])
|
||||
response.successfulProjects = completedProjects
|
||||
} else {
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ creator_id: user._id, status: { $in: ['done', 'accepted'] } }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
response.projects = projects.docs
|
||||
response.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
response.totalItems = projects.totalDocs
|
||||
response.allProjectsCount = await ProjectModel.countDocuments({ creator_id: user._id, payment_status: 'done' })
|
||||
// تعداد پروژههای موفق را به دست آورید
|
||||
const successfulProjects = await ProjectModel.countDocuments({ creator_id: user._id, status: 'done' })
|
||||
response.successfulProjects = successfulProjects
|
||||
}
|
||||
return res.status(200).json({ data: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getUserProjectsWeb = async (req, res, next) => {
|
||||
try {
|
||||
const user_id = req.query.user_id
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(user_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کاربر معتبر نیست' })
|
||||
}
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({ message: 'کاربر مورد نظر یافت نشد' })
|
||||
}
|
||||
const data = {}
|
||||
if (user.user_type === 'user') {
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ selected_user: user._id, status: 'done' }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
data.projects = projects.docs
|
||||
data.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
data.totalItems = projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
data.allProjectsCount = await ProjectModel.countDocuments({ selected_user: user._id })
|
||||
const completedProjects = await Promise.all([
|
||||
ProjectModel.countDocuments({ selected_user: user._id, status: 'done' })
|
||||
])
|
||||
data.successfulProjects = completedProjects
|
||||
} else {
|
||||
const options = {
|
||||
page: req.query.page || 1, // صفحه پیشفرض ۱
|
||||
limit: req.query.limit || 10, // حداکثر تعداد موارد برای هر صفحه
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
|
||||
// پیجینیشن بر روی لیست پروژههای کاربر اعمال میشود
|
||||
const projects = await ProjectModel.paginate(
|
||||
{ creator_id: user._id, status: { $in: ['done', 'accepted'] } }, // فیلتر
|
||||
options // گزینههای پیجینیشن
|
||||
)
|
||||
data.projects = projects.docs
|
||||
data.totalPages = projects.totalPages // ارسال تعداد کل صفحات
|
||||
data.totalItems = projects.totalDocs
|
||||
data.allProjectsCount = await ProjectModel.countDocuments({ creator_id: user._id, payment_status: 'done' })
|
||||
// تعداد پروژههای موفق را به دست آورید
|
||||
const successfulProjects = await ProjectModel.countDocuments({ creator_id: user._id, status: 'done' })
|
||||
data.successfulProjects = successfulProjects
|
||||
}
|
||||
return res.status(200).json(data)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getSingleProjects = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const projectId = req.params.projectId
|
||||
const projectRequests = await RequestModel.find({ project: projectId })
|
||||
.populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image')
|
||||
.sort({ status: 1 })
|
||||
.lean()
|
||||
const modifiedRequests = projectRequests.map(request => ({
|
||||
...request,
|
||||
time: request.user._id.toString() === userId ? request.time : null,
|
||||
price: request.user._id.toString() === userId ? request.price : null
|
||||
}))
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' })
|
||||
}
|
||||
// محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده
|
||||
// تابع محاسبه مبلغ پرداخت شده
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
let totalPaidAmount = 0
|
||||
installments.forEach(installment => {
|
||||
totalPaidAmount += installment.amount
|
||||
})
|
||||
return totalPaidAmount
|
||||
}
|
||||
|
||||
// تابع محاسبه مبلغ باقیمانده
|
||||
const getRemainingAmount = (project) => {
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = project.final_price - totalPaidAmount
|
||||
return remainingAmount
|
||||
}
|
||||
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
// اطلاعات کاربر سازنده را نیز دریافت کنید و به آبجکت پروژه اضافه کنید
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
|
||||
const projectWithUserInfo = {
|
||||
...project._doc,
|
||||
creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه
|
||||
}
|
||||
const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score')
|
||||
projectWithUserInfo.selected_user = selectedUser
|
||||
// محاسبه مدت زمان باقیمانده برای پروژه
|
||||
const currentTime = new Date()
|
||||
const projectCreatedAt = new Date(project.createdAt)
|
||||
const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
const remainingTime = calculateRemainingTime(timeDiff)
|
||||
projectWithUserInfo.remainingTime = remainingTime
|
||||
let projectDetails = projectWithUserInfo
|
||||
if ((project.selected_user && project.selected_user.toString()) === userId || project.creator_id.toString() === userId) {
|
||||
projectDetails = {
|
||||
...projectWithUserInfo,
|
||||
total_paid_amount: totalPaidAmount,
|
||||
remaining_amount: remainingAmount
|
||||
}
|
||||
} else {
|
||||
projectDetails =
|
||||
projectWithUserInfo
|
||||
}
|
||||
// }
|
||||
res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getSingleProjectsWeb = async (req, res, next) => {
|
||||
try {
|
||||
let userId = null
|
||||
let token = req.header('Authorization')
|
||||
|
||||
if (token) {
|
||||
try {
|
||||
token = token.split(' ')[1]
|
||||
if (token) {
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
userId = decodedToken.id
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Invalid token:', err.message)
|
||||
}
|
||||
}
|
||||
|
||||
const projectId = req.params.projectId
|
||||
const projectRequests = await RequestModel.find({ project: projectId })
|
||||
.populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image')
|
||||
.sort({ status: 1 })
|
||||
.lean()
|
||||
|
||||
// اگر کاربر لاگین کرده باشد، زمان و قیمت را نشان بده، در غیر این صورت حذف کن
|
||||
const modifiedRequests = projectRequests.map(request => ({
|
||||
...request,
|
||||
time: userId && request.user._id.toString() === userId ? request.time : null,
|
||||
price: userId && request.user._id.toString() === userId ? request.price : null
|
||||
}))
|
||||
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
// محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
return installments.reduce((total, installment) => total + installment.amount, 0)
|
||||
}
|
||||
|
||||
const getRemainingAmount = (project) => {
|
||||
return project.final_price - getTotalPaidAmount(project.installments)
|
||||
}
|
||||
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
|
||||
// دریافت اطلاعات سازنده پروژه
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
|
||||
const projectWithUserInfo = {
|
||||
...project._doc,
|
||||
creator
|
||||
}
|
||||
|
||||
// دریافت اطلاعات کاربر منتخب در صورت وجود
|
||||
const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score')
|
||||
projectWithUserInfo.selected_user = selectedUser
|
||||
|
||||
// محاسبه زمان باقیمانده برای پیشنهادات پروژه
|
||||
const currentTime = new Date()
|
||||
const projectCreatedAt = new Date(project.createdAt)
|
||||
const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
projectWithUserInfo.remainingTime = calculateRemainingTime(timeDiff)
|
||||
|
||||
let projectDetails = projectWithUserInfo
|
||||
|
||||
// فقط اگر کاربر احراز هویت شده باشد و سازنده یا برنده پروژه باشد، اطلاعات مالی را برگردان
|
||||
if (userId && (project.selected_user?.toString() === userId || project.creator_id.toString() === userId)) {
|
||||
projectDetails = {
|
||||
...projectWithUserInfo,
|
||||
total_paid_amount: totalPaidAmount,
|
||||
remaining_amount: remainingAmount
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// const projectDetails = await ProjectModel.findById(projectId).populate('requested_users', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image') // جزییات درخواستهای کاربران
|
||||
|
||||
module.exports = {
|
||||
getProjects, getSingleProjects, getUserProjects, getUserProjectsWeb, getSingleProjectsWeb
|
||||
}
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
const TypeAndPriceModel = require('../../../models/TypeAndPriceModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
|
||||
const getProjectTypes = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
// درخواست انواع پروژه از دیتابیس
|
||||
let projectTypes = await TypeAndPriceModel.find({}, 'name price')
|
||||
|
||||
// بررسی برای مواردی مانند پیدا نشدن انواع پروژه
|
||||
if (!projectTypes) {
|
||||
return res.status(404).json({ message: 'انواع پروژه یافت نشد.' })
|
||||
}
|
||||
// اگر کاربر درخواست رایگان روزانه نداشته باشد، نوع پروژه رایگان را حذف کنید
|
||||
if (user.daily_free_request <= 0) {
|
||||
projectTypes = projectTypes.filter(projectType => projectType.name !== 'free')
|
||||
}
|
||||
// ارسال انواع پروژه به کاربر
|
||||
res.status(200).json({ projectTypes })
|
||||
} catch (error) {
|
||||
// در صورت بروز خطا، ارسال پیام خطا به کاربر
|
||||
console.error('Error in getProjectTypes:', error)
|
||||
res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' })
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getProjectTypes
|
||||
}
|
||||
const TypeAndPriceModel = require('../../../models/TypeAndPriceModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
|
||||
const getProjectTypes = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
// درخواست انواع پروژه از دیتابیس
|
||||
let projectTypes = await TypeAndPriceModel.find({}, 'name price')
|
||||
|
||||
// بررسی برای مواردی مانند پیدا نشدن انواع پروژه
|
||||
if (!projectTypes) {
|
||||
return res.status(404).json({ message: 'انواع پروژه یافت نشد.' })
|
||||
}
|
||||
// اگر کاربر درخواست رایگان روزانه نداشته باشد، نوع پروژه رایگان را حذف کنید
|
||||
if (user.daily_free_request <= 0) {
|
||||
projectTypes = projectTypes.filter(projectType => projectType.name !== 'free')
|
||||
}
|
||||
// ارسال انواع پروژه به کاربر
|
||||
res.status(200).json({ projectTypes })
|
||||
} catch (error) {
|
||||
// در صورت بروز خطا، ارسال پیام خطا به کاربر
|
||||
console.error('Error in getProjectTypes:', error)
|
||||
res.status(500).json({ message: 'خطا در دریافت انواع پروژه.' })
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getProjectTypes
|
||||
}
|
||||
|
||||
@@ -1,195 +1,195 @@
|
||||
/* eslint-disable camelcase */
|
||||
const { default: axios } = require('axios')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const RequestModel = require('../../../models/RequestModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const requestProjectValidationRules = () => {
|
||||
return [
|
||||
check('project_id')
|
||||
.notEmpty().withMessage('آیدی پروژه نمیتواند خالی باشد'),
|
||||
check('request_time')
|
||||
.notEmpty().withMessage('زمان پروژه نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_price')
|
||||
.notEmpty().withMessage('قیمت پیشنهادی نمیتواند خالی باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const requestProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user || user.user_type !== 'user') {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
if (user.is_verified !== 'verified') {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'مدارک شما تایید نشده است'
|
||||
})
|
||||
}
|
||||
// اعتبارسنجی درخواست
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const { request_time, offer_price, project_id } = req.body
|
||||
if (!project_id || !offer_price || !request_time
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
// چک کردن برای وجود درخواست قبلی
|
||||
const existingRequest = await RequestModel.findOne({ project: project_id, user: user._id })
|
||||
if (existingRequest) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما قبلاً برای این پروژه درخواست دادهاید'
|
||||
})
|
||||
}
|
||||
// ایجاد یک درخواست جدید
|
||||
const request = new RequestModel({
|
||||
project: project_id,
|
||||
user: user._id,
|
||||
time: request_time,
|
||||
price: offer_price
|
||||
})
|
||||
await request.save()
|
||||
|
||||
// ثبت اعلان برای سازنده پروژه
|
||||
const project = await ProjectModel.findById(project_id)
|
||||
const creatorId = project.creator_id
|
||||
|
||||
const notification = new NotificationModel({
|
||||
user_id: creatorId,
|
||||
project_post_id: project_id,
|
||||
type: 'request',
|
||||
title: 'پیشنهاد جدید',
|
||||
description: `کاربر ${user.user_name} یک پیشنهاد جدید برای پروژه شما ارسال کرده است.`
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
const userReciver = await UserModel.findById(project.creator_id)
|
||||
|
||||
const data = JSON.stringify({
|
||||
mobile: userReciver?.mobile,
|
||||
templateId: '876533',
|
||||
parameters: [
|
||||
{ name: 'EMPLOYER', value: userReciver?.first_name + ' ' + userReciver?.last_name },
|
||||
{ name: 'PROJECT', value: project?.title }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// به روز رسانی پروژه با افزودن کاربر به لیست کاربران درخواست دهنده
|
||||
const updatedProject = await ProjectModel.findOneAndUpdate(
|
||||
{ _id: project_id },
|
||||
{ $push: { requested_users: user._id } },
|
||||
{ new: true }
|
||||
)
|
||||
|
||||
if (!updatedProject) {
|
||||
console.error('Error adding requested user: Project not found')
|
||||
return res.status(404).json({ error: true, message: 'پروژه پیدا نشد' })
|
||||
}
|
||||
|
||||
res.status(201).json({ message: 'درخواست با موفقیت شد', id: project_id }
|
||||
)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const editRequestProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user || user.user_type !== 'user') {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
if (user.is_verified !== 'verified') {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'مدارک شما تایید نشده است'
|
||||
})
|
||||
}
|
||||
// اعتبارسنجی درخواست
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const { request_time, offer_price, project_id } = req.body
|
||||
if (!project_id || !offer_price || !request_time
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
// چک کردن برای وجود درخواست قبلی
|
||||
const existingRequest = await RequestModel.findOne({ project: project_id, user: user._id })
|
||||
if (!existingRequest) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما قبلاً برای این پروژه درخواست ندادهاید'
|
||||
})
|
||||
}
|
||||
// اکنون میتوانید اطلاعات درخواست را ویرایش کنید
|
||||
existingRequest.time = request_time
|
||||
existingRequest.price = offer_price
|
||||
await existingRequest.save()
|
||||
|
||||
// ثبت اعلان برای سازنده پروژه
|
||||
const project = await ProjectModel.findById(project_id)
|
||||
const creatorId = project.creator_id
|
||||
|
||||
const notification = new NotificationModel({
|
||||
user_id: creatorId,
|
||||
project_post_id: project_id,
|
||||
type: 'request',
|
||||
title: 'ویرایش پیشنهاد',
|
||||
description: `کاربر ${user.user_name} پیشنهاد خود را ویرایش کرد.`
|
||||
})
|
||||
await notification.save()
|
||||
res.status(200).json({
|
||||
message: 'درخواست با موفقیت ویرایش شد',
|
||||
id: project_id
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const acceptProject = async (req, res, next) => { }
|
||||
module.exports = {
|
||||
requestProjectValidationRules,
|
||||
requestProject,
|
||||
acceptProject,
|
||||
editRequestProject
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const { default: axios } = require('axios')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const RequestModel = require('../../../models/RequestModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const requestProjectValidationRules = () => {
|
||||
return [
|
||||
check('project_id')
|
||||
.notEmpty().withMessage('آیدی پروژه نمیتواند خالی باشد'),
|
||||
check('request_time')
|
||||
.notEmpty().withMessage('زمان پروژه نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_price')
|
||||
.notEmpty().withMessage('قیمت پیشنهادی نمیتواند خالی باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const requestProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user || user.user_type !== 'user') {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
if (user.is_verified !== 'verified') {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'مدارک شما تایید نشده است'
|
||||
})
|
||||
}
|
||||
// اعتبارسنجی درخواست
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const { request_time, offer_price, project_id } = req.body
|
||||
if (!project_id || !offer_price || !request_time
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
// چک کردن برای وجود درخواست قبلی
|
||||
const existingRequest = await RequestModel.findOne({ project: project_id, user: user._id })
|
||||
if (existingRequest) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما قبلاً برای این پروژه درخواست دادهاید'
|
||||
})
|
||||
}
|
||||
// ایجاد یک درخواست جدید
|
||||
const request = new RequestModel({
|
||||
project: project_id,
|
||||
user: user._id,
|
||||
time: request_time,
|
||||
price: offer_price
|
||||
})
|
||||
await request.save()
|
||||
|
||||
// ثبت اعلان برای سازنده پروژه
|
||||
const project = await ProjectModel.findById(project_id)
|
||||
const creatorId = project.creator_id
|
||||
|
||||
const notification = new NotificationModel({
|
||||
user_id: creatorId,
|
||||
project_post_id: project_id,
|
||||
type: 'request',
|
||||
title: 'پیشنهاد جدید',
|
||||
description: `کاربر ${user.user_name} یک پیشنهاد جدید برای پروژه شما ارسال کرده است.`
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
const userReciver = await UserModel.findById(project.creator_id)
|
||||
|
||||
const data = JSON.stringify({
|
||||
mobile: userReciver?.mobile,
|
||||
templateId: '876533',
|
||||
parameters: [
|
||||
{ name: 'EMPLOYER', value: userReciver?.first_name + ' ' + userReciver?.last_name },
|
||||
{ name: 'PROJECT', value: project?.title }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
// به روز رسانی پروژه با افزودن کاربر به لیست کاربران درخواست دهنده
|
||||
const updatedProject = await ProjectModel.findOneAndUpdate(
|
||||
{ _id: project_id },
|
||||
{ $push: { requested_users: user._id } },
|
||||
{ new: true }
|
||||
)
|
||||
|
||||
if (!updatedProject) {
|
||||
console.error('Error adding requested user: Project not found')
|
||||
return res.status(404).json({ error: true, message: 'پروژه پیدا نشد' })
|
||||
}
|
||||
|
||||
res.status(201).json({ message: 'درخواست با موفقیت شد', id: project_id }
|
||||
)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const editRequestProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user || user.user_type !== 'user') {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
if (user.is_verified !== 'verified') {
|
||||
return res.status(422).json({
|
||||
error: true, message: 'مدارک شما تایید نشده است'
|
||||
})
|
||||
}
|
||||
// اعتبارسنجی درخواست
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const { request_time, offer_price, project_id } = req.body
|
||||
if (!project_id || !offer_price || !request_time
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
// چک کردن برای وجود درخواست قبلی
|
||||
const existingRequest = await RequestModel.findOne({ project: project_id, user: user._id })
|
||||
if (!existingRequest) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما قبلاً برای این پروژه درخواست ندادهاید'
|
||||
})
|
||||
}
|
||||
// اکنون میتوانید اطلاعات درخواست را ویرایش کنید
|
||||
existingRequest.time = request_time
|
||||
existingRequest.price = offer_price
|
||||
await existingRequest.save()
|
||||
|
||||
// ثبت اعلان برای سازنده پروژه
|
||||
const project = await ProjectModel.findById(project_id)
|
||||
const creatorId = project.creator_id
|
||||
|
||||
const notification = new NotificationModel({
|
||||
user_id: creatorId,
|
||||
project_post_id: project_id,
|
||||
type: 'request',
|
||||
title: 'ویرایش پیشنهاد',
|
||||
description: `کاربر ${user.user_name} پیشنهاد خود را ویرایش کرد.`
|
||||
})
|
||||
await notification.save()
|
||||
res.status(200).json({
|
||||
message: 'درخواست با موفقیت ویرایش شد',
|
||||
id: project_id
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const acceptProject = async (req, res, next) => { }
|
||||
module.exports = {
|
||||
requestProjectValidationRules,
|
||||
requestProject,
|
||||
acceptProject,
|
||||
editRequestProject
|
||||
}
|
||||
|
||||
@@ -1,381 +1,381 @@
|
||||
/* eslint-disable camelcase */
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const { ProvinceModel, CityModel } = require('../../../models/StateCity')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const CommentModel = require('../../../models/CommentModel')
|
||||
|
||||
const doneProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { project_id, comment, rate, user_id } = req.body
|
||||
if (!project_id || !comment || !rate || !user_id) {
|
||||
return res.status(400).send({ message: 'All fields are required' })
|
||||
}
|
||||
|
||||
const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
return installments.reduce((total, installment) => total + installment.amount, 0)
|
||||
}
|
||||
|
||||
const getRemainingAmount = (project) => {
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
return project.final_price - totalPaidAmount
|
||||
}
|
||||
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
if (remainingAmount !== 0) {
|
||||
return res.status(422).send({ message: 'مبلغ کامل پرداخت نشده است' })
|
||||
}
|
||||
|
||||
project.status = 'done'
|
||||
await project.save()
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
project: project_id,
|
||||
creator: userId,
|
||||
rating: rate,
|
||||
comment,
|
||||
comment_for: 'user',
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
// پیدا کردن کامنتها و محاسبهی امتیاز کل
|
||||
const comments = await CommentModel.find({ user: user_id, comment_for: 'user' })
|
||||
const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0))
|
||||
|
||||
let userLevel
|
||||
if (user.expertise === 'مدل') {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
} else if (['زیبایی', 'عکاس'].includes(user.expertise)) {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
}
|
||||
|
||||
user.user_score = totalRating
|
||||
user.user_level = userLevel
|
||||
|
||||
const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' })
|
||||
const averageRating = totalRating / totalComments
|
||||
user.rate = averageRating.toFixed(1)
|
||||
await user.save()
|
||||
|
||||
const notification = new NotificationModel({
|
||||
user_id: user._id,
|
||||
project_post_id: project_id,
|
||||
type: 'end_project',
|
||||
title: 'اتمام پروژه',
|
||||
description: `کارفرما پروژه ${project?.title} را به وضعیت انجام شده تغییر داد و برای شما نظر ثبت کرد(برای ثبت نظر لمس کنید)
|
||||
نظر کارفرما : ${comment}
|
||||
`
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const doneProjectWeb = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { project_id, comment, rate, user_id } = req.body
|
||||
if (!project_id || !comment || !rate || !user_id) {
|
||||
return res.status(400).send({ message: 'All fields are required' })
|
||||
}
|
||||
|
||||
const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
|
||||
project.status = 'done'
|
||||
await project.save()
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
project: project_id,
|
||||
creator: userId,
|
||||
rating: rate,
|
||||
comment,
|
||||
comment_for: 'user',
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
// پیدا کردن کامنتها و محاسبهی امتیاز کل
|
||||
const comments = await CommentModel.find({ user: user_id, comment_for: 'user' })
|
||||
const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0))
|
||||
|
||||
let userLevel
|
||||
if (user.expertise === 'مدل') {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
} else if (['زیبایی', 'عکاس'].includes(user.expertise)) {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
}
|
||||
|
||||
user.user_score = totalRating
|
||||
user.user_level = userLevel
|
||||
|
||||
const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' })
|
||||
const averageRating = totalRating / totalComments
|
||||
user.rate = averageRating.toFixed(1)
|
||||
await user.save()
|
||||
|
||||
const notification = new NotificationModel({
|
||||
user_id: user._id,
|
||||
project_post_id: project_id,
|
||||
type: 'end_project',
|
||||
title: 'اتمام پروژه',
|
||||
description: `کارفرما پروژه ${project?.title} را به وضعیت انجام شده تغییر داد و برای شما نظر ثبت کرد(برای ثبت نظر لمس کنید)
|
||||
نظر کارفرما : ${comment}
|
||||
`
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const cancleProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { project_id, comment, rate, user_id } = req.body
|
||||
|
||||
if (!project_id || !comment || !rate || !user_id) {
|
||||
return res.status(400).send({ message: 'All fields are required' })
|
||||
}
|
||||
|
||||
const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
|
||||
project.status = 'cancled'
|
||||
await project.save()
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
project: project_id,
|
||||
creator: userId,
|
||||
rating: rate,
|
||||
comment,
|
||||
comment_for: 'project',
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const editProjectValidationRules = () => {
|
||||
return [
|
||||
check('title').notEmpty().withMessage('عنوان نمیتواند خالی باشد'),
|
||||
|
||||
check('expertise').notEmpty().withMessage('تخصص نمیتواند خالی باشد'),
|
||||
|
||||
check('gender')
|
||||
.isIn(['male', 'female'])
|
||||
.withMessage('جنسیت باید male یا female باشد'),
|
||||
|
||||
check('age').notEmpty().withMessage('سن نمیتواند خالی باشد'),
|
||||
|
||||
check('conversation_projects')
|
||||
.notEmpty()
|
||||
.withMessage('پروژههای مکالمه نمیتواند خالی باشد')
|
||||
.isBoolean()
|
||||
.withMessage('مقدار پروژههای مکالمه باید یک مقدار boolean باشد'),
|
||||
|
||||
check('province').notEmpty().withMessage('استان نمیتواند خالی باشد'),
|
||||
|
||||
check('city').notEmpty().withMessage('شهر نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_time')
|
||||
.notEmpty()
|
||||
.withMessage('زمان پروژه نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_price')
|
||||
.notEmpty()
|
||||
.withMessage('قیمت پیشنهادی نمیتواند خالی باشد'),
|
||||
|
||||
check('description')
|
||||
.notEmpty()
|
||||
.withMessage('توضیحات نمیتواند خالی باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const editProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
if (user.is_verified !== 'verified') {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'مدارک شما تایید نشده است'
|
||||
})
|
||||
}
|
||||
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
const {
|
||||
title,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province,
|
||||
city,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
projectId
|
||||
} = req.body
|
||||
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'پروژه مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (user._id.toString() != project.creator_id.toString()) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما نمیتوانید این پروژه را ویرایش کنید'
|
||||
})
|
||||
}
|
||||
if (project.status !== 'paid' && project.status !== 'pre_payment') {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما نمیتوانید این پروژه را ویرایش کنید'
|
||||
})
|
||||
}
|
||||
// اعتبارسنجی اطلاعات ویرایش شده
|
||||
if (
|
||||
!title ||
|
||||
!expertise ||
|
||||
!age ||
|
||||
conversation_projects === null ||
|
||||
!province ||
|
||||
!city ||
|
||||
!offer_time ||
|
||||
!offer_price ||
|
||||
!description
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
const provinceFind = await ProvinceModel.findOne(
|
||||
{ id: province },
|
||||
{ _id: 0 }
|
||||
)
|
||||
const cityFind = await CityModel.findOne({ id: city })
|
||||
// ویرایش یک نسخه از پروژه
|
||||
project.title = title
|
||||
project.expertise = expertise
|
||||
project.sub_expertise = sub_expertise
|
||||
project.gender = gender
|
||||
project.age = age
|
||||
project.conversation_projects = conversation_projects
|
||||
project.province = provinceFind
|
||||
project.city = cityFind
|
||||
project.offer_time = offer_time
|
||||
project.offer_price = offer_price
|
||||
project.description = description
|
||||
// ذخیره کردن تغییرات در پایگاه داده
|
||||
await project.save()
|
||||
res.status(200).json({
|
||||
message: 'پروژه با موفقیت ویرایش شد',
|
||||
id: project._id
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const setRateProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { project_id, comment, rate } = req.body
|
||||
const project = await ProjectModel.findOne({ _id: project_id, selected_user: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
project.ratings.push({
|
||||
project_id,
|
||||
rating: rate,
|
||||
comment,
|
||||
creator_id: userId
|
||||
})
|
||||
await project.save()
|
||||
|
||||
res.status(200).json({ message: 'نظر شما با موفقیت ثبت شد.' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
doneProject, cancleProject, editProject, editProjectValidationRules, setRateProject, doneProjectWeb
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const { ProvinceModel, CityModel } = require('../../../models/StateCity')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
const CommentModel = require('../../../models/CommentModel')
|
||||
|
||||
const doneProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { project_id, comment, rate, user_id } = req.body
|
||||
if (!project_id || !comment || !rate || !user_id) {
|
||||
return res.status(400).send({ message: 'All fields are required' })
|
||||
}
|
||||
|
||||
const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
return installments.reduce((total, installment) => total + installment.amount, 0)
|
||||
}
|
||||
|
||||
const getRemainingAmount = (project) => {
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
return project.final_price - totalPaidAmount
|
||||
}
|
||||
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
if (remainingAmount !== 0) {
|
||||
return res.status(422).send({ message: 'مبلغ کامل پرداخت نشده است' })
|
||||
}
|
||||
|
||||
project.status = 'done'
|
||||
await project.save()
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
project: project_id,
|
||||
creator: userId,
|
||||
rating: rate,
|
||||
comment,
|
||||
comment_for: 'user',
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
// پیدا کردن کامنتها و محاسبهی امتیاز کل
|
||||
const comments = await CommentModel.find({ user: user_id, comment_for: 'user' })
|
||||
const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0))
|
||||
|
||||
let userLevel
|
||||
if (user.expertise === 'مدل') {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
} else if (['زیبایی', 'عکاس'].includes(user.expertise)) {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
}
|
||||
|
||||
user.user_score = totalRating
|
||||
user.user_level = userLevel
|
||||
|
||||
const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' })
|
||||
const averageRating = totalRating / totalComments
|
||||
user.rate = averageRating.toFixed(1)
|
||||
await user.save()
|
||||
|
||||
const notification = new NotificationModel({
|
||||
user_id: user._id,
|
||||
project_post_id: project_id,
|
||||
type: 'end_project',
|
||||
title: 'اتمام پروژه',
|
||||
description: `کارفرما پروژه ${project?.title} را به وضعیت انجام شده تغییر داد و برای شما نظر ثبت کرد(برای ثبت نظر لمس کنید)
|
||||
نظر کارفرما : ${comment}
|
||||
`
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const doneProjectWeb = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { project_id, comment, rate, user_id } = req.body
|
||||
if (!project_id || !comment || !rate || !user_id) {
|
||||
return res.status(400).send({ message: 'All fields are required' })
|
||||
}
|
||||
|
||||
const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
|
||||
project.status = 'done'
|
||||
await project.save()
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
project: project_id,
|
||||
creator: userId,
|
||||
rating: rate,
|
||||
comment,
|
||||
comment_for: 'user',
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
const user = await UserModel.findById(user_id)
|
||||
|
||||
// پیدا کردن کامنتها و محاسبهی امتیاز کل
|
||||
const comments = await CommentModel.find({ user: user_id, comment_for: 'user' })
|
||||
const totalRating = Number(comments.reduce((acc, comment) => acc + comment.rating, 0))
|
||||
|
||||
let userLevel
|
||||
if (user.expertise === 'مدل') {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
} else if (['زیبایی', 'عکاس'].includes(user.expertise)) {
|
||||
if (totalRating <= 50) userLevel = 'تازه وارد'
|
||||
else if (totalRating <= 100) userLevel = 'استاندارد'
|
||||
else if (totalRating <= 300) userLevel = 'حرفهای'
|
||||
else userLevel = 'استاد'
|
||||
}
|
||||
|
||||
user.user_score = totalRating
|
||||
user.user_level = userLevel
|
||||
|
||||
const totalComments = await CommentModel.countDocuments({ user: user_id, comment_for: 'user' })
|
||||
const averageRating = totalRating / totalComments
|
||||
user.rate = averageRating.toFixed(1)
|
||||
await user.save()
|
||||
|
||||
const notification = new NotificationModel({
|
||||
user_id: user._id,
|
||||
project_post_id: project_id,
|
||||
type: 'end_project',
|
||||
title: 'اتمام پروژه',
|
||||
description: `کارفرما پروژه ${project?.title} را به وضعیت انجام شده تغییر داد و برای شما نظر ثبت کرد(برای ثبت نظر لمس کنید)
|
||||
نظر کارفرما : ${comment}
|
||||
`
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const cancleProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { project_id, comment, rate, user_id } = req.body
|
||||
|
||||
if (!project_id || !comment || !rate || !user_id) {
|
||||
return res.status(400).send({ message: 'All fields are required' })
|
||||
}
|
||||
|
||||
const project = await ProjectModel.findOne({ _id: project_id, creator_id: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
|
||||
project.status = 'cancled'
|
||||
await project.save()
|
||||
|
||||
const newComment = new CommentModel({
|
||||
user: user_id,
|
||||
project: project_id,
|
||||
creator: userId,
|
||||
rating: rate,
|
||||
comment,
|
||||
comment_for: 'project',
|
||||
status: 'pending'
|
||||
})
|
||||
await newComment.save()
|
||||
|
||||
res.status(200).json({ message: 'پروژه با موفقیت تغییر یافت شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const editProjectValidationRules = () => {
|
||||
return [
|
||||
check('title').notEmpty().withMessage('عنوان نمیتواند خالی باشد'),
|
||||
|
||||
check('expertise').notEmpty().withMessage('تخصص نمیتواند خالی باشد'),
|
||||
|
||||
check('gender')
|
||||
.isIn(['male', 'female'])
|
||||
.withMessage('جنسیت باید male یا female باشد'),
|
||||
|
||||
check('age').notEmpty().withMessage('سن نمیتواند خالی باشد'),
|
||||
|
||||
check('conversation_projects')
|
||||
.notEmpty()
|
||||
.withMessage('پروژههای مکالمه نمیتواند خالی باشد')
|
||||
.isBoolean()
|
||||
.withMessage('مقدار پروژههای مکالمه باید یک مقدار boolean باشد'),
|
||||
|
||||
check('province').notEmpty().withMessage('استان نمیتواند خالی باشد'),
|
||||
|
||||
check('city').notEmpty().withMessage('شهر نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_time')
|
||||
.notEmpty()
|
||||
.withMessage('زمان پروژه نمیتواند خالی باشد'),
|
||||
|
||||
check('offer_price')
|
||||
.notEmpty()
|
||||
.withMessage('قیمت پیشنهادی نمیتواند خالی باشد'),
|
||||
|
||||
check('description')
|
||||
.notEmpty()
|
||||
.withMessage('توضیحات نمیتواند خالی باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const editProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
if (user.is_verified !== 'verified') {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'مدارک شما تایید نشده است'
|
||||
})
|
||||
}
|
||||
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
const {
|
||||
title,
|
||||
expertise,
|
||||
sub_expertise,
|
||||
gender,
|
||||
age,
|
||||
conversation_projects,
|
||||
province,
|
||||
city,
|
||||
offer_time,
|
||||
offer_price,
|
||||
description,
|
||||
projectId
|
||||
} = req.body
|
||||
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'پروژه مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
// eslint-disable-next-line eqeqeq
|
||||
if (user._id.toString() != project.creator_id.toString()) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما نمیتوانید این پروژه را ویرایش کنید'
|
||||
})
|
||||
}
|
||||
if (project.status !== 'paid' && project.status !== 'pre_payment') {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما نمیتوانید این پروژه را ویرایش کنید'
|
||||
})
|
||||
}
|
||||
// اعتبارسنجی اطلاعات ویرایش شده
|
||||
if (
|
||||
!title ||
|
||||
!expertise ||
|
||||
!age ||
|
||||
conversation_projects === null ||
|
||||
!province ||
|
||||
!city ||
|
||||
!offer_time ||
|
||||
!offer_price ||
|
||||
!description
|
||||
) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
const provinceFind = await ProvinceModel.findOne(
|
||||
{ id: province },
|
||||
{ _id: 0 }
|
||||
)
|
||||
const cityFind = await CityModel.findOne({ id: city })
|
||||
// ویرایش یک نسخه از پروژه
|
||||
project.title = title
|
||||
project.expertise = expertise
|
||||
project.sub_expertise = sub_expertise
|
||||
project.gender = gender
|
||||
project.age = age
|
||||
project.conversation_projects = conversation_projects
|
||||
project.province = provinceFind
|
||||
project.city = cityFind
|
||||
project.offer_time = offer_time
|
||||
project.offer_price = offer_price
|
||||
project.description = description
|
||||
// ذخیره کردن تغییرات در پایگاه داده
|
||||
await project.save()
|
||||
res.status(200).json({
|
||||
message: 'پروژه با موفقیت ویرایش شد',
|
||||
id: project._id
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const setRateProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { project_id, comment, rate } = req.body
|
||||
const project = await ProjectModel.findOne({ _id: project_id, selected_user: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
project.ratings.push({
|
||||
project_id,
|
||||
rating: rate,
|
||||
comment,
|
||||
creator_id: userId
|
||||
})
|
||||
await project.save()
|
||||
|
||||
res.status(200).json({ message: 'نظر شما با موفقیت ثبت شد.' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
doneProject, cancleProject, editProject, editProjectValidationRules, setRateProject, doneProjectWeb
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const { ProvinceModel } = require('../../models/StateCity')
|
||||
|
||||
const getProvinces = async (req, res, next) => {
|
||||
try {
|
||||
const provinces = await ProvinceModel.find({})
|
||||
res.status(200).json({
|
||||
provinces
|
||||
})
|
||||
} catch (err) {
|
||||
res.status(500).send('Internal Server Error')
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getProvinces
|
||||
}
|
||||
const { ProvinceModel } = require('../../models/StateCity')
|
||||
|
||||
const getProvinces = async (req, res, next) => {
|
||||
try {
|
||||
const provinces = await ProvinceModel.find({})
|
||||
res.status(200).json({
|
||||
provinces
|
||||
})
|
||||
} catch (err) {
|
||||
res.status(500).send('Internal Server Error')
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getProvinces
|
||||
}
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
const { default: axios } = require('axios')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
// const { Token, VerificationCode } = require('sms-ir')
|
||||
|
||||
const registerValidationRules = () => {
|
||||
return [
|
||||
check('mobile')
|
||||
.notEmpty().withMessage('شماره موبایل نمیتواند خالی باشد')
|
||||
.isLength({ min: 11, max: 11 }).withMessage('شماره موبایل باید دقیقاً 11 رقم باشد')
|
||||
.matches(/^09[0-9]{9}$/).withMessage('فرمت شماره موبایل صحیح نیست')
|
||||
]
|
||||
}
|
||||
|
||||
const registerUser = async (req, res, next) => {
|
||||
try {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
const { mobile } = req.body
|
||||
if (!mobile) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شماره موبایل نمیتواند خالی باشد'
|
||||
})
|
||||
}
|
||||
|
||||
const existingUser = await UserModel.findOne({ mobile })
|
||||
if (existingUser && existingUser.national_code !== null) {
|
||||
return res.status(422).json({ error: true, message: 'شماره موبایل تکراری است' })
|
||||
}
|
||||
function generateOTP () {
|
||||
return Math.floor(100000 + Math.random() * 900000)
|
||||
}
|
||||
|
||||
const otp = generateOTP()
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const user = await UserModel.findOneAndUpdate(
|
||||
{ mobile },
|
||||
{ $set: { mobile, otp } },
|
||||
{ upsert: true, new: true, lean: true }
|
||||
)
|
||||
setTimeout(() => {
|
||||
UserModel.findOneAndUpdate({ mobile }, { $set: { otp: null } }, { new: true })
|
||||
.then(() => {})
|
||||
.catch(error => console.error('Error setting OTP to null:', error))
|
||||
}, 5 * 60 * 1000)
|
||||
const data = JSON.stringify({
|
||||
mobile,
|
||||
templateId: '930719',
|
||||
parameters: [
|
||||
{ name: 'CODE', value: otp.toString() }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
// console.log(JSON.stringify(response.data))
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'کد تایید ارسال شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
registerValidationRules,
|
||||
registerUser
|
||||
}
|
||||
const { default: axios } = require('axios')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
// const { Token, VerificationCode } = require('sms-ir')
|
||||
|
||||
const registerValidationRules = () => {
|
||||
return [
|
||||
check('mobile')
|
||||
.notEmpty().withMessage('شماره موبایل نمیتواند خالی باشد')
|
||||
.isLength({ min: 11, max: 11 }).withMessage('شماره موبایل باید دقیقاً 11 رقم باشد')
|
||||
.matches(/^09[0-9]{9}$/).withMessage('فرمت شماره موبایل صحیح نیست')
|
||||
]
|
||||
}
|
||||
|
||||
const registerUser = async (req, res, next) => {
|
||||
try {
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
const { mobile } = req.body
|
||||
if (!mobile) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شماره موبایل نمیتواند خالی باشد'
|
||||
})
|
||||
}
|
||||
|
||||
const existingUser = await UserModel.findOne({ mobile })
|
||||
if (existingUser && existingUser.national_code !== null) {
|
||||
return res.status(422).json({ error: true, message: 'شماره موبایل تکراری است' })
|
||||
}
|
||||
function generateOTP () {
|
||||
return Math.floor(100000 + Math.random() * 900000)
|
||||
}
|
||||
|
||||
const otp = generateOTP()
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const user = await UserModel.findOneAndUpdate(
|
||||
{ mobile },
|
||||
{ $set: { mobile, otp } },
|
||||
{ upsert: true, new: true, lean: true }
|
||||
)
|
||||
setTimeout(() => {
|
||||
UserModel.findOneAndUpdate({ mobile }, { $set: { otp: null } }, { new: true })
|
||||
.then(() => {})
|
||||
.catch(error => console.error('Error setting OTP to null:', error))
|
||||
}, 5 * 60 * 1000)
|
||||
const data = JSON.stringify({
|
||||
mobile,
|
||||
templateId: '930719',
|
||||
parameters: [
|
||||
{ name: 'CODE', value: otp.toString() }
|
||||
]
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'https://api.sms.ir/v1/send/verify',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'text/plain',
|
||||
'x-api-key': '2JKxGbTzE64t0YTkjip6RYHnm9mq1haMlidF8WWwQunwubHFVW6iaMmfFQbMXEDt'
|
||||
},
|
||||
data
|
||||
}
|
||||
|
||||
axios(config)
|
||||
.then(function (response) {
|
||||
// console.log(JSON.stringify(response.data))
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error)
|
||||
})
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: 'کد تایید ارسال شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
registerValidationRules,
|
||||
registerUser
|
||||
}
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setUserFullNameValidationRules = () => {
|
||||
return [
|
||||
check('first_name')
|
||||
.notEmpty().withMessage('نام نمیتواند خالی باشد'),
|
||||
check('last_name')
|
||||
.notEmpty().withMessage('نام خانوادگی نمیتواند خالی باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const setUserFullName = async (req, res, next) => {
|
||||
try {
|
||||
const { first_name, last_name } = req.body
|
||||
|
||||
// اعتبارسنجی دادههای ورودی
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نام کاربری به صورت lowercase
|
||||
user.first_name = first_name.toLowerCase()
|
||||
user.last_name = last_name.toLowerCase()
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نام و نام خانوادگی با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setUserFullName, setUserFullNameValidationRules
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setUserFullNameValidationRules = () => {
|
||||
return [
|
||||
check('first_name')
|
||||
.notEmpty().withMessage('نام نمیتواند خالی باشد'),
|
||||
check('last_name')
|
||||
.notEmpty().withMessage('نام خانوادگی نمیتواند خالی باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const setUserFullName = async (req, res, next) => {
|
||||
try {
|
||||
const { first_name, last_name } = req.body
|
||||
|
||||
// اعتبارسنجی دادههای ورودی
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نام کاربری به صورت lowercase
|
||||
user.first_name = first_name.toLowerCase()
|
||||
user.last_name = last_name.toLowerCase()
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نام و نام خانوادگی با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setUserFullName, setUserFullNameValidationRules
|
||||
}
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setUserType = async (req, res, next) => {
|
||||
try {
|
||||
const { user_type } = req.body
|
||||
if (!user_type || !['user', 'employer'].includes(user_type)) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نوع یوزر معتبر نیست'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نوع یوزر
|
||||
user.user_type = user_type.toLowerCase()
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نوع کاربر با موفقیت بهروزرسانی شد',
|
||||
id: user._id
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setUserType
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setUserType = async (req, res, next) => {
|
||||
try {
|
||||
const { user_type } = req.body
|
||||
if (!user_type || !['user', 'employer'].includes(user_type)) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نوع یوزر معتبر نیست'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نوع یوزر
|
||||
user.user_type = user_type.toLowerCase()
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نوع کاربر با موفقیت بهروزرسانی شد',
|
||||
id: user._id
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setUserType
|
||||
}
|
||||
|
||||
@@ -1,95 +1,95 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setUserName = async (req, res, next) => {
|
||||
try {
|
||||
const { mobile, user_name } = req.body
|
||||
if (!mobile || !user_name) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const user = await UserModel.findOne({ mobile })
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
// بررسی حداقل طول نام کاربری
|
||||
if (user_name.length < 5) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نام کاربری باید حداقل 5 کاراکتر باشد'
|
||||
})
|
||||
}
|
||||
// بررسی محدودیتهای مجاز در نام کاربری
|
||||
// const usernameRegex = /^[a-zA-Z0-9_]+$/
|
||||
// if (!usernameRegex.test(user_name)) {
|
||||
// return res.status(422).json({
|
||||
// error: true,
|
||||
// message: 'نام کاربری فقط میتواند شامل حروف الفبای انگلیسی، اعداد و کاراکتر _ باشد'
|
||||
// })
|
||||
// }
|
||||
// بررسی تکراری بودن user_name
|
||||
const existingUser = await UserModel.findOne({ user_name: { $regex: new RegExp('^' + user_name + '$', 'i') } })
|
||||
if (existingUser && existingUser._id.toString() !== user._id.toString()) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نام کاربری تکراری است'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نام کاربری به صورت lowercase
|
||||
user.user_name = user_name.toLowerCase()
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نام کاربری با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateUserName = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { user_name } = req.body
|
||||
|
||||
if (!user_name) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findByIdAndUpdate(userId, { user_name }, { new: true })
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
return res.json({
|
||||
message: 'نام کاربری با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setUserName, updateUserName
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setUserName = async (req, res, next) => {
|
||||
try {
|
||||
const { mobile, user_name } = req.body
|
||||
if (!mobile || !user_name) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const user = await UserModel.findOne({ mobile })
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
// بررسی حداقل طول نام کاربری
|
||||
if (user_name.length < 5) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نام کاربری باید حداقل 5 کاراکتر باشد'
|
||||
})
|
||||
}
|
||||
// بررسی محدودیتهای مجاز در نام کاربری
|
||||
// const usernameRegex = /^[a-zA-Z0-9_]+$/
|
||||
// if (!usernameRegex.test(user_name)) {
|
||||
// return res.status(422).json({
|
||||
// error: true,
|
||||
// message: 'نام کاربری فقط میتواند شامل حروف الفبای انگلیسی، اعداد و کاراکتر _ باشد'
|
||||
// })
|
||||
// }
|
||||
// بررسی تکراری بودن user_name
|
||||
const existingUser = await UserModel.findOne({ user_name: { $regex: new RegExp('^' + user_name + '$', 'i') } })
|
||||
if (existingUser && existingUser._id.toString() !== user._id.toString()) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نام کاربری تکراری است'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نام کاربری به صورت lowercase
|
||||
user.user_name = user_name.toLowerCase()
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نام کاربری با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateUserName = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { user_name } = req.body
|
||||
|
||||
if (!user_name) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findByIdAndUpdate(userId, { user_name }, { new: true })
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
return res.json({
|
||||
message: 'نام کاربری با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setUserName, updateUserName
|
||||
}
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const TokenService = require('../../../services/TokenService')
|
||||
// const jwt = require('jsonwebtoken')
|
||||
|
||||
const verifyUser = async (req, res, next) => {
|
||||
try {
|
||||
const { mobile, otp } = req.body
|
||||
if (!mobile || !otp) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findOne({ mobile })
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
const token = TokenService.sign({ id: user._id })
|
||||
let step = ''
|
||||
if (user.user_name === null) { step = 'user_name' } else if
|
||||
(!user.password) { step = 'password' } else if
|
||||
(!user.first_name) { step = 'first_name' } else if
|
||||
(!user.user_type) { step = 'user_type' } else { step = 'profile_image' }
|
||||
if (user.otp === otp) {
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
step
|
||||
})
|
||||
}
|
||||
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'کد تایید اشتباه است'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
verifyUser
|
||||
}
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const TokenService = require('../../../services/TokenService')
|
||||
// const jwt = require('jsonwebtoken')
|
||||
|
||||
const verifyUser = async (req, res, next) => {
|
||||
try {
|
||||
const { mobile, otp } = req.body
|
||||
if (!mobile || !otp) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findOne({ mobile })
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
const token = TokenService.sign({ id: user._id })
|
||||
let step = ''
|
||||
if (user.user_name === null) { step = 'user_name' } else if
|
||||
(!user.password) { step = 'password' } else if
|
||||
(!user.first_name) { step = 'first_name' } else if
|
||||
(!user.user_type) { step = 'user_type' } else { step = 'profile_image' }
|
||||
if (user.otp === otp) {
|
||||
return res.json({
|
||||
message: 'کد تایید صحیح بود',
|
||||
token,
|
||||
step
|
||||
})
|
||||
}
|
||||
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'کد تایید اشتباه است'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
verifyUser
|
||||
}
|
||||
|
||||
@@ -1,52 +1,52 @@
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const getSearch = async (req, res, next) => {
|
||||
try {
|
||||
const { search, type, page = 1, limit = 10 } = req.query
|
||||
let result
|
||||
const selectedFields = '_id user_name first_name last_name user_type is_verified profile_image expertise rate user_level user_score'
|
||||
let filter
|
||||
let totalPages
|
||||
let totalItems
|
||||
if (search) {
|
||||
if (!type) {
|
||||
res.status(422).json({ success: false, message: 'نوع جستجو را مشخص کنید' })
|
||||
} else if (type === 'project') {
|
||||
// جستجو در مدل Project با فیلتر کردن برای user_type === "employer"
|
||||
|
||||
filter = { $or: [{ title: new RegExp(search, 'i'), status: 'accepted' }, { description: new RegExp(search, 'i'), status: 'accepted' }] }
|
||||
result = await ProjectModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), sort: { createdAt: -1 } })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
} else if (type === 'user') {
|
||||
// جستجو در مدل User با فیلتر کردن برای user_type === "user"
|
||||
filter = { user_type: 'user', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] }
|
||||
result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
} else if (type === 'employer') {
|
||||
// جستجو در مدل User با فیلتر کردن برای user_type === "employer"
|
||||
filter = { user_type: 'employer', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] }
|
||||
result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
result: result?.docs,
|
||||
type,
|
||||
totalPages,
|
||||
totalItems
|
||||
})
|
||||
} else {
|
||||
res.status(422).json({ success: false, message: 'چیزی تایپ کنید' })
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSearch
|
||||
}
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const getSearch = async (req, res, next) => {
|
||||
try {
|
||||
const { search, type, page = 1, limit = 10 } = req.query
|
||||
let result
|
||||
const selectedFields = '_id user_name first_name last_name user_type is_verified profile_image expertise rate user_level user_score'
|
||||
let filter
|
||||
let totalPages
|
||||
let totalItems
|
||||
if (search) {
|
||||
if (!type) {
|
||||
res.status(422).json({ success: false, message: 'نوع جستجو را مشخص کنید' })
|
||||
} else if (type === 'project') {
|
||||
// جستجو در مدل Project با فیلتر کردن برای user_type === "employer"
|
||||
|
||||
filter = { $or: [{ title: new RegExp(search, 'i'), status: 'accepted' }, { description: new RegExp(search, 'i'), status: 'accepted' }] }
|
||||
result = await ProjectModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), sort: { createdAt: -1 } })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
} else if (type === 'user') {
|
||||
// جستجو در مدل User با فیلتر کردن برای user_type === "user"
|
||||
filter = { user_type: 'user', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] }
|
||||
result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
} else if (type === 'employer') {
|
||||
// جستجو در مدل User با فیلتر کردن برای user_type === "employer"
|
||||
filter = { user_type: 'employer', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] }
|
||||
result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
result: result?.docs,
|
||||
type,
|
||||
totalPages,
|
||||
totalItems
|
||||
})
|
||||
} else {
|
||||
res.status(422).json({ success: false, message: 'چیزی تایپ کنید' })
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSearch
|
||||
}
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const getSearch = async (req, res, next) => {
|
||||
try {
|
||||
const { search, type, page = 1, limit = 10 } = req.query
|
||||
let result
|
||||
const selectedFields = '_id user_name first_name last_name user_type is_verified profile_image expertise rate user_level user_score'
|
||||
let filter
|
||||
let totalPages
|
||||
let totalItems
|
||||
if (search) {
|
||||
if (!type) {
|
||||
res.status(422).json({ success: false, message: 'نوع جستجو را مشخص کنید' })
|
||||
} else if (type === 'project') {
|
||||
// جستجو در مدل Project با فیلتر کردن برای user_type === "employer"
|
||||
|
||||
filter = { $or: [{ title: new RegExp(search, 'i'), status: 'accepted' }, { description: new RegExp(search, 'i'), status: 'accepted' }] }
|
||||
result = await ProjectModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), sort: { createdAt: -1 } })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
} else if (type === 'user') {
|
||||
// جستجو در مدل User با فیلتر کردن برای user_type === "user"
|
||||
filter = { user_type: 'user', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] }
|
||||
result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
} else if (type === 'employer') {
|
||||
// جستجو در مدل User با فیلتر کردن برای user_type === "employer"
|
||||
filter = { user_type: 'employer', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] }
|
||||
result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
}
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
result: result?.docs,
|
||||
type,
|
||||
totalPages,
|
||||
totalItems
|
||||
})
|
||||
} else {
|
||||
res.status(422).json({ success: false, message: 'چیزی تایپ کنید' })
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSearch
|
||||
}
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const getSearch = async (req, res, next) => {
|
||||
try {
|
||||
const { search, type, page = 1, limit = 10 } = req.query
|
||||
let result
|
||||
const selectedFields = '_id user_name first_name last_name user_type is_verified profile_image expertise rate user_level user_score'
|
||||
let filter
|
||||
let totalPages
|
||||
let totalItems
|
||||
if (search) {
|
||||
if (!type) {
|
||||
res.status(422).json({ success: false, message: 'نوع جستجو را مشخص کنید' })
|
||||
} else if (type === 'project') {
|
||||
// جستجو در مدل Project با فیلتر کردن برای user_type === "employer"
|
||||
|
||||
filter = { $or: [{ title: new RegExp(search, 'i'), status: 'accepted' }, { description: new RegExp(search, 'i'), status: 'accepted' }] }
|
||||
result = await ProjectModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), sort: { createdAt: -1 } })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
} else if (type === 'user') {
|
||||
// جستجو در مدل User با فیلتر کردن برای user_type === "user"
|
||||
filter = { user_type: 'user', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] }
|
||||
result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
} else if (type === 'employer') {
|
||||
// جستجو در مدل User با فیلتر کردن برای user_type === "employer"
|
||||
filter = { user_type: 'employer', $or: [{ user_name: new RegExp(search, 'i') }, { first_name: new RegExp(search, 'i') }, { last_name: new RegExp(search, 'i') }] }
|
||||
result = await UserModel.paginate(filter, { page: parseInt(page), limit: parseInt(limit), select: selectedFields })
|
||||
totalPages = result?.totalPages
|
||||
totalItems = result?.totalDocs
|
||||
}
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
result: result?.docs,
|
||||
type,
|
||||
totalPages,
|
||||
totalItems
|
||||
})
|
||||
} else {
|
||||
res.status(422).json({ success: false, message: 'چیزی تایپ کنید' })
|
||||
}
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSearch
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
// controllers/settingController.js
|
||||
|
||||
const SettingModel = require('../../../models/SettingsModel')
|
||||
|
||||
// متد برای دریافت تنظیمات بر اساس key
|
||||
const getSetting = async (req, res, next) => {
|
||||
try {
|
||||
const { key } = req.params
|
||||
const setting = await SettingModel.findOne({ key })
|
||||
if (!setting) {
|
||||
return res.status(404).json({ message: 'تنظیمات مورد نظر یافت نشد' })
|
||||
}
|
||||
res.status(200).json(setting)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getSetting }
|
||||
// controllers/settingController.js
|
||||
|
||||
const SettingModel = require('../../../models/SettingsModel')
|
||||
|
||||
// متد برای دریافت تنظیمات بر اساس key
|
||||
const getSetting = async (req, res, next) => {
|
||||
try {
|
||||
const { key } = req.params
|
||||
const setting = await SettingModel.findOne({ key })
|
||||
if (!setting) {
|
||||
return res.status(404).json({ message: 'تنظیمات مورد نظر یافت نشد' })
|
||||
}
|
||||
res.status(200).json(setting)
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getSetting }
|
||||
|
||||
@@ -1,147 +1,147 @@
|
||||
const jwt = require('jsonwebtoken')
|
||||
const TicketModel = require('../../../models/TicketModel')
|
||||
const TicketMessageModel = require('../../../models/TicketMessageModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const path = require('path')
|
||||
const fs = require('fs-extra')
|
||||
|
||||
const getUserTickets = async (req, res) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const { page = 1, limit = 10, search } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
const filter = { user: userId }
|
||||
if (search) {
|
||||
filter.$or = [
|
||||
{ title: { $regex: search, $options: 'i' } }
|
||||
]
|
||||
}
|
||||
const options = {
|
||||
page: parseInt(page) || 1,
|
||||
limit: parseInt(limit) || 10,
|
||||
sort: { updatedAt: -1 }
|
||||
}
|
||||
const tickets = await TicketModel.paginate(filter, options)
|
||||
const ticketList = tickets?.docs.map(ticket => {
|
||||
const jDate = jMoment(ticket.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
return {
|
||||
...ticket._doc,
|
||||
createdAt: jDate
|
||||
}
|
||||
})
|
||||
res.json({
|
||||
tickets: ticketList,
|
||||
totalPages: tickets.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: tickets.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' })
|
||||
}
|
||||
}
|
||||
|
||||
const createTicket = async (req, res) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { title } = req.body
|
||||
|
||||
const newTicket = new TicketModel({
|
||||
title,
|
||||
user: userId
|
||||
})
|
||||
await newTicket.save()
|
||||
|
||||
res.status(201).json(newTicket)
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' })
|
||||
}
|
||||
}
|
||||
const addUserMessageToTicket = async (req, res) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { ticketId } = req.query
|
||||
const { text } = req.body
|
||||
const { file } = req.files
|
||||
let fileUrl = null
|
||||
if (file) {
|
||||
// اگر فایل ارسال شده است، آن را ذخیره کنید
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/tickets')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
|
||||
const uniqueFileName = `${Date.now()}-${file.name}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
await fs.move(file.path, filePath)
|
||||
|
||||
fileUrl = `/tickets/${uniqueFileName}`
|
||||
}
|
||||
const newMessage = new TicketMessageModel({
|
||||
text,
|
||||
senderType: 'User',
|
||||
senderId: userId,
|
||||
ticket: ticketId,
|
||||
file: fileUrl
|
||||
})
|
||||
await newMessage.save()
|
||||
|
||||
const ticket = await TicketModel.findById(ticketId)
|
||||
if (!ticket) {
|
||||
return res.status(404).json({ error: 'Ticket not found' })
|
||||
}
|
||||
|
||||
ticket.status = 'Customer Response'
|
||||
await ticket.save()
|
||||
const newMessageWithJalaliDate = {
|
||||
...newMessage._doc,
|
||||
createdAt: jMoment(newMessage.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
}
|
||||
res.status(201).json(newMessageWithJalaliDate)
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' })
|
||||
}
|
||||
}
|
||||
const getTicketMessages = async (req, res) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { ticketId } = req.query
|
||||
const { page = 1, limit = 10 } = req.query
|
||||
const options = {
|
||||
page: parseInt(page) || 1,
|
||||
limit: parseInt(limit) || 10,
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
const messages = await TicketMessageModel.paginate({ ticket: ticketId }, options)
|
||||
const ticket = await TicketModel.findById(ticketId)
|
||||
ticket.new_message = false
|
||||
await ticket.save()
|
||||
const messageList = messages?.docs.map(message => {
|
||||
const jDate = jMoment(message.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
return {
|
||||
...message._doc,
|
||||
createdAt: jDate
|
||||
}
|
||||
})
|
||||
res.json({
|
||||
messages: messageList.reverse(),
|
||||
totalPages: messages.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: messages.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' })
|
||||
}
|
||||
}
|
||||
module.exports = { getUserTickets, createTicket, addUserMessageToTicket, getTicketMessages }
|
||||
const jwt = require('jsonwebtoken')
|
||||
const TicketModel = require('../../../models/TicketModel')
|
||||
const TicketMessageModel = require('../../../models/TicketMessageModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const path = require('path')
|
||||
const fs = require('fs-extra')
|
||||
|
||||
const getUserTickets = async (req, res) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const { page = 1, limit = 10, search } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
const filter = { user: userId }
|
||||
if (search) {
|
||||
filter.$or = [
|
||||
{ title: { $regex: search, $options: 'i' } }
|
||||
]
|
||||
}
|
||||
const options = {
|
||||
page: parseInt(page) || 1,
|
||||
limit: parseInt(limit) || 10,
|
||||
sort: { updatedAt: -1 }
|
||||
}
|
||||
const tickets = await TicketModel.paginate(filter, options)
|
||||
const ticketList = tickets?.docs.map(ticket => {
|
||||
const jDate = jMoment(ticket.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
return {
|
||||
...ticket._doc,
|
||||
createdAt: jDate
|
||||
}
|
||||
})
|
||||
res.json({
|
||||
tickets: ticketList,
|
||||
totalPages: tickets.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: tickets.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' })
|
||||
}
|
||||
}
|
||||
|
||||
const createTicket = async (req, res) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { title } = req.body
|
||||
|
||||
const newTicket = new TicketModel({
|
||||
title,
|
||||
user: userId
|
||||
})
|
||||
await newTicket.save()
|
||||
|
||||
res.status(201).json(newTicket)
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' })
|
||||
}
|
||||
}
|
||||
const addUserMessageToTicket = async (req, res) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
const { ticketId } = req.query
|
||||
const { text } = req.body
|
||||
const { file } = req.files
|
||||
let fileUrl = null
|
||||
if (file) {
|
||||
// اگر فایل ارسال شده است، آن را ذخیره کنید
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/tickets')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
|
||||
const uniqueFileName = `${Date.now()}-${file.name}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
await fs.move(file.path, filePath)
|
||||
|
||||
fileUrl = `/tickets/${uniqueFileName}`
|
||||
}
|
||||
const newMessage = new TicketMessageModel({
|
||||
text,
|
||||
senderType: 'User',
|
||||
senderId: userId,
|
||||
ticket: ticketId,
|
||||
file: fileUrl
|
||||
})
|
||||
await newMessage.save()
|
||||
|
||||
const ticket = await TicketModel.findById(ticketId)
|
||||
if (!ticket) {
|
||||
return res.status(404).json({ error: 'Ticket not found' })
|
||||
}
|
||||
|
||||
ticket.status = 'Customer Response'
|
||||
await ticket.save()
|
||||
const newMessageWithJalaliDate = {
|
||||
...newMessage._doc,
|
||||
createdAt: jMoment(newMessage.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
}
|
||||
res.status(201).json(newMessageWithJalaliDate)
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' })
|
||||
}
|
||||
}
|
||||
const getTicketMessages = async (req, res) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { ticketId } = req.query
|
||||
const { page = 1, limit = 10 } = req.query
|
||||
const options = {
|
||||
page: parseInt(page) || 1,
|
||||
limit: parseInt(limit) || 10,
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
const messages = await TicketMessageModel.paginate({ ticket: ticketId }, options)
|
||||
const ticket = await TicketModel.findById(ticketId)
|
||||
ticket.new_message = false
|
||||
await ticket.save()
|
||||
const messageList = messages?.docs.map(message => {
|
||||
const jDate = jMoment(message.createdAt).format('jYYYY-jMM-jDD HH:mm')
|
||||
return {
|
||||
...message._doc,
|
||||
createdAt: jDate
|
||||
}
|
||||
})
|
||||
res.json({
|
||||
messages: messageList.reverse(),
|
||||
totalPages: messages.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: messages.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Internal Server Error' })
|
||||
}
|
||||
}
|
||||
module.exports = { getUserTickets, createTicket, addUserMessageToTicket, getTicketMessages }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,112 +1,112 @@
|
||||
/* eslint-disable camelcase */
|
||||
const { ProvinceModel, CityModel } = require('../../../models/StateCity')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setAddress = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { province_id, city_id, address, lat, lng, show_location } = req.body
|
||||
// اعتبارسنجی دادهها
|
||||
if (!province_id || !city_id || !address || !lat || !lng || show_location === 'undefined') {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی ناقص است'
|
||||
})
|
||||
}
|
||||
|
||||
// یافتن کاربر با شماره موبایل
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// یافتن استان و شهر
|
||||
const province = await ProvinceModel.findOne({ id: province_id })
|
||||
const city = await CityModel.findOne({ id: city_id })
|
||||
if (!province || !city) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'استان یا شهر موردنظر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.province = province
|
||||
user.city = city
|
||||
user.address = address
|
||||
user.lat = lat
|
||||
user.lng = lng
|
||||
user.show_location = show_location
|
||||
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'آدرس با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateAddress = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { province_id, city_id, address, lat, lng, show_location } = req.body
|
||||
|
||||
// اعتبارسنجی دادهها
|
||||
if (!province_id || !city_id || !address || !lat || !lng || show_location === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی ناقص است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// یافتن کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// یافتن استان و شهر با استفاده از شناسه استان و شهر
|
||||
const province = await ProvinceModel.findOne({ id: province_id })
|
||||
const city = await CityModel.findOne({ id: city_id })
|
||||
if (!province || !city) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'استان یا شهر مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بهروزرسانی اطلاعات آدرس کاربر
|
||||
user.province = province
|
||||
user.city = city
|
||||
user.address = address
|
||||
user.lat = lat
|
||||
user.lng = lng
|
||||
user.show_location = show_location
|
||||
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'آدرس با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setAddress, updateAddress
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const { ProvinceModel, CityModel } = require('../../../models/StateCity')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setAddress = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { province_id, city_id, address, lat, lng, show_location } = req.body
|
||||
// اعتبارسنجی دادهها
|
||||
if (!province_id || !city_id || !address || !lat || !lng || show_location === 'undefined') {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی ناقص است'
|
||||
})
|
||||
}
|
||||
|
||||
// یافتن کاربر با شماره موبایل
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// یافتن استان و شهر
|
||||
const province = await ProvinceModel.findOne({ id: province_id })
|
||||
const city = await CityModel.findOne({ id: city_id })
|
||||
if (!province || !city) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'استان یا شهر موردنظر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.province = province
|
||||
user.city = city
|
||||
user.address = address
|
||||
user.lat = lat
|
||||
user.lng = lng
|
||||
user.show_location = show_location
|
||||
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'آدرس با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateAddress = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { province_id, city_id, address, lat, lng, show_location } = req.body
|
||||
|
||||
// اعتبارسنجی دادهها
|
||||
if (!province_id || !city_id || !address || !lat || !lng || show_location === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی ناقص است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// یافتن کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// یافتن استان و شهر با استفاده از شناسه استان و شهر
|
||||
const province = await ProvinceModel.findOne({ id: province_id })
|
||||
const city = await CityModel.findOne({ id: city_id })
|
||||
if (!province || !city) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'استان یا شهر مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بهروزرسانی اطلاعات آدرس کاربر
|
||||
user.province = province
|
||||
user.city = city
|
||||
user.address = address
|
||||
user.lat = lat
|
||||
user.lng = lng
|
||||
user.show_location = show_location
|
||||
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'آدرس با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setAddress, updateAddress
|
||||
}
|
||||
|
||||
@@ -1,108 +1,108 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const saveAuthValidationRules = () => {
|
||||
return [
|
||||
check('shaba').notEmpty().withMessage('شماره شبا نمیتواند خالی باشد')
|
||||
.matches(/^(?=.{24}$)[0-9]*$/).withMessage('فرمت شماره شبا صحیح نیست'),
|
||||
check('birthday').notEmpty().withMessage('تاریخ تولد نمیتواند خالی باشد'),
|
||||
check('national_code').notEmpty().withMessage('کد ملی نمیتواند خالی باشد')
|
||||
.isLength({ min: 10, max: 10 }).withMessage('کد ملی باید 10 رقم باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const saveAuth = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const { shaba, birthday, national_code } = req.body
|
||||
if (!shaba || !birthday || !national_code) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بررسی تکراری بودن کد ملی
|
||||
const existingUserWithNationalCode = await UserModel.findOne({ national_code })
|
||||
if (existingUserWithNationalCode && existingUserWithNationalCode._id.toString() !== user._id.toString()) {
|
||||
return res.status(409).json({
|
||||
error: true,
|
||||
message: 'کد ملی تکراری است'
|
||||
})
|
||||
}
|
||||
user.shaba = shaba
|
||||
user.birthday = birthday
|
||||
user.national_code = national_code
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'اطلاعات با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateShaba = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
const { shaba } = req.body
|
||||
|
||||
if (!shaba) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شبا ارسال نشده است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// جستجوی کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// فقط شبا را بهروزرسانی کنید
|
||||
user.shaba = shaba
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'شبا با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
saveAuth, saveAuthValidationRules, updateShaba
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const { check, validationResult } = require('express-validator')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const saveAuthValidationRules = () => {
|
||||
return [
|
||||
check('shaba').notEmpty().withMessage('شماره شبا نمیتواند خالی باشد')
|
||||
.matches(/^(?=.{24}$)[0-9]*$/).withMessage('فرمت شماره شبا صحیح نیست'),
|
||||
check('birthday').notEmpty().withMessage('تاریخ تولد نمیتواند خالی باشد'),
|
||||
check('national_code').notEmpty().withMessage('کد ملی نمیتواند خالی باشد')
|
||||
.isLength({ min: 10, max: 10 }).withMessage('کد ملی باید 10 رقم باشد')
|
||||
]
|
||||
}
|
||||
|
||||
const saveAuth = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
const { shaba, birthday, national_code } = req.body
|
||||
if (!shaba || !birthday || !national_code) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بررسی تکراری بودن کد ملی
|
||||
const existingUserWithNationalCode = await UserModel.findOne({ national_code })
|
||||
if (existingUserWithNationalCode && existingUserWithNationalCode._id.toString() !== user._id.toString()) {
|
||||
return res.status(409).json({
|
||||
error: true,
|
||||
message: 'کد ملی تکراری است'
|
||||
})
|
||||
}
|
||||
user.shaba = shaba
|
||||
user.birthday = birthday
|
||||
user.national_code = national_code
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'اطلاعات با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateShaba = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const errors = validationResult(req)
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() })
|
||||
}
|
||||
|
||||
const { shaba } = req.body
|
||||
|
||||
if (!shaba) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شبا ارسال نشده است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// جستجوی کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// فقط شبا را بهروزرسانی کنید
|
||||
user.shaba = shaba
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'شبا با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
saveAuth, saveAuthValidationRules, updateShaba
|
||||
}
|
||||
|
||||
@@ -1,80 +1,80 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setColors = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { eye_color, hair_color } = req.body
|
||||
if (!eye_color || !hair_color) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.eye_color = eye_color
|
||||
user.hair_color = hair_color
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'رنگ ها با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateColors = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { eye_color, hair_color } = req.body
|
||||
|
||||
// اعتبارسنجی دادهها
|
||||
if (!eye_color || !hair_color) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی ناقص است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// یافتن کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بهروزرسانی اطلاعات رنگها
|
||||
user.eye_color = eye_color
|
||||
user.hair_color = hair_color
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'رنگها با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setColors, updateColors
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setColors = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { eye_color, hair_color } = req.body
|
||||
if (!eye_color || !hair_color) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.eye_color = eye_color
|
||||
user.hair_color = hair_color
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'رنگ ها با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateColors = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { eye_color, hair_color } = req.body
|
||||
|
||||
// اعتبارسنجی دادهها
|
||||
if (!eye_color || !hair_color) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی ناقص است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// یافتن کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بهروزرسانی اطلاعات رنگها
|
||||
user.eye_color = eye_color
|
||||
user.hair_color = hair_color
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'رنگها با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setColors, updateColors
|
||||
}
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setConversation = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { bio, conversation_projects } = req.body
|
||||
if (!bio || conversation_projects === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.bio = bio
|
||||
user.conversation_projects = conversation_projects
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'روابط عمومی با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateConversation = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { bio, conversation_projects } = req.body
|
||||
|
||||
if (!bio || conversation_projects === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// جستجوی کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
user.bio = bio
|
||||
user.conversation_projects = conversation_projects
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'روابط عمومی با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setConversation, updateConversation
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setConversation = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { bio, conversation_projects } = req.body
|
||||
if (!bio || conversation_projects === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.bio = bio
|
||||
user.conversation_projects = conversation_projects
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'روابط عمومی با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateConversation = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { bio, conversation_projects } = req.body
|
||||
|
||||
if (!bio || conversation_projects === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// جستجوی کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
user.bio = bio
|
||||
user.conversation_projects = conversation_projects
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'روابط عمومی با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setConversation, updateConversation
|
||||
}
|
||||
|
||||
@@ -1,93 +1,93 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setCooperationType = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { cooperation_type, cooperation_abroad } = req.body
|
||||
if (!cooperation_type || cooperation_abroad === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
if (!['all', 'verified'].includes(cooperation_type)) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نوع همکاری نیست'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.cooperation_type = cooperation_type
|
||||
user.cooperation_abroad = cooperation_abroad
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نوع همکاری با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateCooperationType = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { cooperation_type, cooperation_abroad } = req.body
|
||||
|
||||
if (!cooperation_type || cooperation_abroad === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
if (!['all', 'verified'].includes(cooperation_type)) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نوع همکاری نامعتبر است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// جستجوی کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.cooperation_type = cooperation_type
|
||||
user.cooperation_abroad = cooperation_abroad
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نوع همکاری با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setCooperationType,
|
||||
updateCooperationType
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setCooperationType = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { cooperation_type, cooperation_abroad } = req.body
|
||||
if (!cooperation_type || cooperation_abroad === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
if (!['all', 'verified'].includes(cooperation_type)) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نوع همکاری نیست'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.cooperation_type = cooperation_type
|
||||
user.cooperation_abroad = cooperation_abroad
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نوع همکاری با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const updateCooperationType = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { cooperation_type, cooperation_abroad } = req.body
|
||||
|
||||
if (!cooperation_type || cooperation_abroad === undefined) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
if (!['all', 'verified'].includes(cooperation_type)) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'نوع همکاری نامعتبر است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// جستجوی کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.cooperation_type = cooperation_type
|
||||
user.cooperation_abroad = cooperation_abroad
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'نوع همکاری با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setCooperationType,
|
||||
updateCooperationType
|
||||
}
|
||||
|
||||
@@ -1,81 +1,81 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setExpertise = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { expertise, sub_expertise } = req.body
|
||||
if (!expertise || !sub_expertise) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نام کاربری به صورت lowercase
|
||||
user.expertise = expertise
|
||||
user.sub_expertise = sub_expertise
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'تخصص با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateExpertise = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { expertise, sub_expertise } = req.body
|
||||
|
||||
// اعتبارسنجی دادهها
|
||||
if (!expertise || !sub_expertise) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی ناقص است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// یافتن کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بهروزرسانی اطلاعات تخصص و زیرتخصص
|
||||
user.expertise = expertise
|
||||
user.sub_expertise = sub_expertise
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'تخصص با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setExpertise, updateExpertise
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setExpertise = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { expertise, sub_expertise } = req.body
|
||||
if (!expertise || !sub_expertise) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نام کاربری به صورت lowercase
|
||||
user.expertise = expertise
|
||||
user.sub_expertise = sub_expertise
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'تخصص با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateExpertise = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { expertise, sub_expertise } = req.body
|
||||
|
||||
// اعتبارسنجی دادهها
|
||||
if (!expertise || !sub_expertise) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی ناقص است'
|
||||
})
|
||||
}
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
|
||||
// یافتن کاربر با استفاده از شناسه کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شناسه یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// بهروزرسانی اطلاعات تخصص و زیرتخصص
|
||||
user.expertise = expertise
|
||||
user.sub_expertise = sub_expertise
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'تخصص با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setExpertise, updateExpertise
|
||||
}
|
||||
|
||||
@@ -1,46 +1,46 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setGender = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { gender } = req.body
|
||||
if (!gender) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ورودی اشتباه است'
|
||||
})
|
||||
}
|
||||
if (!['male', 'female'].includes(gender)) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'جنسیت معتبر نیست'
|
||||
})
|
||||
}
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نوع یوزر
|
||||
user.gender = gender.toLowerCase()
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'جنسیت با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setGender
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setGender = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { gender } = req.body
|
||||
if (!gender) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ورودی اشتباه است'
|
||||
})
|
||||
}
|
||||
if (!['male', 'female'].includes(gender)) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'جنسیت معتبر نیست'
|
||||
})
|
||||
}
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
// آپدیت نوع یوزر
|
||||
user.gender = gender.toLowerCase()
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'جنسیت با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setGender
|
||||
}
|
||||
|
||||
@@ -1,107 +1,107 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
|
||||
const setServices = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
const { services } = req.body
|
||||
if (!services) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// مدیریت تصاویر برای خدمات
|
||||
const servicesWithImages = []
|
||||
const parsedServices = JSON.parse(services) // پارس کردن رشته JSON به آرایه جاوا اسکریپت
|
||||
if (parsedServices && parsedServices.length > 0) {
|
||||
for (const service of parsedServices) {
|
||||
const serviceImages = []
|
||||
const serviceId = service.id
|
||||
if (req.files && req.files.serviceImages && req.files.serviceImages[serviceId]) {
|
||||
const imageFiles = Array.isArray(req.files.serviceImages[serviceId]) ? req.files.serviceImages[serviceId] : [req.files.serviceImages[serviceId]]
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/services')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
for (const imageFile of imageFiles) {
|
||||
const uniqueFileName = `${user.user_name}-${Date.now()}${Math.random().toString().slice(2, 11)}${path.extname(imageFile.name)}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
// await fs.promises.rename(imageFile.path, filePath)
|
||||
await fs.move(imageFile.path, filePath)
|
||||
const imageUrl = `/services/${uniqueFileName}`
|
||||
serviceImages.push(imageUrl)
|
||||
// بهروزرسانی مسیر تصویر در آبجکت service
|
||||
service.image = imageUrl
|
||||
}
|
||||
} else {
|
||||
console.log('sss')
|
||||
}
|
||||
servicesWithImages.push({ ...service, images: serviceImages })
|
||||
}
|
||||
}
|
||||
|
||||
user.services = servicesWithImages
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'خدمات با موفقیت ثبت شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateServices = async (req, res, next) => {
|
||||
try {
|
||||
const { height, weight, size } = req.body
|
||||
|
||||
if (!height || !weight || !size) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// جستجوی کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.height = height
|
||||
user.weight = weight
|
||||
user.size = size
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'سایز با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setServices, updateServices
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
|
||||
const setServices = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'شما دسترسی به این بخش ندارید'
|
||||
})
|
||||
}
|
||||
const { services } = req.body
|
||||
if (!services) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// مدیریت تصاویر برای خدمات
|
||||
const servicesWithImages = []
|
||||
const parsedServices = JSON.parse(services) // پارس کردن رشته JSON به آرایه جاوا اسکریپت
|
||||
if (parsedServices && parsedServices.length > 0) {
|
||||
for (const service of parsedServices) {
|
||||
const serviceImages = []
|
||||
const serviceId = service.id
|
||||
if (req.files && req.files.serviceImages && req.files.serviceImages[serviceId]) {
|
||||
const imageFiles = Array.isArray(req.files.serviceImages[serviceId]) ? req.files.serviceImages[serviceId] : [req.files.serviceImages[serviceId]]
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/services')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
for (const imageFile of imageFiles) {
|
||||
const uniqueFileName = `${user.user_name}-${Date.now()}${Math.random().toString().slice(2, 11)}${path.extname(imageFile.name)}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
// await fs.promises.rename(imageFile.path, filePath)
|
||||
await fs.move(imageFile.path, filePath)
|
||||
const imageUrl = `/services/${uniqueFileName}`
|
||||
serviceImages.push(imageUrl)
|
||||
// بهروزرسانی مسیر تصویر در آبجکت service
|
||||
service.image = imageUrl
|
||||
}
|
||||
} else {
|
||||
console.log('sss')
|
||||
}
|
||||
servicesWithImages.push({ ...service, images: serviceImages })
|
||||
}
|
||||
}
|
||||
|
||||
user.services = servicesWithImages
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'خدمات با موفقیت ثبت شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateServices = async (req, res, next) => {
|
||||
try {
|
||||
const { height, weight, size } = req.body
|
||||
|
||||
if (!height || !weight || !size) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// جستجوی کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.height = height
|
||||
user.weight = weight
|
||||
user.size = size
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'سایز با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setServices, updateServices
|
||||
}
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
/* eslint-disable camelcase */
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setNationalCardImage = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { national_card_image } = req.files
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
// بررسی آیا فایل آپلود شده است
|
||||
if (!national_card_image) {
|
||||
return res.status(400).json({
|
||||
error: true,
|
||||
message: 'لطفاً عکس کارت ملی را انتخاب کنید'
|
||||
})
|
||||
}
|
||||
|
||||
// ذخیره فایل عکس پروفایل
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/carts')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
|
||||
const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(national_card_image.name)}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
await fs.move(national_card_image.path, filePath)
|
||||
|
||||
// ذخیره مسیر فایل در دیتابیس
|
||||
user.national_card_image = `/carts/${uniqueFileName}`
|
||||
user.is_verified = 'pending'
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'عکس کارت ملی با موفقیت ذخیره شد',
|
||||
national_card_image: user.national_card_image
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setNationalCardImage
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setNationalCardImage = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { national_card_image } = req.files
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
// بررسی آیا فایل آپلود شده است
|
||||
if (!national_card_image) {
|
||||
return res.status(400).json({
|
||||
error: true,
|
||||
message: 'لطفاً عکس کارت ملی را انتخاب کنید'
|
||||
})
|
||||
}
|
||||
|
||||
// ذخیره فایل عکس پروفایل
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/carts')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
|
||||
const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(national_card_image.name)}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
await fs.move(national_card_image.path, filePath)
|
||||
|
||||
// ذخیره مسیر فایل در دیتابیس
|
||||
user.national_card_image = `/carts/${uniqueFileName}`
|
||||
user.is_verified = 'pending'
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'عکس کارت ملی با موفقیت ذخیره شد',
|
||||
national_card_image: user.national_card_image
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
setNationalCardImage
|
||||
}
|
||||
|
||||
@@ -1,105 +1,105 @@
|
||||
/* eslint-disable camelcase */
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setProfileImage = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { mobile } = req.body
|
||||
const { profile_image } = req.files
|
||||
if (!mobile) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
// بررسی آیا فایل آپلود شده است
|
||||
if (!profile_image) {
|
||||
return res.status(400).json({
|
||||
error: true,
|
||||
message: 'لطفاً عکس پروفایل را انتخاب کنید'
|
||||
})
|
||||
}
|
||||
|
||||
// ذخیره فایل عکس پروفایل
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/profiles')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(profile_image.name)}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
|
||||
await fs.move(profile_image.path, filePath)
|
||||
// ذخیره مسیر فایل در دیتابیس
|
||||
user.profile_image = `/profiles/${uniqueFileName}`
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'عکس پروفایل با موفقیت ذخیره شد',
|
||||
profile_image: user.profile_image
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateProfileImage = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const { profile_image } = req.files
|
||||
|
||||
if (!profile_image) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/profiles')
|
||||
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
|
||||
const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(profile_image.name)}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
|
||||
await fs.move(profile_image.path, filePath)
|
||||
|
||||
user.profile_image = `/profiles/${uniqueFileName}`
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'عکس پروفایل با موفقیت بهروزرسانی شد',
|
||||
profile_image: user.profile_image
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setProfileImage, updateProfileImage
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const fs = require('fs-extra')
|
||||
const path = require('path')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setProfileImage = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { mobile } = req.body
|
||||
const { profile_image } = req.files
|
||||
if (!mobile) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
// بررسی آیا فایل آپلود شده است
|
||||
if (!profile_image) {
|
||||
return res.status(400).json({
|
||||
error: true,
|
||||
message: 'لطفاً عکس پروفایل را انتخاب کنید'
|
||||
})
|
||||
}
|
||||
|
||||
// ذخیره فایل عکس پروفایل
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/profiles')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(profile_image.name)}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
|
||||
await fs.move(profile_image.path, filePath)
|
||||
// ذخیره مسیر فایل در دیتابیس
|
||||
user.profile_image = `/profiles/${uniqueFileName}`
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'عکس پروفایل با موفقیت ذخیره شد',
|
||||
profile_image: user.profile_image
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateProfileImage = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const { profile_image } = req.files
|
||||
|
||||
if (!profile_image) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
const uploadDir = path.join(__dirname, '../../../../storage/profiles')
|
||||
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir, { recursive: true })
|
||||
}
|
||||
|
||||
const uniqueFileName = `${user.user_name}-${Date.now()}${path.extname(profile_image.name)}`
|
||||
const filePath = path.join(uploadDir, uniqueFileName)
|
||||
|
||||
await fs.move(profile_image.path, filePath)
|
||||
|
||||
user.profile_image = `/profiles/${uniqueFileName}`
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'عکس پروفایل با موفقیت بهروزرسانی شد',
|
||||
profile_image: user.profile_image
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setProfileImage, updateProfileImage
|
||||
}
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setSizes = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { height, weight, size } = req.body
|
||||
if (!height || !weight || !size) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.height = height
|
||||
user.weight = weight
|
||||
user.size = size
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'سایز با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateSizes = async (req, res, next) => {
|
||||
try {
|
||||
const { height, weight, size } = req.body
|
||||
|
||||
if (!height || !weight || !size) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// جستجوی کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.height = height
|
||||
user.weight = weight
|
||||
user.size = size
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'سایز با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setSizes, updateSizes
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
|
||||
const setSizes = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const { height, weight, size } = req.body
|
||||
if (!height || !weight || !size) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
// جستجوی کاربر با شماره موبایل ارسالی
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربری با این شماره موبایل یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.height = height
|
||||
user.weight = weight
|
||||
user.size = size
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'سایز با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateSizes = async (req, res, next) => {
|
||||
try {
|
||||
const { height, weight, size } = req.body
|
||||
|
||||
if (!height || !weight || !size) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// جستجوی کاربر
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (!user) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کاربر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
user.height = height
|
||||
user.weight = weight
|
||||
user.size = size
|
||||
await user.save()
|
||||
|
||||
return res.json({
|
||||
message: 'سایز با موفقیت بهروزرسانی شد'
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
setSizes, updateSizes
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
const VersionModel = require('../../../models/VersionModel')
|
||||
|
||||
// Endpoint برای دریافت نسخه فعلی
|
||||
const getVersion = async (req, res, next) => {
|
||||
try {
|
||||
const currentVersion = await VersionModel.findOne().sort({ _id: -1 }).exec()
|
||||
if (!currentVersion) {
|
||||
return res.status(200).json({ message: 'نسخهای پیدا نشد' })
|
||||
}
|
||||
res.json(currentVersion)
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: 'خطای سرور', error })
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getVersion }
|
||||
const VersionModel = require('../../../models/VersionModel')
|
||||
|
||||
// Endpoint برای دریافت نسخه فعلی
|
||||
const getVersion = async (req, res, next) => {
|
||||
try {
|
||||
const currentVersion = await VersionModel.findOne().sort({ _id: -1 }).exec()
|
||||
if (!currentVersion) {
|
||||
return res.status(200).json({ message: 'نسخهای پیدا نشد' })
|
||||
}
|
||||
res.json(currentVersion)
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: 'خطای سرور', error })
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { getVersion }
|
||||
|
||||
@@ -1,232 +1,232 @@
|
||||
/* eslint-disable camelcase */
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const RequestModel = require('../../../models/RequestModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const calculateRemainingTime = (milliseconds) => {
|
||||
const days = Math.floor(milliseconds / (1000 * 60 * 60 * 24))
|
||||
const hours = Math.floor((milliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
|
||||
|
||||
return `${days} روز و ${hours} ساعت`
|
||||
}
|
||||
const getProjects = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
const { status_filter, page = 1, limit = 10 } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
// ساخت فیلتر برای استفاده در جستجوی MongoDB
|
||||
let filter = {} // افزودن شرط برای payment_status
|
||||
if (user.user_type === 'user') {
|
||||
if (status_filter) {
|
||||
if (status_filter === 'دریافتی') {
|
||||
filter = { created_for_user: userId, status: 'accepted' }
|
||||
} else if (status_filter === 'ارسال شده') {
|
||||
filter = { requested_users: userId, status: 'accepted' }
|
||||
} else if (status_filter === 'در دست اقدام') {
|
||||
filter = { selected_user: userId, status: 'ongoing' }
|
||||
} else if (status_filter === 'اتمام پروژه') {
|
||||
filter = { selected_user: userId, status: 'done' }
|
||||
} else if (status_filter === 'کنسل شده') {
|
||||
filter = { selected_user: userId, status: 'cancled' }
|
||||
} else {
|
||||
filter = {
|
||||
$or: [
|
||||
{ selected_user: userId },
|
||||
{ requested_users: userId },
|
||||
{ created_for_user: userId }
|
||||
]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filter = {
|
||||
$or: [
|
||||
{ selected_user: userId },
|
||||
{ requested_users: userId },
|
||||
{ created_for_user: userId }
|
||||
]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (status_filter) {
|
||||
if (status_filter === 'منتشر شده') {
|
||||
filter = { creator_id: userId, status: 'accepted' }
|
||||
} else if (status_filter === 'در دست اقدام') {
|
||||
filter = { creator_id: userId, status: 'ongoing' }
|
||||
} else if (status_filter === 'اتمام پروژه') {
|
||||
filter = { creator_id: userId, status: 'done' }
|
||||
} else if (status_filter === 'کنسل شده') {
|
||||
filter = { creator_id: userId, status: 'cancled' }
|
||||
} else if (status_filter === 'در دست بررسی') {
|
||||
filter = { creator_id: userId, status: { $in: ['paid', 'rejected'] } }
|
||||
} else if (status_filter === 'پرداخت نشده') {
|
||||
filter = { creator_id: userId, status: 'pre_payment' }
|
||||
} else {
|
||||
filter = { creator_id: userId }
|
||||
}
|
||||
} else {
|
||||
filter = { creator_id: userId }
|
||||
}
|
||||
}
|
||||
// paid
|
||||
// دریافت لیست پروژهها با استفاده از فیلتر
|
||||
|
||||
// استفاده از مدل پیجینیت شده برای دریافت نتایج صفحهبندی شده
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
const projects = await ProjectModel.paginate(filter, options)
|
||||
const projectsWithUserInfo = await Promise.all(projects?.docs.map(async project => {
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
const projectWithUserInfo = {
|
||||
...project._doc,
|
||||
creator,
|
||||
status_filter
|
||||
}
|
||||
const currentTime = new Date()
|
||||
const projectCreatedAt = new Date(project.createdAt)
|
||||
const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
const remainingTime = calculateRemainingTime(timeDiff)
|
||||
projectWithUserInfo.remainingTime = remainingTime
|
||||
return projectWithUserInfo
|
||||
}))
|
||||
res.status(200).json({
|
||||
projects: projectsWithUserInfo,
|
||||
totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getSingleProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const projectId = req.query.projectId
|
||||
const projectRequests = await RequestModel.find({ project: projectId })
|
||||
.populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image')
|
||||
.sort({ status: 1 })
|
||||
.lean()
|
||||
const modifiedRequests = projectRequests.map(request => ({
|
||||
...request,
|
||||
time: request?.user?._id.toString() === userId ? request.time : null,
|
||||
price: request?.user?._id.toString() === userId ? request.price : null
|
||||
}))
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' })
|
||||
}
|
||||
// محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده
|
||||
// تابع محاسبه مبلغ پرداخت شده
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
let totalPaidAmount = 0
|
||||
installments.forEach(installment => {
|
||||
totalPaidAmount += installment.amount
|
||||
})
|
||||
return totalPaidAmount
|
||||
}
|
||||
|
||||
// تابع محاسبه مبلغ باقیمانده
|
||||
const getRemainingAmount = (project) => {
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = project.final_price - totalPaidAmount
|
||||
return remainingAmount
|
||||
}
|
||||
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
// اطلاعات کاربر سازنده را نیز دریافت کنید و به آبجکت پروژه اضافه کنید
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
|
||||
const projectWithUserInfo = {
|
||||
...project._doc,
|
||||
creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه
|
||||
}
|
||||
const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score')
|
||||
projectWithUserInfo.selected_user = selectedUser
|
||||
// محاسبه مدت زمان باقیمانده برای پروژه
|
||||
const currentTime = new Date()
|
||||
const projectCreatedAt = new Date(project.createdAt)
|
||||
const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
const remainingTime = calculateRemainingTime(timeDiff)
|
||||
projectWithUserInfo.remainingTime = remainingTime
|
||||
let projectDetails = projectWithUserInfo
|
||||
if ((project.selected_user && project.selected_user.toString()) === userId || project.creator_id.toString() === userId) {
|
||||
projectDetails = {
|
||||
...projectWithUserInfo,
|
||||
total_paid_amount: totalPaidAmount,
|
||||
remaining_amount: remainingAmount
|
||||
}
|
||||
} else {
|
||||
projectDetails =
|
||||
projectWithUserInfo
|
||||
}
|
||||
// }
|
||||
res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const getProjectRequests = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// بررسی اینکه آیا کاربر ایجاد کننده پروژه است یا خیر
|
||||
const projectId = req.params.projectId
|
||||
const project = await ProjectModel.findOne({ _id: projectId, creator_id: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
|
||||
// تابع محاسبه مبلغ پرداخت شده
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
let totalPaidAmount = 0
|
||||
installments.forEach(installment => {
|
||||
totalPaidAmount += installment.amount
|
||||
})
|
||||
return totalPaidAmount
|
||||
}
|
||||
|
||||
// تابع محاسبه مبلغ باقیمانده
|
||||
const getRemainingAmount = (project) => {
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = project.final_price - totalPaidAmount
|
||||
return remainingAmount
|
||||
}
|
||||
|
||||
// محاسبه مبلغ باقیمانده
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
|
||||
// یافتن جزییات پروژه
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score')
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
|
||||
const projectRequests = await RequestModel.find({ project: projectId }).populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image').sort({ status: 1 })
|
||||
const projectinfo = await ProjectModel.findById(projectId) // جزییات درخواستهای کاربران
|
||||
projectinfo.selected_user = selectedUser
|
||||
const projectDetails = {
|
||||
...projectinfo._doc,
|
||||
creator,
|
||||
total_paid_amount: totalPaidAmount,
|
||||
remaining_amount: remainingAmount
|
||||
}
|
||||
res.status(200).json({ projectRequests, projectDetails })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getProjects, getSingleProject, getProjectRequests
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const ProjectModel = require('../../../models/ProjectModel')
|
||||
const RequestModel = require('../../../models/RequestModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const jwt = require('jsonwebtoken')
|
||||
const calculateRemainingTime = (milliseconds) => {
|
||||
const days = Math.floor(milliseconds / (1000 * 60 * 60 * 24))
|
||||
const hours = Math.floor((milliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
|
||||
|
||||
return `${days} روز و ${hours} ساعت`
|
||||
}
|
||||
const getProjects = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const user = await UserModel.findById(decodedToken.id)
|
||||
const { status_filter, page = 1, limit = 10 } = req.query // افزودن پارامترهای صفحهبندی به درخواست
|
||||
// ساخت فیلتر برای استفاده در جستجوی MongoDB
|
||||
let filter = {} // افزودن شرط برای payment_status
|
||||
if (user.user_type === 'user') {
|
||||
if (status_filter) {
|
||||
if (status_filter === 'دریافتی') {
|
||||
filter = { created_for_user: userId, status: 'accepted' }
|
||||
} else if (status_filter === 'ارسال شده') {
|
||||
filter = { requested_users: userId, status: 'accepted' }
|
||||
} else if (status_filter === 'در دست اقدام') {
|
||||
filter = { selected_user: userId, status: 'ongoing' }
|
||||
} else if (status_filter === 'اتمام پروژه') {
|
||||
filter = { selected_user: userId, status: 'done' }
|
||||
} else if (status_filter === 'کنسل شده') {
|
||||
filter = { selected_user: userId, status: 'cancled' }
|
||||
} else {
|
||||
filter = {
|
||||
$or: [
|
||||
{ selected_user: userId },
|
||||
{ requested_users: userId },
|
||||
{ created_for_user: userId }
|
||||
]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
filter = {
|
||||
$or: [
|
||||
{ selected_user: userId },
|
||||
{ requested_users: userId },
|
||||
{ created_for_user: userId }
|
||||
]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (status_filter) {
|
||||
if (status_filter === 'منتشر شده') {
|
||||
filter = { creator_id: userId, status: 'accepted' }
|
||||
} else if (status_filter === 'در دست اقدام') {
|
||||
filter = { creator_id: userId, status: 'ongoing' }
|
||||
} else if (status_filter === 'اتمام پروژه') {
|
||||
filter = { creator_id: userId, status: 'done' }
|
||||
} else if (status_filter === 'کنسل شده') {
|
||||
filter = { creator_id: userId, status: 'cancled' }
|
||||
} else if (status_filter === 'در دست بررسی') {
|
||||
filter = { creator_id: userId, status: { $in: ['paid', 'rejected'] } }
|
||||
} else if (status_filter === 'پرداخت نشده') {
|
||||
filter = { creator_id: userId, status: 'pre_payment' }
|
||||
} else {
|
||||
filter = { creator_id: userId }
|
||||
}
|
||||
} else {
|
||||
filter = { creator_id: userId }
|
||||
}
|
||||
}
|
||||
// paid
|
||||
// دریافت لیست پروژهها با استفاده از فیلتر
|
||||
|
||||
// استفاده از مدل پیجینیت شده برای دریافت نتایج صفحهبندی شده
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { createdAt: -1 }
|
||||
}
|
||||
const projects = await ProjectModel.paginate(filter, options)
|
||||
const projectsWithUserInfo = await Promise.all(projects?.docs.map(async project => {
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
const projectWithUserInfo = {
|
||||
...project._doc,
|
||||
creator,
|
||||
status_filter
|
||||
}
|
||||
const currentTime = new Date()
|
||||
const projectCreatedAt = new Date(project.createdAt)
|
||||
const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
const remainingTime = calculateRemainingTime(timeDiff)
|
||||
projectWithUserInfo.remainingTime = remainingTime
|
||||
return projectWithUserInfo
|
||||
}))
|
||||
res.status(200).json({
|
||||
projects: projectsWithUserInfo,
|
||||
totalPages: projects.totalPages, // ارسال تعداد کل صفحات
|
||||
totalItems: projects.totalDocs // ارسال تعداد کل آیتمها
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
const getSingleProject = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
const projectId = req.query.projectId
|
||||
const projectRequests = await RequestModel.find({ project: projectId })
|
||||
.populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image')
|
||||
.sort({ status: 1 })
|
||||
.lean()
|
||||
const modifiedRequests = projectRequests.map(request => ({
|
||||
...request,
|
||||
time: request?.user?._id.toString() === userId ? request.time : null,
|
||||
price: request?.user?._id.toString() === userId ? request.price : null
|
||||
}))
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({ message: 'پروژه مورد نظر یافت نشد' })
|
||||
}
|
||||
// محاسبه مبلغ باقیمانده و مجموع مبلغ پرداخت شده
|
||||
// تابع محاسبه مبلغ پرداخت شده
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
let totalPaidAmount = 0
|
||||
installments.forEach(installment => {
|
||||
totalPaidAmount += installment.amount
|
||||
})
|
||||
return totalPaidAmount
|
||||
}
|
||||
|
||||
// تابع محاسبه مبلغ باقیمانده
|
||||
const getRemainingAmount = (project) => {
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = project.final_price - totalPaidAmount
|
||||
return remainingAmount
|
||||
}
|
||||
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
// اطلاعات کاربر سازنده را نیز دریافت کنید و به آبجکت پروژه اضافه کنید
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
|
||||
const projectWithUserInfo = {
|
||||
...project._doc,
|
||||
creator // اضافه کردن اطلاعات کاربر به آبجکت پروژه
|
||||
}
|
||||
const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score')
|
||||
projectWithUserInfo.selected_user = selectedUser
|
||||
// محاسبه مدت زمان باقیمانده برای پروژه
|
||||
const currentTime = new Date()
|
||||
const projectCreatedAt = new Date(project.createdAt)
|
||||
const timeDiff = project.offer_time * 24 * 60 * 60 * 1000 - (currentTime - projectCreatedAt)
|
||||
const remainingTime = calculateRemainingTime(timeDiff)
|
||||
projectWithUserInfo.remainingTime = remainingTime
|
||||
let projectDetails = projectWithUserInfo
|
||||
if ((project.selected_user && project.selected_user.toString()) === userId || project.creator_id.toString() === userId) {
|
||||
projectDetails = {
|
||||
...projectWithUserInfo,
|
||||
total_paid_amount: totalPaidAmount,
|
||||
remaining_amount: remainingAmount
|
||||
}
|
||||
} else {
|
||||
projectDetails =
|
||||
projectWithUserInfo
|
||||
}
|
||||
// }
|
||||
res.status(200).json({ project: projectDetails, projectRequests: modifiedRequests })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
const getProjectRequests = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
const decodedToken = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decodedToken.id
|
||||
// بررسی اینکه آیا کاربر ایجاد کننده پروژه است یا خیر
|
||||
const projectId = req.params.projectId
|
||||
const project = await ProjectModel.findOne({ _id: projectId, creator_id: userId })
|
||||
if (!project) {
|
||||
return res.status(403).send({ message: 'Access denied: You are not the creator of this project.' })
|
||||
}
|
||||
|
||||
// تابع محاسبه مبلغ پرداخت شده
|
||||
const getTotalPaidAmount = (installments) => {
|
||||
let totalPaidAmount = 0
|
||||
installments.forEach(installment => {
|
||||
totalPaidAmount += installment.amount
|
||||
})
|
||||
return totalPaidAmount
|
||||
}
|
||||
|
||||
// تابع محاسبه مبلغ باقیمانده
|
||||
const getRemainingAmount = (project) => {
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
const remainingAmount = project.final_price - totalPaidAmount
|
||||
return remainingAmount
|
||||
}
|
||||
|
||||
// محاسبه مبلغ باقیمانده
|
||||
const remainingAmount = getRemainingAmount(project)
|
||||
|
||||
// یافتن جزییات پروژه
|
||||
const creator = await UserModel.findById(project.creator_id).select('first_name last_name user_name user_type is_verified profile_image gender province city rate')
|
||||
const selectedUser = await UserModel.findById(project.selected_user).select('_id user_name first_name last_name user_type is_verified profile_image expertise sub_expertise province city rate user_level user_score')
|
||||
const totalPaidAmount = getTotalPaidAmount(project.installments)
|
||||
|
||||
const projectRequests = await RequestModel.find({ project: projectId }).populate('user', 'price time user_level first_name last_name user_name is_verified user_score rate profile_image').sort({ status: 1 })
|
||||
const projectinfo = await ProjectModel.findById(projectId) // جزییات درخواستهای کاربران
|
||||
projectinfo.selected_user = selectedUser
|
||||
const projectDetails = {
|
||||
...projectinfo._doc,
|
||||
creator,
|
||||
total_paid_amount: totalPaidAmount,
|
||||
remaining_amount: remainingAmount
|
||||
}
|
||||
res.status(200).json({ projectRequests, projectDetails })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
module.exports = {
|
||||
getProjects, getSingleProject, getProjectRequests
|
||||
}
|
||||
|
||||
@@ -1,50 +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 });
|
||||
}
|
||||
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 });
|
||||
}
|
||||
};
|
||||
@@ -1,350 +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
|
||||
}
|
||||
/* 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
|
||||
}
|
||||
|
||||
@@ -1,195 +1,195 @@
|
||||
/* eslint-disable camelcase */
|
||||
const AdvertisingComment = require('../../../models/AdvertisingCommentModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const mongoose = require('mongoose')
|
||||
const AdvertisingModel = require('../../../models/AdvertisingModel')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
|
||||
// دریافت کامنتها
|
||||
const getAdvertisingComments = 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,
|
||||
startDate,
|
||||
endDate,
|
||||
status
|
||||
} = req.query
|
||||
const filter = {}
|
||||
|
||||
// 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: 'userId', select: 'user_name first_name last_name profile_image' },
|
||||
{ path: 'advertisingId', select: 'title', populate: { path: 'creator_id', select: 'user_name first_name last_name' } }
|
||||
// اضافه کردن اطلاعات سازنده
|
||||
]
|
||||
}
|
||||
|
||||
const comments = await AdvertisingComment.paginate(filter, options)
|
||||
const commentList = comments.docs.map(comment => ({
|
||||
_id: comment._id,
|
||||
createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'),
|
||||
status: comment.status,
|
||||
text: comment.text,
|
||||
advertising: comment.advertisingId ? comment.advertisingId.title : null,
|
||||
user: comment.userId ? {
|
||||
_id: comment.userId._id,
|
||||
user_name: comment.userId.user_name,
|
||||
first_name: comment.userId.first_name,
|
||||
last_name: comment.userId.last_name,
|
||||
profile_image: comment.userId.profile_image
|
||||
} : null,
|
||||
creator: (comment.advertisingId && comment.advertisingId.creator_id) ? {
|
||||
_id: comment.advertisingId.creator_id._id,
|
||||
user_name: comment.advertisingId.creator_id.user_name,
|
||||
first_name: comment.advertisingId.creator_id.first_name,
|
||||
last_name: comment.advertisingId.creator_id.last_name
|
||||
} : null
|
||||
}));
|
||||
|
||||
|
||||
res.status(200).json({
|
||||
comments: commentList,
|
||||
totalPages: comments.totalPages,
|
||||
totalItems: comments.totalDocs
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// دریافت جزئیات یک کامنت
|
||||
const getAdvertisingCommentDetail = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const comment_id = req.query.comment_id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(comment_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کامنت معتبر نیست' })
|
||||
}
|
||||
|
||||
const comment = await AdvertisingComment.findById(comment_id)
|
||||
.populate('userId', 'user_name first_name last_name profile_image')
|
||||
.populate({
|
||||
path: 'advertisingId',
|
||||
select: 'title creator_id',
|
||||
populate: {
|
||||
path: 'creator_id',
|
||||
select: 'user_name first_name last_name'
|
||||
}
|
||||
})
|
||||
if (!comment) {
|
||||
return res.status(404).json({ message: 'کامنت مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
const response = {
|
||||
_id: comment._id,
|
||||
text: comment.text,
|
||||
createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'),
|
||||
status: comment.status,
|
||||
advertising: comment.advertisingId ? comment.advertisingId.title : null,
|
||||
creator: {
|
||||
_id: comment?.advertisingId?.creator_id._id,
|
||||
user_name: comment?.advertisingId?.creator_id.user_name,
|
||||
first_name: comment?.advertisingId?.creator_id.first_name,
|
||||
last_name: comment?.advertisingId?.creator_id.last_name
|
||||
},
|
||||
user: {
|
||||
_id: comment.userId._id,
|
||||
user_name: comment.userId.user_name,
|
||||
first_name: comment.userId.first_name,
|
||||
last_name: comment.userId.last_name,
|
||||
profile_image: comment.userId.profile_image
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({ comment: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// تایید یک کامنت
|
||||
const acceptAdvertisingComment = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { id, status, text } = req.body
|
||||
|
||||
if (!id || !status) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const comment = await AdvertisingComment.findById(id)
|
||||
// افزایش تعداد کامنتهای تبلیغ
|
||||
await AdvertisingModel.findByIdAndUpdate(comment?.advertisingId, { $inc: { commentsCount: 1 } })
|
||||
if (!comment) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کامنت مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
if (text) {
|
||||
comment.text = text
|
||||
}
|
||||
comment.status = status
|
||||
await comment.save()
|
||||
|
||||
if (status === 'accepted') {
|
||||
const notification = new NotificationModel({
|
||||
user_id: comment?.userId,
|
||||
project_post_id: comment?.advertisingId,
|
||||
type: 'vitrine-comment',
|
||||
title: 'انتشار نظر',
|
||||
description: 'نظر شما منتشر شد.'
|
||||
})
|
||||
await notification.save()
|
||||
} else {
|
||||
const notification = new NotificationModel({
|
||||
user_id: comment?.userId,
|
||||
project_post_id: comment?.advertisingId,
|
||||
type: 'vitrine-comment',
|
||||
title: 'رد نظر',
|
||||
description: 'نظر شما رد شد.'
|
||||
})
|
||||
await notification.save()
|
||||
}
|
||||
res.status(201).json({ message: 'کامنت با موفقیت تایید شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getAdvertisingComments,
|
||||
getAdvertisingCommentDetail,
|
||||
acceptAdvertisingComment
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const AdvertisingComment = require('../../../models/AdvertisingCommentModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const mongoose = require('mongoose')
|
||||
const AdvertisingModel = require('../../../models/AdvertisingModel')
|
||||
const NotificationModel = require('../../../models/NotificationModel')
|
||||
|
||||
// دریافت کامنتها
|
||||
const getAdvertisingComments = 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,
|
||||
startDate,
|
||||
endDate,
|
||||
status
|
||||
} = req.query
|
||||
const filter = {}
|
||||
|
||||
// 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: 'userId', select: 'user_name first_name last_name profile_image' },
|
||||
{ path: 'advertisingId', select: 'title', populate: { path: 'creator_id', select: 'user_name first_name last_name' } }
|
||||
// اضافه کردن اطلاعات سازنده
|
||||
]
|
||||
}
|
||||
|
||||
const comments = await AdvertisingComment.paginate(filter, options)
|
||||
const commentList = comments.docs.map(comment => ({
|
||||
_id: comment._id,
|
||||
createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'),
|
||||
status: comment.status,
|
||||
text: comment.text,
|
||||
advertising: comment.advertisingId ? comment.advertisingId.title : null,
|
||||
user: comment.userId ? {
|
||||
_id: comment.userId._id,
|
||||
user_name: comment.userId.user_name,
|
||||
first_name: comment.userId.first_name,
|
||||
last_name: comment.userId.last_name,
|
||||
profile_image: comment.userId.profile_image
|
||||
} : null,
|
||||
creator: (comment.advertisingId && comment.advertisingId.creator_id) ? {
|
||||
_id: comment.advertisingId.creator_id._id,
|
||||
user_name: comment.advertisingId.creator_id.user_name,
|
||||
first_name: comment.advertisingId.creator_id.first_name,
|
||||
last_name: comment.advertisingId.creator_id.last_name
|
||||
} : null
|
||||
}));
|
||||
|
||||
|
||||
res.status(200).json({
|
||||
comments: commentList,
|
||||
totalPages: comments.totalPages,
|
||||
totalItems: comments.totalDocs
|
||||
})
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// دریافت جزئیات یک کامنت
|
||||
const getAdvertisingCommentDetail = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const comment_id = req.query.comment_id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(comment_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کامنت معتبر نیست' })
|
||||
}
|
||||
|
||||
const comment = await AdvertisingComment.findById(comment_id)
|
||||
.populate('userId', 'user_name first_name last_name profile_image')
|
||||
.populate({
|
||||
path: 'advertisingId',
|
||||
select: 'title creator_id',
|
||||
populate: {
|
||||
path: 'creator_id',
|
||||
select: 'user_name first_name last_name'
|
||||
}
|
||||
})
|
||||
if (!comment) {
|
||||
return res.status(404).json({ message: 'کامنت مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
const response = {
|
||||
_id: comment._id,
|
||||
text: comment.text,
|
||||
createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'),
|
||||
status: comment.status,
|
||||
advertising: comment.advertisingId ? comment.advertisingId.title : null,
|
||||
creator: {
|
||||
_id: comment?.advertisingId?.creator_id._id,
|
||||
user_name: comment?.advertisingId?.creator_id.user_name,
|
||||
first_name: comment?.advertisingId?.creator_id.first_name,
|
||||
last_name: comment?.advertisingId?.creator_id.last_name
|
||||
},
|
||||
user: {
|
||||
_id: comment.userId._id,
|
||||
user_name: comment.userId.user_name,
|
||||
first_name: comment.userId.first_name,
|
||||
last_name: comment.userId.last_name,
|
||||
profile_image: comment.userId.profile_image
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({ comment: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// تایید یک کامنت
|
||||
const acceptAdvertisingComment = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { id, status, text } = req.body
|
||||
|
||||
if (!id || !status) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const comment = await AdvertisingComment.findById(id)
|
||||
// افزایش تعداد کامنتهای تبلیغ
|
||||
await AdvertisingModel.findByIdAndUpdate(comment?.advertisingId, { $inc: { commentsCount: 1 } })
|
||||
if (!comment) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کامنت مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
|
||||
if (text) {
|
||||
comment.text = text
|
||||
}
|
||||
comment.status = status
|
||||
await comment.save()
|
||||
|
||||
if (status === 'accepted') {
|
||||
const notification = new NotificationModel({
|
||||
user_id: comment?.userId,
|
||||
project_post_id: comment?.advertisingId,
|
||||
type: 'vitrine-comment',
|
||||
title: 'انتشار نظر',
|
||||
description: 'نظر شما منتشر شد.'
|
||||
})
|
||||
await notification.save()
|
||||
} else {
|
||||
const notification = new NotificationModel({
|
||||
user_id: comment?.userId,
|
||||
project_post_id: comment?.advertisingId,
|
||||
type: 'vitrine-comment',
|
||||
title: 'رد نظر',
|
||||
description: 'نظر شما رد شد.'
|
||||
})
|
||||
await notification.save()
|
||||
}
|
||||
res.status(201).json({ message: 'کامنت با موفقیت تایید شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getAdvertisingComments,
|
||||
getAdvertisingCommentDetail,
|
||||
acceptAdvertisingComment
|
||||
}
|
||||
|
||||
@@ -1,172 +1,172 @@
|
||||
/* eslint-disable camelcase */
|
||||
const CommentModel = require('../../../models/CommentModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const { default: mongoose } = require('mongoose')
|
||||
|
||||
// دریافت لیست کامنتها با پیجینیشن
|
||||
const getComments = async (req, res, next) => {
|
||||
try {
|
||||
console.log("gg6");
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const {
|
||||
page = 1, limit = 10,
|
||||
startDate,
|
||||
endDate,
|
||||
status
|
||||
} = req.query
|
||||
const filter = {} // فیلتر بر اساس وضعیت کامنت
|
||||
|
||||
// Date
|
||||
if (startDate || endDate) {
|
||||
filter.createdAt = {}
|
||||
|
||||
if (startDate) {
|
||||
filter.createdAt.$gte = new Date(startDate) // تاریخ شروع
|
||||
}
|
||||
|
||||
if (endDate) {
|
||||
filter.createdAt.$lte = new Date(endDate) // تاریخ پایان
|
||||
}
|
||||
}
|
||||
console.log("gg8");
|
||||
if (status) {
|
||||
filter.status = status
|
||||
}
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { createdAt: -1 },
|
||||
populate: [
|
||||
{ path: 'creator', select: 'user_name first_name last_name profile_image ' },
|
||||
{ path: 'user', select: 'user_name first_name last_name' },
|
||||
{ path: 'project', select: 'title' }
|
||||
]
|
||||
}
|
||||
|
||||
const comments = await CommentModel.paginate(filter, options)
|
||||
const commentList = comments.docs.map(comment => ({
|
||||
_id: comment._id,
|
||||
createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'),
|
||||
status: comment.status,
|
||||
comment_for: comment.comment_for,
|
||||
project: comment.project ? comment.project.title : null,
|
||||
creator: comment.creator ? {
|
||||
_id: comment.creator._id,
|
||||
user_name: comment.creator.user_name,
|
||||
first_name: comment.creator.first_name,
|
||||
last_name: comment.creator.last_name,
|
||||
profile_image: comment.creator.profile_image
|
||||
} : null,
|
||||
user: comment.user ? {
|
||||
_id: comment.user._id,
|
||||
user_name: comment.user.user_name,
|
||||
first_name: comment.user.first_name,
|
||||
last_name: comment.user.last_name
|
||||
} : null
|
||||
}));
|
||||
|
||||
console.log("gg9");
|
||||
res.status(200).json({
|
||||
comments: commentList,
|
||||
totalPages: comments.totalPages,
|
||||
totalItems: comments.totalDocs
|
||||
})
|
||||
} catch (error) {
|
||||
console.log("gg");
|
||||
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// دریافت جزئیات یک کامنت
|
||||
const getCommentDetail = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const comment_id = req.query.comment_id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(comment_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کامنت معتبر نیست' })
|
||||
}
|
||||
|
||||
const comment = await CommentModel.findById(comment_id)
|
||||
.populate('creator', 'user_name first_name last_name profile_image ')
|
||||
.populate('user', 'user_name first_name last_name')
|
||||
.populate('project', 'title')
|
||||
|
||||
if (!comment) {
|
||||
return res.status(404).json({ message: 'کامنت مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
const response = {
|
||||
_id: comment._id,
|
||||
comment: comment.comment,
|
||||
rating: comment.rating,
|
||||
createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'),
|
||||
status: comment.status,
|
||||
comment_for: comment.comment_for,
|
||||
project: comment.project ? comment.project.title : null,
|
||||
creator: {
|
||||
_id: comment.creator._id,
|
||||
user_name: comment.creator.user_name,
|
||||
first_name: comment.creator.first_name,
|
||||
last_name: comment.creator.last_name,
|
||||
profile_image: comment.creator.profile_image
|
||||
},
|
||||
user: {
|
||||
_id: comment.user._id,
|
||||
user_name: comment.user.user_name,
|
||||
first_name: comment.user.first_name,
|
||||
last_name: comment.user.last_name
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({ comment: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// تایید یک کامنت
|
||||
const acceptComment = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { id, status, text } = req.body
|
||||
|
||||
if (!id || !status) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const comment = await CommentModel.findById(id)
|
||||
|
||||
if (!comment) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کامنت مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
if (text) {
|
||||
comment.comment = text
|
||||
}
|
||||
comment.status = status
|
||||
await comment.save()
|
||||
|
||||
res.status(201).json({ message: 'کامنت با موفقیت تایید شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getComments,
|
||||
getCommentDetail,
|
||||
acceptComment
|
||||
}
|
||||
/* eslint-disable camelcase */
|
||||
const CommentModel = require('../../../models/CommentModel')
|
||||
const jMoment = require('moment-jalaali')
|
||||
const { default: mongoose } = require('mongoose')
|
||||
|
||||
// دریافت لیست کامنتها با پیجینیشن
|
||||
const getComments = async (req, res, next) => {
|
||||
try {
|
||||
console.log("gg6");
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const {
|
||||
page = 1, limit = 10,
|
||||
startDate,
|
||||
endDate,
|
||||
status
|
||||
} = req.query
|
||||
const filter = {} // فیلتر بر اساس وضعیت کامنت
|
||||
|
||||
// Date
|
||||
if (startDate || endDate) {
|
||||
filter.createdAt = {}
|
||||
|
||||
if (startDate) {
|
||||
filter.createdAt.$gte = new Date(startDate) // تاریخ شروع
|
||||
}
|
||||
|
||||
if (endDate) {
|
||||
filter.createdAt.$lte = new Date(endDate) // تاریخ پایان
|
||||
}
|
||||
}
|
||||
console.log("gg8");
|
||||
if (status) {
|
||||
filter.status = status
|
||||
}
|
||||
const options = {
|
||||
page: parseInt(page), // تبدیل صفحه به عدد صحیح
|
||||
limit: parseInt(limit), // تبدیل محدودیت به عدد صحیح
|
||||
sort: { createdAt: -1 },
|
||||
populate: [
|
||||
{ path: 'creator', select: 'user_name first_name last_name profile_image ' },
|
||||
{ path: 'user', select: 'user_name first_name last_name' },
|
||||
{ path: 'project', select: 'title' }
|
||||
]
|
||||
}
|
||||
|
||||
const comments = await CommentModel.paginate(filter, options)
|
||||
const commentList = comments.docs.map(comment => ({
|
||||
_id: comment._id,
|
||||
createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'),
|
||||
status: comment.status,
|
||||
comment_for: comment.comment_for,
|
||||
project: comment.project ? comment.project.title : null,
|
||||
creator: comment.creator ? {
|
||||
_id: comment.creator._id,
|
||||
user_name: comment.creator.user_name,
|
||||
first_name: comment.creator.first_name,
|
||||
last_name: comment.creator.last_name,
|
||||
profile_image: comment.creator.profile_image
|
||||
} : null,
|
||||
user: comment.user ? {
|
||||
_id: comment.user._id,
|
||||
user_name: comment.user.user_name,
|
||||
first_name: comment.user.first_name,
|
||||
last_name: comment.user.last_name
|
||||
} : null
|
||||
}));
|
||||
|
||||
console.log("gg9");
|
||||
res.status(200).json({
|
||||
comments: commentList,
|
||||
totalPages: comments.totalPages,
|
||||
totalItems: comments.totalDocs
|
||||
})
|
||||
} catch (error) {
|
||||
console.log("gg");
|
||||
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// دریافت جزئیات یک کامنت
|
||||
const getCommentDetail = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const comment_id = req.query.comment_id
|
||||
|
||||
if (!mongoose.Types.ObjectId.isValid(comment_id)) {
|
||||
return res.status(400).json({ message: 'شناسه کامنت معتبر نیست' })
|
||||
}
|
||||
|
||||
const comment = await CommentModel.findById(comment_id)
|
||||
.populate('creator', 'user_name first_name last_name profile_image ')
|
||||
.populate('user', 'user_name first_name last_name')
|
||||
.populate('project', 'title')
|
||||
|
||||
if (!comment) {
|
||||
return res.status(404).json({ message: 'کامنت مورد نظر یافت نشد' })
|
||||
}
|
||||
|
||||
const response = {
|
||||
_id: comment._id,
|
||||
comment: comment.comment,
|
||||
rating: comment.rating,
|
||||
createdAt: jMoment(comment.createdAt).format('jYYYY-jMM-jDD HH:mm'),
|
||||
status: comment.status,
|
||||
comment_for: comment.comment_for,
|
||||
project: comment.project ? comment.project.title : null,
|
||||
creator: {
|
||||
_id: comment.creator._id,
|
||||
user_name: comment.creator.user_name,
|
||||
first_name: comment.creator.first_name,
|
||||
last_name: comment.creator.last_name,
|
||||
profile_image: comment.creator.profile_image
|
||||
},
|
||||
user: {
|
||||
_id: comment.user._id,
|
||||
user_name: comment.user.user_name,
|
||||
first_name: comment.user.first_name,
|
||||
last_name: comment.user.last_name
|
||||
}
|
||||
}
|
||||
|
||||
res.status(200).json({ comment: response })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
// تایید یک کامنت
|
||||
const acceptComment = async (req, res, next) => {
|
||||
try {
|
||||
const token = req.header('Authorization').split(' ')[1]
|
||||
if (!token) return res.status(401).send('Access Denied')
|
||||
|
||||
const { id, status, text } = req.body
|
||||
|
||||
if (!id || !status) {
|
||||
return res.status(422).json({
|
||||
error: true,
|
||||
message: 'اطلاعات ارسالی اشتباه است'
|
||||
})
|
||||
}
|
||||
|
||||
const comment = await CommentModel.findById(id)
|
||||
|
||||
if (!comment) {
|
||||
return res.status(404).json({
|
||||
error: true,
|
||||
message: 'کامنت مورد نظر یافت نشد'
|
||||
})
|
||||
}
|
||||
if (text) {
|
||||
comment.comment = text
|
||||
}
|
||||
comment.status = status
|
||||
await comment.save()
|
||||
|
||||
res.status(201).json({ message: 'کامنت با موفقیت تایید شد' })
|
||||
} catch (error) {
|
||||
next(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getComments,
|
||||
getCommentDetail,
|
||||
acceptComment
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user